Coolify is a self-hosted alternative to Heroku, Vercel and Netlify. You install it on your own server, point it at a Git repository, and it builds the app, runs it in Docker, routes a domain to it and gets a certificate. On October 16, 2026, the GitHub repository had about 63,000 stars, and the coollabsio/coolify image had about 3.3 million pulls on Docker Hub. Version 4.0.0, the first stable v4 release, came out on April 27, 2026, and 4.4.6 followed on October 9.
This guide installs Coolify 4.4.6 with the official script, closes the hole a fresh install leaves open, deploys a small Node.js app from a public GitHub repository and adds a domain with HTTPS. Every step ran on Ubuntu 24.04.5 LTS. It ran as a container with its own Docker Engine and systemd, standing in for a VPS, so the server IPs and the HTTPS test differ from a real cloud server, and the guide points out where.
Short version:
- Use a fresh Ubuntu LTS server with at least 2 cores, 2 GB of RAM and 10 GB free. Run
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash -s 4.4.6to install a specific version. - The dashboard is at
http://your-server-ip:8000, and the first person to open it becomes root. Create your account right away, or bind port 8000 to127.0.0.1with a compose override and use an SSH tunnel. - In the dashboard, pick This machine, then add a Public Git Repository with the right base directory and port, and click Deploy. My first build took 37 seconds.
- Add an
https://domain, redeploy, and Traefik requests a Let's Encrypt certificate. That needs a DNS record pointing at the server and port 80 open. - Coolify updates itself every night by default. Turn that off if you want to stay on the version you tested.
What Coolify installs and what you need
What runs on the server
Coolify isn't one container. The installer sets up Docker, then runs Coolify's own containers next to the apps you deploy:
-
coolifyis the dashboard and API. It also serves real-time updates on port 6001 and the web terminal on port 6002. -
coolify-dbandcoolify-redisare PostgreSQL and Redis for Coolify's own data. The 4.4.6 compose file usespostgres:15-alpineandredis:7-alpine. -
coolify-proxyis Traefik. It owns ports 80 and 443 and sends each domain to the right app. -
coolify-sentinelcollects server metrics.
Coolify manages the server it runs on the same way it manages a remote one, over SSH. The installer generates a key, adds it to root's ~/.ssh/authorized_keys, and the dashboard then logs in as root at host.docker.internal. That's why it needs SSH running and root login with a key allowed. Ubuntu's default (PermitRootLogin prohibit-password) is fine.
After the setup below, with one small app deployed, docker stats on the test server showed about 500 MB for Coolify's own containers: 428 MB for coolify, 45 MB for the database, 22 MB for Traefik, 7 MB for Redis and 3 MB for Sentinel. The Railpack build container stayed running after the build and used another 549 MB.
Server requirements and ports
The installation docs ask for 2 CPU cores, 2 GB of RAM and 10 GB of free disk, on amd64 or arm64. They add that Coolify can run on smaller servers, "but this is not recommended", and that builds on the same server as Coolify need watching because high resource use can make the server unresponsive. Ubuntu should be an LTS release. The docs name 20.04, 22.04 and 24.04 and suggest the manual install if the script fails on a non-LTS release. Ubuntu 26.04 isn't on that list yet, which is why the test used 24.04.
Use a fresh server. The script installs Docker Engine itself, rewrites /etc/docker/daemon.json (it keeps a backup of an existing one) and expects ports 80 and 443 to be free. If you already run Nginx Proxy Manager or another proxy on 80 and 443, give Coolify its own server.
The firewall docs list the ports:
| Port | Used for |
|---|---|
| 22 | SSH |
| 80 and 443 | Your apps through Traefik, and Let's Encrypt |
| 8000 | The dashboard at http://server-ip:8000
|
| 6001 and 6002 | Real-time updates and the web terminal when you use the IP address |
Once the dashboard has its own domain through the proxy, the docs say you can close 8000, 6001 and 6002. Use your hosting provider's firewall for this. On Linux, Docker publishes ports through its own firewall rules, so ufw rules don't stop traffic to a container port.
Install Coolify with the script
Run the installer with a pinned version
SSH in as root or a sudo user and run the script. The plain command from the docs installs the newest release. Adding a version number after bash -s installs that one instead, which the script supports and which is what this guide does:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash -s 4.4.6
To read the script before it runs as root, download it with curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o install.sh, look through it and run sudo bash install.sh 4.4.6.
On the test server it finished in 1 minute 22 seconds. The output, with the server's addresses replaced by an example IP and the private addresses left out:
1/9 Installing required packages curl wget git jq openssl 23.1s done
2/9 Checking OpenSSH server configuration 0.0s done
3/9 Installing Docker Engine v29.9.1 22.4s done
4/9 Configuring Docker daemon log rotation, address pools 1.4s done
5/9 Downloading required files from CDN 0.2s done
6/9 Setting up environment variables 0.0s done
7/9 Checking SSH key for localhost access generated new key 0.0s done
8/9 Pulling images coolify, postgres, redis, helper 18.6s done
9/9 Starting Coolify v4.4.6 16.0s done
Coolify is ready! Installed in 1m 22s
Public IPv4 http://203.0.113.10:8000
! Back up /data/coolify/source/.env to a safe place outside this server (e.g. a password manager).
Step 4 set log rotation (10 MB files, 3 per container) and an address pool of 10.0.0.0/8 for Docker networks in /etc/docker/daemon.json. If your VPS provider uses addresses in that range, the docs have a custom network option for the installer.
Do what the last line says. /data/coolify/source/.env holds the generated secrets, including APP_KEY, which encrypts values in Coolify's database. The docs say you need it to restore Coolify from a backup.
Lock down port 8000 before anyone else finds it
The dashboard is now live on port 8000 on every interface, and it has no account yet. The installation docs warn: "Anyone who reaches the registration page first can become the instance admin and gain root access to your server." Do one of these right away.
The quick fix is to open http://your-server-ip:8000 and create your account (next section). The safer fix is to stop publishing the dashboard to the internet at all. Coolify reads a compose override from /data/coolify/source/docker-compose.custom.yml and keeps it across upgrades. The installation docs show this example for binding the dashboard to localhost:
services:
coolify:
ports:
- "127.0.0.1:8000:8080"
That didn't work as written on 4.4.6. Compose adds override ports to the existing list instead of replacing it, so the merged config had both 8000 on all interfaces and 127.0.0.1:8000. Applying it failed and left the dashboard stopped:
failed to bind host port 127.0.0.1:8000/tcp: address already in use
Compose's !override tag replaces the whole list. The firewall docs already use it in their version of this override. This one worked, and it also keeps the real-time and terminal ports off the internet:
services:
coolify:
ports: !override
- "127.0.0.1:8000:8080"
- "127.0.0.1:6001:6001"
- "127.0.0.1:6002:6002"
Apply it with the command from the docs:
cd /data/coolify/source
sudo docker compose --env-file /data/coolify/source/.env \
-f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.custom.yml \
up -d --pull always --remove-orphans --force-recreate
After that, docker port coolify listed all three ports on 127.0.0.1 only. From your own computer, open a tunnel and use the dashboard at http://localhost:8000:
ssh -L 8000:127.0.0.1:8000 -L 6001:127.0.0.1:6001 -L 6002:127.0.0.1:6002 root@your-server-ip
Logging in through that tunnel worked, and real-time updates worked, because the browser reaches 6001 and 6002 through the same tunnel. You can also skip the open registration page completely. The docs describe ROOT_USERNAME, ROOT_USER_EMAIL and ROOT_USER_PASSWORD variables that create the root account during the install.
First login and connecting the server
Create the root account
The first visit shows the sign-up form, with a clear warning:
The password needs at least 8 characters with uppercase, lowercase, a number and a symbol. Use a password manager, and turn on two-factor authentication in your profile once you're in. This account can run commands as root on every server you connect.
Connect this machine
After sign-up, an onboarding wizard asks where to deploy. Pick This machine. Coolify then connects to the server over SSH as root with the key the installer created and checks that Docker works. On the test server, that check passed in a few seconds and the wizard moved on to creating a project. This guide accepts the default, "My first project", with a production environment.
During that step, Coolify also started coolify-proxy, the Traefik container that will receive web traffic. Run sudo docker ps afterwards and you should see coolify, coolify-db, coolify-redis, coolify-proxy and coolify-sentinel.
If the wizard says the server isn't reachable, it's an SSH problem between the Coolify container and the host. Check that sshd is running, that root may log in with a key, and that the public key shown in the wizard is in /root/.ssh/authorized_keys.
Deploy your first app from Git
Pick the repository and build settings
Open your project, go to the production environment and click New resource. Under Applications, the first option is Public Git Repository. It needs no credentials. For private repositories, Coolify offers a deploy key or a GitHub App. The resource picker describes the GitHub App option as the one with automatic webhooks and pull request previews.
This guide uses Coolify's own example repository, https://github.com/coollabsio/coolify-examples, which holds many small apps in subfolders. After Check Repository, Coolify read the default branch and showed the build settings:
- Build pack: Railpack was the default on 4.4.6. It detects the language and builds an image without a Dockerfile. Pick Dockerfile or Docker Compose if your repository has one.
- Base directory: the folder with the app. Here it's
/javascript/runtimes/nodejs, a small Fastify server. - Port: the port the app listens on inside the container. This app uses 3000. Get this wrong and the app builds fine but the domain returns errors.
Click Continue. Coolify creates the application and opens its settings page.
Deploy and check the result
Click Deploy at the top. The Deployment Logs page shows each step:
My first deployment took 37 seconds. Coolify cloned the commit, generated a Railpack build plan, built the image, then did a rolling update: start the new container, then remove the old one. Click Show Debug Logs to see the full build output when a build fails.
Coolify also gave the app a generated sslip.io address. In the lab that address didn't resolve to the server from the browser, so the test went through Traefik with the matching Host header and got the app's response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"hello":"from nodejs #2"}
The app's status read "Running (no healthcheck)". Add a health check under Healthcheck (this app has a /health route) so Coolify can tell when a new version is broken. If you'd rather run a ready-made app than build one, the same New resource page has Docker Compose and Docker image options, so the compose files from the Uptime Kuma, Umami or Paperless-ngx guides are a starting point there too.
Domains, HTTPS and updates
Add a domain with automatic HTTPS
First, create a DNS A record (and an AAAA record if the server has working IPv6) for your domain, pointing at the server. Then open the app's Domains page and click Add Domain. Pick https, enter the host name and the app's port, and save. Coolify then showed the domain twice:
Coolify added the www. version of the domain on its own, and it shows Changes pending. The new domain only takes effect after you redeploy. After clicking Deploy again, Traefik redirected plain HTTP to HTTPS with a 307 Temporary Redirect and served the app on HTTPS.
The certificate step is the part that couldn't be finished in a lab. Traefik asks Let's Encrypt for a certificate using the HTTP challenge on port 80. The test domain ended in .test, which Let's Encrypt never issues for, so the proxy log showed:
Unable to obtain ACME certificate for domains ... Cannot issue for "hello.coolify-lab.test": Domain name does not end with a valid public suffix (TLD)
Meanwhile, Traefik served its fallback certificate, with subject=CN=TRAEFIK DEFAULT CERT. That's the same certificate you'll see on a real domain whenever the certificate request fails. The Let's Encrypt troubleshooting page lists the usual causes: port 80 closed, a third-party proxy such as Cloudflare in front of the domain, or an AAAA record pointing at a server without working IPv6. The docs point to Servers, your server, Proxy, Logs in the dashboard for the proxy log. sudo docker logs coolify-proxy on the server shows the same thing.
Keep Coolify updated
Coolify updates itself by default. On a fresh 4.4.6 install, automatic updates were already on, which matches the default in Coolify's instance settings migration, with an update frequency of 0 0 * * *, daily at midnight in the instance's time zone. It also means a server you installed with 4.4.6 won't stay on 4.4.6.
To control updates yourself, turn off Automatic updates under Settings, then Updates, and update by hand after reading the release notes. The update docs describe two ways: the Upgrade Now button in the dashboard, or the upgrade script with a version number:
curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | sudo bash -s 4.4.6
Replace 4.4.6 with the version you want. The docs warn not to rerun install.sh on an existing instance, because it resets ownership and permissions under /data/coolify. They also say to check for running deployments first, since an update can make them fail. Back up /data/coolify/source/.env before any update.
FAQ
Server and setup
How much RAM does Coolify need?
The docs ask for 2 GB of RAM and 2 CPU cores. On the test server, Coolify's own five containers used about 500 MB, and the build container added about 550 MB while it was running. That fits in 2 GB with a small app, but larger builds on the same server need more memory or swap.
Can Coolify run on the same server as your apps?
Yes. That's what the This machine option does, and it's how the test app ran. Coolify's own containers and your apps share the server's CPU and RAM, so a heavy build or a busy app slows the dashboard too. The docs show the same pattern for production, with a 4 GB example server running more than 40 small services next to Coolify, with the apps built elsewhere.
Does Coolify update itself automatically?
Yes, by default. My fresh install had automatic updates on, scheduled daily at midnight. Turn them off under Settings, then Updates, if you want to choose when to upgrade, and use the dashboard or upgrade.sh with a version number.
Dashboard and HTTPS
Why does Coolify say "Cannot connect to real-time service"?
Your browser can't reach port 6001 on the server. This message showed on every page while port 6001 wasn't reachable, and it went away once the browser could connect. Open 6001 and 6002 in the firewall, forward them through your SSH tunnel, or give the dashboard a domain so the proxy carries that traffic over 443.
Why does a Coolify app show TRAEFIK DEFAULT CERT?
Traefik couldn't get a Let's Encrypt certificate for that domain, so it served its built-in fallback. Check the proxy log for the ACME error. In the test the reason was a .test domain. On a real domain, check that DNS points at the server, that port 80 is open, and that no third-party proxy sits in front during the HTTP challenge. Redeploy the app after you change its domain.
How do you open the dashboard on a domain instead of port 8000?
Set Instance Domain under Settings to a domain that points at the server. Coolify team member Cinzya explained: "If you set up the Instance Domain under Settings you don't need to add the port at the end of the URL anymore, as you would access coolify through the proxy." Once that works, the firewall docs say you can close ports 8000, 6001 and 6002.
Originally published on DeployLark: Install Coolify on a VPS and Deploy Your First App





Top comments (0)