C.W.K.
Stream
Lesson 08 of 08 · published

Encrypted YAML, Templating, and the CUE Alternative

~10 min · yaml, sops, kustomize, cue

Level 0Plaintext
0 XP0/64 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

The escape hatches — when plain YAML isn't enough

SOPS — committed-but-encrypted secrets

SOPS encrypts YAML values (keys stay in plaintext for grep-ability). Backed by AWS KMS, GCP KMS, Azure Key Vault, or age. Common pattern: secrets.enc.yaml in git, decrypted at deploy time by a CI key. Never commit plaintext secrets again.

Kustomize — overlays, no templating

Kustomize composes YAML via overlays. A base directory has standard manifests; an overlay directory has patches. kustomize build prod/ emits the merged result. No Go templates, no string-vs-typed traps — just YAML merging YAML.

Jinja2 — full templating for Ansible / k8s / config

Where YAML's anchors aren't enough and you need conditionals, loops, includes, reach for Jinja2. Ansible has it built-in; j2cli templates standalone YAML files; FluxCD's HelmReleases support Jinja-rendered values.

CUE — typed config superset of YAML/JSON

CUE is a config language that compiles to YAML/JSON. It adds types, constraints, and unification (multiple partial schemas merge into one). Used by Istio, Dagger, KubeVela. Steeper learning curve; once internalized, you stop writing YAML by hand for complex platforms.

Principle: reach for the next layer only when YAML alone hurts. Plain YAML → anchors → Kustomize overlays → Helm templates → CUE. Each step adds power and learning cost. Most projects live happily at 'plain YAML + anchors' forever; only platform teams climb to CUE.

Code

SOPS — encrypt and decrypt YAML·bash
# Install
brew install sops

# One-time: configure a default KMS key in .sops.yaml
cat > .sops.yaml <<EOF
creation_rules:
  - kms: arn:aws:kms:us-east-1:123:key/abc
EOF

# Encrypt
sops --encrypt --in-place secrets.enc.yaml

# Decrypt to stdout
sops --decrypt secrets.enc.yaml

# Edit in place (decrypts + re-encrypts on save)
sops secrets.enc.yaml
SOPS-encrypted YAML (committed to git, safely)·yaml
# secrets.enc.yaml  — committed!
database_url: ENC[AES256_GCM,data:Tr3y+kQs...,iv:abcd...,tag:efgh...]
api_key:      ENC[AES256_GCM,data:9Pq2...,iv:1234...,tag:5678...]
sops:
  kms:
    - arn: arn:aws:kms:us-east-1:123:key/abc
      created_at: '2026-05-04T01:30:11Z'
Kustomize — base + overlay·yaml
# base/kustomization.yaml
resources:
  - deployment.yaml
  - service.yaml

# overlays/prod/kustomization.yaml
resources:
  - ../../base
replicas:
  - name: pippa
    count: 10
images:
  - name: ghcr.io/cwk/pippa
    newTag: '1.0.42'

# Build the prod manifest
kustomize build overlays/prod/ | kubectl apply -f -
CUE — same data, with types·text
// pippa.cue
package pippa

#Service: {
    name:     string
    replicas: int & >0 & <=20
    image:    string
    port:     int & >=1024 & <=65535
}

production: #Service & {
    name:     "pippa"
    replicas: 10
    image:    "ghcr.io/cwk/pippa:1.0.42"
    port:     8000
}

// cue export pippa.cue --out yaml > production.yaml

External links

Exercise

Pick one repo where you currently have plaintext-ish secrets (.env files, hard-coded API endpoints in YAML). Set up SOPS with age encryption (no AWS account required). Encrypt one secret, commit it, decrypt locally. Add the decrypt step to your dev/start script. The 'never accidentally commit a key' problem is now structurally fixed.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.