Self-Hosting with Coolify and Hetzner
TOP 5 Dec. 31, 2025, 11:30 p.m.

Self-Hosting with Coolify and Hetzner

Self‑hosting your own web services can feel like stepping into a secret club where you control every knob, from performance tuning to cost‑saving tricks. With Coolify’s sleek Docker‑orchestrated UI and Hetzner’s rock‑solid, budget‑friendly servers, you get a powerful combo that rivals big‑cloud providers without the “pay‑as‑you‑go surprise”. In this guide we’ll walk through provisioning a Hetzner cloud instance, installing Coolify, and deploying a real‑world Python app—all while sprinkling in pro tips to keep your stack secure and efficient.

Why Self‑Hosting Matters in 2025

Even though serverless platforms dominate headlines, many developers still crave full control over their runtime environment. Self‑hosting eliminates vendor lock‑in, lets you fine‑tune resource allocation, and often reduces monthly bills dramatically. Moreover, with GDPR and data‑sovereignty regulations tightening, keeping data on a European provider like Hetzner can simplify compliance.

Coolify adds a layer of abstraction that makes Docker feel like a drag‑and‑drop canvas rather than a command‑line maze. It bundles CI/CD pipelines, automatic SSL, and a built‑in monitoring dashboard—all essential for production‑grade deployments.

Meet the Players: Coolify & Hetzner

Coolify at a Glance

  • Open‑source, Docker‑native PaaS with a clean web UI.
  • Supports multiple services: web apps, databases, workers, and static sites.
  • One‑click SSL via Let’s Encrypt and built‑in health checks.

Why Hetzner?

  • Data centers in Germany, Finland, and South Africa—great latency for European users.
  • Transparent pricing (e.g., a CX31 server starts at €7.49/month).
  • Robust API for automated server provisioning.

Provisioning Your Hetzner Cloud Server

Start by creating a Hetzner account and generating an API token. The token will be used later for automated provisioning, but you can also spin up a server manually via the Hetzner Cloud Console.

import requests, json

API_TOKEN = "YOUR_HETZNER_TOKEN"
HEADERS = {"Authorization": f"Bearer {API_TOKEN}", "Content-Type": "application/json"}

payload = {
    "name": "coolify-node",
    "server_type": "cx31",          # 2 vCPU, 4 GB RAM
    "image": "ubuntu-22.04",
    "location": "nbg1",            # Nuremberg
    "ssh_keys": ["your-ssh-key-id"]
}

response = requests.post(
    "https://api.hetzner.cloud/v1/servers",
    headers=HEADERS,
    data=json.dumps(payload)
)

print(response.json())

The script creates a 2‑CPU, 4 GB RAM instance—perfect for a small‑to‑medium Coolify deployment. Once the server is up, note its public IP; you’ll need it for SSH access and DNS configuration.

Preparing the Server: Docker & Essentials

Coolify runs entirely on Docker, so the first step is to install Docker Engine and Docker Compose. Hetzner’s Ubuntu images ship with snap, making the installation straightforward.

#!/usr/bin/env bash
set -e

# Update and install prerequisites
sudo apt-get update && sudo apt-get install -y \
    ca-certificates curl gnupg lsb-release

# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Set up the stable repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine and Compose plugin
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Verify installation
docker --version
docker compose version

Run the script via ssh root@YOUR_IP 'bash -s' < install_docker.sh. After it finishes, add your non‑root user to the docker group to avoid sudo for every command.

Pro tip: Enable Docker’s experimental features (e.g., BuildKit) by adding {"features":{"buildkit":true}} to /etc/docker/daemon.json and restarting the daemon.

Deploying Coolify with Docker Compose

Coolify provides a ready‑made Docker Compose file that pulls all required services (Coolify UI, Redis, Postgres, and a built‑in proxy). Create a directory on your server and fetch the compose file.

mkdir -p ~/coolify && cd ~/coolify
curl -O https://raw.githubusercontent.com/coollabsio/coolify/master/docker-compose.yml

Before launching, edit the environment variables to set a strong admin password and configure your domain.

# .env (partial)
COOLIFY_ADMIN_EMAIL=admin@example.com
COOLIFY_ADMIN_PASSWORD=SuperSecret123!
COOLIFY_DOMAIN=app.example.com

Now spin up the stack:

docker compose up -d

Coolify’s UI should be reachable at http://YOUR_IP:3000. Log in with the admin credentials you defined, and you’ll be greeted by a clean dashboard ready for app deployments.

Connecting Your Domain & Enabling SSL

Point your domain’s A record to the Hetzner server’s IP. In Coolify, navigate to Settings → Domains, add app.example.com, and click “Enable SSL”. Coolify automatically requests a Let’s Encrypt certificate and configures the built‑in Nginx proxy.

If you prefer to manage DNS via Hetzner’s DNS Console, the steps are identical—just add an A record under your domain zone.

Pro tip: Use a CNAME record for sub‑domains (e.g., api.example.com) pointing to the root domain. This way you only need to renew the SSL certificate once.

Deploying a Real‑World Python Flask App

To showcase Coolify’s CI/CD pipeline, we’ll deploy a simple Flask API that returns the current server time. Create a new GitHub repository with the following structure:

  • app.py – Flask application
  • requirements.txt – Python dependencies
  • Dockerfile – Build instructions
