I'm trying to avoid redirect chains in Nginx, which I am using as a reverse proxy to Apache.
I've been able to find plenty of documentation about redirecting HTTP
to HTTPS
.
I've also found plenty of documentation about redirecting www
to naked domain (or vice versa).
The vhosts/websites are (for the most part) subdomains of my primary website, example.com
.
Background: I am using this configuration because I am most familiar with Apache but I appreciate the performance improvements of Nginx and, more importantly, I have a NodeJS application running on the server and I'd like users to be able to access it without appending a port to the request. Nginx listens on port 80 for HTTP and port 443 for HTTPS and routes requests to the ports that I have configured Apache and NodeJS to use (port 8080 for Apache and port 4000 for Node).
Edit: I found the config generator tools at nginxconfig.io to be very helpful and much of what I got from there has been included unchanged.
For the "main" website, I'm using the www
subdomain so I need to redirect the following domains to https://www.example.com
:
http://example.com
http://www.example.com
https://example.com
Everything I can find seems to handle this in 2 redirects such as:
http://example.com
to https://example.com
to https://www.example.com
The answer in this question (which is actually a redirect of www
to the naked domain), uses an if
statement but Nginx docs suggest avoiding if
statements for performance reasons.
Question 1 Is there are way to handle these redirects in one redirect, and without triggering warnings about having blocks with duplicate server names?
Question 2 When I set up the block for port 80, what parameters do I need to include if all I am doing is redirecting?
My .conf
file looks like this:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
root /var/www/html/example.com;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# security
include nginxconfig.io/security.conf;
# logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log warn;
# index.html fallback
location / {
try_files $uri $uri/ /index.html;
}
# additional config
include nginxconfig.io/general.conf;
}
# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name example.com;
include nginxconfig.io/letsencrypt.conf;
location / {
return 301 https://$server_name$request_uri;
}
}
Do I need to have include nginxconfig.io/letsencrypt.conf;
in the block for port 80?
Do I need to add http2
after the listen
directives in the block for port 80 so that HTTP2 requests over HTTP get redirected to HTTPS while still supporting HTTP2 or is it sufficient to just include the http2
directive in the block for HTTPS/port 443.
The contents of nginxconfig.io/letsencrypt.conf
are:
# ACME-challenge
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
Contents of .../security.conf
are:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
#add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# . files
location ~ /\.(?!well-known) {
deny all;
}
location ~* (?:#.*#|\.(?:bak|conf|dist|fla|in[ci]|log|orig|psd|sh|sql|sw[op])|~)$ {
deny all;
}
I do plan to implement HSTS eventually, but obviously, need to get my basic configuration sorted out first.
Contents of .../general.conf
:
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;