CLI Reference

secrets

Manage encrypted secrets for your deployments.


Synopsis

odysseus secrets <command> [options]

Commands for managing encrypted secrets files.

Each subcommand takes --file (default secrets.yml.enc), never --configsecrets never reads deploy.yml at all, and passing --config to it is an option-parsing error, not a no-op. None of the subcommands parse -v/--verbose either, and in that secrets isn't unusual: app and dependency subcommands don't define -v either (bin/odysseus:171-177, :222-227) — it's only deploy, rollback, build, pussh, status, containers, logs, cleanup, validate, doctor and setup that parse it at all. See Global options for which of those actually read it.


Commands

generate-key

Generate a new master key for encrypting secrets.

odysseus secrets generate-key

Output:

  Secrets: Generate Key

  ✓ Generated master key:

  a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd

  ! Save this key securely!
  › Set as ODYSSEUS_MASTER_KEY environment variable

The key is a 64-character hex string (256 bits).

Store securely

This key is required to decrypt your secrets. Store it in a password manager or secure secret storage. If lost, you cannot recover encrypted secrets.


encrypt

Encrypt a plaintext secrets file.

odysseus secrets encrypt --input <file> --file <output>

Options

--input FILE

Source plaintext YAML file.

--file FILE

Output encrypted file.

Example

# Create plaintext secrets
cat > secrets.yml << EOF
DATABASE_URL: postgres://user:pass@localhost/myapp
RAILS_MASTER_KEY: abc123def456
REDIS_URL: redis://localhost:6379
EOF

# Encrypt
ODYSSEUS_MASTER_KEY=your-key odysseus secrets encrypt \
  --input secrets.yml \
  --file secrets.yml.enc

# Clean up plaintext
rm secrets.yml

Output:

  Secrets: Encrypt
  Input: secrets.yml
  Output: secrets.yml.enc

  ✓ Secrets encrypted to secrets.yml.enc

decrypt

Decrypt a secrets file and print its keys — with values masked, not the plaintext.

odysseus secrets decrypt --file <file>

Options

--file FILE

Encrypted file to decrypt.

Example

ODYSSEUS_MASTER_KEY=your-key odysseus secrets decrypt --file secrets.yml.enc

Output:

  Secrets: Decrypt
  File: secrets.yml.enc

  DATABASE_URL: post********************************
  RAILS_MASTER_KEY: abc1********
  REDIS_URL: redi******************

  › (values masked)

Each value keeps its first 4 characters and replaces the rest with * (a value 4 characters or shorter becomes **** outright) — enough to recognize which secret is which, not enough to read it over someone's shoulder or leak it into a captured terminal.

This can't reconstruct a working plaintext file

Because the values are masked, piping this to a file — odysseus secrets decrypt --file secrets.yml.enc > secrets.yml — does not give you back the original secrets.yml; it gives you a file of truncated, un-decryptable fragments. If you need the real values — to inspect one, or to rebuild a plaintext file — use edit, which decrypts to a temporary file for exactly that, then re-encrypts it when you're done.


edit

Edit secrets in your default editor.

odysseus secrets edit --file <file>

Options

--file FILE

Encrypted file to edit.

Example

ODYSSEUS_MASTER_KEY=your-key odysseus secrets edit --file secrets.yml.enc

This:

  1. Decrypts to a temporary file — or starts from an empty one if --file doesn't exist yet, so edit can create a secrets file directly, without an encrypt step first
  2. Opens in $EDITOR (or vi if not set)
  3. Re-encrypts when you save and close
  4. Removes the temporary file

Set your editor

Configure your preferred editor:

export EDITOR=vim
export EDITOR="code --wait"  # VS Code
export EDITOR=nano

Environment variables

ODYSSEUS_MASTER_KEY

The encryption key. Required for all secrets operations.

export ODYSSEUS_MASTER_KEY=your-key
odysseus secrets decrypt --file secrets.yml.enc

Or inline:

ODYSSEUS_MASTER_KEY=your-key odysseus secrets decrypt --file secrets.yml.enc

Secrets file format

Plaintext format

Standard YAML key-value pairs:

DATABASE_URL: postgres://user:pass@localhost/myapp
RAILS_MASTER_KEY: abc123def456
REDIS_URL: redis://localhost:6379
AWS_ACCESS_KEY_ID: AKIA...
AWS_SECRET_ACCESS_KEY: secret...

In deploy.yml

Reference secrets in your configuration:

env:
  clear:
    RAILS_ENV: production
  secret:
    - DATABASE_URL
    - RAILS_MASTER_KEY
    - REDIS_URL

secrets_file: secrets.yml.enc

Workflows

Initial setup

# 1. Generate key (once)
odysseus secrets generate-key
# Save the output key securely

# 2. Create secrets file
cat > secrets.yml << EOF
DATABASE_URL: postgres://...
RAILS_MASTER_KEY: ...
EOF

# 3. Encrypt
ODYSSEUS_MASTER_KEY=your-key odysseus secrets encrypt \
  --input secrets.yml \
  --file secrets.yml.enc

# 4. Clean up and commit
rm secrets.yml
git add secrets.yml.enc
git commit -m "Add encrypted secrets"

Adding a secret

ODYSSEUS_MASTER_KEY=your-key odysseus secrets edit --file secrets.yml.enc
# Add new line: NEW_SECRET: value
# Save and close

Rotating secrets

# Edit and change values
ODYSSEUS_MASTER_KEY=your-key odysseus secrets edit --file secrets.yml.enc

# Deploy with new secrets
ODYSSEUS_MASTER_KEY=your-key odysseus deploy --image v1.0.0

Multiple environments

# Production secrets
odysseus secrets encrypt --input prod-secrets.yml --file secrets.prod.yml.enc

# Staging secrets
odysseus secrets encrypt --input staging-secrets.yml --file secrets.staging.yml.enc

Exit codes

CodeMeaning
0Success
1The master key wasn't set, the file wasn't found, or encryption/decryption failed
Previous
build & pussh