Hetzner Bare Metal Setup: Custom RAID and Firewall Configuration

Hetzner dedicated servers require manual provisioning to achieve production-ready storage layouts and network security. The default automated installation does not support custom partition schemes or proper Docker firewall integration. This guide covers booting into rescue mode, deploying Ubuntu with multiple MD RAID arrays, and configuring both UFW and the Hetzner hardware firewall.

Prerequisites

The following items are required:

  • A Hetzner Robot account with access to a bare metal server
  • An SSH public key added to the Hetzner profile
  • Basic familiarity with Linux command line and software RAID

Boot into Rescue Mode

Hetzner provides a RAM-based rescue environment for OS installation and system recovery. Access the rescue system through the Robot control panel:

  1. Log in to the Hetzner Robot Dashboard
  2. Select the server from the Servers list
  3. Navigate to the Rescue tab
  4. Select Linux and 64-bit architecture
  5. Choose the SSH key for authentication
  6. Click Activate rescue system
  7. Navigate to the Reset tab and issue an Automatic Hardware Reset

The server will reboot into the rescue environment. Connect via SSH:

ssh root@YOUR_SERVER_IP -i <full path to certificate>

For example, if you a certificate named id_ed25519 (the default name for the certificate type), is expressed as such:

ssh root@172.16.30.130 -i ~/.ssh/id_ed25519

If all default settings were used in creating the certificate, then the default option should work.

Install Ubuntu with Custom RAID Arrays

The installimage tool automates OS deployment and software RAID configuration. It uses a text-based configuration file to define partition layouts and array parameters.

Launch the installer:

installimage

Select Ubuntu and the desired version. Ubuntu 26.04 LTS is current as of this writing. The configuration file will open in a text editor.

Configure Software RAID

Enable RAID 1 mirroring across two drives. For servers with /dev/sda and /dev/sdb:

DRIVE1 /dev/sda
DRIVE2 /dev/sdb

SWRAID 1
SWRAIDLEVEL 1

IMPORTANT: Remark out any drives that are not part of the boot layout. For example, if the server has two SSDs and two HDDs, remark out the HDDs in the installimage configuration. Installimage is for setting up boot drives, only. Other drives need tobe configured form the console.

Define Partition Layout

Replace the default PART section with a custom layout. This example creates separate arrays for boot, root, applications, and temporary files:

PART /boot ext4 2G
PART /     ext4 64G
PART /opt  ext4 300G
PART /tmp  ext4 all

The installimage tool creates the following MD devices:

  • /dev/md0 mounted at /boot (2GB)
  • /dev/md1 mounted at / (64GB)
  • /dev/md2 mounted at /opt (300GB)
  • /dev/md3 mounted at /tmp (remaining space)

Separating /opt and /tmp isolates container data and temporary files from the root filesystem. This prevents log or cache bloat from filling the system partition.

Save the configuration with F10. Confirm the destructive operation when prompted. The installer will partition the drives, create RAID arrays, install Ubuntu, and sync the initial mirror. Reboot when complete:

reboot

Post-Installation Updates

Log into the fresh Ubuntu installation and apply system updates. Install basic network and firewall utilities:

sudo apt update && sudo apt dist-upgrade -y
sudo apt install -y curl wget git net-tools ufw

Configure DNS Resolution

Ubuntu uses systemd-resolved for DNS lookups. The default configuration may cause slow resolution or timeouts when pulling container images. Configure reliable upstream DNS servers in /etc/systemd/resolved.conf:

[Resolve]
DNS=1.1.1.1 9.9.9.9
FallbackDNS=1.0.0.1 8.8.8.8
MulticastDNS=no
DNSSEC=allow-downgrade

Restart the resolver service:

sudo systemctl restart systemd-resolved

Configure UFW with Docker Integration

Docker modifies iptables directly and bypasses UFW rules by default. Published container ports become publicly accessible regardless of UFW configuration. The DOCKER-USER chain allows UFW rules to apply to container traffic without breaking container networking and this chain is, by default, considered first..

Enable UFW

Configure basic host firewall rules with UFW from the command line. Do not close the session. Once the rules are applied, open another session and be sure connection with SSH is possible.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH Access'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

sudo ufw enable

Configure Hetzner Hardware Firewall

Hetzner provides a stateless hardware firewall that filters traffic before it reaches the server network interface. The firewall has a hard limit of 10 rules per direction. Rules must be broad enough to cover necessary services while blocking common attack vectors.

Access the firewall configuration in Robot Dashboard under Server, then Firewall. Set the default inbound policy to Discard and configure the following rules:

PriorityNameProtocolSource IPDest PortActionPurpose
1Allow EstablishedTCPAnyAnyAcceptFlag: ACK (Return traffic)
2Allow ICMPICMPAnyAnyAcceptPath MTU discovery and ping
3Allow SSHTCPAny22AcceptHost management
4Allow HTTPTCPAny80AcceptWeb traffic and ACME challenges
5Allow HTTPSTCPAny443AcceptEncrypted web traffic
6Block LegacyTCPAny21,23,135-139,445,3389DiscardDrop unencrypted management protocols
7Block DatabaseTCPAny3306,5432,6379,27017DiscardShield database ports from scans

Save and apply the ruleset. The hardware firewall handles high-volume attacks and port scans before they consume CPU resources on the host. UFW provides per-service and per-container filtering on the host itself.

Hetzner limits this firewall to 10 rules. If more then 10 rules are required, some creativity may be needed; for example, it is possible to set the firewall to Allow mode, allowing all traffic through, but with only the valuable ports blocked.

Verification

Check RAID array status after the first boot:

cat /proc/mdstat

The output must looks something like this, with all drives included and [UU] to indicate the drives are part of the array and active.

Personalities : [raid1] 
md0 : active raid1 nvme0n1p1[1] nvme1n1p1[0]
      2094080 blocks super 1.2 [2/2] [UU]
      
md1 : active raid1 nvme1n1p2[0] nvme0n1p2[1]
      497876288 blocks super 1.2 [2/2] [UU]
      bitmap: 1/4 pages [4KB], 65536KB chunk

unused devices: <none>

Confirm the firewall is operating as expected. Check the setup:

sudo ufw status verbose

Confirm the hardware firewall rules are active in the Hetzner Robot panel. Test SSH access, then verify that blocked ports such as 3306 are not accessible from external networks, using a tool such as nmap:

sudo nmap -4 -p- -sS -Pn -T4 -v <IP address of your server>

AI assistance is used on this site for language, formatting, and turning research into a consistent template. It is not used to perform the underlying research or verify technical claims. Every command, configuration, and step in this post is tested by hand before publication.

Leave a Reply

Your email address will not be published. Required fields are marked *

3 × 4 =