OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 100

sops usage guide: command-line operations

Edit encrypted files, inspect their status, and manage recipients and data keys.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSSOPS encrypted configuration and key lifecycles ↗
About 6 min readStart reading

The following are general SOPS CLI examples; supported subcommands and argument placement depend on the installed version. Private-key read permissions and machine configuration determine whether administrator privileges are needed.

Subcommand overview#

sops edit        编辑加密文件(最常用,解密→编辑器→自动加密)
sops set         设置某个 key 的值
sops unset       删除某个 key
sops decrypt     解密输出到 stdout / -i 原地写回
sops encrypt     加密(需指定 recipient)
sops filestatus  检查文件加密状态
sops updatekeys  按 .sops.yaml 同步接收者
sops rotate      生成新数据密钥重加密
sops exec-env    解密后注入环境变量执行命令

Editing plaintext: the core workflow#

Method 1: sops edit (recommended, standard workflow)

sops edit host/secrets/secrets.yaml

It automatically decrypts → opens $EDITOR to edit plaintext → automatically encrypts and writes back after saving. You never handle the ciphertext directly, and there is no need to manually decrypt, edit, and encrypt.

Editing permissions Administrators should first confirm the decryption identity and file write permissions. A dedicated user age identity avoids relying on the system host key for everyday editing. Do not put private keys in the repository or command arguments.

Method 2: edit in a restricted temporary file, then encrypt

# Bash 示例;在含 .sops.yaml 的配置仓库根目录中执行
# 先确认私钥可用,且解密目标与 creation_rules 的路径匹配
umask 077
task_secret_dir=$(mktemp -d "${TMPDIR:-/tmp}/sops-edit.XXXXXXXX")
trap 'rm -rf -- "$task_secret_dir"' EXIT
sops decrypt host/secrets/secrets.yaml > "$task_secret_dir/plain.yaml" &&
  "${EDITOR:-nano}" "$task_secret_dir/plain.yaml" &&
  sops encrypt --filename-override host/secrets/secrets.yaml \
    "$task_secret_dir/plain.yaml" > "$task_secret_dir/encrypted.yaml" &&
  sops filestatus "$task_secret_dir/encrypted.yaml" &&
  cp -- "$task_secret_dir/encrypted.yaml" host/secrets/secrets.yaml
# 成功或失败退出后都清理私有临时目录;不要提交明文

Delete temporary plaintext Use a randomly named private directory and 0700/0600 permissions for temporary files, set an exit cleanup hook, and prevent leaks through editor backups, swap files, and logs. Deletion does not guarantee secure erasure from the storage medium; choose an appropriately protected memory filesystem when needed. If encryption fails, do not overwrite the original ciphertext.

Method 3: set/unset (change one key without editing the entire file)

# 设置 app_env 的值(value 是 JSON 字符串)
sops set host/secrets/secrets.yaml '["app_env"]' '"NON_SECRET_EXAMPLE_VALUE"'

# 删除某个 key
sops unset host/secrets/secrets.yaml '["app_env"]'

Encryption, decryption, and inspection#

# 解密到 stdout
sops -d host/secrets/secrets.yaml

# 解密并提取某个 key
sops -d --extract '["app_env"]' host/secrets/secrets.yaml

# 原地解密成明文文件(危险,别提交 git)
sops -d -i host/secrets/secrets.yaml

# 加密一份明文文件(需指定 recipient,或依赖 .sops.yaml)
sops -e --age "$PUB_KEY" "$task_secret_dir/plain.yaml" > "$task_secret_dir/encrypted.yaml"
# PUB_KEY 是已核对的 recipient;先检查加密成功再替换目标密文

# 检查文件是否加密
sops filestatus host/secrets/secrets.yaml

Key and recipient management#

Add a recipient (authorize multiple machines):

# 1. 在 .sops.yaml 的 keys 添加新公钥,creation_rules 里加上
# 2. 用 updatekeys 同步(需有旧 key 权限解密)
sops updatekeys host/secrets/secrets.yaml

Remove a recipient: remove that key from .sops.yaml, then run sops updatekeys.

Rotate the data key (generate a new AES key and re-encrypt; existing recipients remain valid):

sops rotate --in-place host/secrets/secrets.yaml

A safe key-change workflow Add the new recipient first (keep both as a safeguard) → verify that the new key can decrypt → remove the old recipient only after confirming stability. During the transition, rollback is possible if you retain the old ciphertext, old keys, and a working system recovery path. See the sops migration guide for the full process.

Understanding .sops.yaml#

.sops.yaml is the sops client configuration file. It determines which public key encrypts which file. A general example follows (placeholders are not valid keys):

keys:
  - &server-key AGE_RECIPIENT_PLACEHOLDER_NOT_VALID
creation_rules:
  - path_regex: host/secrets/secrets\.yaml$
    key_groups:
      - age:
        - *server-key

Field-by-field meaning:

Field Meaning
keys: A helper area for storing YAML anchors, not an independent SOPS authorization field
&server-key YAML anchor: assigns a label to a public-key string
creation_rules: An array of encryption rules, each matching certain files
path_regex: A path regular expression determining which files a rule applies to
key_groups: Key groups; within a group, any one identity can usually obtain the group’s share, while the Shamir threshold governs recovery across groups
*server-key YAML alias: resolves to the full public key

Multiple secrets files: creation_rules is an array, so you can add rules matching different files. Filenames are arbitrary as long as path_regex matches. Declare the runtime mapping in host/sops.nix using sopsFile:

sops = {
  defaultSopsFile = ./secrets/secrets.yaml;
  secrets = {
    another = { sopsFile = ./secrets/another.yaml; };
  };
};

The roles of .sops.yaml and host/sops.nix .sops.yaml controls which public key is used during encryption (CLI side); host/sops.nix controls which secret is taken from which file during decryption (runtime side). Their recipient and private key must match.

Regex vs. glob: * is a repetition operator, not a wildcard

In a regular expression (regex), * means repeat the preceding character, rather than the shell glob meaning of “match anything”:

secrets\.yaml$        # 精确:只匹配 secrets.yaml(\. 转义点号,$ 锚定结尾)
.*secrets.*           # 任意路径含 "secrets" 的都匹配(.* 才是 glob 的 *)
secrets-[0-9]+\.yaml$ # secrets-1.yaml, secrets-2.yaml...

YAML’s & / * are not pointers

&name (anchor) and *name (alias) are YAML declarations/references, not memory pointers. They express an anchor/alias relationship between YAML nodes: *server-key refers to the previously defined public-key node during parsing. Their purpose is to define once, reference many times, so a change needs to be made only at the & definition. “Variable-like” is a better analogy than “pointer.”

The layers behind the syntax

.sops.yaml has two layers of logic:

Layer Defined by Examples
Format layer (YAML syntax) The YAML specification &anchor, *alias, indentation, lists, and key-value pairs
Semantic layer (configuration fields) Defined by sops creation_rules、path_regex、key_groups、age

Anchors and aliases are YAML features; sops merely uses them. Fields such as path_regex are where sops-specific logic begins. This distinction applies to any tool that uses YAML for configuration.

How .sops.yaml is located: check the working directory and explicit configuration

By default, the current upstream CLI searches upward for configuration from the process’s current directory, . (configuration-path environment variables may also affect this), not from the target file’s directory. When invoking it across directories, run it from the repository root or specify the configuration explicitly with --config /path/to/config-repo/.sops.yaml. path_regex interprets the target path relative to the configuration file’s directory. When re-encrypting a temporary file, use --filename-override to specify the intended repository filename so the rules match.

The roles of .sops.yaml and sopsFile in sops.nix

.sops.yaml In sops.nix: sopsFile
Who reads it SOPS CLI The sops-nix module
What it controls Encryption/recipient-update rules and CLI storage options Which source to decrypt at runtime and which secret to export
When it is needed Creating ciphertext, updating authorization, and similar operations Deploying secrets during system activation

SopsFile does not determine the recipient used for CLI encryption. Existing ciphertext carries key-wrapping metadata, so decryption itself does not depend on creation_rules. However, .sops.yaml can also define storage or editing options, so it cannot be described as being read at only two points.

Quick reference for NixOS#

Command-line decryption and sops-nix runtime decryption use different entry points. sops-nix imports SSH keys through age.sshKeyPaths, whereas the SOPS CLI should explicitly use a readable age identity. --age takes an encryption recipient; a private-key file or process-substitution path cannot be supplied there in place of a decryption identity.

# 管理员在已授权读取 host key 的受控 shell 内执行;不要打印私钥
umask 077
task_key_dir=$(mktemp -d /run/sops-key-check.XXXXXXXX)
trap 'rm -rf -- "$task_key_dir"' EXIT
ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key > "$task_key_dir/identity.txt" &&
  SOPS_AGE_KEY_FILE="$task_key_dir/identity.txt" \
    sops decrypt host/secrets/secrets.yaml > /dev/null
# 检查退出码;不将明文或派生私钥写到终端

This is only an executable example; it was not run on the current machine. If other default age identities exist, disable those additional identities in an isolated, controlled environment before testing the target private key, to avoid a false positive.

# 经授权激活后检查运行时产物,不读取内容
ls -la /run/secrets/app_env
systemctl status example-app.service

The JSON value passed to set can enter shell history or process arguments; the example uses only non-secret strings. For real values, prefer sops edit or a controlled file/standard-input interface supported by the current version. sops -d -i turns the original repository file into plaintext and should generally be avoided. If used by mistake, stop committing and restore protected ciphertext. filestatus checks the encryption status recorded in the format; it does not prove that there have been no leaks, that decryption works, or that runtime deployment succeeded.

Related articles#


References & further reading

  1. Official SOPS documentation ↗
  2. SOPS CLI source ↗
  3. SOPS configuration source ↗
  4. Official sops-nix documentation ↗
  5. sops-nix module ↗
  6. sops-nix templates module ↗
  7. Official ssh-to-age documentation ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

SOPS encrypted configuration and key lifecycles

  1. 01sops principles: hybrid encryption and recipients
  2. 02sops-nix integration: runtime, ordering, and SSH host keys
  3. 03sops usage guide: command-line operations
  4. 04sops configuration templates and runtime rendering
  5. 05sops key migration and rotation
CONTINUE READING / NEXT ARTICLEsops configuration templates and runtime rendering

Understand encryption rules, sops-nix configuration, and runtime placeholders field by field.