VPS Tutorials
Building a Coolify Self-Hosted Deployment Platform on a VPS (2026): Docker, Git Auto-Deploy, Traefik HTTPS, and Backup Pitfalls Guide
This tutorial explains how to self-host Coolify on a VPS and turn an ordinary server into a deployment platform similar to Vercel, Heroku, or Railway. It covers VPS spec selection, the official install script, ports and domains, Traefik automatic HTTPS, Git repository deployment, environment variables, database services, backup and upgrades, security hardening, and common 502, SSL, and build failure issues.
I don't really like dumping all my small projects onto a pile of different platforms anymore.
One Next.js project on Vercel, one backend on Railway, one database on Supabase, plus a Redis and a cron job. At first it really does save effort, but once projects pile up, billing, environment variables, domains, logs, and backups start to scatter.
Coolify solves this problem: you buy a VPS yourself, then build a deployment panel on it similar to Vercel / Heroku / Railway.
It's not Kubernetes, and it's not a traditional BaoTa panel. More accurately, it's a self-hosted PaaS: connect a Git repository, fill in environment variables, bind a domain, click deploy, and then Coolify handles Docker builds, container runtime, reverse proxy, and HTTPS for you.
This article explains it the way I'd walk a friend through it: what VPS suits running Coolify, how to install it, how to get your first app online, and which pitfalls to avoid in advance.
If you're only deploying a static site, Vercel and Netlify are still less hassle. Coolify is really suited to these kinds of people:
| Scenario | Suited to Coolify | Reason |
|---|---|---|
| Multiple small projects running long-term | Suited | One VPS manages multiple apps, fixed cost |
| Want to self-host n8n, Umami, Postgres, Redis | Suited | Coolify has service templates, easy to manage |
| Internal company tools, admin backends | Suited | Data and deployment flow stay on your own server |
| Only running a single static website | Not necessarily | May be more hassle than Vercel |
| High-concurrency large business | Be cautious | A single VPS is not an auto-scaling platform |
My own judgment is simple:
- If you have 3 or more projects to run, Coolify starts to be worth it
- If you only want to deploy one blog, plain Docker Compose + Caddy may be lighter
- If you don't want to deal with server security and backups at all, then don't self-host
What Coolify saves is the time of "hand-writing Docker Compose, reverse proxy, certificates, and environment variables for every project" — not the server maintenance itself.
Coolify itself isn't especially resource-hungry; what really eats resources is the build process.
For example, when you deploy a Next.js project, CPU and memory spike during the build; when you deploy a service with a database, you also need to leave room for Postgres, Redis, and the app containers.
I suggest choosing like this:
| Usage | Minimum config | More stable config |
|---|---|---|
| Trial, testing | 2 cores / 2GB / 30GB SSD | 2 cores / 4GB / 40GB SSD |
| Running 2-5 small apps | 2 cores / 4GB / 60GB SSD | 4 cores / 8GB / 80GB SSD |
| Multiple production projects | 4 cores / 8GB to start | Dedicated CPU is more comfortable |
Here's an easily overlooked point: a cheap shared-CPU VPS can run it, but builds will be slow.
If your project frequently npm install, pnpm build, shared CPU jitter is very noticeable. The app may run fine, but waiting ages on every deployment gets annoying.
For the OS, prioritize:
- Ubuntu 22.04 / 24.04 LTS
- Debian 12
- A clean system, don't install a pile of old panels
If this VPS already runs Nginx, Caddy, BaoTa, or 1Panel, think it through before installing Coolify. Because Coolify comes with its own reverse proxy, port and certificate management can easily clash with existing services.
The official install is simple, but don't rush to copy the command.
First SSH into the VPS:
ssh root@your_server_ip
Update the system:
apt update && apt upgrade -y
Check disk space:
df -h
Check whether ports are occupied:
ss -tlnp | grep -E ':80|:443|:8000|:6001|:6002'
Coolify self-hosting commonly uses these ports:
| Port | Purpose |
|---|---|
| 22 | SSH login to the server |
| 80 | HTTP / Let's Encrypt certificate validation |
| 443 | HTTPS access to apps |
| 8000 | Coolify initial panel access |
| 6001 | Real-time communication |
| 6002 | Web Terminal, needed by some versions |
If you already have Nginx occupying 80/443, Coolify's Traefik can't properly take over public traffic.
The officially recommended install method is the script installer. As the root user you can run:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
If you're not the root user, use sudo:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash
The install script does several things:
- Installs Docker and Docker Compose
- Creates
/data/coolify/related directories - Pulls the Coolify container image
- Starts the Coolify panel
- Starts the default reverse proxy
- Configures the internal database and required services
After installation, first check whether the containers are up:
docker ps --filter "name=coolify"
If you see Coolify-related containers in Up state, it basically started successfully.
Visit in your browser:
http://your_server_ip:8000
After going in, create an admin account. Don't use a weak password here — once someone gets into the Coolify panel, they can basically control the apps on your server.
Using IP + 8000 is fine during testing, but for long-term use you must bind a domain.
For example, you plan:
coolify.example.com
Add an A record in DNS:
coolify.example.com -> your_server_ip
At first, I suggest keeping Cloudflare on DNS only, i.e. the grey cloud. Once certificates are issued normally and both the panel and apps are accessible, then consider turning on the orange-cloud proxy.
Then in Coolify's settings, change the Instance Domain to:
https://coolify.example.com
Coolify uses Traefik as the reverse proxy by default and handles HTTPS automatically. Normally you don't need to install Certbot yourself or hand-write Nginx configs.
If you already have an outer Cloudflare layer, note two things:
- On the first certificate issuance, ports 80/443 must be reachable
- After turning on the Cloudflare proxy, test the panel log stream and deployment status to avoid WebSocket issues
The most common Coolify usage is deploying from a Git repository.
The rough flow is:
- Add a GitHub / GitLab connection in Coolify
- Select the repository and branch
- Select the build method, e.g. Nixpacks, Dockerfile, or Docker Compose
- Fill in environment variables
- Bind a domain
- Click Deploy
For an ordinary Node.js project, Coolify can usually detect it automatically.
But I'd rather prepare my own Dockerfile for production projects, at least it's more controllable. For example, a simple Node app:
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app .
EXPOSE 3000
CMD ["npm", "start"]
Then in Coolify set the app port to 3000, and fill in the domain:
app.example.com
After a successful deployment, Coolify forwards requests from the public domain to the container's internal port.
Coolify is convenient, but you still need to manage environment variables well yourself.
Common variables include:
DATABASE_URL=postgresql://user:password@host:5432/db
REDIS_URL=redis://redis:6379
APP_URL=https://app.example.com
NODE_ENV=production
A few suggestions:
- Don't commit
.envto the Git repository - Use random long strings for production passwords
- Don't use the same password for the database as for the panel
- After changing key variables, redeploy and check the logs
If the app fails to start, look at the deployment logs first — don't blindly reinstall.
Coolify can deploy apps and also services, such as PostgreSQL, Redis, MySQL, MongoDB, n8n, Umami, and the like.
But don't take it as "click once and never worry again." The most important thing for a database is backups.
If you deploy PostgreSQL with Coolify, at minimum confirm:
- The data directory is in a persistent Volume
- There are regular backups
- Backup files aren't stored only on the same VPS
- You can restore before upgrading
I usually put backups in object storage, e.g. Cloudflare R2, Backblaze B2, S3-compatible storage.
A simple database backup approach is:
pg_dump "$DATABASE_URL" | gzip > app-db-$(date +%F).sql.gz
Then sync to remote with rclone:
rclone copy app-db-$(date +%F).sql.gz r2:backup-bucket/coolify/app/
This isn't necessarily the most elegant way, but at least it's more reliable than "backups and database on the same VPS disk."
If you lock down all ports right after installing, you can easily lock yourself out.
First confirm the SSH port:
ss -tlnp | grep ssh
Then configure UFW:
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 8000/tcp
ufw allow 6001/tcp
ufw allow 6002/tcp
ufw enable
ufw status
Once you can access the panel normally via https://coolify.example.com, 8000 usually no longer needs to be exposed to the public internet.
You can tighten it:
ufw delete allow 8000/tcp
If you don't use the Web Terminal, you can also tighten 6002 as appropriate. But don't copy mechanically — first confirm whether the current version and features need it.
First run the most critical few from the official diagnostic approach:
docker --version
docker compose version
systemctl status docker --no-pager -l
docker ps -a --filter "name=coolify"
df -h /
ls -lt /data/coolify/source/*.log 2>/dev/null | head -5
Many failures aren't Coolify itself being broken, but:
- The system is too old
- Docker isn't installed properly
- The disk is full
- Port 8000 is occupied
- The script has no permission to write to the directory
First check the containers:
docker ps -a --filter "name=coolify"
Then check the ports:
ss -tlnp | grep 8000
If the container is running but you can't access it, check the cloud provider's security group and UFW. Many people only open the system firewall and forget there's another security group layer in the cloud provider's console.
The most common cause of 502 is the app port not matching.
For example, your Node app actually listens on 3000, but you fill in 8080 in Coolify, so Traefik forwards to the wrong place.
Enter the container to check the listening port:
docker ps
docker logs container_name --tail=100
In the app, also confirm the listen address isn't bound only to 127.0.0.1. In a container you usually need to listen on:
0.0.0.0
Check in order:
- Whether the DNS A record points to this VPS
- Whether 80 and 443 are open
- Whether Cloudflare is temporarily set to DNS only
- Whether the domain has an AAAA record pointing to a wrong IPv6
- Whether the same domain is occupied by an old Nginx / Caddy
Don't delete containers right away. Certificate problems are mostly DNS and port problems.
This kind of problem is very common on 2GB memory VPS.
First check memory:
free -h
Then check OOM:
journalctl -k | grep -i "out of memory"
As a temporary mitigation you can add swap:
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
But in the long run, if you frequently build large frontend projects, upgrading to 4GB or 8GB is more practical.
Coolify supports updates, but in production don't just click the button when you see it.
My habit is:
- First check whether the current business is running normally
- Back up Coolify-related data and app databases
- Avoid business peak hours
- After updating, test the panel, deployment, log stream, and HTTPS
If you use it to host multiple projects, updating Coolify isn't just updating a panel — it affects the entire deployment platform.
These tools are often compared together, but their purposes differ.
| Tool | Better suited for |
|---|---|
| Coolify | Git-driven app deployment, PaaS, self-hosted project launches |
| 1Panel | Docker app store, website management, server panel |
| Portainer | Docker container, Stack, Volume management |
| BaoTa / aaPanel | Traditional PHP websites, LNMP, visual site building |
If your core need is "deploy as soon as code is pushed," Coolify is handier.
If you just want to manage Docker containers, Portainer is lighter.
If you're a beginner building WordPress, 1Panel or BaoTa may be more direct.
The most worthwhile scenario for Coolify isn't saving those few dollars in platform fees, but taking back control of the deployment flow.
You can run on a 4-core 8GB VPS:
- A frontend app
- A backend API
- A PostgreSQL
- A Redis
- An n8n
- An Umami
- An internal admin backend
All of these are managed in the same panel, with domains, certificates, logs, and deployment records centralized — it really is comfortable.
But the cost is also clear: server security, backups, upgrades, and monitoring all become your responsibility.
So I'd choose like this:
- Just playing around: a 2-core 4GB VPS is worth a try
- Planning long-term use: 4 cores 8GB + automatic backups + monitoring
- Company core business: don't rely on a single machine alone; at least have off-site backups and a migration plan
Coolify is a good tool, but it's not magic. It can turn a VPS into a deployment platform, on the premise that you're willing to maintain this VPS as a real production environment.