Skip to content

envdrift push

Encrypt secret files for partial encryption workflows.

Synopsis

envdrift push [OPTIONS]

Description

The push command is part of the partial encryption workflow. Its exact behaviour depends on the mode configured for each environment:

Combine mode (default):

  1. Encrypts .secret files using dotenvx
  2. Combines .clear and encrypted .secret files into a single output file
  3. Adds a warning header to the generated file

Secrets-only mode (secrets_only = true):

  1. Encrypts every file matching pattern inside secrets_dir in place
  2. Does not read or write any configs directory
  3. Produces no combined output file

The pattern glob is non-recursive by default; use **/.env* for nested subdirectories. secrets_dir is required — pushing with secrets_only = true but no secrets_dir is rejected at config-load time.

The summary panel labels secrets-only counts as "Encrypted files (secrets-only)" and combine-mode counts as "Encrypted vars" (and shows both when an envdrift run mixes the two modes).

In both modes, push ensures the dotenvx private-key file (.env.keys) is listed in .gitignore so the decryption key is never committed. In combine mode it also adds each combined_file to .gitignore.

This command requires partial encryption to be configured in envdrift.toml.

Safety guarantees

push verifies its outcome instead of trusting the encryptor's exit code, and it fails (exit 1, no success banner) rather than report a false success:

  • Encryption is verified. After encrypting, push re-reads each secret file and fails if any plaintext value survived (for example when .env.keys is read-only, a directory, or malformed — dotenvx only warns and exits 0 in those cases).
  • Empty secret files are refused. A .secret (or secrets-only) file with no variable assignments is rejected with "Nothing to encrypt" instead of being handed to dotenvx, which would scaffold placeholder secrets into it.
  • Filenames dotenvx cannot turn into a valid key name are refused. dotenvx derives the DOTENV_PRIVATE_KEY_<NAME> entry from the filename, so a secret file whose name contains a space or non-ASCII character (e.g. my secret.env, café.env.secret) would encrypt cleanly yet be permanently undecryptable. push refuses such names before invoking dotenvx, leaving the plaintext intact — rename the file to use only ASCII letters, digits, ., - and _ (the guard's [A-Za-z0-9._-] set, so an accented name like résumé.env.secret is rejected too).
  • The combined file is never replaced with an empty scaffold. If both the clear_file and the secret_file are missing (deleted by mistake, or a path typo in envdrift.toml), push errors out and leaves the existing combined file untouched. A single missing source file is still fine.
  • The combined file is written atomically with owner-only permissions (0600 on POSIX, like .env.keys), since it carries the encrypted secret section and holds decrypted values after envdrift pull --merge.

Options

--env, -e

Process only a specific environment instead of all configured environments.

envdrift push --env production

--check

Dry run: verify that combined files are up to date with their source files without encrypting, writing, or modifying .gitignore. Exits non-zero if any combined file is missing or out of date (for example, after editing a .clear file but forgetting to re-run push, or after manually editing the generated combined file). Ideal for CI or a pre-commit hook.

envdrift push --check

In secrets-only mode, --check reports how many files would be encrypted and exits non-zero if any plaintext files remain.

Configuration

Partial encryption must be enabled in envdrift.toml:

[partial_encryption]
enabled = true

# Combine mode
[[partial_encryption.environments]]
name = "staging"
clear_file = ".env.staging.clear"
secret_file = ".env.staging.secret"
combined_file = ".env.staging"

# Secrets-only mode
[[partial_encryption.environments]]
name = "production"
secrets_only = true
secrets_dir = "secrets/production/"
pattern = ".env*"

Examples

Push All Environments

envdrift push

Encrypts and combines files for all configured environments.

Push Specific Environment

envdrift push --env production

Only processes the production environment.

Typical Workflow

# 1. Edit source files
vim .env.production.clear    # Non-sensitive changes
vim .env.production.secret   # Sensitive changes (decrypted)

# 2. Encrypt and combine
envdrift push

# 3. Commit source files only — the combined file is gitignored
git add .env.production.clear .env.production.secret
git commit -m "Update configuration"

Verify Combined Files Are Up to Date (CI / pre-commit)

envdrift push --check

Reports whether each combined file matches its source files and exits non-zero if a push is needed. Nothing is written.

Output

The combined file includes a warning header. The box auto-sizes to fit the file paths, so the right-hand border stays aligned even with long paths:

#/--------------------------------------------------------------------/
#/ WARNING: AUTO-GENERATED FILE                                       /
#/ DO NOT EDIT THIS FILE DIRECTLY                                     /
#/                                                                    /
#/ This file is generated by: envdrift push                           /
#/                                                                    /
#/ To make changes:                                                   /
#/   1. Run:  envdrift pull-partial (decrypts the .secret file)       /
#/   2. Edit: .env.production.clear                                   /
#/   3. Edit: .env.production.secret                                  /
#/   4. Run:  envdrift push (re-encrypts .secret and regenerates this)/
#/--------------------------------------------------------------------/

# From .env.production.clear
DEBUG=false
LOG_LEVEL=info

# From .env.production.secret (encrypted)
DATABASE_URL="encrypted:BD7HQzbvYWcHPy8jGI..."

The reported "encrypted vars" count reflects only real secret variables; dotenvx's DOTENV_PUBLIC_KEY_* line is not counted (public keys are not secrets).

Exit Codes

Code Meaning
0 Push completed successfully (or, with --check, everything is up to date)
1 Error (missing config, file not found, encryption failed), or --check found an out-of-date combined file

See Also