Skip to content
beginner5 minutesevnx v0.3.8+

evnx backup

Create an encrypted, portable backup of your .env file using AES-256-GCM and Argon2id key derivation.

Prerequisites

evnx backup creates a cryptographically secure, portable backup of your .env file. The backup is encrypted with AES-256-GCM using a key derived from your password via Argon2id, ensuring your secrets remain confidential even if the backup file is exposed.


Command signature

Bash
evnx backup [OPTIONS]

Options:

FlagTypeDefaultDescription
--envstring.envPath to the .env file to back up
--outputstring<env>.backupDestination path for the encrypted backup
--key-filepathUse a file as the encryption key instead of a password prompt
--keepnumber3Number of previous backups to retain alongside the new one
--verifyboolfalseRe-decrypt and integrity-check the backup immediately after writing
--verboseboolfalsePrint diagnostic information at each pipeline stage

How encryption works

Security model

Every backup uses industry-standard cryptography:

┌─────────────────────────────────────────┐
│ 1. Password entered or read from file   │
│ 2. Fresh 32-byte salt generated         │
│ 3. Argon2id derives 32-byte AES key     │
│    • Memory: 64 MiB                     │
│    • Iterations: 3                      │
│    • Parallelism: 1                     │
│ 4. Fresh 12-byte nonce generated        │
│ 5. AES-256-GCM encrypts JSON envelope   │
│ 6. Binary envelope Base64-encoded       │
│ 7. File written with 0o600 permissions  │
└─────────────────────────────────────────┘

Binary format (version 1)

Text
┌─────────┬────────────┬──────────┬────────────────────────────────┐
│ version │    salt    │  nonce   │  AES-256-GCM ciphertext        │
│  1 byte │  32 bytes  │ 12 bytes │  variable (JSON envelope)      │
└─────────┴────────────┴──────────┴────────────────────────────────┘

The entire structure is Base64-encoded before being written to disk.

Encrypted payload structure

The ciphertext decrypts to a JSON envelope containing both your .env content and metadata:

JSON
{
  "schema_version": 1,
  "version": 1,
  "created_at": "2026-03-10T14:30:00Z",
  "original_file": ".env.production",
  "tool_version": "0.4.0",
  "content": "DATABASE_URL=postgresql://...\nAPI_KEY=sk-...\n"
}

Why metadata is encrypted

Embedding metadata inside the encrypted payload means it is both confidential (an attacker cannot learn filenames or timestamps without the password) and tamper-evident (altering metadata invalidates the GCM authentication tag).


Basic usage

Create a backup of .env

Bash
evnx backup
╔══════════════════════════════════════╗
║  evnx backup                        ║
║  Encrypt and back up your .env file ║
╚══════════════════════════════════════╝

✓ Read 342 bytes from .env
Enter encryption password: ••••••••
Confirm password: ••••••••

✓ Backup created successfully
  Source   .env
  Backup   .env.backup
  Size     1 024 bytes (encrypted + Base64)
  Verified no

⚠️  Important:
  • Keep your password (or key file) safe — it cannot be recovered
  • Store the backup in a secure, separate location
  • To restore: evnx restore .env.backup --output .env
  • Test the restore before deleting the original .env

Backup a specific environment file

Bash
evnx backup --env .env.production --output prod.backup

Verbose mode for debugging

Bash
evnx backup --verbose
╔══════════════════════════════════════╗
║  evnx backup                        ║
║  Encrypt and back up your .env file ║
╚══════════════════════════════════════╝

  Source path  : .env
  Read 342 bytes from .env
✓ Read 342 bytes from .env
Enter encryption password: ••••••••
  Password accepted — awaiting confirmation
Confirm password: ••••••••
  Passwords match
  Backup pipeline starting
  Source       : .env
  Output       : .env.backup
  Keep         : 3
  Verify       : false
  Argon2id key derivation in progress…
  Encryption complete — writing backup file
  Backup written to .env.backup

✓ Backup created successfully
  Source   .env
  Backup   .env.backup
  Size     1 024 bytes (encrypted + Base64)
  Verified no

Backup rotation

By default evnx keeps the 3 most recent backups alongside the new one. Before each write, existing files are shifted up by one position:

.env.backup   →  .env.backup.1
.env.backup.1 →  .env.backup.2
.env.backup.2 →  .env.backup.3  (overwritten if already exists — see warning)

After the rotation the slot is free and the new backup is written to .env.backup.

Bash
# Keep the last 5 backups
evnx backup --keep 5

# Disable rotation — overwrite silently
evnx backup --keep 0

Files beyond --keep are overwritten, never deleted

If a file already exists at position --keep (e.g. .env.backup.5 when using --keep 5), evnx will warn you and overwrite it during rotation. Increase --keep or prune the file manually if you need to retain it.


Post-write integrity verification

The --verify flag re-decrypts the backup immediately after writing and compares the recovered content byte-for-byte against the original. This proves the backup is readable before you discard or archive the source file.

Bash
evnx backup --verify
✓ Backup created and verified successfully
  Source   .env
  Backup   .env.backup
  Size     1 024 bytes (encrypted + Base64)
  Verified yes

If the check fails (corrupt write, filesystem error) evnx exits with code 6 and leaves the backup file on disk for manual inspection. Your original .env is never modified.

