Automating CIS Level 2 Compliance on Norwegian VPS: A CTO’s Guide to Surviving Datatilsynet
If you are still manually editing /etc/ssh/sshd_config in October 2025, you are not managing infrastructure; you are crafting artisanal security vulnerabilities. As a CTO or Lead Architect operating in the European market, specifically Norway, the landscape has shifted. It’s no longer just about keeping hackers out; it’s about proving to Datatilsynet (The Norwegian Data Protection Authority) that you’ve done your due diligence when—not if—an audit happens.
The reality of the post-Schrems II era is that data residency is not a feature; it is a legal requirement for sensitive workloads. While the 2023 EU-US Data Privacy Framework attempted to smooth things over, pragmatic technical leaders know that political winds change. The only safe harbor is actual harbor: keeping your data on physical disks located within Norwegian borders, governed by Norwegian law.
This guide moves beyond the basics. We aren't discussing how to install a firewall. We are discussing how to automate CIS (Center for Internet Security) Level 2 benchmarks using OpenSCAP and Ansible on Ubuntu 24.04 LTS, ensuring your CoolVDS instances are fortress-grade from the second they boot.
The Architecture of Compliance
Compliance is often viewed as a stack of paperwork. In DevOps, it is a state of infrastructure. To achieve this state without exploding your TCO (Total Cost of Ownership), we need three components:
- Sovereign Infrastructure: A VPS provider that guarantees data residency (CoolVDS in Oslo).
- Assessment Engine: A tool to compare current state against policy (OpenSCAP).
- Remediation Engine: A tool to enforce state (Ansible).
Let's look at the implementation. We will use the SSG (SCAP Security Guide) which comes standard with most modern Linux distributions.
Step 1: The Assessment (OpenSCAP)
First, we need to quantify how "insecure" a stock installation is. While CoolVDS images are optimized for performance and basic security, a CIS Level 2 profile requires strict hardening that might break casual workflows (like X11 forwarding or root login).
Install the necessary tooling on your control node:
sudo apt-get update
sudo apt-get install libopenscap8 ssg-base ssg-deb ssg-applications ssg-nonfree
Now, run a scan against the ssg-ubuntu2404-ds.xml datastream. This command checks the system against the CIS Level 2 Server benchmark.
oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis_level2_server \
--results scan-results.xml \
--report report.html \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml
Pro Tip: Don't run Level 2 immediately on production databases. The kernel parameter hardening can affect high-throughput I/O. Start with Level 1, benchmark your NVMe performance, and then graduate to Level 2. CoolVDS NVMe instances handle the I/O overhead of encryption and auditing better than standard SATA SSD VPSs, but testing is mandatory.
Step 2: Automating Remediation with Ansible
Once you see the sea of red "Fail" messages in your report, don't panic. We automate the fix. Writing Ansible roles from scratch is noble but inefficient. The RHEL System Roles upstream project (which works on other distros) or the Ansible Lockdown collection are the industry standards in 2025.
However, for a targeted approach, we will create a playbook that fixes the most critical failures: SSH hardening and Kernel Sysctl parameters.
The Playbook Structure
Create a file named harden_cis.yml. This playbook ensures we disable unused filesystems (a common CIS requirement) and lock down the network stack.
---
- name: Apply CIS Level 2 Hardening
hosts: coolvds_servers
become: yes
vars:
sysctl_config:
- { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.secure_redirects', value: '0' }
- { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' }
- { name: 'kernel.randomize_va_space', value: '2' }
tasks:
- name: Ensure specific filesystems are disabled (CIS 1.1.1)
community.general.modprobe:
name: "{{ item }}"
state: absent
persistent: present
loop:
- cramfs
- freevxfs
- jffs2
- hfs
- hfsplus
- squashfs
- udf
- name: Apply Kernel Hardening Parameters
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: yes
loop: "{{ sysctl_config }}"
- name: Secure SSH Configuration
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
validate: '/usr/sbin/sshd -t -f %s'
loop:
- { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^MaxAuthTries', line: 'MaxAuthTries 4' }
- { regexp: '^LoginGraceTime', line: 'LoginGraceTime 60' }
notify: restart sshd
handlers:
- name: restart sshd
service:
name: sshd
state: restarted
Running this playbook across your fleet ensures consistency. If an auditor asks, "How do you ensure squashfs is disabled?" you don't show them a terminal; you show them the git commit history of this playbook.
Step 3: Network-Level Isolation and Latency
Software hardening is useless if the network layer is porous. One reason we deploy on CoolVDS is the KVM architecture. Unlike container-based VPS solutions where kernel sharing can lead to escape vulnerabilities, KVM provides hardware-assisted virtualization. This strict isolation is a requirement for many high-security compliance frameworks.
Furthermore, consider the physical aspect. If your customers are in Norway, routing traffic through a compliant data center in Oslo via NIX (Norwegian Internet Exchange) drastically reduces attack surface area compared to routing through Frankfurt or Amsterdam. It also drops latency to ~2-5ms for local users.
Firewall Strategy (UFW Automation)
We must default to deny. Here is how to configure ufw programmatically to allow only SSH (rate limited) and HTTPS.
- name: Configure Firewall (UFW)
community.general.ufw:
state: enabled
policy: deny
direction: incoming
- name: Allow SSH with Rate Limiting
community.general.ufw:
rule: limit
port: ssh
proto: tcp
- name: Allow HTTPS
community.general.ufw:
rule: allow
port: '443'
proto: tcp
The Trade-Off: Security vs. Usability
When you apply CIS Level 2, things will break. For example, setting noexec on /tmp (a common requirement) will prevent many installation scripts and some monitoring agents from running.
This is where the Pragmatic CTO mindset applies. You document the exception. If you cannot mount /tmp with noexec because your Java application uses it for unpacking JARs, you implement File Integrity Monitoring (FIM) using tools like AIDE or Wazuh instead. Compliance is not about checking every box blindly; it is about mitigating risk to an acceptable level.
Why Infrastructure Choice Dictates Compliance Success
You can automate the OS, but you cannot automate the hardware or the building security. When you sign a Data Processing Agreement (DPA), you are vouching for the entire chain.
Using a provider like CoolVDS allows you to inherit their physical security controls. You don't have to worry about who has access to the physical racks in the Oslo data center—that is managed. Your focus remains entirely on the layer you control: the OS and the Application.
| Feature | General Public Cloud | CoolVDS (Norway) |
|---|---|---|
| Data Residency | Zones often span countries | Guaranteed Norway (Oslo) |
| Virtualization | Opaque / Shared Kernels | KVM (Kernel-based Virtual Machine) |
| Latency to NIX | 15-30ms | < 5ms |
| Storage | Networked Block Storage (Variable Latency) | Local NVMe (Consistent I/O) |
Conclusion
In 2025, security compliance is an engineering challenge, not a legal one. By leveraging OpenSCAP for visibility and Ansible for enforcement, you turn compliance into code. This allows your team to deploy faster, sleep better, and face auditors with confidence.
Don't build a fortress on sinking sand. Start your compliance journey on infrastructure designed for the Nordic market.
Ready to harden your stack? Deploy a CoolVDS instance in Oslo today and benchmark your security posture in under 60 seconds.