Secrets-free .env with 1Password CLI and DDEV
/ 2 min read
Link post → studiomitte.comI wrote up a guide for using 1Password CLI with DDEV for my companies blog. Here you can read the english version.
Your .env file sits one git add . away from leaking your database password. 1Password CLI fixes this without extra infrastructure. Replace credential values with references, and let op run inject the real secrets at container start. Nothing sensitive ever even touches your filesystem.
Prerequisites
- A 1Password account (individual or teams)
- 1Password CLI installed
- A DDEV project with credentials in a
.envfile
Connect 1Password CLI
Add your account and sign in:
op account add
eval $(op signin)
eval $(op signin) sets session tokens in your current shell. You’ll re-run this each session, or configure biometric unlock for automatic authentication.
Find your secret references
1Password references use the format op://vault-name/item-name/field-name. To find the exact field names for an item, fetch it as JSON:
op item get "My Database" --format json
Look for the reference key inside each field object - it gives you the exact string to paste. You can also right-click any field in the 1Password desktop app and copy its secret reference directly.
Replace values in .env
Swap out credential values for their op:// references:
DB_PASSWORD=supersecret123
STRIPE_SECRET=sk-live-abcdef123456
SMTP_PASSWORD=mailpassword DB_PASSWORD="op://Private/My Database/password"
STRIPE_SECRET="op://Private/Stripe/secret key"
SMTP_PASSWORD="op://Private/Mailgun/password" The .env is now safe to commit or sync - it holds paths, not secrets.
Tell DDEV to accept injected variables
DDEV doesn’t automatically forward host environment variables into the web container. Add each variable name to web_environment in .ddev/config.yaml:
web_environment:
- DB_PASSWORD
- STRIPE_SECRET
- SMTP_PASSWORD
Without this, op run resolves the secrets into the host process but they never reach the container.
Start DDEV with secrets resolved
op run --env-file=".env" -- ddev start
op run reads the .env file, resolves each op:// reference against 1Password, injects the real values into the process environment, then hands off to ddev start. The secrets exist in memory for that process only - never written to disk.
💡 If your .env file isn’t in the project root, adjust the path: op run --env-file="config/.env" -- ddev start
The main trade-off: everyone running the project needs 1Password CLI and vault access. For solo work that’s nothing. For teams, make sure the relevant items are in a shared vault before rolling this out.