Networking & Firewalls
”Origin unreachable” errors behind a CDN/proxy
If you’re running behind a CDN or reverse proxy (e.g. Cloudflare) in front of Nginx in front of your app container, an “origin unreachable”-class error means traffic never reached your server at all — narrow it down from the inside out:
# From the server itself - bypasses the CDN/DNS/firewall entirely,
# isolates whether Nginx + certificate + backend proxy actually works
curl -vk https://localhost/If that succeeds locally but the public domain still fails, the problem is somewhere between the CDN and your server — most likely a firewall layer.
Two independent firewall layers (cloud security groups vs. OS firewall)
Symptom: a cloud provider’s network-level security rules (security group / security list / VCN ingress rules) already allow the port, Nginx is confirmed listening and serving valid TLS locally, but the public domain still can’t reach it.
Cause: many cloud instances have two separate firewall layers: the
cloud-level security group controls whether traffic reaches the instance’s
network interface at all, but does not touch the instance’s own
OS-level firewall (iptables/ufw). Opening a port in one layer doesn’t
open it in the other.
Diagnose:
# Confirm Nginx is actually bound to the port
sudo ss -tlnp | grep -E ':80|:443'
# Check the OS-level firewall's rule set directly
sudo iptables -L INPUT -n --line-numbers
# Check the higher-level firewall tool too, if present
sudo ufw status verboseFix: add an explicit accept rule for the port, inserted before the final reject/drop rule (check its line number first, since it varies per instance):
sudo iptables -I INPUT <line-before-reject> -p tcp --dport <port> -m state --state NEW -j ACCEPT
# Persist across reboots
sudo netfilter-persistent save
# if not installed:
sudo apt-get install -y iptables-persistent && sudo netfilter-persistent saveAfter fixing the firewall layer, an “origin unreachable” error changing to a “bad gateway”-class error is a good sign — it means the connection is now reaching your server, and the next problem (nothing actually listening on the port the proxy forwards to) is a separate, later-stage issue. See Deployment & Docker.
CSRF round-trip testing across a real domain
A single request/response round-trip can hide session-ordering bugs (e.g. a filter that clears a token on its own response). Test the same session twice in a row, reusing the same cookie jar:
curl -i -c cookies.txt https://your-api-domain/api/v1/auth/me
TOKEN=$(grep XSRF-TOKEN cookies.txt | awk '{print $NF}')
curl -i -b cookies.txt -c cookies.txt -H "X-XSRF-TOKEN: $TOKEN" \
-H "Content-Type: application/json" \
-X POST https://your-api-domain/api/v1/some-endpoint -d '{}'
# Second mutating request, same session - re-read the token since it
# may have changed, then confirm this one also succeeds
TOKEN=$(grep XSRF-TOKEN cookies.txt | awk '{print $NF}')
curl -i -b cookies.txt -c cookies.txt -H "X-XSRF-TOKEN: $TOKEN" \
-H "Content-Type: application/json" \
-X POST https://your-api-domain/api/v1/some-endpoint -d '{}'