# `secrets/` — sops + age secret material This folder holds **per-environment** runtime configuration for the Admin API. | File | Tracked | Encrypted | Loaded by | |------|---------|-----------|-----------| | `.sops.yaml` | yes | n/a | sops itself (resolves recipients) | | `staging.public.env` | yes | no | `scripts/_lib.sh` → `set -a; .` (loaded BEFORE the encrypted overlay) | | `production.public.env` | yes | no | same | | `staging.env` | yes (after first encryption) | **yes** (sops + age) | `scripts/deploy.sh` decrypts to a tempfile then sources it | | `production.env` | yes (after first encryption) | **yes** (sops + age) | same | | age private key | **never tracked** | n/a | lives at `/etc/azaion/age.key` on the deploy host (mode 0400) | ## First-time bootstrap on a fresh host ```bash # 1. Install sops + age on the host sudo apt-get install -y sops age # 2. Generate the host's age keypair sudo install -d -m 0700 /etc/azaion sudo age-keygen -o /etc/azaion/age.key sudo chmod 0400 /etc/azaion/age.key sudo grep '^# public key:' /etc/azaion/age.key # → copy the public key string # 3. On a developer machine, replace the placeholder in `secrets/.sops.yaml` # with the public key from step 2 (for the matching environment), then # encrypt the env file: # sops --encrypt --age secrets/staging.env > secrets/staging.enc.tmp # mv secrets/staging.enc.tmp secrets/staging.env # Commit `.sops.yaml` and the encrypted file together. # 4. Sanity-check on the host: SOPS_AGE_KEY_FILE=/etc/azaion/age.key sops -d secrets/staging.env | head ``` ## Rotation See `_docs/04_deploy/environment_strategy.md` §3 for the per-secret rotation cadence and procedure. ## What goes where - **Public env (staging.public.env / production.public.env)** — anything that is NOT a secret: hostname, port, container name, JWT issuer/audience, resource folder names. Reviewable in PRs. - **Encrypted env (staging.env / production.env)** — DB connection strings (with passwords), `JwtConfig__Secret`, `REGISTRY_USER`, `REGISTRY_TOKEN`, anything else sensitive. NEVER readable in plain text outside the host. ## Schema (variables that MUST be in the encrypted file) ``` ASPNETCORE_ConnectionStrings__AzaionDb=Host=...;Port=4312;Database=azaion;Username=azaion_reader;Password=... ASPNETCORE_ConnectionStrings__AzaionDbAdmin=Host=...;Port=4312;Database=azaion;Username=azaion_admin;Password=... ASPNETCORE_JwtConfig__Secret=<>= 32 random bytes> REGISTRY_USER= REGISTRY_TOKEN= ``` The deploy script will fail-fast if any of the first three are missing once the container starts.