Secrets in code and CI
Launches after an independent review. Reference the vault's secrets from code and CI with varn, without putting them in code.
Launches after an independent review – not switched on yet
The secure vault, machine accounts and the varn command-line tool are built but not yet active. They launch once an independent security review is complete. This page describes how they will work.
Passwords and API keys do not belong in code, in shared .env files or in CI settings that many people can read. With Värn you write a reference to the secret in your secure vault instead:
DATABASE_PASSWORD=varn://exempel/Produktion/Produktionsdatabas/password
STRIPE_KEY=varn://exempel/Produktion/Stripe/password
and start the program through the varn command-line tool:
varn run -- npm start
varn fetches the encrypted items, decrypts them on that machine and starts the program with the real values in its environment. Värn never sees the secrets in plain text or any key that can decrypt them – not when a machine reads them either. The secure vault is included in Business and Enterprise.
How it works
- An administrator creates a machine account in the vault and chooses which collections it may read.
- The machine account gets a token that is shown only once. It contains the machine's private key and is stored as a secret where the program runs, for example in GitHub Actions.
varnuses the token to fetch the collections' encrypted content from Värn, decrypts it locally and resolves the names in the references on the machine. Värn never learns which items a program uses.
A machine account can only read. It has an expiry date, can be limited to certain IP addresses and can be revoked at once. Every read is logged with its IP address, and administrators are notified the first time a machine account is used from a new network.
Create a machine account
Open Machine accounts
Go to Secure vault → Machine accounts, unlock the vault and click New machine account. This needs an administrator who holds the collections.
Choose collections, validity and networks
Give the account a name, for example "GitHub Actions – web shop", and only the collections it needs. Choose how long it is valid (at most a year) and, if you can, which IP addresses it may call from.
Store the token
Copy the token or download it as a text file and store it as a secret right away, for example as VARN_TOKEN in GitHub. Värn cannot show it again.
References
varn://<organisation>/<collection>/<item>/<field>
| Part | What it is |
|---|---|
organisation | The organisation's short name in Värn, the one in the address /o/<short-name>/…. Must be the organisation the token belongs to. |
collection | The collection's name, or id: followed by the collection's id. |
item | The item's name, or id: followed by the item's id. |
field | password, username, url or notes. |
- Names are compared case-insensitively and written URL-encoded: a space becomes
%20, a slash%2F.Finance & payrollis writtenFinance%20%26%20payroll. - Ids never change, even when someone renames the item. Names are easier to read.
- If two items in the same collection have the same name,
varnrefuses to guess and shows their ids, so you can rename one of them or useid:. - A reference reveals nothing without a token, so it can live in a public repository.
Install varn
varn is an npm package without dependencies that needs Node.js 20 or newer. Always give an exact version:
npx @varnsecurity/cli@0.1.0 --version
# or install it
npm install --global @varnsecurity/cli@0.1.0
The token is read from the environment variable VARN_TOKEN, or from a file with --token-file <path> (including the text file you downloaded when the account was created).
Run a program
export VARN_TOKEN=varn_mt_…
DATABASE_PASSWORD=varn://exempel/Produktion/Produktionsdatabas/password varn run -- npm start
Every environment variable whose value is a varn:// reference is replaced by the secret before the program starts. With --env-file .env, variables are also read from a file; the file's values take precedence over the normal environment. The program does not get VARN_TOKEN.
If the program prints a secret, it is replaced with <varn:concealed>, so it does not end up in CI logs. The program's output then goes through a pipe instead of straight to the terminal; --no-masking turns masking off. varn forwards signals and exits with the program's own exit code.
Read one value
varn read varn://exempel/Produktion/Stripe/password
The value is written to standard output, with a newline only when it is shown in a terminal.
Fill in a configuration file
Write placeholders in a template, for example config.yml.tpl:
database:
user: {{ varn://exempel/Produktion/Produktionsdatabas/username }}
password: {{ varn://exempel/Produktion/Produktionsdatabas/password }}
varn inject -i config.yml.tpl -o config.yml
The file is written with permissions 0600 so only you can read it. Without -o the result goes to standard output. This is the only way varn writes secrets to disk; delete the file when it is no longer needed.
GitHub Actions
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Deploy
run: npx --yes @varnsecurity/cli@0.1.0 run -- ./deploy.sh
env:
VARN_TOKEN: ${{ secrets.VARN_TOKEN }}
DATABASE_PASSWORD: varn://exempel/Produktion/Produktionsdatabas/password
The secrets then exist only in that step, and everything deploy.sh prints is masked. There is also a ready-made action that can export values to later steps, masked with GitHub's ::add-mask::; see the README of @varnsecurity/cli.
Security
- The token is the key. Whoever has it can read the machine account's collections until it expires or is revoked. Keep it only in a secrets manager, never in code or in the vault.
- Give as little as possible. One collection per environment, one machine account per system, a short validity and allowed networks when you can.
- If a token leaks: revoke the machine account under Secure vault → Machine accounts. Then rotate the collections it could read and change the real passwords.
- No cache.
varnstores nothing on disk except withvarn inject -o, and the values exist only in memory. - Check the package.
@varnsecurity/cliis published from CI with npm provenance. Runnpm audit signaturesin a project that installs it, and always give an exact version.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Done |
| 2 | Wrong command or arguments |
| 3 | Invalid reference |
| 4 | No token, or an invalid one |
| 5 | VARN_API_URL is invalid or not https |
| 6 | Network error, timeout or unexpected response |
| 7 | The token was not accepted (revoked, expired or wrong network) |
| 8 | The plan does not include the secure vault |
| 9 | The collection, item or field does not exist or is empty |
| 10 | The name matches several collections or items |
| 11 | Too many requests – try again in a minute |
| 12 | The vault is switched off |
| 13 | Server error |
| 14 | Something could not be decrypted |
| 15 | The reference is for another organisation |
| 16 | A file could not be read or written |
Once varn run has started the program, it exits with the program's own exit code.
