Firewall & Network Hardening
Which Logship ports to expose, which to keep private, and firewall rules for public-facing servers.
Firewall & Network Hardening
Logship binds several sockets. Only the HTTP API and (optionally) the frontend host should ever be reachable from the public internet. The cluster RPC and metrics ports carry unauthenticated, unencrypted node-to-node traffic and must stay on a trusted network.
Start from a default-deny inbound policy and open only the ports below.
Ports
| Port | Proto | Component | Default bind | Public exposure |
|---|---|---|---|---|
5000 | TCP + UDP | Backend HTTP API & Web UI | all interfaces | Yes — behind a TLS reverse proxy |
8000 | TCP | Frontend SPA host (fe-react) | all interfaces | Only if serving the SPA directly |
6000 | TCP | Database cluster RPC (worker) | all interfaces | No — private network / peers only |
6002 | TCP | Backend cluster RPC (worker) | all interfaces | No — private network / peers only |
6000/6002 | TCP | Cluster RPC (master) | loopback | No — loopback only, never off-host |
49999 | UDP | Internal metrics | outbound (egress) | No — not an inbound listener |
The API port serves HTTP/1.1, HTTP/2, and HTTP/3. HTTP/3 runs over QUIC, so 5000 must be opened for both TCP and UDP if you expose it directly or advertise HTTP/3 through the proxy.
Changing the ports
Every port above is configurable. Override the key in the referenced config section rather than assuming the default.
| Port | Config key | Reference |
|---|---|---|
5000 | backend.listenPort | Database → backend |
8000 | Kestrel.Endpoints.Http.Url | Frontend → Http |
6000 | database.endpoints.worker / database.endpoints.master | Database → endpoints |
6002 | backend.endpoints.worker / backend.endpoints.master | Database → endpoints |
49999 | agent.udpMetricsEndpoint | Database → agent |
The cluster RPC endpoints (6000, 6002) take the bind address as well as the port: change the 0.0.0.0 in the worker endpoint to a private interface to stop binding on all interfaces.
Allow
- TLS ingress (
443/tcp, and443/udpfor HTTP/3). Terminate TLS at a reverse proxy and forward to the backend on5000. Do not expose5000in plaintext to the internet. 8000/tcp— only when the frontend host is served directly. Prefer fronting it with the same TLS proxy on443.
Disallow
The worker endpoints (6000, 6002) bind to 0.0.0.0 by default and the transport is plaintext with no authentication. Anyone who can reach them can read and write cluster data. Restrict them to peer node addresses on a private subnet, or bind them to a private interface in configuration.
6000/tcp,6002/tcp— block from the public internet. Allow only from known cluster peer IPs. Single-node deployments should block them entirely.49999/udp— the metrics socket is outbound only; nothing needs to reach it from outside the host. Block inbound.- Everything else — drop by default.
Reverse proxy pattern
For a public server, expose only the proxy and keep the backend on loopback or a private interface:
internet ──443/tcp+udp──▶ reverse proxy (TLS) ──▶ 127.0.0.1:5000 backendGate load-balancer health checks on GET /health/ready, which is anonymous — see Install → Health checks.
Example rules
Open the TLS port, keep cluster and metrics ports closed, and default-deny the rest.
ufw default deny incoming
ufw default allow outgoing
ufw allow 443/tcp
ufw allow 443/udp
ufw enablefirewall-cmd --permanent --set-target=DROP
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=443/udp
firewall-cmd --reloadnft add table inet filter
nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input iif lo accept
nft add rule inet filter input tcp dport 443 accept
nft add rule inet filter input udp dport 443 acceptWhen running a multi-node cluster, add explicit allow rules for peer addresses rather than opening the ports globally, e.g. ufw allow from 10.0.0.0/24 to any port 6000 proto tcp.