Skip to content

Vars

This document explains how we safely expose secrets and variables managed by Clan (clan.core.vars) as environment variables, both on normal machines and inside MicroVM agents.

flowchart TD
reg["lib/secret-registry.nix<br/>secret definitions"] --> matrix["lib/machine-env-matrix.nix<br/>per-machine selection"]
matrix --> gen["lib/vars-generators.nix<br/>clan.core.vars.generators"]
gen --> sops[("SOPS-encrypted vars")]
sops --> deploy["deployed secret files<br/>/run/secrets/vars/..."]
deploy --> hjem["hjem-session-variables.nix<br/>*_FILE env vars (normal machines)"]
deploy --> bundle["virtiofs secret bundle<br/>/run/host-secrets"]
bundle --> guest["guest env vars (MicroVM agents)"]

We never bake secret values into the Nix store or into generated shell configuration at evaluation time.

  • Secrets are always exposed via the _FILE convention (pointing at the deployed secret file on the target).
  • Non-secret values can be exposed directly.
  • This follows the patterns used by Clan core itself and modern secret management practices (Docker secrets, Kubernetes, 12-factor apps).

On Normal Machines (emily, zoe, vanessa, lea)

Section titled “On Normal Machines (emily, zoe, vanessa, lea)”

We use a small Hjem module that automatically populates environment.sessionVariables:

## Automatically included for all users via modules/clan/hjem-users.nix
(import ../modules/shared/vars/hjem-session-variables.nix { inherit keys; })

For every entry in lib/secret-registry.nix that declares an envVar:

  • Secrets → ANTHROPIC_API_KEY_FILE=/run/secrets/vars/anthropic-api-key/key
  • Non-secrets → OBSIDIAN_VAULT=Main

These session variables are available in shells configured via Hjem (zsh, fish, nushell, bash).

You control exactly which variables a machine sees using the keys parameter:

## In modules/hosts/<name>/default.nix
(mkHjemUser {
...
keys = envMatrix.emily; # or envMatrix.zoe, etc.
})

The envMatrix lives in lib/machine-env-matrix.nix. Only the listed secrets will appear in that machine’s environment.

MicroVM guests (agent-finalform, agent-jadorey, …) use a different delivery mechanism:

  • Secrets are mounted from the host via virtiofs at /run/host-secrets/<name>/...
  • The guests are intentionally minimal and do not run the full Clan + Hjem user stack.

Use the environment option on the agent-vm service:

agent-finalform = {
module.input = "self";
module.name = "@luxus/agent-vm";
roles.host.machines.vanessa = {
settings = {
...
environment = {
ANTHROPIC_API_KEY = "anthropic-api-key";
EXA_API_KEY = "exa-api-key";
TELEGRAM_BOT_TOKEN = "hermes-telegram-bot-token";
};

Secret files with non-standard env var names

Section titled “Secret files with non-standard env var names”
secretFiles = {
HERMES_TELEGRAM_BOT_TOKEN = "/run/secrets/vars/hermes-telegram-bot-token/token";
};
  • All secret content only ever exists on the target machine after deployment.
  • The Nix evaluation only ever sees paths (or, for non-secrets, public values).
  • On main machines this is enforced by Hjem environment.sessionVariables.
  • On MicroVMs this is enforced by the virtiofs secret bundle + runtime reading from /run/host-secrets.

This design prevents the evaluation cycles that previously occurred when trying to introspect vars across mixed Linux + Darwin fleets.

  1. Add it to lib/secret-registry.nix (with envVar if you want it as an environment variable).
  2. Add it to the relevant entries in lib/machine-env-matrix.nix (for normal machines).
  3. For MicroVM agents, add it to the environment block of the specific agent instance in flake.nix.

That’s it — the rest is automatic.

  • lib/secret-registry.nix — source of truth for all secrets
  • lib/machine-env-matrix.nix — which machines get which secrets (normal machines)
  • modules/shared/vars/hjem-session-variables.nix — Hjem integration for normal machines
  • services/agent-vm/default.nix — MicroVM service (the environment option)
  • modules/nixos/agent-vm-guest.nix — how secrets become env vars inside guests
  • Possibly generate a small ~/.config/clan-secrets/env file on MicroVMs as well (for tools that don’t support the _FILE convention).
  • Better support for exposing secrets to specific systemd services inside MicroVMs.