Coolify: Self-Host Your Apps Like Vercel
Imagine having the flexibility of Vercel’s seamless deployments but running everything on your own hardware. That’s the promise of Coolify – a self‑hosted platform that abstracts away the complexity of Docker, CI/CD pipelines, and server management while giving you full control over your infrastructure. In this guide we’ll walk through what Coolify is, how to set it up, and how to deploy real‑world applications with it, all without sacrificing the developer experience you love.
What is Coolify?
Coolify is an open‑source, Docker‑based PaaS that mimics the developer‑friendly workflow of services like Vercel or Netlify. It provides a web UI, API, and CLI to manage projects, databases, and environment variables. Under the hood, Coolify spins up isolated containers for each app, handles SSL termination, and offers built‑in monitoring dashboards.
Because it runs on your own server—or a cheap VPS—you keep your code, data, and traffic private. It also means you can customize the stack (Node, Python, Ruby, Go, etc.) and integrate with existing services like PostgreSQL, Redis, or a private Docker registry.
Getting Started: Installing Coolify
The quickest way to try Coolify is via its official Docker Compose file. Make sure Docker Engine (≥ 20.10) and Docker Compose (v2) are installed on your host.
# Install Docker (Debian/Ubuntu example)
sudo apt-get update
sudo apt-get install -y docker.io docker-compose-plugin
# Verify installation
docker --version
docker compose version
Next, clone the Coolify repository and launch the stack. The script automatically pulls the latest images and creates a coolify network for isolation.
git clone https://github.com/coollabsio/coolify.git
cd coolify
# Start the stack in detached mode
docker compose up -d
After a minute, open http://YOUR_SERVER_IP in a browser. You’ll be prompted to create an admin account, set up a default domain (e.g., coolify.local), and optionally enable HTTPS via Let’s Encrypt.
Deploying Your First App: A Node.js Example
Coolify works with any language that can be containerized, but let’s start with a simple Express server to illustrate the workflow.
Step 1: Prepare the project
# project structure
my-express-app/
├─ Dockerfile
├─ package.json
└─ index.js
Create index.js with a basic route.
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000
app.get('/', (req, res) => {
res.send('Hello from Coolify! 🚀')
})
app.listen(PORT, () => console.log(`Server running on ${PORT}`))
And a minimal Dockerfile that Coolify will use to build the image.
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
Step 2: Connect to Coolify
Log into the Coolify UI, click “New Project”, and give it a name (e.g., express-demo). Under “Source”, choose “Git Repository” and paste the HTTPS URL of your repo. Coolify will automatically detect the Dockerfile, build the image, and expose port 3000.
Set the “Build & Deploy” trigger to “On Push” if you want automatic redeploys. Finally, click “Deploy”. In a few seconds you’ll see a live preview URL like https://express-demo.yourdomain.com.
Deploying a Static Site: Vercel‑like Experience
Static sites are the low‑hanging fruit for any PaaS. Coolify can serve them directly from an Nginx container without any extra configuration.
Project layout
my-static-site/
├─ public/
│ ├─ index.html
│ └─ styles.css
└─ coolify.yml
The coolify.yml file tells Coolify which builder to use. For static assets we use the built‑in static builder.
services:
web:
type: static
path: public
build:
command: ""
Push this repo to GitHub, add it as a new project in Coolify, and select “Static” as the service type. Coolify will copy the public folder into an Nginx container, automatically enable gzip compression, and issue a free SSL certificate.
Leveraging Docker Compose for Complex Stacks
Many real‑world applications require multiple services—databases, caches, background workers. Coolify supports a full Docker Compose definition, letting you spin up a multi‑container stack with a single click.
Example: A Flask API with PostgreSQL
flask-app/
├─ app/
│ ├─ __init__.py
│ └─ routes.py
├─ Dockerfile
├─ requirements.txt
└─ docker-compose.yml
The Dockerfile for the Flask service:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV FLASK_APP=app
ENV FLASK_RUN_HOST=0.0.0.0
EXPOSE 5000
CMD ["flask", "run"]
The docker-compose.yml defines both the Flask container and a PostgreSQL instance.
version: '3.8'
services:
web:
build: .
ports:
- "5000"
environment:
- DATABASE_URL=postgresql://postgres:example@db:5432/mydb
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=example
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Commit the repo, add it to Coolify, and select “Docker Compose” as the deployment type. Coolify will parse the compose file, provision the two containers, and expose the Flask API on a public URL. You can now connect to the database using the DATABASE_URL environment variable inside your Flask code.
Managing Environment Variables Securely
Environment variables are the preferred way to store secrets, API keys, and configuration values. Coolify provides a UI to add them per project, and they are injected into each container at runtime.
- Navigate to your project → “Settings” → “Environment Variables”.
- Click “Add Variable”, give it a name (e.g.,
API_KEY), and paste the secret value. - Mark the variable as “Protected” to hide it from logs and UI displays.
In your code, retrieve the variable as you normally would. For the Flask example above, the DATABASE_URL is already set via the compose file, but you could also add a secret like SECRET_KEY from the UI.
import os
secret_key = os.getenv('SECRET_KEY')
Custom Domains & Automatic SSL
One of the biggest advantages of Vercel is the effortless custom domain binding. Coolify replicates this with a few clicks.
- In the project dashboard, click “Add Domain”.
- Enter your domain (e.g.,
app.example.com) and verify ownership via a DNS TXT record. - Once verified, Coolify will request a Let’s Encrypt certificate and configure Nginx to serve your app over HTTPS.
All traffic is terminated at the edge, then proxied to your internal container over a secure Docker network. This setup eliminates the need for a separate reverse proxy like Traefik.
Scaling, Monitoring, and Logs
Coolify includes built‑in metrics that let you monitor CPU, memory, and network usage per container. The “Metrics” tab shows real‑time graphs, and you can set alerts for thresholds.
For scaling, you can increase the replica count of any service directly from the UI. Coolify will spin up additional containers behind a load balancer, ensuring zero‑downtime deployments.
Logs are aggregated per service and can be filtered by date or severity. Use the “Logs” tab to debug issues without SSH‑ing into the host.
Pro Tip: Enable “Log Persistence” in Settings → “Advanced” to store logs on a mounted volume. This way, logs survive container restarts and are available for long‑term analysis.
Real‑World Use Cases
1. Internal Dashboards – Companies often need private dashboards for analytics or admin panels. With Coolify, you can host these behind your corporate VPN, enforce SSO via environment variables, and keep all data in‑house.
2. SaaS Prototypes – When building a SaaS MVP, you want fast iteration without managing Kubernetes. Coolify’s one‑click deploy and auto‑SSL let you focus on product features while still offering a polished URL to early users.
3. Legacy App Modernization – Older monolithic apps can be containerized and managed through Coolify, giving you the ability to roll out updates, scale components independently, and retire legacy servers gradually.
Pro Tips & Best Practices
- Use a Separate Docker Network for each project to avoid port collisions and improve security.
- Pin Base Images in your Dockerfiles (e.g.,
node:20-alpine@sha256:...) to guarantee reproducible builds.- Leverage Multi‑Stage Builds to keep images small and reduce attack surface.
- Backup the Coolify Database (SQLite or MySQL) regularly; it stores project metadata and secrets.
- Enable Auto‑Scaling only for stateless services; stateful services like databases should be managed separately.
Advanced Customization: Adding Your Own Buildpacks
Coolify ships with a set of default builders (Node, Python, Ruby, etc.). If you need a custom runtime—say, a Go binary with a specific OS version—you can add a custom buildpack.
# Directory: .coolify/buildpacks/go
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY . .
RUN go build -o /app/main .
FROM alpine:3.19
COPY --from=builder /app/main /usr/local/bin/app
EXPOSE 8080
CMD ["app"]
Commit the .coolify/buildpacks/go/Dockerfile to your repository and reference it in coolify.yml:
services:
web:
type: custom
buildpack: .coolify/buildpacks/go
ports:
- "8080"
Coolify will use this custom Dockerfile for building the service, giving you full control over the environment.
Running Migrations and One‑Off Tasks
Many applications require database migrations or background jobs that run only once. Coolify offers a “One‑Off Command” feature that executes a command inside a temporary container based on your project’s image.
- Navigate to “Actions” → “Run Command”.
- Enter the command (e.g.,
python manage.py migratefor Django). - Choose the service you want to target and click “Execute”.
The command runs in an isolated container, ensuring it doesn’t interfere with the running app. Logs are displayed in real time, and you can abort if needed.
Backup and Disaster Recovery
Because Coolify runs on your own hardware, you’re responsible for backups. The simplest strategy is to snapshot the host’s volume that stores the Docker data directory (/var/lib/docker) and the Coolify database.
# Example using rsync for daily backup
rsync -a --delete /var/lib/docker /backup/docker
rsync -a /opt/coolify/db.sqlite /backup/coolify/
Automate this with a cron job and store the backups off‑site (e.g., S3 or another VPS). In a disaster scenario, you can reinstall Docker, restore the volumes, and start the Coolify stack with docker compose up -d.
Conclusion
Coolify bridges the gap between the convenience of serverless platforms like Vercel and the control of self‑hosted infrastructure. By abstracting Docker, CI/CD, SSL, and scaling into a clean UI, it empowers developers to ship apps faster while keeping data and costs under their own roof. Whether you’re building a personal portfolio, a SaaS prototype, or an internal dashboard, Coolify gives you the tools to deploy, monitor, and scale with confidence. Give it a spin on a spare VPS, experiment with multi‑service stacks, and enjoy the freedom of truly owning your deployment pipeline.