Console Login

Compliance as Code: Automating GDPR and Server Hardening in Norway's Threat Landscape

The Excel Spreadsheet is a Lie: Why Manual Compliance Failed You Yesterday

If you are still tracking your server security posture in a shared spreadsheet, you have already been breached; you just haven't found the logs yet. In the fast-paced DevOps environment of 2020, manual audits are dead on arrival. Infrastructure changes too fast. By the time you mark a row as "Compliant," a junior dev has likely changed a firewall rule or opened a port for debugging and forgot to close it.

For those of us operating out of Norway or serving EU clients, the stakes are higher. It's not just about uptime or preventing a script kiddie from mining Monero on your CPU. It's about Datatilsynet (The Norwegian Data Protection Authority) and the looming shadow of GDPR fines. With the US CLOUD Act causing massive uncertainty regarding data stored on American-owned hyperscalers, the only safe harbor is strict data sovereignty.

This guide isn't about policy writing. It's about engineering compliance into the metal. We are going to look at how to automate hardening using Ansible, verify it with OpenSCAP, and ensure your data stays legally safe on Norwegian soil.

1. The Foundation: Infrastructure Sovereignty

Before writing a single line of code, you must address the physical layer. You cannot automate your way out of a bad jurisdiction. If your VPS is hosted in Frankfurt but owned by a US entity, you are exposed to extraterritorial data requests. This is a massive headache for any CTO trying to navigate the conflict between GDPR and the CLOUD Act.

This is where infrastructure choice becomes a compliance tool. When we provision instances on CoolVDS, we aren't just looking for raw NVMe speed (though the low I/O wait is critical for database locking). We are looking for the fact that the metal resides in Oslo. Data doesn't cross borders, and the legal entity is local. That is your "Layer 0" compliance.

2. Hardening with Ansible: Idempotency is Security

Stop configuring servers manually. If you `ssh` into a box to change `sshd_config`, you are doing it wrong. We use Ansible because it documents the state of the server. If the configuration drifts, Ansible brings it back. That is Compliance as Code.

Here is a standard Ansible task we use to secure SSH. It disables root login and forces key-based authentication—two mandatory checks for most CIS Benchmarks.

- name: Secure SSH Configuration
  hosts: all
  become: yes
  tasks:
    - name: Disable Root Login
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PermitRootLogin'
        line: 'PermitRootLogin no'
        state: present
      notify: Restart SSH

    - name: Disable Password Authentication
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PasswordAuthentication'
        line: 'PasswordAuthentication no'
        state: present
      notify: Restart SSH

    - name: Ensure SSH Protocol 2 is used
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^Protocol'
        line: 'Protocol 2'
        state: present
      notify: Restart SSH

  handlers:
    - name: Restart SSH
      service:
        name: sshd
        state: restarted

Running this playbook ensures that every node in your cluster complies with access policies. You can show this YAML file to an auditor as proof of your standard operating procedure.

3. Automated Verification: OpenSCAP

Applying a config is one thing; proving it is another. OpenSCAP is the industry standard for verifying system compliance against known profiles (like PCI-DSS or CIS). It parses the machine's state and generates a report.

On a CentOS 7 or 8 system (common on CoolVDS instances), you can install the scanner and the security guide easily:

yum install openscap-scanner scap-security-guide -y

Once installed, you don't need to manually check settings. Run a scan against the standard profile. This command checks your system and outputs a frighteningly detailed HTML report:

oscap xccdf eval \
  --profile xccdf_org.ssgproject.content_profile_standard \
  --results scan-results.xml \
  --report scan-report.html \
  /usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml
Pro Tip: Don't expect a 100% score on the first run. The default profiles are paranoid. They often require separate partitions for `/var` and `/tmp` with `noexec` flags. While CoolVDS KVM virtualization allows custom partitioning during setup, you might need to adjust the profile to fit your web application's reality. A 95% score with documented exceptions is better than a 100% score that breaks your app.

4. The Audit Trail: auditd and Immutable Logs

GDPR Article 32 requires the ability to restore availability and access, but it also implies traceability. If a breach happens, you must know what was touched. The Linux kernel audit daemon (`auditd`) is your flight recorder.

By default, `auditd` is often too quiet. You need to configure it to watch specific critical files. Add these rules to `/etc/audit/rules.d/audit.rules` to track changes to the password file and network configuration:

# Watch for changes to user database
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity

# Watch for network config changes
-w /etc/sysconfig/network -p wa -k system-locale

# Lock the configuration so it cannot be changed without a reboot
-e 2

The `-e 2` flag is critical. It makes the audit configuration immutable. Even if an attacker gains root, they cannot stop the logging without rebooting the machine (which triggers alerts in your monitoring system).

5. Network Defense: Firewalld & Fail2Ban

CoolVDS provides DDoS protection at the network edge, but that doesn't excuse you from host-level security. We see too many developers flushing `iptables` and forgetting to restore them.

For a standard web server, your `firewalld` setup should be restrictive. Only open what you need. If you are managing the server via SSH, restrict port 22 to your office VPN IP.

# Reset to defaults
firewall-cmd --set-default-zone=drop

# Allow HTTP/HTTPS globally
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --zone=public --add-service=https --permanent

# Allow SSH only from specific subnets (e.g., your VPN)
firewall-cmd --zone=trusted --add-source=192.168.1.0/24 --permanent
firewall-cmd --zone=trusted --add-service=ssh --permanent

firewall-cmd --reload

Combine this with Fail2Ban to punish brute-force attempts. It scans logs for repeated failures and updates the firewall to ban the offending IP.

Latency and Legal Realities

Why do we stress the "Norwegian" aspect of CoolVDS? Beyond the legal protections, there is a technical reality: latency. If your customer base is in Scandinavia, routing traffic through a compliance-heavy datacenter in Oslo reduces RTT (Round Trip Time). We consistently see sub-5ms latency to NIX (Norwegian Internet Exchange) from CoolVDS instances.

When you combine low-latency NVMe storage with the automation scripts above, you get a system that is secure by design, not by accident. You aren't scrambling when the auditor calls; you just send them the latest OpenSCAP report and get back to work.

Next Steps

Compliance is a process, not a destination. Start small. Deploy a fresh CentOS 8 instance on CoolVDS today, run the OpenSCAP scan, and see where you stand. It takes less than 60 seconds to spin up, and it might save you months of legal headaches later.