When running Nginx behind Varnish with non-standard ports (e.g., Varnish on 80, Nginx on 8000), you might encounter unwanted port changes in redirects. For example, accessing example.com/blog
might redirect to example.com:8000/blog/
instead of maintaining the original port 80.
This happens because Nginx's server_name_in_redirect
and port_in_redirect
directives default to using the actual listening port (8000) rather than the client-facing port (80). We need to make Nginx aware of the public-facing port.
Add these directives to your Nginx server block:
server {
listen 8000;
server_name example.com;
# Fix redirect port issues
port_in_redirect off;
server_name_in_redirect off;
absolute_redirect off;
# Alternative if above doesn't work
# proxy_set_header Host $host;
# proxy_set_header X-Forwarded-Port 80;
location / {
# Your regular configuration
try_files $uri $uri/ =404;
}
}
After applying these changes, test with:
curl -I http://example.com/blog
Should return a Location header without port 8000:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/blog/
If you're passing requests through Varnish with proxy headers, ensure proper header forwarding:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 80;
- Forgetting to reload Nginx (
nginx -s reload
) - Multiple server blocks conflicting with each other
- Cache not being cleared between tests
The solution maintains clean URLs while preserving your reverse proxy architecture. Remember to test different scenarios including trailing slashes, missing files, and directory access.
When running Nginx behind Varnish with port translation (e.g., Varnish on port 80 forwarding to Nginx on port 8000), you might encounter an annoying behavior where Nginx adds the backend port to redirect URLs:
# Bad redirect example
curl -I http://example.com/2023
HTTP/1.1 301 Moved Permanently
Location: http://example.com:8000/2023/
Nginx's default behavior is to include the $server_port
in redirects when:
- Using
try_files
with directory redirects - Implementing
rewrite
rules - Handling missing trailing slash redirects
Add these directives to your Nginx server block:
server {
listen 8000;
server_name example.com;
# Critical settings for proper redirects
port_in_redirect off;
absolute_redirect off;
# Alternative if you need absolute redirects
# absolute_redirect on;
# server_name_in_redirect on;
location / {
try_files $uri $uri/ =404;
}
}
If you're behind a reverse proxy, you should also ensure proper header handling:
server {
listen 8000;
set $real_scheme $scheme;
if ($http_x_forwarded_proto) {
set $real_scheme $http_x_forwarded_proto;
}
set $real_port 80;
if ($http_x_forwarded_port) {
set $real_port $http_x_forwarded_port;
}
port_in_redirect off;
absolute_redirect on;
server_name_in_redirect on;
}
Verify with curl commands:
# Should return 301 without port 8000
curl -I http://example.com/blog
# Should maintain your domain without backend port
curl -I http://example.com/2023/
- Forgetting to reload Nginx after changes (
nginx -s reload
) - Mixing relative and absolute redirects
- Not considering HTTPS redirect scenarios