← knowledge.oriz.in

Env keys + GH Actions secrets — single source of truth, two delivery tracks

decision decisionssecurityenvdotenvsecretsdopplergithuborg-levelsyncdrift

Env keys + GH Actions secrets — single source of truth, two delivery tracks

Decision

Manage every environment-variable surface in the family on a two-track model, each with a single source of truth. Per-repo hand-edits are forbidden on both tracks; CI catches drift.

Why

User direction on 2026-06-20 (verbatim): "write the all teh env example files in the .env.example also so everything is managed from one project and we set the github action secret on org chirag127 level." Two locks land in the same conversation:

Implications

Architecture

                    .env.example (PUBLIC, key names only)
                              ¦
templates/.env.example  ------?  sync-env-example.sh  ------?  every repo's .env.example
   (master, edited here)              (sync)                     (verbatim copy)
                                                                       ¦
                                                                       ¦ cp .env.example .env
                                                                       ?
                                                              local dev .env (gitignored)
                                                              filled from Doppler

                    GitHub Actions secrets (PRIVATE, real values)
                              ¦
Doppler (source of truth)  --?  set-org-secrets-from-doppler.sh  --?  chirag127 org-level GH secrets
   (humans write here)              (sync)                            (visibility: all)
                                                                            ¦
                                                                            ?
                                                                  every repo's CI
                                                                  reads via secrets.<NAME>

Drift safeguards

Operational

What this decision does NOT do

Cross-refs

Naming conventions

When per-app .env.example files drifted historically, the same logical key appeared under multiple names. This is the canonical-name policy enforced by the master template (templates/.env.example). Drift variants in the right column must NEVER be re-introduced; CI greps for them.

Canonical (use this) Banned drift variant
CLOUDFLARE_ACCOUNT_ID CF_ACCOUNT_ID
CLOUDFLARE_API_TOKEN CF_API_TOKEN
CLOUDFLARE_ZONE_ID CF_ZONE_ID
CF_TURNSTILE_SECRET CF_TURNSTILE_SECRET_KEY
PUBLIC_CF_TURNSTILE_SITE_KEY CF_TURNSTILE_SITE_KEY
HCAPTCHA_SECRET HCAPTCHA_SECRET_KEY
PUBLIC_HCAPTCHA_SITE_KEY HCAPTCHA_SITE_KEY
LEMONSQUEEZY_API_KEY LEMON_SQUEEZY_API_KEY
EMAILOCTOPUS_API_KEY EMAIL_OCTOPUS_API_KEY
DEVTO_API_KEY DEV_TO_API_KEY
PUBLIC_GA4_MEASUREMENT_ID PUBLIC_GA4_ID
POSTHOG_API_KEY / PUBLIC_POSTHOG_KEY POSTHOG_KEY
PUBLIC_WEB3FORMS_KEY WEB3FORMS_KEY
DOPPLER_SERVICE_TOKEN DOPPLER_TOKEN
WORDPRESS_APP_PASSWORD WORDPRESS_API_TOKEN

Rules of thumb