Infrastructure and deployment
The app can be perfect and the server still wide open. These checks are about how and where it runs.
Checklist
- Expose only the ports you mean to. A host firewall allowing 22, 80, and 443
is not enough on its own: Docker publishes container ports by writing iptables
rules that bypass ufw, so a
-p 9000:9000can be reachable from the internet even when the firewall "only allows 443". Bind container ports to127.0.0.1unless they are meant to be public, and scan your own public IP to confirm what is actually open. - Keep admin panels off the public internet. Dashboards like Portainer, database admin tools, and metrics UIs should never be internet-facing. A fresh admin panel with no account set is a full takeover: anyone who reaches it during the setup window owns the box. Restart policies can reopen that window.
- Bind app servers to loopback and front them with a reverse proxy. The app
listens on
127.0.0.1; nginx or the edge terminates TLS and forwards. - Make the origin unreachable except through the edge. If you use Cloudflare or similar, enforce it with authenticated origin pulls (mTLS) or an IP allowlist, so attackers cannot skip the WAF by hitting the origin IP.
- Set security headers.
Strict-Transport-Security,X-Content-Type-Options: nosniff,X-Frame-Options: DENY(orframe-ancestors 'none'), a strictContent-Security-Policy(ideallyscript-src 'self'with nounsafe-inlineorunsafe-eval), aReferrer-Policy, and a lockedPermissions-Policy. - Do not leak version and stack. Strip
ServerandX-Powered-Bybanners. - Block access to dotfiles and build output.
/.env,/.git/, config files, and source maps must not be web-reachable. Confirm each returns 403 or 404. - Show generic errors. No stack traces or internal paths to users; log the detail server-side.
- Keep the runtime patched and run the app as a non-root, least-privileged user, in a container or sandbox where practical.
How to test
- From a machine outside your network, scan your public IPs for open ports.
- Request
/.env,/.git/config, and a.mapfile on your domain. - Read the response headers of your home page and check each item above.