Fill .env from Bitwarden with make instead of by hand
.env.dist is now a template: `make .env` fetches the CLOUDFLARE_API_TOKEN field of the "mykiwi.blog" vault item and substitutes it for the placeholder, writing the result with owner-only permissions. It is a file target, so it only re-runs when .env is missing or .env.dist is newer. deploy depends on it: its recursive $(MAKE) re-reads the Makefile, so a token fetched in the same run reaches the sub-make. The infra-* and deploy-% targets call nix run directly and are left as they were. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
aebf633 parent: d51e2b6 modified
.env.dist +3 -2 | @@ -1,2 +1,3 @@ | ||
| 1 | -CLOUDFLARE_API_TOKEN= | |
| 2 | -# https://dash.cloudflare.com/profile/api-tokens | |
| 1 | +# Template for .env: `make .env` fills the placeholder in from Bitwarden | |
| 2 | +# (the CLOUDFLARE_API_TOKEN field of the "mykiwi.blog" item). | |
| 3 | +CLOUDFLARE_API_TOKEN=@CLOUDFLARE_API_TOKEN@ | |
| @@ -1,2 +1,3 @@ | |||
| 1 | -CLOUDFLARE_API_TOKEN= | 1 | +# Template for .env: `make .env` fills the placeholder in from Bitwarden |
| 2 | -# https://dash.cloudflare.com/profile/api-tokens | 2 | +# (the CLOUDFLARE_API_TOKEN field of the "mykiwi.blog" item). |
| 3 | +CLOUDFLARE_API_TOKEN=@CLOUDFLARE_API_TOKEN@ | ||
modified
Makefile +12 -3 | @@ -1,6 +1,6 @@ | ||
| 1 | 1 | .DEFAULT_GOAL := help |
| 2 | 2 | |
| 3 | -# CLOUDFLARE_API_TOKEN lives in .env (gitignored, copy from .env.dist) - | |
| 3 | +# CLOUDFLARE_API_TOKEN lives in .env (gitignored, written by `make .env`) - | |
| 4 | 4 | # load it into every recipe's environment, e.g. for infra-plan/infra-apply/deploy. |
| 5 | 5 | ifneq (,$(wildcard .env)) |
| 6 | 6 | include .env |
| @@ -24,7 +24,14 @@ PROD_PORT ?= 8788 | ||
| 24 | 24 | .PHONY: help dev build check-tracked serve prod-server infra-plan infra-apply deploy clean |
| 25 | 25 | |
| 26 | 26 | help: |
| 27 | - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' | |
| 27 | + @grep -E '^[a-zA-Z_.-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' | |
| 28 | + | |
| 29 | +# The token is the CLOUDFLARE_API_TOKEN field of the "mykiwi.blog" Bitwarden | |
| 30 | +# item; bw prompts for the master password unless BW_SESSION is set. A file | |
| 31 | +# target, so it only runs while .env is missing or older than .env.dist. | |
| 32 | +.env: .env.dist ## Write .env from .env.dist, filling in the token from Bitwarden | |
| 33 | + @umask 077; token="$$(bw get item mykiwi.blog | jq -er '.fields[] | select(.name == "CLOUDFLARE_API_TOKEN") | .value')" \ | |
| 34 | + && sed "s|@CLOUDFLARE_API_TOKEN@|$$token|" .env.dist > $@ | |
| 28 | 35 | |
| 29 | 36 | dev: ## Drop into the Hugo dev shell (hugo, dart-sass) |
| 30 | 37 | nix develop |
| @@ -70,7 +77,9 @@ infra-plan: ## Show what infra-apply would change on Cloudflare | ||
| 70 | 77 | infra-apply: ## Apply infra/ changes to Cloudflare |
| 71 | 78 | nix run .#infra -- apply |
| 72 | 79 | |
| 73 | -deploy: build ## Build the site and push it to Cloudflare Pages (all languages, in parallel) | |
| 80 | +# .env before build: the sub-make below re-reads the Makefile, so a token | |
| 81 | +# fetched here is in its environment; deploy-% run directly is not covered. | |
| 82 | +deploy: .env build ## Build the site and push it to Cloudflare Pages (all languages, in parallel) | |
| 74 | 83 | $(MAKE) --no-print-directory --output-sync=target -j$(words $(LANGS)) $(addprefix deploy-,$(LANGS)) |
| 75 | 84 | |
| 76 | 85 | deploy-%: ## Deploy a single language to Cloudflare Pages, e.g. `make deploy-en` (assumes `make build` already ran) |
| @@ -1,6 +1,6 @@ | |||
| 1 | .DEFAULT_GOAL := help | 1 | .DEFAULT_GOAL := help |
| 2 | 2 | ||
| 3 | -# CLOUDFLARE_API_TOKEN lives in .env (gitignored, copy from .env.dist) - | 3 | +# CLOUDFLARE_API_TOKEN lives in .env (gitignored, written by `make .env`) - |
| 4 | # load it into every recipe's environment, e.g. for infra-plan/infra-apply/deploy. | 4 | # load it into every recipe's environment, e.g. for infra-plan/infra-apply/deploy. |
| 5 | ifneq (,$(wildcard .env)) | 5 | ifneq (,$(wildcard .env)) |
| 6 | include .env | 6 | include .env |
| @@ -24,7 +24,14 @@ PROD_PORT ?= 8788 | |||
| 24 | .PHONY: help dev build check-tracked serve prod-server infra-plan infra-apply deploy clean | 24 | .PHONY: help dev build check-tracked serve prod-server infra-plan infra-apply deploy clean |
| 25 | 25 | ||
| 26 | help: | 26 | help: |
| 27 | - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' | 27 | + @grep -E '^[a-zA-Z_.-]+:.*?## .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' |
| 28 | + | ||
| 29 | +# The token is the CLOUDFLARE_API_TOKEN field of the "mykiwi.blog" Bitwarden | ||
| 30 | +# item; bw prompts for the master password unless BW_SESSION is set. A file | ||
| 31 | +# target, so it only runs while .env is missing or older than .env.dist. | ||
| 32 | +.env: .env.dist ## Write .env from .env.dist, filling in the token from Bitwarden | ||
| 33 | + @umask 077; token="$$(bw get item mykiwi.blog | jq -er '.fields[] | select(.name == "CLOUDFLARE_API_TOKEN") | .value')" \ | ||
| 34 | + && sed "s|@CLOUDFLARE_API_TOKEN@|$$token|" .env.dist > $@ | ||
| 28 | 35 | ||
| 29 | dev: ## Drop into the Hugo dev shell (hugo, dart-sass) | 36 | dev: ## Drop into the Hugo dev shell (hugo, dart-sass) |
| 30 | nix develop | 37 | nix develop |
| @@ -70,7 +77,9 @@ infra-plan: ## Show what infra-apply would change on Cloudflare | |||
| 70 | infra-apply: ## Apply infra/ changes to Cloudflare | 77 | infra-apply: ## Apply infra/ changes to Cloudflare |
| 71 | nix run .#infra -- apply | 78 | nix run .#infra -- apply |
| 72 | 79 | ||
| 73 | -deploy: build ## Build the site and push it to Cloudflare Pages (all languages, in parallel) | 80 | +# .env before build: the sub-make below re-reads the Makefile, so a token |
| 81 | +# fetched here is in its environment; deploy-% run directly is not covered. | ||
| 82 | +deploy: .env build ## Build the site and push it to Cloudflare Pages (all languages, in parallel) | ||
| 74 | $(MAKE) --no-print-directory --output-sync=target -j$(words $(LANGS)) $(addprefix deploy-,$(LANGS)) | 83 | $(MAKE) --no-print-directory --output-sync=target -j$(words $(LANGS)) $(addprefix deploy-,$(LANGS)) |
| 75 | 84 | ||
| 76 | deploy-%: ## Deploy a single language to Cloudflare Pages, e.g. `make deploy-en` (assumes `make build` already ran) | 85 | deploy-%: ## Deploy a single language to Cloudflare Pages, e.g. `make deploy-en` (assumes `make build` already ran) |