Deploying Self Hosted Coolify on Linux Server

Deploying Self Hosted Coolify on Linux Server

What You’ll Need

  • A clean Linux VPS (Ubuntu 22.04 LTS or 24.04 LTS recommended) hosted on Hetzner VPS or Contabo VPS (alternatively, use DigitalOcean )
  • A root or sudo-enabled user account with SSH key authentication set up
  • A custom domain managed through Namecheap with access to DNS records
  • n8n Cloud or a self-hosted instance for external deployment notifications
  • Make.com if comparing visual cloud orchestrators alongside self-hosted alternatives

Table of Contents


Architecture Overview & Server Preparation

Coolify is an open-source, self-hosted alternative to Heroku, Netlify, and Render. It sits directly on top of your Linux host, taking control of Docker Engine, a Caddy reverse proxy, an internal PostgreSQL database for state storage, and a automated deployment daemon.

Before running the installation script on a fresh instance from Hetzner VPS , we must prepare the kernel, set proper open file limits, and lock down unnecessary network access through Uncomplicated Firewall (UFW).

#!/usr/bin/env bash
set -euo pipefail

# Update system packages to the latest stable state
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y curl wget git jq ufw ca-certificates gnupg lsb-release

# Configure kernel tuning parameters for high-concurrency Docker workloads
cat << 'EOF' | sudo tee /etc/sysctl.d/99-coolify.conf
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 2048
vm.max_map_count = 262144
fs.file-max = 2097152
EOF

sudo sysctl --system

# Set up UFW firewall rules
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 Web Traffic'
sudo ufw allow 443/tcp comment 'HTTPS Web Traffic'
sudo ufw allow 8000/tcp comment 'Coolify Dashboard Interface'

# Enable firewall without interactive prompt
sudo ufw --force enable

The sysctl configurations ensure your server won’t crash when running multiple isolated containers that perform memory-intensive operations, such as building Docker images locally or maintaining open WebSocket connections across thousands of concurrent clients.


Installing Coolify Engine via Direct Shell Scripts

Coolify requires modern versions of Docker and Docker Compose (v2). While Coolify provides an automated install script, production environments demand explicit configuration of the Docker daemon before engine initialization. This prevents container log files from consuming all disk space and optimizes container routing performance.

First, let me create the optimal /etc/docker/daemon.json configuration file on the Hetzner VPS or DigitalOcean droplet.

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  },
  "live-restore": true,
  "userland-proxy": false,
  "dns": ["1.1.1.1", "8.8.8.8"],
  "storage-driver": "overlay2"
}

Save this file using the bash terminal:

sudo mkdir -p /etc/docker
cat << 'EOF' | sudo tee /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  },
  "live-restore": true,
  "userland-proxy": false,
  "dns": ["1.1.1.1", "8.8.8.8"],
  "storage-driver": "overlay2"
}
EOF

Now, execute the official installation script. This script detects the system architecture, installs official Docker binaries if missing, configures the engine directories inside /data/coolify, and starts the core services:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

Once executed, verify that all core administrative containers are up and running cleanly on your machine:

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

You will see output listing coolify, coolify-db, coolify-proxy (Caddy), and coolify-realtime.

💡 Fast-Track Your Project: Don’t want to configure this yourself? I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.


Configuring Domain, Custom SSL, and GitHub Webhooks

Navigate to your DNS dashboard on Namecheap and set up two DNS A records pointing directly to your VPS IP address:

  1. coolify.yourdomain.com -> YOUR_SERVER_IP
  2. *.apps.yourdomain.com -> YOUR_SERVER_IP

The wildcard entry ensures that every new application deployed through Coolify automatically gets an isolated, SSL-secured domain name without manually touching DNS zone files every time.

Open your browser and visit http://YOUR_SERVER_IP:8000 to set up your primary root user account. Complete the onboarding wizard, enter https://coolify.yourdomain.com inside Settings -> Server Configuration, and activate Caddy auto-TLS SSL acquisition.

To trigger deployments automatically whenever code pushes to a repository, connect GitHub webhooks. Generate a dedicated Deployment Key or Personal Access Token in GitHub, then register it within Coolify under Keys & Tokens.

If you build developer tools, you can pair continuous deployment hooks with automated alerts. For instance, I like Building Telegram Bots for Workflow Management to receive instant deployment success or build failure messages straight to my mobile device.

To verify build notifications on your host system without relying on web interfaces, save this custom shell payload trigger script:

#!/usr/bin/env bash
set -euo pipefail

