Skip to main content

Lightweight encrypted .env secrets manager with key rotation

Project description

Secure Config / Secrets Manager

This is a small, practical secrets tool for teams that want encrypted .env files without running a full vault platform. It is meant to stay easy to understand and easy to operate.

Features

  • Encrypted .env files using AES-256-GCM
  • Key rotation support
  • CLI + Python SDK
  • JS SDK compatible with the same encrypted file format
  • Optional hardware-backed key providers with direct TPM2/YubiKey integrations and command fallback hooks

Threat model and scope

Secure Config protects secrets at rest in repos, build artifacts, and deployment handoffs. It does not try to replace enterprise vault systems, and it does not include network auth, dynamic credentials, or deep policy engines.

Quick start

cd /home/projects/packets/secure-config-secrets-manager
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -e .

Initialize a local software key store:

securecfg init-key

Encrypt an env file:

securecfg encrypt --input .env --output .env.enc.json

Decrypt back to plaintext:

securecfg decrypt --input .env.enc.json --output .env.dec

Rotate key and re-encrypt an existing encrypted file:

securecfg rotate --input .env.enc.json --output .env.enc.json

CLI reference

  • securecfg init-key [--key-id KEY_ID] [--provider software|tpm|yubikey]
  • securecfg list-keys [--provider ...]
  • securecfg encrypt --input .env --output .env.enc.json [--provider ...]
  • securecfg decrypt --input .env.enc.json --output .env [--provider ...]
  • securecfg rotate --input .env.enc.json --output .env.enc.json [--new-key-id KEY_ID] [--provider ...]
  • securecfg policy-check [--provider ...]

Key providers

software (default)

Stores 32-byte AES keys in a local JSON keyring at:

  • Linux/macOS: ~/.securecfg/keys.json

The key file is written with restrictive file permissions.

tpm (optional)

The TPM provider tries direct TPM2 integration first via tpm2-pytss, reading from a persistent handle. If unavailable, it falls back to SECURECFG_TPM_COMMAND.

Optional dependencies:

pip install -e .[hardware]

Direct mode settings:

  • SECURECFG_TPM_KEY_HANDLE (default 0x81010002)

Fallback mode:

  • Set SECURECFG_TPM_COMMAND to a command that prints key material to stdout.
  • Output can be raw text, hex, or base64 and will be normalized into a 32-byte key via SHA-256 when needed.

Example:

export SECURECFG_TPM_COMMAND="tpm2_unseal -c 0x81010002"

yubikey (optional)

The YubiKey provider tries direct integration first via yubikey-manager/yubikit using OTP HMAC challenge-response. If unavailable, it falls back to SECURECFG_YUBIKEY_COMMAND.

Direct mode settings:

  • SECURECFG_YUBIKEY_SLOT (1 or 2, default 2)
  • SECURECFG_YUBIKEY_CHALLENGE (default securecfg-hmac)

Fallback mode:

  • Set SECURECFG_YUBIKEY_COMMAND to a command that prints key material to stdout.
  • The same normalization rules apply.

Example:

export SECURECFG_YUBIKEY_COMMAND="ykman oath accounts code securecfg"

Python SDK

from securecfg import SecureConfigManager

mgr = SecureConfigManager(provider_name="software")

mgr.encrypt_env_file(".env", ".env.enc.json")
mgr.decrypt_env_file(".env.enc.json", ".env.dec")

JS SDK

See sdk/js/README.md.

Tests

Run Python tests:

pip install -e .[dev]
pytest -q

Run JS SDK tests:

cd sdk/js
npm test

Interop tests (Python <-> JS) are included in the Python suite and run automatically when node is available.

Docker

Build and run CLI via container:

docker build -t securecfg .
docker run --rm -v "$HOME/.securecfg:/root/.securecfg" securecfg list-keys --provider software

CI

GitHub Actions workflow is included at .github/workflows/ci.yml and runs:

  • Python tests (pytest)
  • JS SDK tests (npm test)

Encrypted format

Encrypted files are JSON envelopes:

{
  "version": 1,
  "algorithm": "AES-256-GCM",
  "key_id": "k-20260407-1",
  "nonce": "...base64...",
  "ciphertext": "...base64...",
  "tag": "...base64...",
  "created_at": "2026-04-07T12:00:00Z",
  "metadata": {
    "source": ".env"
  }
}

Security notes

  • Keep plaintext .env files out of git and production artifacts.
  • Restrict file permissions for key files.
  • Prefer dedicated hardware-backed commands in production.
  • Rotate keys periodically and on compromise suspicion.

Simple key lifecycle policy

If you want a bit more safety without extra tooling, enable these environment variables:

  • SECURECFG_KEY_MAX_AGE_DAYS: blocks new encryption if active key is older than this many days.
  • SECURECFG_ROTATE_AFTER_DAYS: requires rotation before encryption when active key exceeds this age.
  • SECURECFG_DENY_OLD_KEY_DECRYPT=true: blocks decryption unless envelope key matches current active key.

Example:

export SECURECFG_KEY_MAX_AGE_DAYS=90
export SECURECFG_ROTATE_AFTER_DAYS=60
export SECURECFG_DENY_OLD_KEY_DECRYPT=true

All policy controls are optional. If you do not set them, Secure Config stays permissive.

Quick check:

securecfg policy-check

Exit codes:

  • 0: policy passes
  • 3: policy fails

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

securecfg-0.1.0.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

securecfg-0.1.0-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file securecfg-0.1.0.tar.gz.

File metadata

  • Download URL: securecfg-0.1.0.tar.gz
  • Upload date:
  • Size: 12.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for securecfg-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bace0a5b76eb1c2c18ac2d986c9243b1fa1b266e3e547ceeb7810196bf09fbac
MD5 e82286a2f7c6957a6aaf486469cff669
BLAKE2b-256 c6ea2e4735266b1aef4aef0efac4a0e7e3c89b196269ff3a62d5336d25254299

See more details on using hashes here.

File details

Details for the file securecfg-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: securecfg-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for securecfg-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8033708791e1c032a2fa56cbf55968cfdc5c0a05a8ba73e9d996d19e1d31e4e9
MD5 9c9ee3e4c84835e3955ec4bd7ffe18c4
BLAKE2b-256 b4d8151fc5d9bef6e28a2b343e3d120d16dec4ffaf8525ec2c3892a20bc205aa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page