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
.envfiles 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(default0x81010002)
Fallback mode:
- Set
SECURECFG_TPM_COMMANDto 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(1or2, default2)SECURECFG_YUBIKEY_CHALLENGE(defaultsecurecfg-hmac)
Fallback mode:
- Set
SECURECFG_YUBIKEY_COMMANDto 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
.envfiles 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 passes3: policy fails
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bace0a5b76eb1c2c18ac2d986c9243b1fa1b266e3e547ceeb7810196bf09fbac
|
|
| MD5 |
e82286a2f7c6957a6aaf486469cff669
|
|
| BLAKE2b-256 |
c6ea2e4735266b1aef4aef0efac4a0e7e3c89b196269ff3a62d5336d25254299
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8033708791e1c032a2fa56cbf55968cfdc5c0a05a8ba73e9d996d19e1d31e4e9
|
|
| MD5 |
9c9ee3e4c84835e3955ec4bd7ffe18c4
|
|
| BLAKE2b-256 |
b4d8151fc5d9bef6e28a2b343e3d120d16dec4ffaf8525ec2c3892a20bc205aa
|