Port 80 is the default for HTTP and carries everything in plain text. Port 443 carries HTTPS. The right configuration is not to close port 80 — it is to serve exactly one thing there: a permanent redirect to HTTPS.
Every security guide says the same true thing about port 80, and a certain number of readers respond by firewalling it shut. That breaks two things quietly, and the resulting failures do not obviously point back at the port. Here is what is actually at stake and what the correct setup looks like.
Table of contents
- What plain HTTP exposes
- Why you still keep port 80 open
- HSTS, and the redirect that still leaves a gap
- Ports are conventions, not security boundaries
- How this fits the rest of the stack
- FAQ
What plain HTTP exposes
On port 80 the entire exchange is readable by anyone on the network path — the coffee shop wifi, the ISP, any intermediate network.
- The full URL, including query parameters. A password reset token in a URL is a password reset token in a log file.
- Every header, including cookies. A session cookie observed once is an account taken over.
- The request body. A login form posted over HTTP sends the password as readable text.
- The response. The entire page, including anything private on it.
Worse than observation is modification. Plain HTTP has no integrity protection, so a party in the path can alter the response — injecting scripts or advertising, or rewriting a download link. This has been done at scale by networks and by malware, and the visitor sees nothing unusual.
Browsers have responded accordingly. Plain HTTP is marked Not Secure in the address bar, and secure-context features — service workers, the clipboard API, geolocation, camera access, crypto.subtle — refuse to work. So a site on HTTP is not only insecure, it is functionally limited.
Why you still keep port 80 open
Two things break if you close it, and neither failure names the port.
Certificate renewal. The HTTP-01 challenge used by ACME clients works by serving a file over plain HTTP on port 80. Close it and renewal fails — not immediately, but sixty days later when the certificate expires and every visitor gets a browser warning. This is a delayed-action outage, which is the worst kind.
The alternative is the DNS-01 challenge, which validates by publishing a TXT record and needs no inbound port at all. If you genuinely must close port 80, switch to DNS validation deliberately rather than discovering the problem at expiry.
Everyone who types a bare domain. A browser given example.com with no scheme still tries HTTP first in many cases. With port 80 closed, that request is refused and the visitor sees a connection error rather than your site. Modern browsers increasingly attempt HTTPS first, but the fallback behaviour is not universal across browsers, versions and embedded webviews.
So the correct configuration is: port 80 open, serving one thing.
# nginx: everything on 80 redirects, except the ACME path
server {
listen 80;
server_name example.com www.example.com;
location /.well-known/acme-challenge/ {
root /var/www/acme;
}
location / {
return 301 https://$host$request_uri;
}
}
The 301 matters. A permanent redirect is cached by the browser, so subsequent visits skip the insecure hop entirely. A 302 sends every visitor over plain HTTP first, every time.
HSTS, and the redirect that still leaves a gap
A redirect closes most of the exposure and not all of it: the first request still travels over HTTP before the redirect arrives. An attacker in the path can intercept that first request and prevent the upgrade — the well-known stripping attack.
HSTS closes it. The header tells the browser to use HTTPS for this domain for a stated period, without asking:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
After the first successful HTTPS visit, the browser refuses plain HTTP for your domain entirely, converting it internally before any request goes out.
Deploy it carefully, because it is difficult to reverse. Browsers honour the cached policy for the full duration regardless of what you send afterwards, so a subdomain that cannot serve HTTPS becomes unreachable for up to a year.
- Confirm every subdomain serves HTTPS correctly.
- Start with a short max-age — a few hundred seconds — and verify nothing breaks.
- Raise it in stages to a year.
- Add
includeSubDomainsonly once you are certain about every subdomain. - Consider preloading only after all of the above has been stable for a while.
The always parameter in the nginx example is easy to miss and matters: without it, the header is omitted on error responses, which are exactly the responses an attacker might induce.
Ports are conventions, not security boundaries
One conceptual point that resolves a recurring confusion. Port 80 is not insecure and port 443 is not secure — they are default port numbers. The security comes from TLS, and TLS can run on any port.
# Perfectly valid: HTTPS on a non-standard port
https://example.com:8443/
# Also valid, and a bad idea: plain HTTP on 443
http://example.com:443/
This matters for internal services. A dashboard on port 8080 is not protected by being on an unusual port — it is either encrypted or it is not, and an internal network is not a substitute for encryption. Anyone on that network, including anything that has gained a foothold on it, sees the traffic.
Two practical implications:
- Encrypt internal traffic too. The assumption that the internal network is trusted is exactly what an attacker relies on after a first foothold.
- Do not use an unusual port as a security measure. A port scan finds it in seconds. Use authentication and a firewall, and treat the port choice as a convenience.
The corollary for a public site is short: port 80 open and serving only a permanent redirect, port 443 serving everything, HSTS set, and no path by which real content is delivered unencrypted.
How this fits the rest of the stack
The correct setup here is small and everyone still gets a piece of it wrong — a temporary redirect instead of a permanent one, HSTS without always, or port 80 closed in a burst of tidiness that expires the certificate two months later.
RunxBuild makes it the default rather than a checklist. A custom domain on a static site or a web service gets its certificate issued and renewed automatically, HTTP redirected to HTTPS, and response headers and redirects configured in the dashboard rather than in a server file you edit over SSH. Static sites include 120GB of bandwidth, then $0.10/GB. Services in Node, Next.js, Python, Go, Ruby, Java, .NET or Docker deploy from your GitHub repository with build and runtime logs in one place, and managed MySQL and Postgres sit behind them on private networking rather than on an exposed port. To see what a site, a service and a database add up to, the RunxBuild hosting calculator lists them as separate line items.
Useful related references:
- HTTP/1.1 403 Forbidden: What the Server Is Actually Telling You
- n8n HTTP Request Node: The Auth and Error Playbook
- HTTP Error 509: Bandwidth Limit Exceeded (and How to Fix It)
- Services on RunxBuild
FAQ
Should I close port 80 entirely?
No. Closing it breaks HTTP-01 certificate validation, so renewal fails and the certificate expires weeks later with no obvious cause. It also refuses connections from anyone whose browser tries HTTP first for a bare domain. Keep it open and serve only a permanent redirect to HTTPS.
What is the difference between port 80 and port 443?
They are default port numbers, not security properties: 80 for HTTP and 443 for HTTPS. The security comes from TLS, which can run on any port. HTTPS on port 8443 is just as encrypted, and plain HTTP on 443 is just as exposed.
Should the HTTP to HTTPS redirect be 301 or 302?
- A permanent redirect is cached by the browser, so return visits go straight to HTTPS without an insecure first request. A 302 sends every visitor over plain HTTP first, every single time, which leaves the gap a redirect is supposed to close.
What does HSTS add if I already redirect?
It removes the first insecure request. With only a redirect, the initial connection still travels over HTTP and can be intercepted before the upgrade arrives. HSTS tells the browser to use HTTPS for your domain unconditionally, so it never sends that request. Introduce it with a short max-age first, since the policy is cached and hard to reverse.
Do I need HTTPS on an internal network?
Yes. An internal network is not a trust boundary — anything that gains a foothold on it sees unencrypted traffic, and that is precisely what an attacker counts on after an initial compromise. Running a service on an unusual port is also not protection, since a scan finds it immediately.