MaruOpsInfrastructure and AI notes

About (Korean)Contact (Korean)

[Git and GitOps 23] Manage Secrets with SOPS and age

Workbench with monitor and desktop unit

Reference photo · Workbench with monitor and desktop unit · Photo: Mnicolois / Source / CC BY 4.0 · Resized for listings; illustrative photo, not the tested environment

Kubernetes Secret values encoded as base64 can be decoded by anyone who can read them. Plan separately where encrypted values are stored and who can decrypt them. This exercise uses SOPS and age locally and keeps the boundary with Argo CD’s decryption configuration explicit.

This part is a local encryption exercise using SOPS and age. It uses the example value training-only instead of a real service password. Adding an encrypted file to the Argo CD installation in Part 21 does not configure automatic decryption.

Git · GitOps All Series · 23 / 24

On this page

base64 is the transport representation

printf 'training-only' | base64
printf 'dHJhaW5pbmctb25seQ==' | base64 --decode

Kubernetes Secret’s data is expressed in base64, and stringData receives plaintext input. Encryption settings for storage, API access RBAC, etcd backup, and the path read by the application are separate security scopes. If the permission to read the Secret is wide, simply changing the data representation will not solve the problem.

1. Prepare your tools and a storage location for your private keys.

SOPS is a tool for encrypting values in structured files, and age provides the recipient of the key and the decryption method in this example. Select the files and verification materials appropriate for your OS and CPU architecture from the official release. The confirmed release on October 18, 2026 is SOPS 3.13.3, age 1.3.2. Do not immediately run the downloaded executable file with administrator privileges, but follow the official checksum and signature verification procedures.

sops --version
age --version
umask 077
mkdir -p ~/.config/sops/age
# Use a new name if this file already exists. Do not overwrite an existing key.
age-keygen -o ~/.config/sops/age/git-training.agekey
age-keygen -y ~/.config/sops/age/git-training.agekey

The final output is age1..., which is the public recipient key. The .agekey file contains the private key, so it is not placed in Git. Storage in the user’s home is the starting point for practice, and operations determine separate secret storage, access restrictions, and storage methods for recovery.

2. Encrypt the example Secret file

In the new lab folder, save the file below as secret.example.yaml. It will not be replaced with your actual password. This file is used to learn local encryption operations and is not included in the application path environments/dev.

apiVersion: v1
kind: Secret
metadata:
  name: demo-credentials
  namespace: gitops-demo
type: Opaque
stringData:
  demo-password: training-only

Encrypt the file by reading the public key into a variable. The private key is only needed for decryption; new file encryption is possible with the public recipient key.

recipient=$(age-keygen -y ~/.config/sops/age/git-training.agekey)
sops --encrypt --age "$recipient" \
  --encrypted-regex '^(data|stringData)$' \
  secret.example.yaml > secret.enc.yaml

Verify that the values under secret.enc.yaml to stringData change to ENC[...] and SOPS metadata is added. Some structures, such as resource names and namespaces, may remain visible. We do not assume that it is a tool that hides the existence and operating structure of entire files.

3. Decryption is performed only in the path with the key.

export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/git-training.agekey"
sops --decrypt secret.enc.yaml

The output appears as a plain text value. If it’s an actual secret value, we won’t expose it to CI logs and screen sharing. Rather than having the habit of saving decrypted files in the work tree, design a limited path to deliver them to necessary processes.

If you lose your key, you may not be able to recover it, even if the ciphertext remains. Organizations should consider multiple recipients or a managed KMS and prepare procedures for re-encryption with new keys and recipients when access is revoked. You should also review the ciphertext of past commits and the extent to which previous keys remain.

Argo CD connection requires additional design

A normal Argo CD installation will not automatically decrypt the SOPS ciphertext. If you choose Config Management Plugin, you need to manage plugin execution permissions and secret access scope of repo-server. Another approach is to configure a controller such as External Secrets to reference an external secret store.

If you apply the encrypted YAML as is to Kubernetes Secret, the desired secret will not be created automatically. In this series, we will only practice local round-trip encryption and will not distribute decryption keys mixed with Argo CD storage credentials. After the team’s key management system is decided, select the linkage method.

Definitions and options are Kubernetes Secret, SOPS official repository, age official document, linkage boundary is Argo CD Refer to Secret Management.

Previous · [Git and GitOps 22] Review Auto-Sync, selfHeal, prune and Git Revert · Next · [Git and GitOps 24] Operate Git, CI/CD and GitOps: Diagnose and Recover·Serial list and example files