Skip to content
Content only available in english

How to set up SOPS with age keys

This guide walks through setting up the local toolchain needed to create and work with encrypted files in a CoB project. Once set up, you will be able to encrypt new secret files that cob-cli can deploy and have decrypted on the server.

Prerequisites

Install SOPS and age:

sh
# macOS
brew install sops age

# Windows
winget install --id FiloSottile.age
winget install --id SecretsOPerationS.SOPS

Generate an age key pair and save it to 1Password

Copy and paste this script to generate the key and store it directly in 1Password without writing it to disk:

sh
age_key_output=$(age-keygen)
age_private_key=$(echo "$age_key_output" | grep -o 'AGE-SECRET-KEY-[[:alnum:]]*')
age_public_key=$(echo "$age_key_output" | grep -o 'age1[[:alnum:]]*')

op item create --category=Login --title="cob-cli key" --vault="Employee" \
   "username=$age_public_key" \
   "password=$age_private_key"

WARNING

The Vault Employee was named Private in older versions of 1password so the command above may give an error for not finding the vault.

This is a known naming inconsistency in 1Password. They renamed Teams and Business "private vaults" to "employee vaults" to reduce confusion between work and personal accounts, but no functionality actually changed — just the name. In this case you can chek that the UUID of the vault is the same but the label changed. Solution is changing Employee to Privatein the command above

The public key (saved as username) is safe to share and will be added to the repository configuration. The private key (stored as password) never touches disk.

Add your key to .sops.yaml

The repository should already contain a .sops.yaml at its root, with the server's key. Open it and add your public key as a new entry:

yaml
creation_rules:
  - age:
      # server
      - age1lggyhqjt3nu3tqe5ld8stpkdqe...
      # <your name>
      - age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7...

Replace the second key with your own public key from the previous step, and update the comment to identify yourself. Commit the change — .sops.yaml contains only public keys and is safe to version-control.

TIP

If the file does not exist please contact Cult Of Bits support.

Make the private key available to SOPS

Set SOPS_AGE_KEY_CMD to have SOPS retrieve the private key from 1Password on demand:

sh
export SOPS_AGE_KEY_CMD='op read "op://Employee/cob-cli key/password"'

SOPS will run this command each time it needs the private key, prompting 1Password to authenticate if the session has expired.

Add this to your shell profile.

Before relying on the setup, verify that op can retrieve the key correctly:

sh
eval $SOPS_AGE_KEY_CMD

This should print the AGE-SECRET-KEY-... line. If 1Password prompts for authentication, sign in and run it again.

Alternative: key file

If you are not using 1Password, generate the key to a file instead:

sh
age-keygen -o age-key.txt

Then point SOPS at it:

sh
export SOPS_AGE_KEY_FILE=/path/to/age-key.txt

Add this to your shell profile. Keep the key file outside the repository directory. Do not set both SOPS_AGE_KEY_CMD and SOPS_AGE_KEY_FILE at the same time.

Verify the setup

Check that SOPS can encrypt and decrypt with your key. In a server_* local repo, with an existing .sops.yaml file:

sh
echo "test: secret" > /tmp/test.yml
sops --encrypt /tmp/test.yml > /tmp/test.yml.enc
sops --decrypt --input-type yaml --output-type yaml /tmp/test.yml.enc

If the last command prints test: secret, the setup is complete.