Skip to content
Latchkey

sops With age and KMS Keys

sops can encrypt to an age recipient (--age) or a cloud KMS key (--kms), and reads age identities from SOPS_AGE_KEY or SOPS_AGE_KEY_FILE on decrypt.

Choosing the key backend is the main sops decision. age keys are simple and offline; KMS delegates access control to the cloud. Both are declared in .sops.yaml creation rules or passed on the command line.

What it does

On encrypt, --age <recipient> or --kms <arn> tells sops who can decrypt. On decrypt, sops finds a matching key: for age it reads the identity from SOPS_AGE_KEY (the key text) or SOPS_AGE_KEY_FILE (a path); for KMS it uses the ambient cloud credentials.

Common usage

Terminal
# encrypt to an age recipient
sops -e --age age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
  secrets.yaml > secrets.enc.yaml
# decrypt on the runner with the identity in an env var
export SOPS_AGE_KEY="$AGE_IDENTITY"
sops -d secrets.enc.yaml

Options

Flag / envWhat it does
--age <recipient>Encrypt to an age public key
--kms <arn>Encrypt to an AWS KMS key ARN
--gcp-kms / --azure-kvEncrypt to a GCP or Azure KMS/Key Vault key
SOPS_AGE_KEYAge identity text used for decryption
SOPS_AGE_KEY_FILEPath to an age identity file for decryption

In CI

For age, put the identity in a secret and export SOPS_AGE_KEY in the job. For KMS, rely on the runner OIDC/role rather than long-lived keys. A .sops.yaml with creation_rules keeps recipients out of every command.

Common errors in CI

"Failed to get the data key required to decrypt the SOPS file" plus "no identity matched any of the recipients" means SOPS_AGE_KEY does not correspond to the file recipient. For KMS, "AccessDeniedException" or "KMS.NotFoundException" means the runner role lacks kms:Decrypt or the ARN/region is wrong.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →