Skip to content

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

  1. An administrator creates a machine account in the vault and chooses which collections it may read.
  2. 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.
  3. varn uses 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>
PartWhat it is
organisationThe organisation's short name in Värn, the one in the address /o/<short-name>/…. Must be the organisation the token belongs to.
collectionThe collection's name, or id: followed by the collection's id.
itemThe item's name, or id: followed by the item's id.
fieldpassword, username, url or notes.
  • Names are compared case-insensitively and written URL-encoded: a space becomes %20, a slash %2F. Finance & payroll is written Finance%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, varn refuses to guess and shows their ids, so you can rename one of them or use id:.
  • 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. varn stores nothing on disk except with varn inject -o, and the values exist only in memory.
  • Check the package. @varnsecurity/cli is published from CI with npm provenance. Run npm audit signatures in a project that installs it, and always give an exact version.

Exit codes

CodeMeaning
0Done
2Wrong command or arguments
3Invalid reference
4No token, or an invalid one
5VARN_API_URL is invalid or not https
6Network error, timeout or unexpected response
7The token was not accepted (revoked, expired or wrong network)
8The plan does not include the secure vault
9The collection, item or field does not exist or is empty
10The name matches several collections or items
11Too many requests – try again in a minute
12The vault is switched off
13Server error
14Something could not be decrypted
15The reference is for another organisation
16A file could not be read or written

Once varn run has started the program, it exits with the program's own exit code.