WordPress with NGINX Unit, HTTP2, IPv6

How to install WordPress with NGINX Unit PHP, SSL, HTTP2 and IPv6 on Debian 9.

Some quick notes on my recent WordPress hosting upgrade.

First read and follow Installing WordPress with NGINX Unit. Then make WordPress happy to answer nginx proxy requests via https. And then upgrade your SSL certs. Do an SSL test. Easy.

To make your site work on IPv6 with http2 you need these lines in your nginx config:


listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;

Do NOT use “listen 80 http2;” – http2 on port 80 is a bad idea it seems. If you enable http2 on port 80 you will be prompted to download something when you do an http request.

If you get a 301 redirect loop, you don’t have “$_SERVER[‘HTTPS’]=’on’;” in your WordPress wp-config.php file. This makes WordPress understand the original request was https and it does not need to rewrite the url with its canonical URL auto redirect feature.

Just for fun, you probably want to install some Firefox plugins which tell you if a site uses IPv6 and HTTP2. Check out HTTP/2 Indicator, SixOrNot and SixIndicator.

Obligatory Muppets Pic

Nginx config example:


upstream muppet-index_php_upstream {
server 127.0.0.1:8087; # NGINX Unit backend address for index.php with
# 'script' parameter
}

upstream muppet-direct_php_upstream {
server 127.0.0.1:8088; # NGINX Unit backend address for generic PHP file handling
}

server {
listen 80;
listen [::]:80;
server_name www.muppet.com muppet.com;
return 301 https://www.muppet.com;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name muppet.com;
return 301 https://www.muppet.com;

ssl on;
ssl_certificate /etc/letsencrypt/live/www.muppet.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.muppet.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.muppet.com/chain.pem;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.muppet.com;

ssl on;
ssl_certificate /etc/letsencrypt/live/www.muppet.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.muppet.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.muppet.com/chain.pem;

ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers On;
ssl_session_cache shared:SSL:128m;
add_header Strict-Transport-Security "max-age=31557600; includeSubDomains";
ssl_stapling on;
ssl_stapling_verify on;
# Your favorite resolver may be used instead of the Google one below
resolver 8.8.8.8;

root /var/www/muppet/;

charset utf-8;

location / {
try_files $uri @index_php;
}

location @index_php {
proxy_pass http://muppet-index_php_upstream;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;

}

location /wp-admin {
index index.php;
}

location ~* \.php$ {
try_files $uri =404;
proxy_pass http://muppet-direct_php_upstream;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}

}

LLAP.