Give a VM a secret in two steps: declare it once in your account store with
ix secret set NAME, then attach it when you create a VM with ix new --secret NAME (or mark it a default). At boot ix materializes the attached
secret inside the guest, as an environment variable by default or as a file, and
your service consumes it from there. Values are write-only: they go in through
set and are never shown back. For every flag, run ix secret --help and ix new --help rather than copying flags from here.
- Declare.
ix secret set NAMEstores or rotates one secret in your account store, encrypted. The value comes from a hidden prompt, stdin, or--value-file PATH: never from the command line. The name doubles as the env var name when delivered as an env var. - Attach. A secret is only delivered to VMs you attach it to. Attach per VM
at create time with
ix new --secret NAME(repeat for several), orix run --secret NAME. Or mark it a default withix secret set NAME --defaultso it attaches to every new VM automatically; opt a VM out withix new --no-default-secrets. - Materialize. At boot, ix injects each attached secret into the guest, as an
env var by default, or as a file when you set
--file.
ix secret set GH_TOKEN # paste the value at the hidden prompt
ix new ix/base:latest --secret GH_TOKEN
Inside the guest the value is the environment variable GH_TOKEN, available to
the image command (the env var name is the secret name).
Use --file GUEST_PATH to land the value as a file instead of an env var; pair it
with --owner (guest unix user, defaults to root) and --mode (octal bits,
defaults to 0600):
ix secret set NPM_TOKEN --file .npmrc --owner app --mode 0440
ix new ix/base:latest --secret NPM_TOKEN
The guest gets .npmrc owned by app with mode 0440. --owner and --mode
require --file.
ix secret lslists names and metadata only, never values.ix secret check NAME ...exits non-zero listing any missing names, so deploy tooling can fail fast before doing work.ix secret rm NAMEdeletes a stored secret. VMs that already attached it keep their copy.
Re-run ix secret set NAME with the new value. The store is updated, but VMs that
already attached the old value keep it: attached copies are materialized at boot
and persist until the VM is recreated. To pick up a rotated
value, recreate the VM (delete and ix new again, or use a fleet up/replace).
A fleet plan references secrets by name, never by
value: plaintext stays in your account store, only the names live in the plan
(packages/ix-fleet/src/ix_fleet/__init__.py:85-89). Each node lists secrets: [NAME, ...] and may set noDefaultSecrets: true, the exact equivalents of ix new --secret NAME and --no-default-secrets (__init__.py:89-92). Before any
work, the CLI verifies every referenced secret exists in the store, mirroring ix secret check, and tells you to ix secret set NAME if one is missing
(__init__.py:374-394). The plan's optional secrets.provider defaults to type
runtime-directory with mountRoot /run/secrets, so file-mounted secrets land
under /run/secrets/<name> (__init__.py:124-128).
The platform's own host services do not use the account store above. Their
secrets are encrypted per-machine with the host's TPM2 chip and stored at
/etc/credstore.encrypted/<name>; systemd decrypts them at service start via
systemd-creds into the service's $CREDENTIALS_DIRECTORY. The canonical names map
to a Vaultwarden-backed store for provisioning. This is internal
platform plumbing; your path is ix secret plus fleet secrets above.
- cli.md: the
ixCLI surface. - fleet.md and ix-fleet overview: declarative fleet plans.
- services.md: running and wiring your service in the guest.
- networking.md: VM connectivity and ingress.