# app.py
from flask import Flask, jsonify
from datetime import datetime

app = Flask(__name__)

@app.route('/time')
def get_time():
    return jsonify({
        'server_time': datetime.utcnow().isoformat() + 'Z'
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
# requirements.txt
Flask==3.0.2
# Dockerfile
FROM python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

Push the repo to GitHub, then in Coolify click “Add New Project”, select “Git Repository”, paste the repo URL, and choose the Dockerfile as the build context. Coolify will clone the repo, build the image, and spin up a container automatically.

After deployment, navigate to https://app.example.com/time. You should see a JSON payload with the current UTC time, proving that your pipeline works end‑to‑end.

Monitoring, Logs, and Backups

Coolify ships with a lightweight monitoring dashboard that shows CPU, memory, and network usage per service. For deeper insights, enable Prometheus and Grafana via the “Add‑on” section. This gives you time‑series graphs and alerting capabilities.

Database backups are critical. Coolify can schedule daily snapshots of the internal Postgres instance. In the UI, go to Databases → Backup Settings**, set a retention policy (e.g., keep last 7 backups), and choose an S3‑compatible bucket for off‑site storage.

Pro tip: Hetzner offers “Volume Snapshots” at a low cost. Combine them with Coolify’s internal backups for a two‑layer disaster recovery strategy.

Scaling & Advanced Features

When traffic spikes, you can horizontally scale your Flask service by increasing the replica count in the service definition. In Coolify, edit the service, set “Replicas” to 3, and the platform will spin up additional containers behind the built‑in load balancer.

For background workers, Coolify supports “Queue Workers” that run alongside your web containers. Add a Redis service, then create a worker that pulls jobs from a queue—perfect for email sending, image processing, or long‑running tasks.

Security Best Practices

  • Firewall: Use Hetzner’s Cloud Firewall to allow only ports 22 (SSH), 80/443 (HTTP/HTTPS), and 3000 (Coolify UI) from trusted IPs.
  • SSH Keys: Disable password authentication; enforce key‑based login.
  • Automatic Updates: Enable unattended upgrades on Ubuntu to keep the OS patched.
  • Docker Secrets: Store sensitive env vars (API keys, DB passwords) as Docker secrets instead of plain text.

Cost Optimization on Hetzner

Hetzner’s pricing is linear, but you can still shave dollars by right‑sizing your instance. Monitor average CPU load; if it stays below 30 % for a week, consider downgrading to a CX21. Conversely, use “Floating IPs” to quickly failover to a backup server without downtime.

Take advantage of Hetzner’s “Server Reset” feature to snapshot a clean OS image after you’ve hardened the machine. Future deployments can clone from this image, saving hours of setup time.

Real‑World Use Cases

1. SaaS MVP Launch

A two‑person startup used Coolify + Hetzner to launch a subscription‑based analytics dashboard. They saved >80 % on infrastructure compared to AWS Elastic Beanstalk, while still having CI/CD, auto‑SSL, and daily DB backups out of the box.

2. Internal Tooling for Enterprises

An enterprise IT team migrated legacy PHP tools to Docker containers managed by Coolify. The centralized UI gave them visibility across dozens of micro‑services, and Hetzner’s private networks ensured low‑latency communication between services.

3. Edge‑Computing Node

Developers building IoT gateways deployed Coolify on Hetzner’s Frankfurt data center, exposing a lightweight API that aggregates sensor data. The ability to run custom Docker images meant they could push OTA updates without touching the underlying OS.

Pro Tips & Common Pitfalls

Tip 1 – Use a Dedicated Non‑Root User. Create coolify user, add to docker group, and run all commands under that account. This reduces the blast radius if the UI is compromised.
Tip 2 – Keep Your Docker Images Small. Use python:3.12-slim as the base and clean up caches in the Dockerfile. Smaller images mean faster builds and less storage consumption.
Common Pitfall – Forgetting to Open Port 443. If the firewall blocks HTTPS, Let’s Encrypt validation will fail. Double‑check the Cloud Firewall rules after provisioning.

Next Steps: Automation & CI Integration

Now that you have a manual workflow, consider automating the entire pipeline with GitHub Actions. A simple workflow can SSH into the Hetzner server, pull the latest code, and trigger a Coolify redeploy via its API.

# .github/workflows/deploy.yml
name: Deploy to Coolify

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: SSH and redeploy
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.HETZNER_IP }}
          username: coolify
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd ~/coolify
            docker compose pull
            docker compose up -d --force-recreate

Commit this file, push to GitHub, and watch your app redeploy automatically on every push. The combination of Coolify’s UI and GitHub Actions gives you a full DevOps loop without writing a custom orchestrator.

Conclusion

Self‑hosting with Coolify on Hetzner gives you a production‑grade platform that’s both affordable and highly customizable. You gain the freedom to tweak every layer—from the OS kernel to the Docker networking stack—while still benefiting from a polished UI, automatic SSL, and built‑in monitoring. By following the steps above, you’ll have a robust environment ready for SaaS launches, internal tooling, or edge‑computing projects, all backed by a European provider that respects your data and your budget.

Share this article