I’ve spent the past week migrating this site from HostGator to a personal web server. Its had its literal ups and downs, with a LOT of learning along the way. First however, I’ll discuss why I made this change.

The first and foremost was HTTPS. Obviously HostGator supports HTTPS (what modern hosting service wouldn’t?) however for me to try and get a Let’s Encrypt certificate installed it was $20! Since free certs from Let’s Encrypt only last 90 days, that would very quickly cost me almost $80 per year. The second reason was for flexibility - HostGator has a great control panel if you’re only trying to do basic operations. However it is always challenging to find exactly what you need and its far easier to just cd into the directory and change configs manually. Lastly, I wanted to gain the experience of running my own web server and the challenges that it faces.

So, onto how I actually did it. I came to the realization that I didn’t want this server to only dedicated to Wordpress. I’ve heard many people talk about NGINX as a reverse proxy and decided that was the path I wanted to follow. This way, if I develop other small web apps I can containerize them and proxy requests to them as well. Another feature that was a selling point is that it is able to act as an SSL endpoint. This simplified the implementation of SSL on my server to a few lines in config files. My first step was to get NGINX up and running. In hindsight, it would have been better to get Wordpress up first, but this is how I did it. Live and learn. The install for nginx was simple, I just followed DigitalOcean’s guide on installing it found here: https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04

After I had the proxy up and running, I focused my efforts on installing SSL. Again, DigitalOcean had a guide that came in handy: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04 However I had a few issues in this guide with getting NGINX to server the acme challenge. The solution to this ended up being simple, but different from what they suggest in the guide. I added this location block to my main server block and that did the trick!

location /.well-known/acme-challenge/ {
  try_files $uri /dev/null =404;
}


After I had my certificates, I followed the rest of the guide and was met with the beautiful sight of the green lock when I served static content! I then turned my thoughts to migrating my wordpress instance. I decided to continue using it since it is a super easy platform to maintain my webpage. The biggest downside to Wordpress is the security of it (though it has definitely gotten better over the years. Since I realized security was going to be an issue, I decided to follow the wave of people containerizing their applications. This provides me the security of knowing that even if someone gains control of the container they can’t gain control over my server (which is actually a vm).

The install of a dockerized version of Wordpress was much harder than the NGINX deployment. I faced challenges with the containers unable to communicate, crashing, and redirect looping. After a good deal of searching I found a configuration that worked using the Wordpress image and a MariaDB SQL instance. I actually like this solution better than using MySQL since it has faster security updates and a far more open community. I’ve pasted the yml file I use below, passwords redacted of course :).

version: '2'

services:
   mariadb:
     image: mariadb:latest
     volumes:
       - ./db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: XXXXXXXXXXXXXXXX
       MYSQL_DATABASE: wordpress

   wordpress:
     links:
       - mariadb:mysql
     image: wordpress:latest
     ports:
       - "8080:80"
     environment:
       WORDPRESS_DB_HOST: mariadb:3306
       WORDPRESS_DB_PASSWORD: XXXXXXXXXXXXX
     working_dir: /var/www/html
     volumes:
      - ./code:/code
      - ./html:/var/www/html


Once I had a solid Wordpress instance up and running via localhost, I still faced another issue. When I tried to update the Wordpress and site address to https I got a redirect loop! That’s no fun. And it makes it impossible to access or update the instance via the web interface. I poked around a bit in the wp-config.php file in the image and noticed a few lines that piqued my interest.


After noticing this, I did some googling about wordpress and nginx as an https reverse proxy and found the solution to the redirect problem! I wasn’t using an x-forwarded headers in proxying and based on the code I found Wordpress was looking for it to handle HTTPS. After I added the proxy_set_header lines for host and protocol to my NGINX server block I was met with the elusive green lock! Everything was back up and running but now on my personal server and behind HTTPS!