2.1 KiB
Secret Management — Hermes Environment
Principle
All secrets in one file: ~/.hermes/.env, chmod 600, backed up in S3.
Standalone token files (.hetzner_token, .netcup_api_key, etc.) are fragile — they get left behind during migration, broken during key rotation, and scripts that reference them fail silently when they're missing.
Current secret inventory
| Secret | File location | Permissions | Notes |
|---|---|---|---|
| admin-ai API key | ~/.hermes/config.yaml (2 places) |
Root-readable | Also in .env as backup |
| Telegram bot tokens | ~/.hermes/.env |
600 | Default + Anita profiles |
| Hetzner API token | ~/.hermes/.env |
600 | Was standalone file |
| Netcup API key | ~/.hermes/.env |
600 | Was standalone file |
| SMTP/IMAP passwords | ~/.config/himalaya/*.pass |
600 | Himalaya standard |
| Wasabi S3 keys | ~/.aws/credentials |
600 | AWS CLI standard |
| SSH keys | ~/.ssh/ |
600 | Standard |
Consolidation workflow
When you discover a standalone secret file:
-
Read it and the current
.env:env_path = ~/.hermes/.env standalone_path = ~/.hermes/scripts/.some_token -
Load
.envinto a dict, add the new variable, write back:env_vars['HETZNER_API_TOKEN'] = token_value -
chmod 600 ~/.hermes/.env -
Remove the standalone file:
rm ~/.hermes/scripts/.some_token -
Patch any scripts that referenced the old path to source from
.env.
Reading secrets in scripts
Scripts should source .env at the top:
set -a; source ~/.hermes/.env; set +a
Python scripts should use:
import os
from dotenv import load_dotenv
load_dotenv(os.path.expanduser("~/.hermes/.env"))
token = os.environ["HETZNER_API_TOKEN"]
Special case: config.yaml inline keys
The admin-ai API key lives in config.yaml in two places — providers.admin-ai.api_key and auxiliary.vision.api_key. Hermes reads these directly from the YAML config, not from env vars. The .env copy serves as a backup record for recovery. If the key rotates, update both config.yaml entries AND the .env backup.