Running a cloud server on providers like DigitalOcean, Linode, or AWS requires balancing operational functionality with a strict security boundary. Whether an instance serves as an overlay network gateway, a Tailscale exit node, or an internal infrastructure proxy, standard out-of-the-box operating system deployments leave significant residual exposure: persistent disk logging, unencrypted swap spaces, permissive kernel parameters, and default network policies.

To eliminate these attack vectors, security-first infrastructure must adhere to three core principles: minimizing persistent storage footprints, isolating service execution contexts, and automating defensive maintenance.

The harden-droplet.sh automation framework implements these defense-in-depth strategies across any standard Ubuntu cloud instance.

1. Network Boundary Security & UFW Hardening

A hardened cloud server must default to an explicit drop policy for all unsolicited inbound traffic. Standard setups often leave SSH (port 22) exposed directly to the public IPv4/IPv6 internet, subjecting the instance to continuous automated brute-force attacks.

[ Public Internet ] ---> ( Port 22 Blocked / UFW Default Deny )
                                  |
                                  v
                   [ Tailscale Overlay Interface ]
                                  |
                                  v
                      ( Internal Machine Access )

Key Network Controls

  • Default Policies: Inbound traffic is set to deny, outbound traffic is set to allow.

  • Interface Isolation: Network access is explicitly restricted to overlay network interfaces (tailscale0).

  • Direct Peer Traversal: UDP port 41641 is permitted to allow direct peer-to-peer WireGuard sessions without routing through fallback DERP relay infrastructure.

  • Packet Forwarding: System controls (sysctl) explicitly enable IPv4 and IPv6 forwarding (net.ipv4.ip_forward = 1) to handle internal transit routing securely.

2. Ephemeral Encrypted Swap Space (dm-crypt)

Standard Linux swap configurations write active pages of system memory straight to persistent cloud block storage when physical RAM usage spills over. On low-RAM instances (e.g., 512MB to 1GB instances), sensitive process memory, session tokens, and cryptographic material risk being written in plain text to storage volumes or virtual machine snapshots.

[ Physical RAM ] ---> ( Spills Over ) ---> [ dm-crypt Layer ] ---> [ Single-Use /dev/urandom Key ] ---> [ Disk /swapfile ]

Automated Implementation

Instead of relying on standard unencrypted swap files, the deployment framework configures dynamic block device encryption:

  1. Volume Allocation: A dedicated 2GB file (/swapfile) is allocated with strict 0600 permissions.

  2. Dynamic Cryptographic Mapping: /etc/crypttab maps the volume via dm-crypt using a single-use key drawn directly from /dev/urandom (plain,swap,cipher=aes-xts-plain64,size=256).

  3. Automated Ephemeral Keys: Every reboot destroys the previous encryption key, rendering historical swap data on the physical block storage entirely unrecoverable.

3. Zero-Persistence Logging Architecture (RAM-Only Execution)

For high-privacy cloud workloads, persistent system logs (/var/log/syslog, /var/log/auth.log, systemd journal files) create a permanent record of connection metadata, operational timelines, and internal IP addresses.

The hardening framework transforms the operating system logging pipeline into a volatile RAM-only storage system.

+-----------------------------------------------------------------------+
|                            VOLATILE RAM                               |
|                                                                       |
|   [ Journald (Storage=volatile) ] ----> Writes to RAM (10MB max)       |
|                                                                       |
|   [ /var/log Mount ] -------------> tmpfs (64MB RAM Disk)             |
|   [ /tmp Mount ] -----------------> tmpfs (512MB RAM Disk)            |
|   [ /var/tmp Mount ] --------------> tmpfs (256MB RAM Disk)            |
+-----------------------------------------------------------------------+
                                  |
                                  v
           [ Power Cycle / Reboot ] ===> ALL LOGS PURGED INSTANTLY

Architectural Breakdown

  • Volatile Journald: journald.conf is forced to Storage=volatile with RuntimeMaxUse=10M and MaxRetentionSec=0. System logs exist strictly in RAM and are overwritten dynamically.

  • Service Disablement: Persistent logging daemons such as rsyslog are disabled and masked.

  • Memory Mounts (tmpfs): System directories /var/log, /tmp, and /var/tmp are mounted as temporary in-memory filesystems in /etc/fstab.

