InfraFenceInfraFence

Live Security Operations

Get Started

Securing a Coolify server

Last updated:

Coolify turns a server into your own deployment platform. That also puts a lot on one host: an admin dashboard that can run commands as root, the containers of every app, the Traefik proxy in front of them, and SSH access as root.

This page covers what to lock down by hand first, then what the InfraFence agent adds. The Coolify facts come from Coolify's official documentation, as of October 2026 (Coolify v4).

What a Coolify server exposes

Coolify's firewall page lists the ports of the server that runs Coolify itself:

PortWhat it is for
8000/tcpThe Coolify dashboard, at http://<server-ip>:8000
6001/tcpReal-time dashboard updates, when you use the IP address
6002/tcpThe web terminal, when you use the IP address
22/tcpSSH, unless you moved it to another port
80/tcp, 443/tcpHTTP and HTTPS through the Coolify proxy

Servers that Coolify only manages need 22, 80 and 443. Port 8000 matters most right after installing: Coolify's install guide warns that anyone who reaches the registration page first can become the instance admin and gain root access to the server. Create the admin account as soon as the installation finishes.

1. Put the dashboard behind a domain, then close 8000, 6001 and 6002

Give the Coolify dashboard a domain, served by the Coolify proxy over HTTPS. Once it works there, the dashboard, the real-time connection and the terminal all go through ports 80 and 443, and you can close public access to 8000, 6001 and 6002.

  • The simplest way is your hosting provider's firewall, if it has one: Coolify recommends it, because it drops unwanted traffic before it reaches the server.
  • Or bind the three ports to 127.0.0.1, or remove them, with a Compose override in /data/coolify/source/docker-compose.custom.yml, then run the install script again. Coolify's firewall page has the exact file. Don't edit the base Compose file: Coolify updates replace it.

Check that the dashboard works on its domain before you close the ports. Removing them first can lock you out of Coolify.

2. Don't rely on ufw alone: published container ports skip it

A port published by a Docker container is not filtered by your INPUT rules. Docker's documentation is blunt about ufw: packets are routed before the firewall rules can be applied. Coolify's firewall page says the same: blocking a port with ufw does not guarantee that a Docker-published port is blocked.

Traffic to a container is forwarded, not delivered to the host, so it goes through the FORWARD path. Docker leaves one chain there for your own rules, DOCKER-USER, which it evaluates before its own. A rule that closes a published port has to live there, and has to match the port the client asked for: after Docker's address translation the packet already carries the container's port, which is what --ctorigdstport is for.

# Drop new connections from the internet to published port 8000 (eth0 = the public interface).
iptables -I DOCKER-USER -i eth0 -p tcp -m conntrack --ctstate NEW --ctorigdstport 8000 -j DROP

Rules added with iptables are lost at reboot unless you save them (for example with iptables-persistent or netfilter-persistent). A firewall at your provider avoids the question, and Coolify also mentions the community tool ufw-docker for servers without one.

3. Keep the Traefik dashboard closed

Traefik is Coolify's default proxy (Caddy is the alternative), on ports 80 and 443: see the proxy overview. New proxy configurations do not expose the Traefik dashboard. Coolify's dashboard page warns that --api.insecure=true exposes it without authentication on Traefik's API port, and through the firewall if the proxy configuration publishes port 8080.

  • In the proxy configuration of each server in Coolify, check that the proxy does not publish 8080 and does not use --api.insecure=true.
  • If you need the Traefik dashboard, follow Coolify's page to put it behind a domain with authentication instead.

4. SSH: keys only, root by key

Coolify manages every server over SSH, the one it runs on included, as root with a key it generates. A non-root user is experimental and still needs passwordless sudo. Coolify's OpenSSH page recommends key authentication with root allowed by key only:

# /etc/ssh/sshd_config (or a file in /etc/ssh/sshd_config.d/)
PubkeyAuthentication yes
PermitRootLogin prohibit-password
PasswordAuthentication no

PasswordAuthentication no turns off password logins for every user, not only root: check that each person who logs in has a key first. Then test the configuration and reload SSH from the session you already have open:

sshd -t && systemctl reload ssh    # the service is "sshd" on RHEL-family systems
  • On servers that Coolify manages, allow SSH only from the address of the Coolify server where you can, as Coolify's firewall page suggests.
  • Coolify's key has no passphrase, by necessity. It lives under /data/coolify/ssh/keys, and /data/coolify/source/.env holds the installation's secrets: treat both, and their backups, like root passwords.

5. Keep Coolify up to date

Only Coolify 4.x receives security updates. Coolify publishes its fixes in GitHub security advisories and its versions on the releases page. Updating promptly matters more on a server whose dashboard can run commands as root.

What the InfraFence agent adds

With the steps above done, the agent covers what a firewall alone does not: the attacks that come through the ports you have to keep open.

  • It recognises Coolify (from /data/coolify) and shows it in the dashboard. Where a platform like Coolify manages the web server, the agent never edits its configuration.
  • Bans reach the containers. When Docker is present, the agent jumps to its own chain from DOCKER-USER as well as from INPUT, and keeps that jump first. Its bans, threat lists and country blocks therefore apply to ports published by containers too. If a firewall reload removes the jump, the agent puts it back.
  • It closes exposed database ports, containers included. A database published on a public port (MySQL, PostgreSQL, Redis, MongoDB and the other database, cache and admin ports the agent knows) can be closed to the internet from the dashboard, matching the port the client asked for. Loopback, private networks and your allow list keep access, and the change is checked and undone if SSH or a site stops answering. It does not close Coolify's own 8000, 6001 or 6002: do that as in step 1.
  • It lists your applications' domains. From agent 1.0.35 it reads them, read only, from the labels Coolify writes for its proxy (Traefik router rules or Caddy site addresses), so you can give each site the trust badge, verified with a DNS TXT record. It never runs anything in the proxy container. The web firewall reads access logs in the common or combined format, for example one you point to with the infrafence.log-path label; Coolify's proxy writes JSON logs (only with traffic analytics on), which the agent does not read.
  • It stops SSH brute force at the firewall, scores SSH sessions for risk, and watches outbound traffic, DNS, malware and file integrity like on any Linux server.
  • It stays out of ufw's way. Its rules live in its own INFRAFENCE chains, and it never edits yours.

The agent does not replace steps 1 to 5: creating the admin account right away, closing 8000 and keeping Coolify updated are still yours. What the agent reads and sends is documented in full.

Try it free on 1 server

Starter gives one server full protection, free and with no credit card.

  1. 01

    Create a free account, then open Servers › Add server to get your install token. It is valid for one hour.

    Create the token
  2. 02

    Then run this as root on the server:

    curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>