UFW Firewall
UFW Firewall
Migration in progress.
api.legendary-arena.comand its PostgreSQL are moving off Render onto a self-hosted DigitalOcean Ubuntu droplet fronted by Cloudflare, perdocs/PLAN.md. Until decommission, Render stays warm as the rollback target.
Summary
UFW Firewall sets the droplet’s inbound perimeter to default-deny, then opens only SSH, HTTP, and HTTPS. It is a Phase 1 hardening step that runs after the SSH daemon is locked down and before web traffic is fronted by Cloudflare.
Mechanics
The entity is owned by infra/scripts/06-ufw.ps1
, an idempotent PowerShell provisioner that runs under Set-StrictMode -Version Latest and $ErrorActionPreference = 'Stop' and requires root (per docs/PLAN.md
).
- Root gate.
Require-Rootthrows if the process is not uid 0. - SSH port resolution. Reads
$SshPortfrom theSSH_PORTenvironment variable, defaulting to22when unset. - Default policy.
ufw default deny incomingandufw default allow outgoing— deny everything inbound, permit everything outbound. - Allow rules. Opens SSH on
$SshPort/tcp, then80/tcpand443/tcp. The allow-SSH rule is issued before the firewall is enabled so the default-deny policy never strands the live session. - Enable and report.
ufw --force enableactivates the ruleset non-interactively, thenufw status verboseprints the result.
It is idempotent because UFW rules are declarative — re-running converges to the same ruleset rather than stacking duplicates.
Interactions
- SSH Hardening
. The allow-SSH rule must match the port the hardened daemon actually listens on; if that port is non-standard, pass the same value here via
SSH_PORT. - Cloudflare TLS
. This page opens
443wide; the Cloudflare TLS step (script 21) later narrows the 443 rule to Cloudflare’s published IP ranges so origin HTTPS is reachable only through the CDN. - Fail2ban and Unattended Upgrades . A complementary host-security layer — UFW blocks unlisted ports while fail2ban bans brute-force attempts on the allowed ones.
Edge Cases
- Order-of-operations lockout. Enabling default-deny before the allow-SSH rule would drop your live session. The script issues the SSH allow first for exactly this reason — preserve that order in any manual re-run.
- Port mismatch with the hardened daemon. If SSH runs on a non-standard port, you must export
SSH_PORTto match SSH Hardening ; otherwise UFW opens the wrong port and blocks logins. - 443 is opened broadly here. Until Cloudflare TLS tightens it, the origin’s HTTPS port is reachable from anywhere, not just Cloudflare. That is expected at this stage, not a final state.
- Outbound is unrestricted.
default allow outgoingmeans the host can reach anything egress-side; this firewall governs inbound only.
Execute
sudo pwsh -File infra/scripts/06-ufw.ps1
# Override the SSH port to match a non-standard hardened daemon:
sudo SSH_PORT=22 pwsh -File infra/scripts/06-ufw.ps1
Verify
sudo ufw status verbose
# expected: Status: active
# Default: deny (incoming), allow (outgoing)
# 22/tcp ALLOW IN Anywhere
# 80/tcp ALLOW IN Anywhere
# 443/tcp ALLOW IN Anywhere
References
- infra/scripts/06-ufw.ps1 — the owning provisioner
- docs/PLAN.md — Phase 1 hardening and script conventions