CoursesSOPSBeginner

Install, encrypt & decrypt

sops -e / -d in practice.

Intermediate10 min · lesson 2 of 12

SOPS is a single binary. The two core operations are sops -e (encrypt) and sops -d (decrypt), each reading a file and writing to stdout (or in place). To encrypt you need a key — the simplest to start is age (a modern, simple encryption tool) — and you tell SOPS which recipient(s) to encrypt for. Once encrypted, the file is safe to commit; to use it, whoever has the corresponding key runs sops -d.

terminal
$ age-keygen -o key.txt # generate an age keypair (once)
Public key: age1ql3z7hjy54pw3hyww5ay...
$ sops -e --age age1ql3z7hjy54pw3hyww5ay... secrets.yaml > secrets.enc.yaml
$ git add secrets.enc.yaml # safe: values are encrypted
$ SOPS_AGE_KEY_FILE=key.txt sops -d secrets.enc.yaml # decrypt with the private key

Encrypt vs decrypt, and in-place

You can encrypt/decrypt in place (-i) or to stdout. The private key is supplied out of band — via an environment variable, a key file, or (for cloud KMS) your cloud credentials — never committed. The public key (or KMS key ARN) is what you encrypt to, and SOPS stores in the file which keys can decrypt it, so anyone with a listed key can decrypt without extra configuration. That embedded metadata is what makes SOPS files self-describing.

secrets.enc.yaml (excerpt)
db_password: ENC[AES256_GCM,data:8fKz...,iv:...,tag:...,type:str]
sops:
age:
- recipient: age1ql3z7hjy54pw3hyww5ay...
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
...
lastmodified: "2026-01-15T..."
mac: ENC[AES256_GCM,data:...] # integrity check over the whole file
Never commit the private key or a decrypted file
The whole scheme fails if the private key (key.txt) or a decrypted copy of the file lands in Git. Add private keys and *.dec / plaintext secret files to .gitignore, supply keys via environment or a secret store at use time, and double-check that what you commit is the ENC[...] version. A leaked key or an accidentally-committed plaintext file exposes every secret it protects.