Coolify: Self-Hosted Heroku Alternative for Deploying Apps
Why Coolify Beats a Manual Docker Stack for Homelab Deployments
You've got your homelab running, but deploying applications still requires SSH, manual docker-compose files, and remembering which container needs which environment variable. Coolify is a self-hosted PaaS that eliminates that friction—it's Heroku's deployment experience running on your own hardware, with Git webhooks, automatic database provisioning, and SSL certificates handled automatically.
This post walks you through installing Coolify 4.x on a production homelab server, configuring it for Git auto-deployment, and spinning up your first application with a managed PostgreSQL database and HTTPS. You'll have a functioning self-hosted PaaS in under 30 minutes.
Prerequisites and System Requirements
Software versions tested:
- Coolify 4.5.4 (latest stable)
- Docker 26.1.3 with Docker Compose 2.29.2
- Ubuntu 24.04.1 LTS (also tested on Debian 12)
- Git 2.43+ (for webhook support)
Hardware minimum: 4GB RAM, 20GB free disk space. On my T5810 with 24GB RAM running Ubuntu 24.04, Coolify idles at ~300MB memory.
Network requirements:
- Static IP or DDNS pointing to your homelab server
- Ports 80, 443 open (Coolify proxies all deployments through these)
- Port 3000 accessible internally (Coolify dashboard)
- Outbound HTTPS to Docker Hub or your private registry
Optional but strongly recommended: A domain you control (for SSL certificates via Let's Encrypt).
Installing Coolify with Docker Compose
Coolify ships as a single Docker container that manages everything—the API, dashboard, and orchestration. Installation is one command, but the setup file needs adjustment for homelab DNS.
First, create a dedicated directory and pull the official docker-compose file:
mkdir -p ~/coolify && cd ~/coolify
curl -fsSL https://get.coollabs.io/docker-compose.yml -o docker-compose.yml
Open the compose file and make these edits:
version: '3.8'
services:
coolify:
image: ghcr.io/coollabsio/coolify:latest
container_name: coolify
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "3000:3000"
environment:
- COOLIFY_SECRET_ENCRYPTION_KEY=your-random-32-char-key-here
- COOLIFY_DATABASE_URL=postgresql://coolify:coolify@postgres:5432/coolify
- COOLIFY_FQDN=coolify.yourdomain.com
- [email protected]
- COOLIFY_AUTO_UPDATE=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- coolify:/data
depends_on:
- postgres
postgres:
image: postgres:16-alpine
container_name: coolify-postgres
restart: unless-stopped
environment:
POSTGRES_USER: coolify
POSTGRES_PASSWORD: coolify
POSTGRES_DB: coolify
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
coolify:
postgres_data:
Critical gotcha: The `COOLIFY_SECRET_ENCRYPTION_KEY` must be exactly 32 characters. Generate one with:
openssl rand -base64 32 | head -c 32
Replace `coolify.yourdomain.com` with your actual domain (or use a subdomain). The `COOLIFY_FQDN` variable tells Coolify how external users will reach it—this affects SSL certificate generation.
Start the stack:
docker compose up -d
docker compose logs -f coolify # Monitor startup
Coolify takes 30-60 seconds to initialize the database and start the dashboard. Wait for the log line: `Coolify started on...`
Configuring Coolify: Initial Setup and Git Integration
Once running, access the dashboard at `http://your-homelab-ip:3000` (or `https://coolify.yourdomain.com` if DNS is already pointing there). You'll land on the onboarding screen.
First-time setup:
- Create an admin account (this is local, not cloud-based)
- Accept the terms
- Choose your default Docker host (local socket is pre-configured)
After onboarding, navigate to Settings → Git Providers to enable automatic deployments from GitHub, GitLab, or Gitea. For GitHub, you'll need a Personal Access Token:
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Create a token with scopes: `repo`, `admin:repo_hook`
- Paste the token into Coolify's GitHub integration screen
This enables Coolify to read your repos and set up webhooks automatically.
Deploying Your First Application with Auto-Git Sync
Now deploy an application. Create a new project: Projects → New Project.
In the project, create a new application: Add Service → Application.
Fill in the details:
- Name: my-app
- Repository: Select from GitHub (if integrated) or paste a Git URL
- Branch: main
- Build Pack: Auto-detect (Coolify reads Dockerfile or buildpack.yml)
- Port: 3000 (or whatever your app listens on)
- Domains: myapp.yourdomain.com
Under Deployment Triggers, enable Automatic deployment on push. Coolify creates a webhook in your Git provider—every push to your branch triggers a rebuild.
Click Deploy. Coolify pulls the repo, builds the image, and starts the container. Watch the logs in real-time from the dashboard.
Gotcha: Coolify assumes your app listens on `0.0.0.0` (not `localhost`). If your Node.js app has `server.listen('localhost', port)`, it won't be reachable. Use environment variables to make it configurable:
const host = process.env.HOST || '0.0.0.0';
const port = process.env.PORT || 3000;
server.listen(port, host);
Adding a Managed PostgreSQL Database
Most applications need persistent data. Coolify provisions databases alongside apps. In your project, click Add Service → PostgreSQL.
Name: postgres-prod
Root Password: [auto-generate strong password]
Initial Database: app_production
Expose Port: 5432 (on localhost only)
Coolify spins up a PostgreSQL container and exposes connection details. Link it to your application by adding environment variables:
DATABASE_URL=postgresql://postgres:PASSWORD@postgres-prod:5432/app_production
Set these in your app's Environment tab. On the next deployment (or manual restart), your app connects to the database.
For backups, Coolify includes automated snapshots. Configure in Project Settings → Backups to store snapshots on NAS or external storage.
SSL Certificates and Custom Domains
Coolify handles SSL automatically if you've set `COOLIFY_FQDN` to a real domain and `COOLIFY_LETS_ENCRYPT_EMAIL` is valid. Point your DNS to your homelab IP:
myapp.yourdomain.com A 192.168.1.50
Wait 5 minutes for DNS propagation, then restart Coolify:
docker compose restart coolify
Coolify requests a certificate from Let's Encrypt automatically. Check Application Settings → Domains to verify the certificate status. Once provisioned, HTTPS is enabled with zero additional config.
For internal-only deployments: If you don't have a public domain, use a self-signed certificate or skip HTTPS and rely on your firewall. This is fine for homelab—just document it.
Common Issues and Troubleshooting
Issue: Deployment fails with "Port already in use"
Coolify assigns ports dynamically to containers. If you're running other services on your homelab, conflicts occur. Check with:
docker ps -a | grep -E "0.0.0.0"
netstat -tlnp | grep LISTEN
Either free the port or configure Coolify to use a different port range in Settings → Docker.
Issue: Git webhook fires but deployment doesn't start
Verify the webhook payload reaches Coolify by checking the application logs:
docker compose logs coolify | grep webhook
If nothing appears, confirm your firewall allows inbound HTTP/HTTPS from your Git provider. Test manually by pushing to a branch and monitoring the dashboard.
Issue: SSL certificate not renewing after 30 days
Let's Encrypt certificates expire after 90 days. Coolify should renew automatically 30 days before expiry. If it doesn't, check that your `COOLIFY_LETS_ENCRYPT_EMAIL` is correct and restart the Coolify container to trigger renewal:
docker compose restart coolify
docker compose logs coolify | grep -i "certificate"
Issue: Database connection timeout from application
Ensure the database container is running and the hostname resolves correctly. From your app container, test:
docker exec my-app ping postgres-prod
docker exec my-app curl -v postgres-prod:5432
If ping fails, the containers aren't on the same Docker network. Coolify automatically puts services in the project network—verify with `docker network ls` and `docker network inspect`.
What You Now Have
You've deployed a fully functional self-hosted PaaS that handles the tedium: automatic Git deployments, managed databases, SSL certificates, and a web dashboard to manage everything. No more SSH into servers, manually running docker-compose, or wrestling with certificate renewal.
Next steps:
- Deploy a few test applications to lock in the workflow
- Configure automated backups to an external location
- Set up resource monitoring and alerts if you have multiple apps
- Explore pre-built services like Redis, MongoDB, or Stripe webhooks
Coolify transforms your homelab from a hobby infrastructure into something that feels production-grade. For homelabbers running 5-10 applications, it's the sweet spot between full Kubernetes complexity and manual container management.