Migrate from .env to fnox + 1Password
This skill guides the migration from plaintext .env files to fnox with 1Password as the secret provider. fnox is provider-agnostic and supports multiple backends (1Password, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, age encryption, etc.).
Prerequisites
Before starting, verify:
- •1Password CLI is installed:
op --version - •User is authenticated to 1Password:
op vault list - •mise is installed (optional but recommended):
mise --version
Migration Workflow
Step 1: Analyze Existing .env
Read the existing .env file to understand what secrets need migration:
cat .env
Categorize the secrets:
- •Cloud provider credentials (AWS_, ARM_, GOOGLE_*)
- •API tokens (CLOUDFLARE_, GITHUB_, etc.)
- •Application secrets (DATABASE_URL, API_KEY, etc.)
- •Configuration values (non-secret defaults like regions)
Step 2: Install fnox
Install fnox via mise (recommended):
mise use fnox
Or add to mise.toml:
[tools] fnox = "latest"
Initialize fnox configuration:
mise exec -- fnox init mise exec -- fnox provider add op 1password
Step 3: Create 1Password Item
Create a single 1Password item containing all secrets. Use the API Credential category for organization:
op item create \ --category="API Credential" \ --title="project-name" \ --vault="Private" \ 'Field Name[text]=value' \ 'Secret Field[password]=secret-value'
Field naming conventions:
- •Use descriptive names: "AWS Access Key ID" not "aws_key"
- •Use
[text]for non-sensitive values (IDs, regions, emails) - •Use
[password]for sensitive values (secrets, tokens, keys)
Example for a typical project:
op item create \ --category="API Credential" \ --title="myproject" \ --vault="Private" \ 'AWS Access Key ID[text]=AKIA...' \ 'AWS Secret Access Key[password]=...' \ 'Database URL[password]=postgres://...' \ 'API Token[password]=...'
Step 4: Configure fnox.toml
Update fnox.toml to reference the 1Password item:
[providers.op]
type = "1password"
vault = "Private"
[secrets]
# Format: ENV_VAR = { provider = "op", value = "item-title/Field Name" }
AWS_ACCESS_KEY_ID = { provider = "op", value = "myproject/AWS Access Key ID" }
AWS_SECRET_ACCESS_KEY = { provider = "op", value = "myproject/AWS Secret Access Key" }
DATABASE_URL = { provider = "op", value = "myproject/Database URL" }
# Non-secret defaults don't need 1Password
AWS_DEFAULT_REGION = { default = "us-east-1" }
Step 5: Integrate with mise
Update mise.toml to use fnox instead of .env:
[tools] fnox = "latest" # ... other tools [env] _.source = "fnox export"
Remove the old .env reference:
- _.file = ".env" + _.source = "fnox export"
Step 6: Verify and Clean Up
Test the configuration:
# List configured secrets mise exec -- fnox list # Verify a secret can be retrieved mise exec -- fnox get AWS_ACCESS_KEY_ID # Test full environment mise exec -- printenv | grep AWS_
Once verified, delete the old .env file:
rm .env
Commit fnox.toml (it contains no secrets, only references):
git add fnox.toml mise.toml git commit -m "Migrate secrets from .env to fnox + 1Password"
fnox.toml Reference
Provider Configuration
# 1Password [providers.op] type = "1password" vault = "Private" # account = "my.1password.com" # Optional: specify account # Age encryption (for git-stored encrypted secrets) [providers.age] type = "age" recipients = ["age1..."] # AWS Secrets Manager [providers.aws] type = "aws-sm" region = "us-east-1" prefix = "myapp/"
Secret Reference Formats
[secrets]
# 1Password: item-title/field-name
SECRET = { provider = "op", value = "myproject/Secret Field" }
# 1Password: full op:// URI
SECRET = { provider = "op", value = "op://Vault/Item/Field" }
# Default value (no provider needed)
REGION = { default = "us-east-1" }
# Age-encrypted value
SECRET = { provider = "age", value = "YWdlLWVu..." }
Profiles for Multiple Environments
[providers.op]
type = "1password"
vault = "Development"
[secrets]
DATABASE_URL = { provider = "op", value = "dev-db/url" }
[profiles.production.providers.op]
vault = "Production"
[profiles.production.secrets]
DATABASE_URL = { provider = "op", value = "prod-db/url" }
Use profiles with: FNOX_PROFILE=production fnox export
Troubleshooting
"No configuration file found"
Run fnox init to create fnox.toml, or check that you're in the correct directory.
1Password authentication errors
Ensure you're signed in: op signin or check that "Integrate with other apps" is enabled in 1Password Settings > Developer.
Secrets not loading in shell
If using mise, ensure mise trust has been run for the project directory.
fnox command not found after mise install
Use mise exec -- fnox or restart your shell to pick up the new PATH.