Manage Secrets
on this page
Use this guide to store sensitive values in repo-backed age files and reference them from playbooks, actions, or inventory.
If you want the design rationale first, read Secrets and age.
Prerequisites
- A project root that contains
preflight.yml - At least one
ageidentity that can decrypt the project secrets
If you are starting from zero, generate an identity:
preflight secret identity generate --out .age/keys.txtThe output includes a public recipient string beginning with age1.... That public value goes into preflight.yml; the private identity file stays out of version control.
To print the public recipient for an existing identity file later:
preflight secret identity recipient .age/keys.txtThe identity file is the secret. Treat it like a private key, keep it out of Git, and distribute it only to people or systems that should be able to decrypt project secrets.
1. Configure Secrets In preflight.yml
Example:
project: museum-kiosk
secrets:
identity: ".age/keys.txt"
recipients:
- "age1ql3z7hjy54pw5k8kr0jsjrl4f8yl0v0l7x7y9h8n5v9s0k4m5qkq9v9abc"
entries:
autologin-password:
file: "secrets/autologin-password.age"What each field means:
identityis the private key file Preflight uses to decrypt locally.recipientsare the public keys used for encryption.entriesmaps logical secret names to encrypted files in the repo.
If multiple people or machines need access, add multiple recipients. They can all decrypt the same encrypted file with their own private identities.
2. Encrypt A Secret
Preflight can read the plaintext from a file, from standard input, or from an interactive prompt. Pick the source that keeps the plaintext closest to memory and farthest from disk and shell history.
From An Interactive Prompt (Recommended For One-Offs)
Run with no source flag in a terminal:
preflight secret encrypt autologin-passwordPreflight prompts twice without echoing, then encrypts the entered value. The plaintext never touches disk and never appears in your shell history.
From Standard Input (Recommended For Scripts And Password Managers)
op read "op://Vault/Item/password" | preflight secret encrypt autologin-password --from-stdinprintf '%s' "$LOOKED_UP_PASSWORD" | preflight secret encrypt autologin-password --from-stdinA single trailing \n or \r\n is trimmed, so echo "value" | preflight secret encrypt ... --from-stdin works as expected. Embedded newlines (for multi-line secrets like PEM blocks) are preserved.
Avoid preflight secret encrypt foo --from-stdin <<<"$secret" patterns that
expand the secret on the command line — that exposes it to process listings.
Prefer piping from a tool that emits the secret directly.
From A File
preflight secret encrypt autologin-password \
--from-file ./secrets/autologin-password.txtUseful when the plaintext is already on disk (for example, a downloaded PEM). Delete the plaintext file afterwards.
Common Notes
If the named entry does not already exist, Preflight creates it in preflight.yml and defaults the encrypted path to secrets/<name>.age.
Override recipients or identity when needed:
preflight secret encrypt autologin-password \
--recipient age1example... \
--identity .age/keys.txt--from-file and --from-stdin are mutually exclusive. If neither is set and
stdin is not a terminal, Preflight refuses to run rather than silently consume
whatever happens to be piped in.
3. List Configured Secrets
preflight secret listThis prints the logical name plus the encrypted file path recorded in preflight.yml.
4. Edit A Secret Safely
EDITOR=nvim preflight secret edit autologin-passwordPreflight decrypts the secret to a temporary file, opens your editor, then re-encrypts the updated contents.
Notes:
- If
EDITORis not set, Preflight falls back tovi. - The temporary plaintext file is created outside the repo and cleaned up after the edit flow.
5. Reference Secrets In YAML
Use inline secret:<name> references anywhere a string field accepts a secret value:
tasks:
- name: Configure auto-login
uses: preflight/autologin
with:
username: exhibituser
password: secret:autologin-passwordInventory can do the same thing:
hosts:
- name: lobby-pc-01
transport: winrm
username: exhibit-admin
password: secret:winrm-passwordFor file payloads, use the file module’s content field:
tasks:
- name: Write license file
file:
dest: "C:\\Exhibits\\license.txt"
content: secret:license-fileWhen only part of a file is secret, use content_template and reference
secrets with secret("name"):
tasks:
- name: Write app config
file:
dest: "C:\\Exhibits\\app.ini"
content_template: |
username={{ vars.app_user }}
password={{ secret("app-password") }}The built-in provider name is secret, so repo-backed references use secret:<name>.
Use secret:<name> when a whole string field should resolve to one secret.
Use secret("name") only inside content_template, where the secret is
interpolated into a larger file body.
6. Rekey Secrets After Recipient Changes
When secrets.recipients changes, re-encrypt the secret files so the new recipient set can decrypt them:
preflight secret rekeyTo rekey only specific secrets:
preflight secret rekey autologin-password winrm-passwordsecret rekey uses the configured secrets.identity to decrypt existing files and the configured secrets.recipients to write updated files. You can override either value for the command:
preflight secret rekey \
--identity .age/keys.txt \
--recipient age1example...When you pass an identity or recipient override, Preflight saves the updated setting back to preflight.yml. Overrides are only allowed when rekeying all configured secrets, because those settings apply project-wide.
7. Move The Project To Another Machine
If a different machine will run preflight, it needs everything required for local decryption:
- the
preflightbinary - the repo or exported project directory
preflight.yml- the encrypted
.agefiles referenced bysecrets.entries - one private identity matching one of the configured recipients
This is the important rule: decryption happens on whichever machine is actually running Preflight.
For staged offline bundles, that usually means adding a target machine recipient, rekeying the secrets, staging the bundle, and applying it on the target with that target’s identity. See Stage bundles for air-gapped deployment.
Troubleshooting
no recipients configured
Add secrets.recipients to preflight.yml or pass one or more --recipient flags to preflight secret encrypt.
no identity configured
Set secrets.identity in preflight.yml or pass --identity for the current command.
secret "<name>" is not defined
Create the entry under secrets.entries, or run preflight secret encrypt <name> --from-file ... so Preflight can create it for you.