evnx restore
Decrypt and restore a .env file from an encrypted backup created by evnx backup. Includes safety features to prevent accidental overwrites, non-interactive CI/CD support, and structured exit codes for scripting.
Prerequisites
evnx restore decrypts and restores a .env file from an encrypted backup created by evnx backup. It uses the same AES-256-GCM encryption and Argon2id key derivation, ensuring your secrets are only accessible with the correct password.
Before you start
Command signature
evnx restore [OPTIONS] <BACKUP>Arguments:
| Argument | Required | Description |
|---|---|---|
<BACKUP> | Yes | Path to the .backup file, or cloud://project[/backup-id] |
Options:
| Flag | Type | Default | Description |
|---|---|---|---|
--output | string | .env | Destination path for the restored file |
--inspect | bool | false | List variable names (never values) without writing any files |
--dry-run | bool | false | Decrypt and validate but do not write any files |
--password-file | path | — | Read decryption password from a file (CI/CD) |
--verbose | bool | false | Print a diagnostic line at each pipeline stage |
EVNX_PASSWORD environment variable is also accepted as a password source. See Non-interactive password input for the full priority order.
Safety features
Overwrite protection (no --force)
If the output file already exists, evnx restore always prompts before overwriting. There is intentionally no --force flag.
⚠️ Output file already exists: .env
Overwrite .env? (y/N) ›
Why no --force?
The .env file often contains production credentials. An accidental overwrite could:
- ›Destroy credentials not backed up elsewhere
- ›Break running applications
- ›Require manual recovery from other sources
The prompt adds intentional friction to prevent costly mistakes.
Validation fallback (.restored suffix)
If decrypted content does not look like a valid .env file, evnx writes to <output>.restored instead:
⚠️ Decrypted content does not look like a valid .env file.
Writing to .env.restored instead of .env to protect your current file.
Inspect the file manually, then rename it if the content is correct:
mv .env.restored .env
The validation uses a heuristic: at least 80% of non-empty lines must be blank, comments (#), or KEY=VALUE assignments with alphanumeric keys. When the fallback path is used, the process exits with code 5 so scripts can branch accordingly.
When fallback is useful
The .restored fallback helps when:
- ›The backup was created with a different tool or format
- ›The file was corrupted during transfer
- ›You're restoring a non-.env file that was encrypted with evnx
You can inspect the output and manually rename it if the content is correct.
Password handling asymmetry
Unlike backup, the restore command uses a single password prompt without confirmation.
Why single prompt for restore?
- ›Backup: A typo in the password makes data permanently unrecoverable → confirmation required
- ›Restore: A typo simply fails decryption (safe, reversible error) → single prompt is sufficient
This asymmetry is intentional.
Memory safety
Sensitive data is explicitly cleared from heap memory after use:
- ›The password is moved into a RAII guard that zeroizes it on every exit path, including errors and panics.
- ›The ciphertext blob is zeroized immediately after decryption, whether it succeeded or failed.
- ›The decrypted content is zeroized after the file is written.
✓ Decryption key cleared from memory
Basic usage
Restore to default location
evnx restore .env.backup┌─ evnx restore ──────────────────────────────────────────────────┐
│ Decrypt and restore from an encrypted backup │
└─────────────────────────────────────────────────────────────────┘
✓ Read backup from .env.backup
Enter decryption password: ••••••••
⠙ Decrypting… (Argon2id key derivation in progress)
✓ Decryption successful
✓ Decryption key cleared from memory
📦 Backup information:
Schema version: v1
Original file : .env
Created at : 2026-03-10T14:30:00Z
Tool version : evnx v0.3.7
Variables : 12
✓ Restored 12 variable(s) to .env
Next steps:
1. Run: evnx validate --env .env
2. Verify your application starts correctly
3. Delete the backup file once you have confirmed the restore
Restore to a custom path
evnx restore .env.backup --output .env.productionUseful when restoring to a different environment or testing before overwriting the live file.
Inspect mode
--inspect decrypts the backup and lists variable key names only — values are never displayed. No files are written and no overwrite prompt is shown.
evnx restore .env.backup --inspect📦 Backup information:
Schema version: v1
Original file : .env
Created at : 2026-03-10T14:30:00Z
Tool version : evnx v0.3.7
Variables : 5
📋 Variables in this backup (names only — values never shown):
DATABASE_URL
REDIS_URL
API_KEY
SECRET_KEY
PORT
✓ 5 variable(s) found
To restore: evnx restore <backup-file>
Inspect vs dry-run
--inspect | --dry-run | |
|---|---|---|
| Decrypts backup | ✓ | ✓ |
| Shows metadata | ✓ | ✓ |
| Shows key names | ✓ | ✗ |
| Validates .env format | ✗ | ✓ |
| Writes files | ✗ | ✗ |
| Overwrite prompt | ✗ | ✗ |
| Exit code on bad content | — | — |
Use --inspect to answer "what keys are in this backup?" before committing to a full restore.
Use --dry-run to verify the backup is structurally valid and the content passes .env validation.
Dry-run mode
evnx restore .env.backup --dry-run📦 Backup information:
Schema version: v1
Original file : .env
Created at : 2026-03-10T14:30:00Z
Tool version : evnx v0.3.7
Variables : 12
✓ Decrypted content appears to be a valid .env file
✓ Dry-run complete — no files were written
When to use --dry-run
Use --dry-run to:
- ›Verify a backup is readable before a critical restore
- ›Check which environment a backup was created for (via metadata)
- ›Confirm variable count matches expectations
- ›Test automation scripts before enabling writes
Non-interactive password input
For CI/CD pipelines where interactive prompts are not possible, passwords are resolved in this priority order:
1. --password-file <path> — read from a file, trailing newline stripped automatically.
evnx restore .env.backup --password-file /run/secrets/evnx-pass2. EVNX_PASSWORD environment variable — read and immediately removed from the process environment.
EVNX_PASSWORD=mypass evnx restore .env.backup3. Interactive prompt — the default; most secure.
Security: non-interactive options are less secure
--password-file and EVNX_PASSWORD both print a warning to stderr and are less secure than the interactive prompt:
- ›The password may appear in process listings (
ps aux), shell history, or CI log output. - ›
EVNX_PASSWORDis removed from the environment immediately after reading, but it may already have been captured by a shell, process monitor, or CI log.
Recommendations:
- ›Use
--password-filewith a path ontmpfsor a secrets volume (e.g./run/secrets/) rather than a regular file on disk. - ›Prefer your CI/CD platform's native secrets injection over plain environment variables where available.
- ›Never hardcode passwords in scripts or pipeline definitions.
Automation and CI/CD
Inspect before restoring
# Check what keys are in the backup before committing to a restore
evnx restore latest.backup --inspect --password-file /run/secrets/evnx-passValidate then restore (two-step pipeline)
- name: Validate backup integrity
run: evnx restore latest.backup --dry-run
env:
EVNX_PASSWORD: ${{ secrets.BACKUP_PASSWORD }}
- name: Restore .env
run: evnx restore latest.backup --output .env
env:
EVNX_PASSWORD: ${{ secrets.BACKUP_PASSWORD }}
if: success()Branch on exit codes
#!/bin/bash
evnx restore .env.backup --password-file /run/secrets/evnx-pass
code=$?
case $code in
0) echo "✓ Restore successful" ;;
2) echo "✗ Wrong password or corrupt backup" ; exit 1 ;;
3) echo "✗ Backup file not found" ; exit 1 ;;
4) echo "✗ Restore cancelled" ; exit 0 ;;
5) echo "⚠ Restored to .env.restored — inspect before renaming" ;;
6) echo "✗ evnx-cloud not yet available" ; exit 1 ;;
*) echo "✗ Unexpected error (exit $code)" ; exit 1 ;;
esacConditional restore based on environment
#!/bin/bash
BACKUP="backups/prod.backup"
OUTPUT=".env.production"
if [ ! -f "$OUTPUT" ]; then
echo "No $OUTPUT found — restoring from backup..."
evnx restore "$BACKUP" --output "$OUTPUT" \
--password-file /run/secrets/evnx-pass
else
echo "$OUTPUT already exists — skipping restore"
fiExit codes
| Code | Meaning |
|---|---|
0 | Success (restore, inspect, or dry-run completed) |
1 | Generic error — IO failure, encoding error, unexpected failure |
2 | Wrong password or corrupt backup |
3 | Backup file not found |
4 | Restore cancelled — user declined the overwrite prompt |
5 | Restored to .restored fallback — content failed .env validation |
6 | evnx-cloud restore not yet available |
Exit codes 4 and 5 are informational
Exit codes 4 (cancelled) and 5 (validation fallback) do not print an additional error line — the inline message already explains what happened. Both are safe outcomes: no data was lost or corrupted.
Error handling and troubleshooting
"Backup file not found" (exit code 3)
✗ Backup file not found: .env.backup
Fix: Verify the backup path. If the path is a directory rather than a file, the same error is shown with a (not a regular file) suffix.
"Wrong password or corrupt backup" (exit code 2)
Decryption uses authenticated encryption (AES-256-GCM). The error intentionally does not distinguish between a wrong password and file corruption — both produce the same message to avoid leaking information.
Troubleshooting steps:
- ›Verify you are using the correct password for this backup.
- ›Check the file was not truncated during transfer:
wc -c .env.backup. - ›Run
--inspector--dry-runto confirm metadata is readable. - ›Restore from a different backup generation if you suspect corruption.
"Restored to .restored fallback" (exit code 5)
⚠️ Decrypted content does not look like a valid .env file.
Writing to .env.restored instead of .env to protect your current file.
The file was written successfully, but the content did not pass the .env validation heuristic. Run --inspect first to confirm the expected keys are present, then manually rename the file if the content looks correct:
cat .env.restored # inspect the content
mv .env.restored .env # rename when satisfied
evnx validate --env .env # validate the result"Backup envelope is missing the 'content' field"
The decrypted JSON envelope is malformed — possible causes: incompatible tool version, file corruption, or tampering. Try an earlier backup generation or upgrade evnx.
"Unsupported backup format version"
Error: Unsupported backup format version: 2.
This backup was created by a newer version of evnx.
Please upgrade the tool and try again.
Fix:
cargo install evnx --features backup --force"Feature not enabled"
✗ Backup/restore feature not enabled
Rebuild with: cargo build --features backup
Fix: Rebuild with the feature flag (see backup docs).
Security considerations
File permissions
Restored .env files are created with restrictive permissions on Unix:
$ ls -l .env
-rw------- 1 user user 342 Mar 20 15:00 .env # 0o600: owner read/write onlyMetadata exposure
Backup metadata (original filename, creation timestamp, tool version) is encrypted inside the payload. Without the correct password an attacker cannot determine which environment a backup belongs to, when it was created, or whether metadata has been tampered with.
Password sources and risk profile
| Source | Risk level | Notes |
|---|---|---|
| Interactive prompt | Lowest | Never stored; not visible in logs or process listings |
--password-file | Medium | Use tmpfs/secrets volume; avoid world-readable paths |
EVNX_PASSWORD | Medium-high | May appear in CI logs; removed from env after reading |
Best practices
Inspect before restoring
Always use --inspect to confirm backup contents before a full restore, especially in disaster-recovery scenarios:
evnx restore .env.backup --inspect
evnx restore .env.backup --dry-run
evnx restore .env.backup --output .env.staging # restore to staging first
evnx restore .env.backup # restore to productionTest restores regularly
A backup strategy is only as good as your ability to restore. Schedule periodic dry-run tests:
#!/bin/bash
# Monthly backup validation script
BACKUP_DIR="backups"
for backup in "$BACKUP_DIR"/*.backup; do
echo "Testing: $backup"
evnx restore "$backup" --dry-run \
--password-file /run/secrets/evnx-pass \
&& echo " ✓ Valid" \
|| echo " ✗ Failed (exit $?)"
doneDocument restore procedures
Include restore instructions in your runbooks:
## Emergency restore procedure
1. List available backups: ls -lt backups/*.backup
2. Inspect backup contents: evnx restore latest.backup --inspect
3. Validate backup integrity: evnx restore latest.backup --dry-run
4. Restore to staging first: evnx restore latest.backup --output .env.staging
5. Test application with restored config
6. Restore to production: evnx restore latest.backup --output .env.production
7. Monitor application logs for credential-related errorsRotate backup passwords
Periodically rotate backup passwords and re-encrypt existing backups:
# Inspect old backup, re-encrypt with new password
evnx restore old.backup --inspect --password-file /run/secrets/old-pass
evnx restore old.backup --output /tmp/plain.env --password-file /run/secrets/old-pass
evnx backup /tmp/plain.env --output new.backup # encrypts with new password prompt
rm /tmp/plain.envRelated commands
- ›evnx backup — create an encrypted backup of your
.envfile - ›evnx validate — check
.envfiles for misconfiguration - ›evnx scan — detect secrets and sensitive patterns in
.envfiles - ›evnx doctor — full environment health check including backup status