The command curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash installs a fully functional PaaS (Platform as a Service) control panel on a blank Linux server in a single line. Coolify is an open-source PaaS solution that allows you to run automatic Git integration, reverse proxy management, database orchestrator, and SSL certification processes on your own bare-metal or VPS infrastructure, similar to commercial cloud platforms like Heroku, Netlify, and Render. When configured correctly, it significantly reduces monthly cloud costs while eliminating the maintenance burden of manual Docker Compose management.
However, the default (out-of-the-box) installation settings are usually designed with single-server test environments in mind. Using Coolify in a production environment that handles live traffic and includes databases requires detailed planning, from swap management to Docker socket security, Traefik routing architecture, and storage unit persistence. In this guide, we will explore the current principles of setting up and operating the Coolify architecture to production standards.
Understanding the Coolify Architecture: Control Plane and Worker Division of Labor
Understanding how Coolify works is crucial before setting it up. Coolify consists of two main components: the Control Plane (Coolify Engine), which includes the management interface and business logic, and the Target/Worker nodes, where applications actually run. By default, these two roles are combined on the same server.
The Control Plane hosts the web interface, database (PostgreSQL for documentation and status information), queue manager (Redis), and SSH/API services that communicate with the Docker Engine. Deployed applications run as isolated containers on the Docker Daemon. The task of handling traffic is delegated to the integrated Traefik reverse proxy layer by default.
In this architecture, Coolify does not interfere with the runtime of your applications. This means that if the Coolify panel crashes or is shut down, Traefik and your containers will continue to run. This is one of the most critical resilience criteria for self-hosted solutions.
Pre-Installation Server Hardening and Linux Kernel Settings
Before running the installation script, the operating system needs to be prepared for the PaaS load. Running the bash script directly on a clean Debian 12 or Ubuntu 24.04 LTS installation can lead to issues due to the lack of necessary optimizations.
First, you need to adjust the swap space and memory management (out-of-memory killer) settings. The swap space acts as a critical buffer in case of insufficient memory, preventing the Linux kernel from killing the Docker daemon or Traefik. These steps are general Linux server hardening practices.
# Create and authorize a 4GB Swap space
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Sysctl optimizations
sudo sysctl -w vm.swappiness=20
sudo sysctl -w vm.vfs_cache_pressure=50
Setting vm.swappiness to 20 instead of the default 60 prevents the system from aggressively swapping to disk before using physical RAM. vfs_cache_pressure improves I/O performance by keeping the file system cache in memory longer.
Additionally, increasing the file descriptor limits prevents Traefik from throwing too many open files errors under high concurrent connections. The following lines should be added to /etc/security/limits.conf:
* soft nofile 65536
* hard nofile 65536
⚠️ Be Cautious When Modifying System Settings
Modifying system files like
/etc/fstabor changingsysctlsettings can affect system stability. Before making such changes, ensure you have a backup of your server and understand the implications. Incorrect configurations can render your system unbootable.
Coolify Installation and Firewall (UFW) Configuration
After preparing the server, you need to configure the security rules. Instead of directly exposing the management panel to the outside, it's more secure to place it behind a reverse proxy or only allow access from specific static IPs.
However, for the initial setup, you need to open the basic ports:
| Port | Protocol | Purpose | Should Be Exposed to the Outside? |
|---|---|---|---|
| 22 | TCP | SSH Access (for Coolify Worker communication) | Only to Administrator / Static IP |
| 80 | TCP | HTTP Traffic (for ACME Challenge & Redirection) | Yes (to the whole world) |
| 443 | TCP | HTTPS Traffic (for TLS secure communication) | Yes (to the whole world) |
| 8000 | TCP | Coolify Dashboard (for initial setup and management) | Preferably Restricted / VPN |
After configuring UFW, you can run the official installation script:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8000/tcp
sudo ufw enable
# Coolify Installation
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
⚠️ Docker iptables Conflict
Remember that when using UFW, Docker applies its own
iptablesrules before UFW. If you expose a port via Docker (e.g.,-p 5432:5432), it may still be accessible from the outside world even if you've closed the port in UFW. Never expose database ports to the outside (127.0.0.1:5432:5432or leave port definitions empty).
Once the installation is complete, you can access the management panel at http://server_ip:8000 to create the first admin account.
Traefik and Automatic Let's Encrypt Wildcard TLS Setup
One of the significant advantages of Coolify is its ability to automatically assign SSL/TLS certificates to subdomains (e.g., api.company.com or app.company.com) of your applications. By default, it uses the HTTP-01 challenge, but this method requires independent verification for each subdomain and can hit rate limits.
In production environments, using DNS-01 challenge to create a Wildcard certificate (*.company.com) is recommended. You can configure Traefik with a Cloudflare or similar DNS provider API key through the Coolify interface.
An example Cloudflare DNS-01 structure to be added to the Traefik Dynamic Configuration panel is as follows:
# Added to Traefik Environment Variables section
CF_DNS_API_TOKEN=your_cloudflare_api_token_here
# Traefik Configuration
certificatesResolvers:
letsencrypt:
acme:
email: admin@company.com
storage: /etc/traefik/acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
This configuration allows any new microservice or web application added to your server to be published immediately with a valid TLS certificate, without waiting for HTTP verification.
Database Management and Storage (Volume) Strategies
Coolify allows you to deploy services like PostgreSQL, Redis, MySQL, or ClickHouse with a single click. However, a common mistake when running containerized databases is mismanaging the storage layer (volume).
To prevent data loss when a container is deleted, Coolify automatically creates a Named Volume. However, for backup and disaster recovery scenarios, it's crucial to mount these volumes to a known directory on the server or regularly back them up to an S3-compatible storage.
# Correct Docker Volume Definition Logic
services:
postgres:
image: postgres:16-alpine
volumes:
- /var/lib/coolify/databases/postgres-prod/data:/var/lib/postgresql/data
environment:
POSTGRES_DB: app_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
💡 Use Automatic S3 Backup
Coolify has a built-in database backup mechanism. In the database settings section, you can enter your Hetzner Storage Box, AWS S3, or Cloudflare R2 information to automate daily
pg_dumporwal-gbackups. Even if your server completely crashes, your data will be safe.
To improve PostgreSQL performance, you must optimize the default shared_buffers and work_mem values in the Docker Compose override area based on your server's RAM.
Security and Isolation: Production Hardening
When running Coolify in production, one of the most critical security concerns is docker.sock access. Coolify Engine, by default, has full access to the server's Docker socket to manage containers. Any process with access to the Docker socket essentially has root privileges on the server.
In multi-tenant or high-security environments, separating the Coolify Control Plane from the Worker servers is the best architectural approach.
+------------------------+ SSH (Port 22) +------------------------+
| Coolify Control Plane | -----------------------------------> | Worker Server 1 |
| (Management Panel) | | (Applications & DBs) |
+------------------------+ +------------------------+
In this setup, the Control Plane connects to the Worker server via a restricted SSH key. The Docker Daemon on the Worker server only accepts commands through this SSH connection. Thus, even if the management panel is compromised, the server running your live applications remains isolated. The Worker nodes only need to run Docker and the SSH server.
Additionally, to restrict network access between applications, instead of using the default bridge network, a custom overlay/bridge network should be used for each project. Coolify provides this isolation automatically on a per-project basis; however, when writing Docker Compose files manually, attention must be paid to network definitions.
Conclusion
Coolify, when combined with the right architectural setup, is a powerful alternative PaaS solution that breaks cloud vendor lock-in for small and medium-sized teams. It allows you to run modern software development processes (Git push to deploy, automatic SSL, preview environments) on your own infrastructure without paying license fees, giving you full control over your setup.
However, remember that the PaaS concept does not completely eliminate server management responsibilities; it merely abstracts them. Correctly configuring core parameters, disk cleanup automations, resource limits, and database backup strategies ensures that you can run hundreds of containers smoothly and reliably on Coolify.
Before exposing your server to live traffic, applying the swap, firewall, and cgroup limits mentioned above will secure your infrastructure.
Top comments (0)