COOLIFY_API_TOKEN="your_generated_coolify_api_token_here"
COOLIFY_INSTANCE_URL="https://coolify.yourdomain.com"
DEPLOYMENT_UUID="app_uuid_from_coolify_dashboard"

echo "Triggering automated build for App UUID: ${DEPLOYMENT_UUID}..."

RESPONSE_CODE=$(curl -s -o /tmp/coolify_deploy_response.json -w "%{http_code}" \
  -X POST "${COOLIFY_INSTANCE_URL}/api/v1/deploy?uuid=${DEPLOYMENT_UUID}" \
  -H "Authorization: Bearer ${COOLIFY_API_TOKEN}" \
  -H "Content-Type: application/json")

if [ "${RESPONSE_CODE}" -eq 200 ] || [ "${RESPONSE_CODE}" -eq 201 ]; then
  echo "Deployment successfully initiated!"
  cat /tmp/coolify_deploy_response.json | jq .
else
  echo "Deployment failed with status code ${RESPONSE_CODE}"
  cat /tmp/coolify_deploy_response.json
  exit 1
fi

Production Hardening, Backup Automation, and Disaster Recovery

Relying solely on local Docker state is risky for production deployments. Coolify stores all user configurations, environment variables, server connection states, and app metadata inside an isolated internal PostgreSQL database container named coolify-db.

We need an automated, scheduled offsite backup script that dumps this internal state, encrypts it, and uploads it securely. When comparing data replication methods, reading about Temporal vs Airflow for API-First Automation or Airbyte vs n8n vs Temporal for API data pipelines helps clarify how offsite pipeline scheduling operates at scale.

Here is a automated backup script saved to /usr/local/bin/backup-coolify.sh:

#!/usr/bin/env bash
set -euo pipefail

TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/var/backups/coolify"
BACKUP_FILE="${BACKUP_DIR}/coolify_db_${TIMESTAMP}.sql.gz"
RETENTION_DAYS=7

mkdir -p "${BACKUP_DIR}"

echo "[${TIMESTAMP}] Starting Coolify PostgreSQL database backup..."

# Execute pg_dump directly inside the running container
docker exec coolify-db pg_dump -U coolify -d coolify | gzip -9 > "${BACKUP_FILE}"

if [ -s "${BACKUP_FILE}" ]; then
  echo "[${TIMESTAMP}] Backup completed successfully: ${BACKUP_FILE}"
  chmod 600 "${BACKUP_FILE}"
else
  echo "[${TIMESTAMP}] ERROR: Backup file was created but is empty!"
  exit 1
fi

# Clean up local backups older than retention window
echo "Cleaning up local backups older than ${RETENTION_DAYS} days..."
find "${BACKUP_DIR}" -type f -name "coolify_db_*.sql.gz" -mtime +${RETENTION_DAYS} -delete

echo "Backup cycle completed successfully."

Make the script executable:

sudo chmod +x /usr/local/bin/backup-coolify.sh

Now, create a Systemd service and timer to automate this backup every night at 2:00 AM UTC without relying on external cron configurations.

Create /etc/systemd/system/coolify-backup.service:

[Unit]
Description=Coolify Database Automated Backup Service
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-coolify.sh
User=root
StandardOutput=journal
StandardError=journal

Create /etc/systemd/system/coolify-backup.timer:

[Unit]
Description=Run Coolify Database Backup daily at 2:00 AM UTC

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Reload systemd daemon, enable, and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now coolify-backup.timer
sudo systemctl status coolify-backup.timer

Verify that the service works manually by running a single invocation test:

sudo systemctl start coolify-backup.service
sudo journalctl -u coolify-backup.service --no-pager -n 20

Getting Started

Self-hosting Coolify provides absolute control over your deployment infrastructure while completely avoiding expensive per-seat PaaS pricing models. By hosting on reliable providers like Hetzner VPS , Contabo VPS , or DigitalOcean , and setting up custom domains via Namecheap , you gain a enterprise-grade engine ready for production code. For webhooks and workflow orchestration, combine Coolify with n8n Cloud to build end-to-end continuous integration pipelines.

Outsource Your Automation

Don’t have time? I build production n8n workflows, WhatsApp bots, and fully automated YouTube Shorts pipelines. Hire me on Fiverr — mention SYS3-HUGO for priority. Or DM at chasebot.online .

Want to automate this yourself?

Start with n8n Cloud (free tier available) or self-host on a Hetzner VPS for full control.

Want this engine running on your own VPS?

This blog publishes itself — daily, unattended, on free API tiers. The full engine, Hugo theme, and setup guide are available as System 3.

Get System 3
system online