Secrets Management
All secrets are managed using a hybrid approach combining 1Password as the primary source of truth, and Agenix for the initial deployment bootstrap. This ensures no sensitive secrets are exposed in the git repository while maintaining a fully automated deployment.
The Hybrid Workflow
Section titled “The Hybrid Workflow”- Agenix for the Bootstrap Token: We use Agenix to securely encrypt a single file in the repository:
1password-token.age. This file contains the 1Password Service Account Token. NixOS decrypts this file at boot using the host’s private SSH key (/etc/ssh/ssh_host_ed25519_key). - 1Password for Everything Else: Once the
1password-tokenis available on the machine, NixOS systemd services (likecloudflared) use the 1Password CLI (op) to fetch the rest of the required credentials dynamically at runtime.
Restricted Access (Least Privilege)
Section titled “Restricted Access (Least Privilege)”To maintain security, the infrastructure only has access to the specific secrets it needs:
- Dedicated Vault: A specific vault (e.g.,
Homelab) contains only the items required for this infrastructure (Cloudflare tokens, etc.). - Service Account: A 1Password Service Account is created and granted “Read-Only” access exclusively to that dedicated vault.
- Token-based Auth: The server uses the Service Account Token (injected via Agenix) to authenticate. If the machine is ever compromised, your personal vaults and other sensitive data remain completely isolated and inaccessible.
Integration with systemd Services
Section titled “Integration with systemd Services”To inject secrets securely, we use a unified set of NixOS helpers defined in the infrastructure repository. This follows security best practices:
- Unified Helper Flow:
homelab.mkSecretService: Creates a dedicatedoneshotservice (e.g.,transmission-secrets) to fetch credentials. It runs asroot, fetches secrets with automatic retries, writes them to a private RAM-based directory (/run/<service>/), and sets correct ownership.homelab.serviceConfig: Configures the main service to have access to these secrets, setting0700permissions on the runtime directory and loading the 1Password token via systemdLoadCredential.
- Resilience & Security:
- Automatic Retries: All 1Password fetching includes a retry mechanism to handle transient network issues.
- Safe Writing: Environment files are generated using
printfto ensure special characters in passwords don’t break the shell parsing. - RAM-based storage: Secrets never touch the disk; they live in
tmpfs(/run) and are automatically wiped on service stop or reboot. - Leak Prevention: We avoid passing secrets as environment variables in the service definition. Instead, we use
EnvironmentFileor direct file-based reading, preventing secrets from appearing insystemctl statusor/proc.
- DynamicUser Support: For services that use systemd
DynamicUser(where the user ID changes on every start), we use an inlineExecStartPrehook viahomelab.fetchSecretFileto fetch secrets directly within the service context.
Manual Usage
Section titled “Manual Usage”You can still interact with secrets manually using the 1Password CLI:
# Authenticate (if not using a Service Account token locally)op signin
# Read a specific secretop read "op://Homelab/Cloudflare/api-token"