Deployment

Server Setup

Minimal host preparation for Kamal and accessories.

Goal

Prepare one Hetzner server so Kamal can run app, Postgres, Redis, and backup containers.

Step 0: Provision resources in Hetzner

Before host configuration, provision required infrastructure in Hetzner Cloud:

  • Create and pay for at least one server in your target region.
  • Provision a Volume if you need persistent app/database storage.
  • Provision Object Storage and create a bucket if you plan to store uploads or database backups.

Step 1: Base host setup

Run on server:

apt update && apt upgrade -y
apt install -y docker.io curl git

After base updates, disable SSH password authentication and keep SSH key authentication only. Edit /etc/ssh/sshd_config and set PasswordAuthentication no (or uncomment the line and change it to no).

Step 2: Prepare persistent volume mount

Use your Hetzner volume and mount it, for example to /mnt/main-volume.

Preferred option (automatic):

  • Use Hetzner Cloud Console and attach/mount the volume with automatic configuration.
  • This is the safest default for most teams.

Manual option:

  • If you configure manually, you must:
    • format the volume filesystem
    • mount the volume to your target path
    • add persistent mount entry in /etc/fstab
  • Follow Hetzner guide: Creating and mounting a volume

This guide uses paths:

  • /mnt/main-volume/example-app/postgres-data
  • /mnt/main-volume/example-app/redis-data

Create directories:

mkdir -p /mnt/main-volume/example-app/postgres-data
mkdir -p /mnt/main-volume/example-app/redis-data

Step 3: Open required ports

  • 22 for SSH
  • 80 and 443 for Kamal proxy

Configure this in Hetzner Cloud UI in the server Firewall tab. Allow inbound TCP only for ports 22, 80, and 443.

Notes

  • This page is intentionally short. You can expand hardening and monitoring later.
  • In this example, accessory data is mapped to /mnt/main-volume/... in config/deploy.yml.

Verify

  • Docker is running: docker ps
  • Mount exists: df -h | grep /mnt/main-volume
  • Data directories exist: ls -la /mnt/main-volume/example-app

On this page