Performance cost

--verify runs a second full Argon2id round (~1 s on commodity hardware). For interactive use this is imperceptible. In CI pipelines backing up many files in sequence, consider whether the safety guarantee is worth the added time.


Non-interactive / CI usage with --key-file

For automated pipelines where typing a password is not possible, supply a key file instead. The file's contents are used as the encryption password source — no prompts are shown.

Bash
evnx backup --key-file /run/secrets/backup-key

How key material is read:

  • UTF-8 files — content is trimmed of surrounding whitespace. A file containing correct-horse-battery-staple\n is treated identically to one without the trailing newline.
  • Binary files — content is Base64-encoded first to produce a stable ASCII string before being fed into Argon2id.

Both paths go through the same Argon2id KDF, so key length beyond the KDF input limit is handled automatically.

Full CI example

Bash
# GitHub Actions
- name: Backup .env.production
  run: |
    evnx backup \
      --env .env.production \
      --output backups/prod-$(date +%Y%m%d).backup \
      --key-file /run/secrets/BACKUP_KEY \
      --keep 7 \
      --verify
Bash
# Docker / docker-compose
services:
  backup:
    image: evnx
    command: >
      backup
      --env /secrets/.env
      --key-file /run/secrets/backup_key
      --keep 5
      --verify
    volumes:
      - ./backups:/backups
    secrets:
      - backup_key

Key file security

Treat key files with the same care as the .env file itself. Store them in a secrets manager (Vault, AWS Secrets Manager, GitHub Secrets) rather than on disk alongside your repository. Never commit a key file to version control.


File permissions and security

Automatic permission hardening

On Unix-like systems, evnx backup creates backup files with restrictive permissions regardless of the current umask:

Bash
$ evnx backup
$ ls -l .env.backup
-rw------- 1 user user 1024 Mar 10 14:30 .env.backup  # 0o600: owner read/write only

This applies to every file in the rotation chain (.env.backup.1, .env.backup.2, …) — all are originally created by evnx with 0o600.


Troubleshooting

"Password must be at least 8 characters"

evnx enforces a minimum password length as a sanity guard. Argon2id makes brute-forcing expensive, but short passwords remain vulnerable to dictionary attacks.

Fix: Use a longer password or passphrase:

Bash
# ✅ Strong passphrase
evnx backup  # then type: correct-horse-battery-staple

"Passwords do not match" (exit code 3)

The confirmation prompt did not match the original entry. Re-run the command and type both prompts carefully. This check does not apply when --key-file is used.

"File does not look like a standard .env file"

evnx heuristically checks whether the input resembles a .env file. This warning is non-fatal — the backup proceeds regardless.

⚠️  File does not look like a standard .env file — backing up anyway

When this is expected

This warning appears when backing up files with unusual formatting, files containing mostly comments, or non-.env files you intentionally want to encrypt. If unexpected, verify the --env path is correct.

"Backup integrity check failed" (exit code 6)

The --verify check failed: evnx could not re-decrypt the file it just wrote, or the recovered content did not match the original. The backup file is left on disk for inspection.

Possible causes:

  • Filesystem error during write (full disk, permission change mid-write)
  • Storage hardware fault

Fix: Check available disk space, inspect the backup file, and retry. If the problem persists on a specific path, try a different output location.

"Key file not found" or "Key file is not a regular file"

evnx validates the key file path before attempting to read it.

Fix: Verify the path exists and is a regular file (not a directory or symlink to a missing target):

Bash
ls -l /run/secrets/backup-key

"Backup feature not enabled"

The backup/restore feature is optional and must be enabled at build time:

✗ Backup feature not enabled
Rebuild with: cargo build --features backup

Fix:

Bash
cargo install evnx --features backup
# or for local development:
cargo build --features backup

Best practices

Password and key file management

  • Never commit passwords or key files to version control
  • Use a password manager or secrets manager (Vault, AWS Secrets Manager, 1Password Secrets Automation) to generate and store credentials
  • Use different passwords/keys for different environments (dev / staging / prod)
  • Rotate credentials periodically and re-encrypt existing backups after rotation

Backup storage

  • Store backups in a location separate from your source code repository
  • Use encrypted storage or a secret manager for the backup files themselves
  • Use --keep with a value appropriate to your recovery window
  • Run --verify for any backup you intend to archive or ship offsite
  • Test restore procedures regularly — a backup you cannot restore is not a backup

Recommended CI invocation

Bash
evnx backup \
  --env .env.production \
  --output /secure/backups/prod.backup \
  --key-file /run/secrets/backup_key \
  --keep 7 \
  --verify

This combination: uses a machine-readable key (no TTY required), retains a week of daily backups, and proves each one is readable before the job exits.


Exit codes

CodeMeaning
0Backup created successfully
1Generic error: IO failure, encoding error, unexpected failure
2Source file not found or not a regular file
3Password confirmation did not match
4Encryption failed
5Failed to write backup file to disk
6Post-write integrity check failed (--verify)

Related commands

  • evnx restore — decrypt and restore a backup to a .env file
  • evnx validate — check .env files for misconfiguration
  • evnx scan — detect secrets and sensitive patterns in .env files