Lessons Learned : nginx and mixed HTTP/HTTPS Hosting
Stupid computers. That is exactly how I feel after beating my head against the wall for the past week while migrating several sites to a new nginx server. These are my crib notes so I can find the answers in one place next time I mess up the configuration.
My sites are running WordPress. Some are using one base domain with multiple hosts. Some of the hosts are going through a web proxy. Others are direct. Most of the hosts on the primary domain are going through SSL via a wildcard certificate. It is an interesting mix that pushes the limits of my newb nginx configuration skills.
HTTP2 Is A SSL Feature
This one took a while. It was NOT my FPM configuration for PHP. It was not browser cache issues. What it was, and something I learned tonight, was configuration nginx to process HTTP2 requests on port 80. Turns out HTTP2 is ONLY available for SSL connections, aka HTTPS on port 443 in web server terms.
My issue was adding http2 to the listen directive for ALL of my sites in the nginx sites-available/* files.
server { listen 80 http2; listen [::]:80 http2; server_name lance.bio; // more stuff here }
The proper configuration:
server { listen 80; listen [::]:80; server_name lance.bio; // more stuff here }
If you do try to server http2 data over port 80 all kinds of weird things happen. In Firefox I was getting downloads of DMS files. On Safari it just refused to do anything.
The best part is when this incorrect schmutz gets cached. By the browser, or opcache, or FPM, or even the proxy server.
Clear Your Cache
Once I fixed the HTTP2 protocol mix-up it didn’t appear to fix anything. Safari was exceptionally good at caching bad connection data. It has done this several times. The fix was to find my local browser cache and clear it. Sadly those people that visited the site while it was broken most likely will not be technical enough to know to even try clearing this so they’ll get a broken site until their cache expires. Hopefully that’s not set to be sometime in the year 2035.
I found that Sucuri likes to cache things too. Any sites I had running through that cloud proxy server needed to clear the cache. It can be very good at remembering malformed data.
Lastly clear the FPM cache on the server. Restarting FPM and nginx after any configuration changes is always a good idea.
service nginx retart && service php7.0-fpm restart
Do Not Set Two Default Servers
Copying configuration settings between my various site configuration files became a common theme. Make sure only ONE of your sites adds the default_server directive to the listen line. Otherwise nginx will not start.
All SSL Sites Need A Cert
Make sure you have an SSL certificate specified for all sites that are listening to the SSL port (HTTPS port 443). You will need a certificate that matches the server_name directive and will need to specify the path to the private key file and certificate file.
Common practice is to store the ssl configuration lines in a snippets subdirectory for nginx. You include the proper snippet for the server_name you are configuring. The ssl-params file is typically shared with all your SSL enabled sites.
server { listen 443 http2 ssl; server_name storelocatorplus.com; include snippets/ssl-domain.conf; include snippets/ssl-params.conf; ... }
The snippets/ssl-<domain>.conf file:
ssl_certificate /etc/ssl/domain.com.crt; ssl_certificate_key /etc/ssl/domain.com.key;
The CRT Is A COMBINED Certificate File
nginx needs the CA Intermediate certificate concatenated to the end of your domain-specific certificate. Load them both on your web server then cat cat_intermediate.crt >> domain.com.crt. If you do not do this nginx will not start after adding the above cert lines.
Thanks for this. I’ve finally figured out that nginx doesn’t particularly like mixed hosting, and your piece here seems to confirm it. I have struggled with the same problems (minus the http2 and plus letsencrypt). Yes, it can be done with separate IPs and other magic, but it’s just not worth it. I’m segregating the https and non-https sites by server so they’ll work until I get them all onto TLS.