yq — Infrastructure
systemd Unit Files (YAML-adjacent)
systemd units are INI, not YAML — but systemd overrides and drop-ins often ship as YAML in configuration management. These patterns parse YAML inventories of systemd configurations.
Parse a service inventory
cat <<'YAML' > /tmp/services.yml
services:
- name: vault
unit: vault.service
enabled: true
port: 8200
- name: consul
unit: consul.service
enabled: true
port: 8500
- name: nomad
unit: nomad.service
enabled: false
port: 4646
YAML
yq -r '.services[] | select(.enabled == true) | "\(.name): \(.unit) (port \(.port))"' /tmp/services.yml
# Output:
# vault: vault.service (port 8200)
# consul: consul.service (port 8500)
Generate systemctl commands from inventory
cat <<'YAML' > /tmp/services.yml
services:
- name: vault
unit: vault.service
enabled: true
- name: nomad
unit: nomad.service
enabled: false
YAML
yq -r '.services[] | select(.enabled == true) | "sudo systemctl enable --now \(.unit)"' /tmp/services.yml
# Output:
# sudo systemctl enable --now vault.service
Docker Compose
List all services in a compose file
cat <<'YAML' > /tmp/docker-compose.yml
version: "3.8"
services:
kroki:
image: yuzutech/kroki
ports:
- "8000:8000"
environment:
KROKI_SAFE_MODE: unsafe
kroki-mermaid:
image: yuzutech/kroki-mermaid
expose:
- "8002"
YAML
yq -r '.services | keys | .[]' /tmp/docker-compose.yml
# Output:
# kroki
# kroki-mermaid
Extract image names and tags
cat <<'YAML' > /tmp/docker-compose.yml
version: "3.8"
services:
kroki:
image: yuzutech/kroki
kroki-mermaid:
image: yuzutech/kroki-mermaid
kroki-bpmn:
image: yuzutech/kroki-bpmn
YAML
yq -r '.services | to_entries[] | "\(.key): \(.value.image)"' /tmp/docker-compose.yml
# Output:
# kroki: yuzutech/kroki
# kroki-mermaid: yuzutech/kroki-mermaid
# kroki-bpmn: yuzutech/kroki-bpmn
Find services exposing specific ports
cat <<'YAML' > /tmp/docker-compose.yml
version: "3.8"
services:
web:
image: nginx
ports:
- "80:80"
- "443:443"
api:
image: api-server
ports:
- "8080:8080"
db:
image: postgres
expose:
- "5432"
YAML
yq -r '.services | to_entries[] | select(.value.ports != null) | "\(.key): \(.value.ports[])"' /tmp/docker-compose.yml
# Output:
# web: 80:80
# web: 443:443
# api: 8080:8080
List environment variables across all services
cat <<'YAML' > /tmp/docker-compose.yml
version: "3.8"
services:
app:
image: myapp
environment:
DB_HOST: db
DB_PORT: "5432"
LOG_LEVEL: info
db:
image: postgres
environment:
POSTGRES_DB: mydb
POSTGRES_USER: admin
YAML
yq -r '.services | to_entries[] | .key as $svc | .value.environment // {} | to_entries[] | "\($svc): \(.key)=\(.value)"' /tmp/docker-compose.yml
# Output:
# app: DB_HOST=db
# app: DB_PORT=5432
# app: LOG_LEVEL=info
# db: POSTGRES_DB=mydb
# db: POSTGRES_USER=admin
Kubernetes Manifests
Extract metadata from a deployment
cat <<'YAML' > /tmp/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: monad-api
namespace: monad
labels:
app: monad
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: monad
YAML
yq '{name: .metadata.name, namespace: .metadata.namespace, replicas: .spec.replicas}' /tmp/deployment.yml
# Output:
# name: monad-api
# namespace: monad
# replicas: 3
List container images in a pod spec
cat <<'YAML' > /tmp/pod.yml
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
spec:
containers:
- name: app
image: myapp:v1.2.3
ports:
- containerPort: 8080
- name: sidecar
image: envoyproxy/envoy:v1.28
ports:
- containerPort: 9901
YAML
yq -r '.spec.containers[] | "\(.name): \(.image)"' /tmp/pod.yml
# Output:
# app: myapp:v1.2.3
# sidecar: envoyproxy/envoy:v1.28
Decode a Kubernetes secret value
cat <<'YAML' > /tmp/secret.yml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4=
password: cDRzc3cwcmQ=
YAML
yq -r '.data.username | @base64d' /tmp/secret.yml
# Output: admin
Kubernetes secrets store values in base64.
yq’s @base64d decodes inline — no need for a separate base64 -d command.
Helm Values
Override specific Helm values
cat <<'YAML' > /tmp/values.yml
replicaCount: 1
image:
repository: nginx
tag: "1.25"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
YAML
yq -i '.replicaCount = 3 | .service.type = "LoadBalancer" | .ingress.enabled = true' /tmp/values.yml
yq '{replicas: .replicaCount, svcType: .service.type, ingress: .ingress.enabled}' /tmp/values.yml
# Output:
# replicas: 3
# svcType: LoadBalancer
# ingress: true
Extract all non-default values (values that are not empty/false/null)
cat <<'YAML' > /tmp/values.yml
replicaCount: 3
image:
repository: nginx
tag: "1.25"
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
YAML
yq 'with_entries(select(.value | (type == "!!map" and length > 0) or (type == "!!seq" and length > 0) or (type != "!!map" and type != "!!seq")))' /tmp/values.yml
# Output: only keys with actual values, filtering out empty maps/arrays
Cloud-Init
Parse cloud-init user data
cat <<'YAML' > /tmp/cloud-init.yml
#cloud-config
hostname: k3s-worker-01
fqdn: k3s-worker-01.inside.domusdigitalis.dev
manage_etc_hosts: true
users:
- name: evan
sudo: ALL=(ALL) NOPASSWD:ALL
groups: wheel, docker
shell: /bin/zsh
ssh_authorized_keys:
- ssh-ed25519 AAAA... evan@modestus-razer
packages:
- curl
- vim
- htop
runcmd:
- systemctl enable --now docker
YAML
yq -r '.users[].name' /tmp/cloud-init.yml
# Output: evan
List packages to install
cat <<'YAML' > /tmp/cloud-init.yml
#cloud-config
packages:
- curl
- vim
- htop
- jq
- yq
YAML
yq -r '.packages[]' /tmp/cloud-init.yml
# Output:
# curl
# vim
# htop
# jq
# yq
Extract runcmd as a shell script
cat <<'YAML' > /tmp/cloud-init.yml
#cloud-config
runcmd:
- systemctl enable --now docker
- curl -sfL https://get.k3s.io | sh -
- kubectl apply -f /tmp/manifests/
YAML
yq -r '.runcmd[]' /tmp/cloud-init.yml
# Output:
# systemctl enable --now docker
# curl -sfL https://get.k3s.io | sh -
# kubectl apply -f /tmp/manifests/
Each runcmd entry becomes a runnable shell command — yq extracts them for review or execution.