Compliance audits are painful. Anyone who’s been through ISO 27001 certification knows the drill: weeks of documentation gathering, screenshots of configurations, evidence of change management processes, proof that what you say you do is what you actually do.
But here’s something I’ve realized after running declarative infrastructure for years: systems like Talos and NixOS don’t just make infrastructure better — they make compliance dramatically easier. The same properties that make these systems reliable (immutability, reproducibility, auditability) are exactly what auditors want to see.
Let me show you how declarative infrastructure becomes compliance documentation.
The Compliance Problem
Most compliance frameworks — ISO 27001, SOC 2, NIS2, PCI-DSS — ask variations of the same questions:
- What is your system configuration? (Asset management, configuration management)
- How do you control changes? (Change management, access control)
- Can you prove it? (Audit trails, evidence)
- Is it consistent? (No drift, no undocumented changes)
Traditional infrastructure answers these questions with… documentation. Word documents describing what should be configured. Screenshots proving it was configured that way on a specific date. Change tickets referencing vague “server updates.”
The problem? Documentation drifts from reality. That Word document says servers have automatic updates enabled, but does anyone verify that’s still true six months later?
Declarative Systems as Source of Truth
With Talos or NixOS, your configuration is your documentation. There’s no gap between “what we say” and “what we do” because the system enforces the declared state.
Talos Example
# This isn't documentation about the system.
# This IS the system.
machine:
type: controlplane
network:
hostname: prod-control-01
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.6.0
sysctls:
net.ipv4.ip_forward: "1"
kubelet:
extraArgs:
rotate-server-certificates: "true"
cluster:
clusterName: production
apiServer:
admissionControl:
- name: PodSecurity
configuration:
defaults:
enforce: "restricted"
When an auditor asks “How are your Kubernetes nodes configured?”, you hand them this file. It’s not an approximation — it’s the exact, current, enforced configuration.
NixOS Example
{
# Security hardening - this is both config AND documentation
security.sudo.wheelNeedsPassword = true;
security.auditd.enable = true;
security.audit.rules = [
"-w /etc/passwd -p wa -k identity"
"-w /etc/group -p wa -k identity"
];
# Firewall configuration
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 443 6443 ];
logRefusedConnections = true;
};
# Automatic security updates
system.autoUpgrade = {
enable = true;
allowReboot = false;
dates = "04:00";
};
}
Every security control is defined in code. The auditor can see exactly what’s configured, and they know it’s enforced because NixOS won’t boot a system that doesn’t match this config.
Mapping to Compliance Controls
Let me show how declarative configs map to specific compliance requirements:
ISO 27001: A.12.1.2 - Change Management
Requirement: Changes to systems shall be controlled.
Traditional approach: Change tickets, approval workflows, manual documentation.
Declarative approach:
- All changes are Git commits
- Pull requests require review
- Merge to main triggers deployment
- Git history IS the change log
# Your change management evidence
git log --oneline --since="2025-01-01" -- infrastructure/
a]2d8d00e Add NixOS vs Talos comparison
e49f5bd Add Talos Linux blog post
defb991 Switch image generation to DALL-E
...
Every change has: who made it, when, what changed, who approved it (PR reviewers), and why (commit message). This is better evidence than any ticketing system.
ISO 27001: A.12.6.1 - Management of Technical Vulnerabilities
Requirement: Information about technical vulnerabilities shall be obtained and appropriate measures taken.
Declarative approach with Talos:
machine:
install:
image: ghcr.io/siderolabs/installer:v1.7.0 # Specific version
- Exact OS version is in Git
- Updating means changing version and deploying
- You can prove which version ran at any point in time
- Rollback is trivial if a vulnerability is found in a new version
NIS2: Article 21 - Cybersecurity Risk Management
Requirement: Appropriate technical and organizational measures to manage risks.
Declarative evidence:
{
# Network segmentation
networking.vlans = {
management = { id = 10; interface = "eth0"; };
production = { id = 20; interface = "eth0"; };
};
# Encryption at rest
boot.initrd.luks.devices."encrypted".device = "/dev/sda2";
# Access control
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
}
Each control is visible, auditable, and enforced.
SOC 2: CC6.1 - Logical Access Controls
Requirement: The entity implements logical access security software, infrastructure, and architectures.
Talos approach (radical but effective):
- No SSH access at all
- All management through authenticated API
- mTLS for all API communication
- Role-based access via Kubernetes RBAC
# Talos machine config
machine:
features:
rbac: true # Kubernetes RBAC enabled
# No SSH configuration because SSH doesn't exist
The auditor can verify: there is literally no SSH daemon. Access control is enforced by architecture, not policy.
Generating Compliance Reports
Here’s where it gets interesting. Because everything is in code, you can automatically generate compliance documentation.
Configuration Drift Report
#!/bin/bash
# For Talos: compare declared vs actual
for node in $(talosctl get members -o json | jq -r '.[] | .hostname'); do
echo "=== $node ==="
talosctl get machineconfig -n $node -o yaml > /tmp/actual.yaml
diff infrastructure/talos/$node.yaml /tmp/actual.yaml
done
If this script produces no output, you have proof of zero configuration drift.
NixOS System Closure
# Generate a complete list of all software and versions
nix-store -q --requisites /run/current-system | \
xargs -I {} nix-store -q --binding name {} 2>/dev/null | \
sort -u > system-inventory.txt
This produces a complete software inventory — every package, every library, every version. Auditors love this.
Git-Based Audit Trail
# Generate change report for audit period
git log --pretty=format:"%h|%an|%ad|%s" \
--date=short \
--since="2025-01-01" \
--until="2025-12-31" \
-- infrastructure/ > annual-changes.csv
Import into Excel, hand to auditor. Done.
Continuous Compliance
The real power isn’t just passing audits — it’s continuous compliance. With declarative systems and GitOps:
# ArgoCD Application for infrastructure
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure
spec:
source:
repoURL: https://github.com/company/infrastructure
path: kubernetes/
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true # Automatically fix drift
If someone manually changes something, ArgoCD reverts it. The system continuously enforces the declared state. You’re not compliant at audit time — you’re compliant all the time.
Practical Tips for Compliance-Ready Infrastructure
1. Use Meaningful Commit Messages
# Bad
git commit -m "Update config"
# Good
git commit -m "Enable audit logging per ISO 27001 A.12.4.1
- Added auditd configuration for file access monitoring
- Configured log retention for 90 days
- Addresses finding from Q3 security review
Ticket: SEC-1234"
Your Git history becomes compliance evidence. Treat it that way.
2. Tag Compliance-Related Configs
{
# ISO 27001 A.12.4.1 - Event Logging
security.auditd.enable = true;
# ISO 27001 A.13.1.1 - Network Controls
networking.firewall.enable = true;
# NIS2 Art.21(2)(d) - Supply Chain Security
nix.settings.require-sigs = true;
}
Comments linking config to specific controls make audits trivial.
3. Version Everything
# Talos machine config
machine:
install:
image: ghcr.io/siderolabs/installer:v1.6.0 # Not :latest
Auditors want to know exactly what version was running on a specific date. Pinned versions + Git history = complete audit trail.
4. Automate Evidence Collection
#!/bin/bash
# Quarterly compliance report generator
REPORT_DIR="compliance-reports/$(date +%Y-Q%q)"
mkdir -p $REPORT_DIR
# System inventory
nix-store -q --requisites /run/current-system > $REPORT_DIR/inventory.txt
# Configuration snapshots
cp -r /etc/nixos $REPORT_DIR/nixos-config/
# Change log
git log --since="3 months ago" -- infrastructure/ > $REPORT_DIR/changes.txt
# Drift check
./scripts/check-drift.sh > $REPORT_DIR/drift-report.txt
echo "Report generated in $REPORT_DIR"
Run quarterly, archive, present to auditors.
The Bigger Picture
Declarative infrastructure doesn’t just make compliance easier — it makes compliance real.
Traditional compliance often devolves into checkbox exercises. Documents say one thing, reality says another, and everyone pretends during audit season. This is theater, not security.
With Talos, NixOS, and GitOps, compliance becomes a side effect of good engineering. The system is secure because it’s immutable. Changes are tracked because they go through Git. Drift is impossible because the system enforces declared state.
You’re not doing extra work for compliance — you’re doing infrastructure correctly, and compliance evidence falls out naturally.
The best compliance posture is infrastructure that can’t be non-compliant. Declarative systems get you there.
