Skip to main content

Ports and firewall

Clouduler does not open ports on your host firewall. If you run ufw, firewalld or nftables, you add the rules yourself. This page lists every port, who uses it, and which ones must be open between your nodes versus to the internet. It also describes the iptables chains Clouduler manages for container traffic, so you know what not to touch.

The short version​

  • Between nodes (internal network only): TCP 7373, 7374, 7375 and UDP 4789. Never expose these to the internet. Put the internal network on a VPN (WireGuard, Tailscale, Headscale) or an isolated VLAN.
  • To your users: TCP 80 and 443 for published apps, and 8443 for the dashboard (can be limited to admin networks).
  • Only if you use the feature: TCP 2049 (served drives), port 53 (cluster DNS server), a UDP port for each WireGuard tunnel, and the ports of any raw expose entries.
  • Outbound: HTTPS to Let's Encrypt, Cloudflare, GitHub (self-update) and your image registries.

Port table​

PortProtocolWhat uses itBound onWho connectsOpen to
7373 (rpc_port)TCPRaft, forwarded writes, CLI trafficThe node's internal IPOther nodes, and the CLI on a managerOther nodes only
7374 (rpc_port + 1)TCPDrive transport: volume sync, served-drive handoff, folder importInternal IPOther nodesOther nodes only
7375 (rpc_port + 2)TCPRelay: connections to containers that run on another nodeInternal IPOther nodesOther nodes only
4789UDPVXLAN overlay for stack networksInternal IPOther nodesOther nodes only
8443 (web.port)TCP, HTTPSDashboard and APIAll addressesAdmin browsers, clouduler init --join, MCP clientsYour admin networks
8444 (web.backend_port)TCP, HTTPProxy to dashboard (bound only when the dashboard is served through the proxy)127.0.0.1 onlyThe local proxyNobody (loopback)
80 (proxy.http_port)TCP, HTTPReverse proxy: redirects, ACME HTTP-01, tls: false routesAll addressesClients of published hostnamesClients, and the internet for public apps
443 (proxy.https_port)TCP, HTTPSReverse proxyAll addressesClients of published hostnamesClients, and the internet for public apps
2049TCPNFSv4, served drives onlyExported to the internal subnetNodes that mount a served driveOther nodes only
53 (proxy.dns_server.port)UDP and TCPCluster DNS server, only when proxy.dns_server.enabledNode address on each listed networkLAN clientsYour LAN
Your choice, 51820 in examplesUDPWireGuard tunnel, wireguard networks onlyThe wg-<network> interfaceRemote peersThe tunnel's peers
Your choiceTCP or UDPx-clouduler.expose published ports0.0.0.0 on every nodeWhoever you intendSee the warning below

rpc_port is configurable per node. A node with rpc_port: 7373 occupies 7373 to 7375, so those three must be free. The VXLAN port, the relay offset and the address pools are fixed constants and cannot be changed.

Open the ports​

Replace the subnets with yours. The examples assume the internal network is 10.10.0.0/24, your LAN is 192.168.1.0/24, and SSH stays open.

The web UI cannot change your host firewall. Use the tabs in the CLI / config view. To check which ports your own cluster uses, open Settings > Network (web.port, proxy ports, DNS server port) and Nodes (each node's Cluster RPC port).

/settings/network?page=proxy
Settings, Network, Reverse proxy: the HTTP and HTTPS ports.

Outbound access​

Each node needs outbound TCP 443 to: Let's Encrypt (when proxy.acme.enabled), the Cloudflare API (when cloudflare is set), GitHub (when self_update is set), and your container registries. Git backup uses SSH to your repository host. The default registry is registry-1.docker.io over HTTPS 443; git backup uses SSH (port 22 unless your URL says otherwise).

The CLDR chains Clouduler manages​

Clouduler keeps its own iptables chains for container traffic. They are applied with iptables -w and replaced atomically, and the jumps into them are checked every 10 seconds so they survive a Docker restart. Only chains with the CLDR- prefix belong to Clouduler. Your own rules are not touched, but a hand edit to a CLDR- chain is overwritten within about 10 seconds.

ChainTable and hookWhat it does
CLDR-INfilter, INPUT position 1Stops containers from reaching the host's own listeners (dashboard API, raft, drive and relay ports). For packets from the overlay, egress and nat address pools it accepts: established and related traffic, DNS (port 53) to the overlay pool, the proxy's HTTP and HTTPS ports, every x-clouduler.expose port published on this node, and ICMP echo. Everything else is dropped. Docker -p publishes are not affected.
CLDR-OVL-SNATnat, POSTROUTINGMasquerades overlay traffic going to another node, only for TCP to the proxy ports and ICMP echo, so the remote proxy sees a node address and the network gate passes.
CLDR-NAT-<bridge>nat, POSTROUTINGMasquerades an egress or nat network's bridge out of its host interface.
CLDR-FWD-<bridge>filter, DOCKER-USER (else FORWARD)Egress kill-switch: accept bridge to interface, drop the rest from the bridge.
CLDR-WGIN-<iface>filter and natWireGuard ingress: default deny for new packets from the tunnel, accept only the opened ports. Ports that differ from their target get a DNAT to the node's internal address.
CLDR-ALLOWfilter, DOCKER-USER firstPer-stack allowed enforcement for routed packets. Exists only when some stack has an allowed list.
CLDR-ALLOW-NATnat, PREROUTING firstRedirects proxy traffic from a restricted stack to another node to this node's own proxy, so the proxy can tell the stack apart by source address.

What this means for you:

  • A container can reach the proxy (80/443) on any node, DNS on its overlay gateway, and expose ports on any node. It cannot reach 8443, 7373 to 7375 or any other host listener.
  • A container reaching another node's address is only NATed for TCP to the proxy ports and ICMP echo. Its other traffic there is dropped.
  • You can inspect the rules with sudo iptables -S CLDR-IN and sudo iptables -t nat -S CLDR-OVL-SNAT. Do not edit them.

Quirks and gotchas​