Skip to content

Migrate from .env

Take an existing .env file, move the sensitive values into your dotsecenv vault, and set up .secenv so everything still loads automatically.

.env filedotsecenv
One file per project, plain textOne vault file per project, encrypted
Edit a line to change a valuesecret store NAME writes a new entry; old values stay as history
Cannot commit safelyVault file commits safely to git
No history of who could read whatAppend-only; recipients tracked per entry
Loaded by source .env at runtimeLoaded by the shell plugin on cd

The unit of encryption and audit is the individual secret, not the file. There is no bulk-import command for that reason; the loop below loops the single-secret store call over your .env lines.

  1. Start with your .env file

    A typical project .env looks like this:

    .env
    DATABASE_HOST=localhost
    DATABASE_PORT=5432
    DATABASE_NAME=myapp
    DATABASE_PASSWORD=super-secret-password
    API_KEY=sk-live-abc123xyz

    Three of these are non-sensitive configuration. Two are secrets you would not want in a public repo.

  2. Identify the secrets

    Ask yourself: would I panic if this value appeared on a public GitHub repo? If yes, it belongs in the vault.

    In this example: DATABASE_PASSWORD and API_KEY.

  3. Store the secrets in your vault

    Terminal window
    echo "super-secret-password" | dotsecenv secret store DATABASE_PASSWORD
    echo "sk-live-abc123xyz" | dotsecenv secret store API_KEY
  4. Create a .secenv file

    Terminal window
    cat > .secenv << 'EOF'
    DATABASE_PASSWORD={dotsecenv}
    API_KEY={dotsecenv}
    EOF

    The {dotsecenv} syntax tells the shell plugin to fetch the secret with the same name as the variable.

  5. Remove the secrets from .env

    Your .env now contains only non-sensitive values:

    .env
    DATABASE_HOST=localhost
    DATABASE_PORT=5432
    DATABASE_NAME=myapp
  6. Verify everything loads

    Terminal window
    cd ~
    cd ~/my-project
    # dotsecenv: loaded 2 secret(s) from .secenv: DATABASE_PASSWORD, API_KEY
    echo $DATABASE_HOST
    # Output: localhost
    echo $DATABASE_PASSWORD
    # Output: super-secret-password
    echo $API_KEY
    # Output: sk-live-abc123xyz

    All five variables are available. Only three are on disk in plaintext.

  7. Update version control

    Terminal window
    echo ".env" >> .gitignore
    git add .secenv .gitignore
    git commit -m "chore: move secrets to dotsecenv vault"
VariableSourceOn disk in plaintext?
DATABASE_HOST.envYes
DATABASE_PORT.envYes
DATABASE_NAME.envYes
DATABASE_PASSWORDvault via .secenvNo
API_KEYvault via .secenvNo

For a .env with many keys, a shell loop is faster than copy-pasting:

Terminal window
while IFS='=' read -r name value; do
case "$name" in ''|\#*) continue ;; esac
printf '%s' "$value" | dotsecenv secret store "$name"
done < .env

Inspect any quoted or multi-line values manually before relying on this; IFS='=' splits on the first = only and does not handle escapes.