Mastering Nginx: Serving HTTP&HTTPS Traffic from a Single Port

When I first set up my web server, I used port 8086 for HTTP traffic. It worked fine—it was functional, accessible, and did what I needed. But as time went on, I realized something: sticking to standard ports, 80 for HTTP and 443 for HTTPS, isn’t just about following convention; it’s about improving accessibility, security, and professionalism.

In this post, I’ll share why I decided to migrate from port 8086 to standard ports 80 and 443 and how I redirected traffic to ensure a smooth transition without breaking anything.

Why Move from non-default port?

  1. Accessibility:
    • Let’s face it—most users (and even some tools) expect websites to operate on ports 80 and 443. Using non-standard ports like 8086 often requires users to manually enter the port number, which is far from intuitive.
  2. Professionalism:
    • Imagine typing a URL like http://mywebsite.com:8086. It doesn’t scream “professional,” does it? Using standard ports makes your website feel more polished.
  3. Security:
    • HTTPS on port 443 is the industry standard for secure communication. It’s what modern browsers look for, and moving to 443 ensures encryption and compliance with best practices.
  4. Compatibility:
    • Many firewalls and network configurations assume traffic on 80 and 443 is legitimate, but non-standard ports like 8086 might be blocked or flagged as suspicious.

The Challenge

One hurdle in this migration was ensuring traffic to 8086 didn’t suddenly break. People already using the old setup needed to be redirected seamlessly to the new ports. What made this trickier was that port 8086 was handling both HTTP and HTTPS traffic, and I wanted a clean solution without duplicating configurations.

The Solution

After some experimentation, I came up with a simple yet effective Nginx configuration. Here’s how I handled it based an stackexchange post1:

Nginx Configuration for Port 8086

This configuration ensures:

  • HTTP requests on 8086 are redirected to 80.
  • HTTPS requests on 8086 are redirected to 443.
server {
    listen 8086 ssl;

    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;

    # Redirect HTTP traffic (error 497)
    error_page 497 301 =307 https://$host$request_uri;

    # Redirect HTTPS traffic
    location / {
        return 301 https://$host$request_uri;
    }
}
Bash

When a client sends plain HTTP traffic to a port configured for SSL/TLS, Nginx cannot complete the SSL handshake because the client did not initiate an encrypted connection. This results in an internal Nginx error.

Nginx Error Code 497
  • Nginx uses error code 4972 to represent this situation: “Plain HTTP traffic received on an HTTPS port.”
  • This error is specific to Nginx and not a standard HTTP status code.
Redirecting HTTP Traffic
error_page 497 301 =307 https://$host$request_uri;
Bash

This directive does the following:

  • Captures the 497 error.
  • Issues a 307 Temporary Redirect (overrides the default 301 Moved Permanently) to the same host and URI but forces HTTPS.

This way, when HTTP traffic accidentally reaches port 8086, the client is instructed to retry the request over HTTPS.

Aspect301 or =301=307
Caching BehaviorRedirects are cached permanently.Redirects are not cached.
Request Method ChangeSome browsers may change POST to GET.Original request method is preserved.
Temporary vs PermanentIndicates a permanent move.Indicates a temporary move.
Nginx-Specific BehaviorWithout =, the behavior may vary.Always enforces 307 with =.

GET and POST are two fundamental HTTP methods, each serving distinct purposes. GET is used to retrieve data from a server, appending parameters to the URL, making it suitable for idempotent, cacheable requests like searches or data retrieval. In contrast, POST sends data in the request body, ideal for submitting sensitive or large payloads such as forms, uploads, or creating resources. While GET exposes data in URLs (less secure for sensitive information), POST keeps it hidden in the body, enhancing security when combined with HTTPS. Choosing between them depends on the task: GET for reading and POST for modifying data or handling sensitive operations.

The following command and its output shows what 301 looks like with curl -v http://blog.wangxm.com:

home  curl -v http://blog.wangxm.com                                                                     git:master*
*   Trying xxx.xxx.xxx.xxx:80...
* Connected to blog.wangxm.com (xxx.xxx.xxx.xxx) port 80 (#0)
> GET / HTTP/1.1
> Host: blog.wangxm.com
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Length: 169
< Content-Type: text/html
< Date: Fri, xx Xxx xxxx 19:31:08 GMT
< Location: https://blog.wangxm.com/
< Server: nginx/x.xx.x
<
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/x.xx.x</center>
</body>
</html>
* Connection #0 to host blog.wangxm.com left intact
Bash

For comparison, this is what 307 looks like with the command curl -v http://blog.wangxm.com:8086:

home  curl -v http://blog.wangxm.com:8086                                                                git:master*
*   Trying xxx.xxx.xxx.xxx:8086...
* Connected to blog.wangxm.com (xxx.xxx.xxx.xxx) port 8086 (#0)
> GET / HTTP/1.1
> Host: blog.wangxm.com:8086
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 307 Temporary Redirect
< Server: nginx/x.xx.x
< Date: Fri, XX Xxx xxxx 19:31:17 GMT
< Content-Type: text/html
< Content-Length: 171
< Connection: close
< Location: https://blog.wangxm.com/
<
<html>
<head><title>307 Temporary Redirect</title></head>
<body>
<center><h1>307 Temporary Redirect</h1></center>
<hr><center>nginx/x.xx.x</center>
</body>
</html>
* Closing connection 0
Bash
HANDLING The Expected Behavior

For HTTPS requests, the client initiates a proper SSL/TLS handshake. Once the handshake is successful, the request is processed as usual.

location / {
    return 301 https://$host$request_uri;
}
Bash
  • For valid HTTPS requests, this block issues a 301 Moved Permanently redirect.
  • It ensures all traffic on port 8086 is redirected to the appropriate HTTPS URL, typically on port 443.

Lessons Learned

1. Simplicity is Key

Previously, I tried setting up separate directives for HTTP and HTTPS on port 8086. It worked but felt clunky. By using error_page 497, I streamlined the configuration and avoided duplication.

2. Test Before Deploying

Running nginx -t before restarting the server saved me from potential headaches. If you’re not using this command yet, make it your best friend:

nginx -t
Bash

3. Redirection Matters

Redirecting old traffic to the new setup is crucial. Without this step, users trying to access http://mywebsite.com:8086 would hit a dead end.

The Result

Now my website:

  • Operates on standard ports 80 and 443.
  • Automatically redirects old traffic from 8086.
  • Looks and feels more professional, with HTTPS enabled across the board.
PortProtocolSite Link
80httphttp://blog.wangxm.com
8086httphttp://blog.wangxm.com:8086
443httpshttps://blog.wangxm.com
8086httpshttps://blog.wangxm.com:8086

Conclusion

Migrating from port 8086 to 80 and 443 was more than a technical change—it was a step toward aligning with best practices, enhancing security, and improving the user experience. If you’re considering a similar migration, I hope this guide makes the process easier and inspires you to embrace the simplicity and standards of ports 80 and 443.

Have you done a similar migration? Share your experience in the comments!

  1. Handling http and https requests using a single port with nginx[]
  2. Module ngx_http_ssl_module[]

Posted

in

,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

🧭