Install Nginx
Verify the version:
Firewall
sudo ufw allow 'Nginx Full'
sudo ufw allow 'Nginx Full'
UFW ships with predefined app profiles.
'Nginx Full' opens both port 80 (HTTP) and port 443 (HTTPS). There are also 'Nginx HTTP' (80 only) and 'Nginx HTTPS' (443 only) if you want to be more restrictive — but since SSL gets added later via Certbot, both ports need to be open, so Full is correct here.sudo ufw allow OpenSSH
sudo ufw allow OpenSSH
Opens port 22 (SSH). This step is critical — if UFW is enabled without explicitly allowing SSH first, you’ll lock yourself out of the VPS the moment the firewall activates, since UFW defaults to denying all incoming connections.
sudo ufw --force enable
sudo ufw --force enable
Turns the firewall on. By default
ufw enable asks for a y/n confirmation (since it could disrupt active SSH sessions) — --force skips that prompt, which is useful for scripting/automation but means you must be 100% sure SSH is already allowed before running it.Confirm the rules took effect:
Default catch-all redirect (HTTP → HTTPS)
Before setting up per-app server blocks, add a catch-all block that handles any request that doesn’t match a known domain (raw IP hits, typo’d hostnames, unmatchedHost headers) and forces it onto HTTPS.
/etc/nginx/sites-available/default:
default_server
default_server
Marks this block as the fallback for port 80 — any request whose
Host header doesn’t match a server_name in your other configs lands here instead of silently hitting the first server block in load order. Assigned inline on the listen line itself; no separate config or setup needed.server_name _;
server_name _;
The underscore is a catch-all placeholder that matches nothing by name — Nginx relies on
default_server (not this line) to route unmatched traffic here.return 308 vs 301
return 308 vs 301
308 preserves the original HTTP method and body on redirect (unlike the older 301, which some clients silently downgrade to GET) — important if a client sends a POST and you don’t want it dropped.Example reverse proxy config
/etc/nginx/sites-available/j-optic-backend: