Skip to content

Fix: Nginx 1.22 Redirects Dropping Port Number

Following an upgrade to Nginx 1.22 (common in Amazon Linux 2023, Ubuntu 22.04, and updated Docker images), many administrators notice that internal redirects—such as appending a trailing slash to a directory—strip the port number from the URL.

For example, a request to http://example.com:8080/dashboard is redirected to http://example.com/dashboard/, causing a “Connection Refused” error because the client attempts to reach the service on the default port 80 instead of the custom port 8080. This is primarily due to changes in how Nginx 1.22 handles absolute_redirect defaults and Host header inheritance.

While Nginx logs may show a standard 301 Moved Permanently, the symptom is visible via curl or browser developer tools:

Terminal window
# Requesting a directory without a trailing slash
$ curl -I http://api.internal.cloud:8443/v1/docs
HTTP/1.1 301 Moved Permanently
Server: nginx/1.22.1
Date: Wed, 24 May 2023 10:00:00 GMT
Content-Type: text/html
Content-Length: 169
Location: http://api.internal.cloud/v1/docs/ <-- PORT 8443 IS MISSING
Connection: keep-alive
  1. Check Listen Port vs. Host Header: Is Nginx listening on a port that differs from what the client sees (e.g., Docker port mapping -p 8443:80)?
  2. Verify absolute_redirect State: In 1.22, the default is on. This forces Nginx to generate a full URL for redirects rather than a relative path.
  3. Inspect Proxy Headers: If Nginx is behind an AWS ALB or NLB, verify if the Host header passed to Nginx includes the $proxy_port.
  4. Validate port_in_redirect: Ensure Nginx is explicitly told to include the listening port in its redirect calculations.
  5. Identify OS/Distribution: This behavior is prevalent in environments using NGINX Mainline or updated Stable packages on Debian 11/12 or RHEL-based systems.

To resolve this, you must modify the Nginx configuration at the http, server, or location block level. There are two primary strategies depending on your Cloud architecture.

Section titled “Option 1: Disable Absolute Redirects (Recommended for Local/Docker)”

By setting absolute_redirect off;, Nginx will issue a relative redirect (e.g., Location: /v1/docs/). The browser will then automatically append this to the existing domain and port.

Edit your nginx.conf or site-specific configuration:

Terminal window
http {
# ... existing config ...
server {
listen 8080;
server_name _;
# Fix for Nginx 1.22+ port dropping
absolute_redirect off;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
Section titled “Option 2: Force Port Inclusion (Recommended for Cloud LBs)”

If your environment requires absolute URLs (e.g., specific security requirements or complex proxy chains), ensure Nginx acknowledges the port.

Terminal window
server {
listen 8080;
server_name example.com;
# Ensure the port is included in the Location header
port_in_redirect on;
absolute_redirect on;
# Ensure Host header includes the port if proxying
proxy_set_header Host $host:$proxy_port;
}

If you are using the official nginx:1.22-alpine image, you can use an environment variable substitution or a custom config snippet:

FROM nginx:1.22-alpine
# Inject a custom config snippet to disable absolute redirects globally
RUN echo "absolute_redirect off;" > /etc/nginx/conf.d/fix-redirects.conf
COPY ./html /usr/share/nginx/html

After applying the changes and reloading Nginx (nginx -s reload), verify the Location header again:

Terminal window
$ curl -I http://api.internal.cloud:8443/v1/docs
HTTP/1.1 301 Moved Permanently
Location: /v1/docs/ <-- Relative path preserves the original port
# OR
Location: http://api.internal.cloud:8443/v1/docs/ <-- Port preserved