Who needs a self-hosted PaaS?
A managed PaaS like Heroku or Render works well for a prototype or small project. As soon as you host multiple applications or traffic grows, the bill rises proportionally — sometimes beyond the cost of a dedicated VPS. Coolify targets three specific profiles. Web agencies managing dozens of client projects: a single Coolify VPS replaces just as many Heroku accounts. Freelancers who want to control their infrastructure costs without sacrificing the convenience of automated deployment. Teams that cannot entrust their data to a third party — GDPR, public sector clients, medical or financial data. In all three cases, Coolify reproduces the PaaS workflow (git push → deployment) on infrastructure you control entirely.
Coolify vs Heroku and Vercel: what you gain
- Fixed, predictable cost: you pay for the VPS, not usage — a €10 VPS hosts as many applications as you want
- Sovereign data: no data leaves your infrastructure, simplified GDPR compliance
- Automatic deployment on
git push: built-in GitHub, GitLab, and Gitea webhooks, no third-party plugin needed - Automatic stack detection: Nixpacks, Dockerfile, or Docker Compose — Coolify chooses or you take the wheel
- Let's Encrypt SSL certificates managed automatically, renewed without intervention
- One-click databases (PostgreSQL, MySQL, MongoDB, Redis) with scheduled backups, written on the server and then copied to S3 storage if you configure it
- Multi-server management: a single interface for multiple VPS, load distribution possible
- Open source (Apache 2.0 license): no vendor lock-in, auditable and self-hostable code
Minimum requirements before installation
Coolify itself uses few resources, but it orchestrates Docker and potentially hosts your applications and databases on the same server. Plan for at least 2 vCPU and 2 GB of RAM for Coolify alone. As soon as you run several services simultaneously, 4 GB of RAM becomes the recommended minimum. Disk space depends on your applications: allow 20 GB for the system and Coolify, plus space for your Docker images and data.
Operating system: Ubuntu 22.04 LTS or Debian 12 on a freshly provisioned server. Do not install Docker manually beforehand — Coolify's installation script handles this step and a pre-installed Docker version can cause conflicts.
Ports to open in your firewall: 22 (SSH), 80 (HTTP), 443 (HTTPS), and 8000 (Coolify's initial installation interface). You can close port 8000 after configuring a domain and switching to HTTPS. A domain name or subdomain is required for the Coolify interface and for each application you deploy.
Install and deploy with Coolify: 10 steps
Provision a clean VPS
Order an Ubuntu 22.04 LTS (or Debian 12) VPS dedicated to Coolify. Update packages:
apt update && apt upgrade -y. Enable UFW, allowing SSH (22), HTTP (80), and HTTPS (443), plus port 8000 temporarily for initial access. Do not install Docker — the installation script handles it.Run the official installation script
Execute the installation script as root:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash. The script installs Docker, deploys the Coolify stack (which runs in containers itself) and starts the dashboard. Installation takes one to three minutes depending on the server's connection speed.Create the administrator account immediately
Open
http://your-ip:8000as soon as installation finishes and create your administrator account. This step is urgent: until the account is created, the registration page is accessible to anyone who knows the server's IP address. The first visitor who creates an account gets full administrator rights.Configure the Coolify interface domain
Under Settings > Instance, enter the instance domain (
coolify.your-domain.com). First create an A record in your DNS pointing to the VPS IP. Coolify automatically generates the SSL certificate via Let's Encrypt and switches access to HTTPS. You can then close port 8000 in UFW.Connect a Git source
Under Sources, add a GitHub integration (via GitHub App) or GitLab (via deployment key or OAuth). The GitHub App integration is recommended: it allows Coolify to automatically create webhooks on your repositories and clone private repositories without manual SSH key management.
Create your first application
Create a project, then a resource of type Application. Select your Git source, the repository, and the deployment branch. Coolify analyzes the repository and suggests a build method: Nixpacks (automatic stack detection for Node, Python, PHP, Ruby, etc.), Dockerfile if the repository contains one, or Docker Compose. Enter the application domain and required environment variables.
Launch the first deployment
Click Deploy. Coolify clones the repository, runs the build, creates the container, configures the Traefik reverse proxy, and generates the SSL certificate. Build logs display in real time in the interface. A typical deployment takes between 30 seconds and 3 minutes depending on application size.
Provision a database
In your project, create a resource of type Database and choose the engine (PostgreSQL, MySQL, MariaDB, MongoDB, or Redis). Coolify starts the container, generates a random password, and displays the connection string. Inject it as an environment variable in your application. Scheduled backups to S3-compatible storage are configured directly from the interface.
Configure a custom domain for the application
In the application settings, enter the domain or domains. Create the corresponding A records in your DNS. Coolify reconfigures Traefik and triggers SSL certificate generation. If your domain is behind a CDN (Cloudflare in proxy mode), switch the certificate type to DNS Challenge and enter the Cloudflare API token in the instance settings.
Enable Coolify's own backups
The configuration of all your resources (applications, databases, secrets) is stored in
/data/coolify. Schedule a backup of this directory to external storage independent of the VPS: if you lose the server, you can restore the entire Coolify environment from this archive. A crontab or rsync script to an S3 bucket is sufficient.
Post-installation configuration
Once the first application is deployed, several settings improve day-to-day reliability.
Automatic Git webhooks. The GitHub App or GitLab OAuth integration creates webhooks on each repository when you configure the resource. If you use a manual SSH deployment key, create the webhook on the Git side pointing to https://coolify.your-domain.com/api/v1/deploy?uuid=<application-uuid>&secret=<secret>. The UUID and secret are visible in the Webhooks tab of each resource.
Environment variables and secrets. Coolify distinguishes variables visible in the interface (classic environment variables) from masked secrets (tokens, API keys). Both are encrypted in the database. You can define variables at the project level — they are inherited by all resources — or per individual resource.
Built-in monitoring. The Metrics tab of each server shows CPU, RAM, and disk usage in real time. You can configure notifications (email, Telegram, Slack, Discord, ntfy) for deployment events, errors, and resource alerts.
Coolify updates. Updates are triggered from the interface (Settings > Update). Coolify pulls the new version of its Docker images, recreates its own containers, and restarts. The update does not touch your deployed applications.
Hardening: network access and authentication
Two steps to take before putting Coolify into production. Enable two-factor authentication (2FA) on your administrator account: Settings > Profile > Two-Factor Authentication. Close port 8000 in UFW after configuring the HTTPS domain (ufw delete allow 8000). If your VPS is exposed directly to the internet without a CDN, consider restricting access to the Coolify interface by IP in UFW — only your network or VPN can reach the panel, while port 443 remains open for your applications.
Troubleshooting: common errors
Build fails with No build method detected. Nixpacks did not recognize the stack. Add a Dockerfile to the root of the repository or manually select the build method in the application settings (Docker Compose if you have one). You can also force the Nixpacks stack by adding a nixpacks.toml file to the root.
Domain shows 502 Bad Gateway after deployment. The application is not listening on the port Traefik expects. Check the exposure port in the resource settings: it must match the port on which your application listens inside the container. For a Node.js app starting on port 3000, enter 3000 in the Port field.
SSL certificate does not generate, access stays on HTTP. Verify the DNS A record points to the VPS IP (propagation can take time). Verify that port 80 is open in UFW — Let's Encrypt in HTTP Challenge mode must be able to reach the server on that port. If you are behind Cloudflare in proxy mode, switch to DNS Challenge.
Application restarts in a loop (Restarting). The startup command is failing. Check container logs in the resource's Logs tab. The error is usually a missing environment variable, an impossible database connection (check the connection string), or a port already in use on the server.
Insufficient resources: build is killed (Killed). The VPS does not have enough memory during the build. Two options: add swap memory temporarily (fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile) or migrate to a VPS with more RAM. For large Node.js applications, add NODE_OPTIONS=--max-old-space-size=4096 in the build environment variables.
Backups: what Coolify covers, and what it does not
Databases are backed up from the Backups tab of the resource: you choose a frequency (cron expression) and a retention. According to the Coolify documentation, each backup is first written to the server that hosts the database, under /data/coolify/backups. A copy can then be sent to S3-compatible storage once that storage has been added and validated in Coolify; local retention and S3 retention are set separately. The documentation lists, among others, Amazon S3, Cloudflare R2, MinIO, Backblaze B2, Scaleway, Hetzner, Wasabi and DigitalOcean Spaces, and says other S3-compatible providers may work.
A local-only backup is not a backup. A file sitting on the VPS disk disappears with the VPS: without an S3 destination (or a copy you move yourself) you only have a restore point against a handling mistake, not against losing the server.
The destination is S3, full stop. The request for a fuller backup manager (SFTP, WebDAV, encryption of the backups sent out, folder and subfolder in the bucket, remote deletion, download) is tracked in coollabsio/coolify issue #2389. At the time of writing this issue is open and assigned to a team member, with no delivery announced: do not build your recovery plan on those features. If you need SFTP or encryption, plan a second mechanism outside Coolify, for example rsync or an encrypted backup tool that reads /data/coolify/backups and pushes it elsewhere.
The database backups documentation page does not cover backing up the Coolify instance itself. That is why step 10 above stays relevant: copy /data/coolify off the VPS.
Test the restore. Coolify says it itself: a successful backup only proves that a file was created. Restore it into a disposable database and check the data before relying on it.
The application sees the proxy IP instead of the visitor's
Symptom: behind Traefik or Caddy (Coolify's proxy), your application sometimes receives an internal Docker address (such as 172.18.0.1) in X-Forwarded-For instead of the visitor's IP. Concrete consequences: rate limiting and IP bans that target the proxy itself, unusable logs, wrong geolocation.
What the primary source says (coollabsio/coolify issue #3436, "Randomly receiving proxy IP as X-Forwarded-For header using Traefik or Caddy"): at the time of writing, the issue is open, labelled "Possible Bug", and no merged fix is confirmed in it. Several users report the same behaviour, and the reporter states the problem is not solved at Coolify's level. The workaround that keeps coming back in the thread: IPv6 visitors appear with an internal Docker address when the coolify Docker network (the proxy's network) does not have IPv6 enabled. Enabling IPv6 on that network, then recreating it and redeploying the applications, fixed the case for several participants; changing only daemon.json and rebooting was not enough for one of them. One participant also found that this network is created IPv4-only on remotely managed servers.
How to proceed without trusting an anecdote:
- Check the network state: docker network inspect coolify --format '{{.EnableIPv6}}'. A false is the lead described in the thread.
- Reproduce before changing anything: call the application over IPv4 then IPv6 (curl -4 and curl -6) and compare what the application logs.
- Recreating the network cuts traffic for the duration of the redeploy: do it off-peak, with a backup of /data/coolify.
- Behind Cloudflare in proxy mode, read the CF-Connecting-IP header rather than deducing the IP from X-Forwarded-For, and only trust these headers when they come from ranges you control.
This guide is provided as is, without support for Coolify itself: the state of this issue may have changed since, so re-read it before acting.
Coolify, CapRover or Dokploy: which one to choose?
Coolify is not the only self-hosted PaaS available. CapRover, Dokploy, and Dokku cover similar needs with different philosophies. Coolify stands out for its modern interface, native multi-server support, and built-in monitoring — it suits teams managing a fleet of servers from a single control point. CapRover is lighter and suited to single-server use with a single administrator. Dokploy is newer, Docker Compose and Kubernetes oriented with a clean interface. For a detailed comparison of the three platforms on the criteria that matter (resources, build, databases, collaborative access), see our comparison article.