Securing your self-hosted website with Let’s Encrypt, part 7: a workflow to migrate from HTTP to HTTPS

If you've followed along the previous posts you will have noticed that I didn't get into details when mentioning how to migrate--I just assumed that you knew how to do that and eventually your site would be serving HTTPS using a certificate from Let's Encrypt.

But turns out that finding a good workflow to do this was one of the things that consumed most of my time initially! That, and the sheer fear of repetition.

I finally ended up writing a small node.js utility, site-setup, that would do a series of things for me:

  • generate the nginx configuration file, with variable features depending on command line parameters
  • generate a dhparams.pem file (why?)
  • create directories and set their proper permissions (e.g. a logs directory which is only owned by root, a public_html directory, etc)
  • enable the site in nginx (by creating a symbolic link), but not restart nginx

The utility is probably not really ready to be used by people other than me, which is why it doesn't have a README, but I published it anyway just in case you're curious. Although hey, it has built-in help for the command line arguments, so it's better documented than most of the code I've seen ;-)

This is the workflow I followed, armed with my utility:

  • If migrating from another server:
    1. Create the 'site' in nginx using the site-setup tool, enabling features such as php as needed, but not https yet. Also creating directories, setting proper permissions and enabling the site: sudo node index.js --domain --create-directories --write-nginx-conf --with-php --enable-site --user foo
    2. Test nginx configuration: sudo nginx -t
    3. Install files for site and import database (if required); this is different per site
    4. Edit /etc/hosts locally and make the domain point to the new IP address: 123.456.789.111
    5. Restart nginx: sudo service nginx restart
    6. Make sure the site works in the new server, maybe fix little silly things (e.g. adjust write permissions)
    7. If all looks good, change the DNS to point the A record (and maybe the WWW) to the new IP address (depends on each DNS manager)
  • Once the DNS have been propagated and the server is reachable via http and port 80, without the /etc/hosts 'trick':
    1. Log into server and run the Let's Encrypt client to obtain a certificate (more info)
    2. Run site-setup again with the same parameters as initially, but also add HTTPS features, generate dh-params and the HTTP to HTTPS redirect. E.g. sudo node index.js --domain --create-dhparams-file --write-nginx-conf --with-php --with-http-to-https-redirect --with-www-redirect --with-lets-encrypt --with-static-caching
    3. Test nginx configuration again (just in case!)
    4. All fine? Restart nginx and you're done for this domain!
  • Go to the next domain and repeat until done with all domains! 😎

The utility creates nginx configurations which should give you an A+ in the SSL labs test, which is cool.

But what is even cooler is that it is really fast to alter the domain nginx configuration without actually editing the configuration file, just by running the utility again but changing the command line parameters. That way, I avoided introducing errors, as I was not editing the file by hand, but it was generated.

I could think of two improvements for the site-setup tool:

  • Store the last used settings for a domain in a file, for example in /var/www/site-setup.ini, so you don't need to scroll up and down your bash history
  • Maybe make a kind of GUI front-end for the configuration so you don't need to remember all the possible options

but I have no plans to implement them any time soon, so don't get your hopes too high :P