Nginx: IPv6 and SSL termination

Sep 2, 2012   #https  #IPv6  #nginx  #ssl 

I just installed the beautiful NGINX reverse proxy on my personal server. I use it to run various personal web-based services like this blog, Etherpad or Gitlab. That’s 3 different programming languages, PHP, JS, Ruby. Wow.

Sadly, none of them handles natively HTTPS nor IPv6 moreover, they all require a standalone port to run on. Hopefully, reverse proxies are here to solve the problem. And I chose NGINX. I was previously using a home grown one which is much, much easier to configure but not really state of the art. So Bye Bye :)

I want to to enforce HTTPS connections and allow both IPv4 and IPv6.

Add this to the top of each “server” block:

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

Add this right after the previous or directly in the “http” block if “nginx.conf” if you have wildcard certificate:

ssl_certificate /etc/ssl/private/ssl-full-chain.crt;
ssl_certificate_key /etc/ssl/private/ssl-main.key;

Note that Nginx expects the whole certificate chain to be in the .crt or .pem file that is you actual certificate followed by the whole certification chain up to the root CA at the end.

The last step is now to “force” HTTPS. The idea is to read an ssl variable. If unset, redirect to the HTTPS version of the page:

if ($ssl_protocol = "") {
    rewrite ^   https://$server_name$request_uri? permanent;

If Nginx complains with “nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)”, try appending “ipv6only=on” to the the faulty config line.

Try on this blog, it should only be accessible with HTTPS :)