This is a public, sanitized pattern for small home-lab or self-hosted operations.
No real hostnames, tokens, keys, webhook URLs, IPs, or .env values should be copied into this document.
Keep source control useful without turning it into a secret store.
| Place | Role |
|---|---|
| 1Password | Source of truth for secret material. |
| GitHub Secrets | Runtime/bootstrap copy only when GitHub Actions needs it. |
Server .env files |
Runtime copy for Docker/services. |
| GitHub repositories | Docs, templates, fake examples, secret names, and recovery steps. |
.env.example, never real .env.Bad:
services:
app:
environment:
- DISCORD_WEBHOOK_URL=https://example.invalid/real-secret
Good:
services:
app:
env_file:
- .env
environment:
- APP_MODE=production
DISCORD_WEBHOOK_URL=op://example-vault/example-item/DISCORD_WEBHOOK_URL
Use one bootstrap secret to read values from 1Password:
- uses: 1password/load-secrets-action/configure@v3
with:
service-account-token: $
- uses: 1password/load-secrets-action@v3
with:
export-env: true
env:
API_KEY: "op://example-vault/example-api-key/API_KEY"
Validate presence without printing values:
if [ -z "${API_KEY:-}" ]; then
echo "::error::API_KEY did not load"
exit 1
fi
Automation may prepare safe changes, but production-impacting operations should require explicit owner approval:
Keep a private ledger that records:
.env files are backed up in 1PasswordThe ledger should never include secret values.