When the cloud instance undergoes a power state change or reboot, all runtime state and temporary operational files are flushed.

4. Kernel Protection Parameters & Low-RAM Memory Tuning

Linux kernel defaults prioritize general compatibility over security. The hardening script deploys custom configuration files to /etc/sysctl.d/ to restrict diagnostic capabilities and reduce memory exhaustion risks.

Sysctl Security Parameters

  • IP Stack Hardening: Rejects ICMP redirects (net.ipv4.conf.all.accept_redirects = 0) and enables Reverse Path Filtering (rp_filter = 1) to block IP spoofing attempts.

  • RAM Inspection Protections:

    • kernel.dmesg_restrict = 1: Prevents non-root users from reading kernel ring buffers.

    • kernel.kptr_restrict = 2: Hides kernel memory addresses from user space.

    • kernel.unprivileged_bpf_disabled = 1: Blocks unprivileged eBPF execution to prevent memory-sniffing vectors.

    • kernel.yama.ptrace_scope = 2: Restricts process tracing to administrative contexts.

Memory Optimization for Low-Resource Droplets

On 512MB instances, aggressive swap usage degrades network throughput. The framework sets:

  • vm.swappiness = 10: Instructs the kernel to keep active networking and transit buffers in physical RAM as long as possible.

  • vm.vfs_cache_pressure = 50: Retains directory and inode caches longer to minimize unnecessary disk IOPS.

5. Process Isolation with Custom AppArmor Profiles

While SELinux requires complex policy rebuilds that risk boot failure on standard cloud images, AppArmor provides profile-based mandatory access control (MAC) natively integrated into Ubuntu.

[ tailscaled Daemon ]
        │
        ├── ALLOW: Network Sockets (inet, dgram, raw)
        ├── ALLOW: /var/lib/tailscale/** , /dev/net/tun
        │
        └── DENY (Explicit): /bin/sh , /bin/bash execution

The script verifies AppArmor activation, imports system default profiles into strict enforcement mode, and writes a target policy for process execution.

tailscaled Isolation Policy Example

The custom profile permits necessary system capabilities (net_admin, net_raw, sys_module) and network socket creation while explicitly blocking shell execution vulnerabilities:

Code snippet

#include <tunables/global>

profile tailscaled /usr/sbin/tailscaled {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  capability net_admin,
  capability net_raw,
  capability sys_module,

  network inet stream,
  network inet dgram,
  network inet6 stream,
  network inet6 dgram,
  network raw,

  /var/lib/tailscale/** rw,
  /run/tailscale/** rw,
  /etc/tailscale/** r,
  /dev/net/tun rw,

  # Deny execution of unexpected administrative shells
  deny /bin/sh x,
  deny /bin/bash x,
}

6. Automated Defenses & Routine Auditing

System maintenance and automated intrusion prevention are handled natively without adding user management overhead:

  1. Intrusion Mitigation (Fail2ban): Monitors authentication vectors via systemd journal backend rules, banning repetitive unauthorized connection attempts for 24-hour periods.

  2. Antivirus Scanning (ClamAV): Installs the clamav-daemon engine, updates signatures automatically via freshclam, and schedules a non-persistent weekly scan via cron to inspect system binaries without retaining audit logs on disk.

  3. Patch Management: Configures unattended-upgrades to automatically install low-priority OS security patches directly from Ubuntu repositories.

Executing the Hardening Automation

The complete setup is encapsulated in a single, idempotent deployment script. Run the script on a fresh Ubuntu installation to configure the network, memory encryption, logging defaults, and mandatory access controls:

Bash

# Fetch and review the deployment script
nano harden-droplet.sh

# Grant execution rights
chmod +x harden-droplet.sh

# Execute hardening script with custom target hostname
sudo ./harden-droplet.sh cloud-node-01

By enforcing encrypted ephemeral swap, RAM-backed log paths, strict firewall bounds, and mandatory process isolation, Hardening Ubuntu Cloud Server deployments converts standard cloud droplets into resilient, zero-persistence infrastructure nodes.