Automating Security Compliance: Surviving Datatilsynet with Ansible and OpenSCAP
If you are still manually editing /etc/ssh/sshd_config on your production servers, you are already non-compliant. I don’t say that to be abrasive; I say it because in 2020, manual configuration drift is the primary vector for security incidents.
As a CTO or Lead Architect, your nightmare isn't just a rootkit; it's the letter from Datatilsynet (The Norwegian Data Protection Authority) asking for audit logs you don't have. With the US Cloud Act casting a long shadow over trans-Atlantic data transfers and the validity of the Privacy Shield framework looking increasingly shaky, hosting your data physically in Norway isn't just patriotism—it's risk management.
But geography alone doesn't secure a server. Today, we are going to look at how to automate compliance with the CIS (Center for Internet Security) Benchmarks on the newly released Ubuntu 20.04 LTS using Ansible and OpenSCAP. This is the exact stack we recommend for high-compliance workloads running on CoolVDS NVMe instances.
The "Treat Servers Like Cattle" Compliance Model
The old way of securing a VPS involved a checklist and a tired sysadmin. The new way is Infrastructure as Code (IaC). If a server is compromised or drifts from its configuration state, we don't fix it. We kill it and spin up a new one that is mathematically guaranteed to be compliant.
To achieve this, we need two things:
- Enforcement: Ansible roles that apply hardening rules.
- Validation: OpenSCAP scanners that verify the rules are applied.
Step 1: Hardening SSH via Ansible
The CIS Benchmark for Ubuntu requires disabling root login, enforcing protocol 2, and limiting authentication retries. Doing this manually is prone to error. Here is a production-ready Ansible task snippet that enforces these settings. We use this standard on our CoolVDS managed images.
- name: Secure SSH Configuration per CIS Benchmarks
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
validate: 'sshd -t -f %s'
loop:
- { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^MaxAuthTries', line: 'MaxAuthTries 4' }
- { regexp: '^Protocol', line: 'Protocol 2' }
- { regexp: '^ClientAliveInterval', line: 'ClientAliveInterval 300' }
- { regexp: '^ClientAliveCountMax', line: 'ClientAliveCountMax 0' }
notify: restart sshd
- name: Ensure SSH permissions are restrictive
file:
path: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
Pro Tip: Always use thevalidateparameter in Ansible when editing service configs. It prevents you from deploying a broken config file that locks you out of your VPS. Ifsshd -tfails, Ansible aborts the change. Safety first.
Step 2: Automating IP Stack Hardening
Default Linux kernel settings are tuned for compatibility, not security. For a public-facing web server, you need to prevent IP spoofing and man-in-the-middle redirects. We modify sysctl.conf.
# Ansible Task: Kernel Hardening
- name: Set kernel parameters for CIS compliance
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: yes
loop:
- { key: 'net.ipv4.conf.all.accept_redirects', value: '0' }
- { key: 'net.ipv4.conf.default.accept_redirects', value: '0' }
- { key: 'net.ipv4.conf.all.secure_redirects', value: '0' }
- { key: 'net.ipv4.conf.all.log_martians', value: '1' }
- { key: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' }
Verification: Trust, But Verify with OpenSCAP
Applying the config is half the battle. Proving it to an auditor is the other half. OpenSCAP is an open-source tool that scans your system against a standard profile (like PCI-DSS or CIS).
On Ubuntu 20.04, you can install the tooling easily:
apt-get update && apt-get install libopenscap8 scap-security-guide -y
Once installed, you can run a scan. Be warned: the first time you run this on a generic VPS from a budget provider, you will likely see a fail rate of over 40%. On a properly configured CoolVDS instance, we aim for >95% out of the box.
#!/bin/bash
# Run CIS Level 1 Server Audit
PROFILE="xccdf_org.ssgproject.content_profile_cis_level1_server"
REPORT_NAME="audit-report-$(date +%F).html"
oscap xccdf eval \
--profile $PROFILE \
--report /var/www/html/reports/$REPORT_NAME \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2004-ds.xml
echo "Audit complete. Report generated at /var/www/html/reports/$REPORT_NAME"
This script generates an HTML report that highlights exactly which configurations failed. It is brutal, honest, and necessary.
The Infrastructure Layer: Why Virtualization Matters
You can have the most hardened OS in the world, but if your hypervisor leaks, you are finished. This is where the choice of hosting provider becomes a compliance decision.
| Feature | Container (LXC/OpenVZ) | CoolVDS (KVM) |
|---|---|---|
| Kernel Isolation | Shared (Risk of escape) | Dedicated (Hardware Virtualization) |
| Resource Guarantee | Burstable/Oversold | Dedicated RAM/NVMe |
| Encryption | File-level only | Full Disk Encryption capable |
Many "cheap" VPS providers use container-based virtualization. This means you share a kernel with neighbors. If a vulnerability is found in the host kernel (like the Dirty COW exploit from a few years back), your container is exposed regardless of your internal firewalls.
At CoolVDS, we exclusively use KVM (Kernel-based Virtual Machine). Each instance has its own kernel. This provides the isolation required for strict GDPR compliance and allows you to enable kernel-level auditing features (like auditd) that are often disabled in containers.
Network Latency and Legal Jurisdiction
Finally, let's talk about the physical layer. If you are serving Norwegian users, routing traffic through Frankfurt or London adds unnecessary milliseconds. But more importantly, it adds legal complexity.
Data stored in our Oslo datacenter stays under Norwegian jurisdiction. We connect directly to the NIX (Norwegian Internet Exchange), ensuring that local traffic stays local. This low latency is critical for database replication and API response times, but the legal certainty is what lets you sleep at night.
A Simple Firewall Rule for the Paralyzingly Cautious
If you want to ensure your management interface is only accessible from your office in Oslo, do not rely on high-level application logic. Use ufw (Uncomplicated Firewall) right at the OS level.
# Reset UFW to default deny
ufw default deny incoming
ufw default allow outgoing
# Allow SSH only from your static office IP
ufw allow from 81.x.x.x to any port 22 proto tcp
# Allow HTTP/HTTPS from everywhere
ufw allow 80/tcp
ufw allow 443/tcp
# Enable
ufw enable
Conclusion
Compliance is not a checkbox; it is a continuous process of automated verification. By combining Ansible for consistent configuration, OpenSCAP for auditing, and KVM-based isolation for architectural integrity, you build a fortress.
Don't let your infrastructure be the weak link in your GDPR strategy. Deploy your hardened environment on a platform that respects data sovereignty and raw performance.
Ready to audit your stack? Spin up a CoolVDS instance in Oslo today and run your first OpenSCAP scan in under 60 seconds.