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:
- Log in to the Hetzner Robot Dashboard
- Select the server from the Servers list
- Navigate to the Rescue tab
- Select Linux and 64-bit architecture
- Choose the SSH key for authentication
- Click Activate rescue system
- 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_ed25519If 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:
installimageSelect 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 1IMPORTANT: 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 allThe 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:
rebootPost-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 ufwConfigure 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-downgradeRestart the resolver service:
sudo systemctl restart systemd-resolvedConfigure 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 enableConfigure 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:
| Priority | Name | Protocol | Source IP | Dest Port | Action | Purpose |
|---|---|---|---|---|---|---|
| 1 | Allow Established | TCP | Any | Any | Accept | Flag: ACK (Return traffic) |
| 2 | Allow ICMP | ICMP | Any | Any | Accept | Path MTU discovery and ping |
| 3 | Allow SSH | TCP | Any | 22 | Accept | Host management |
| 4 | Allow HTTP | TCP | Any | 80 | Accept | Web traffic and ACME challenges |
| 5 | Allow HTTPS | TCP | Any | 443 | Accept | Encrypted web traffic |
| 6 | Block Legacy | TCP | Any | 21,23,135-139,445,3389 | Discard | Drop unencrypted management protocols |
| 7 | Block Database | TCP | Any | 3306,5432,6379,27017 | Discard | Shield 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/mdstatThe 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 verboseConfirm 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.