Finally moving to a static site

Amazon have made some changes to the (admittedly generous) Alexa AWS credits programme which made me think about the services that I run there and how to reduce my bill a bit. This WP blog was hosted on a t2.micro instance running Apache, MySQL, PHP, and WordPress. You need to add a bit of swap in order to keep MySQL happy but generally speaking it will tick along at very low load. So low in fact that I thought about merging the blog hosting instance with another instance which runs various home automation services, but decided that was too risky.

Rather than a security bug in WordPress exposing my internal network to the world I’ve decided to move everything to static pages. I don’t really post here any more, so it’s not like I need everything that WordPress offers and there are lots of places which will host static pages for either free or very cheap, so why not try it out? Here’s what I decided on and how I did it.

Hosting

I considered the following:

  1. Creating a virtualhost in an already existing Apache set up
  2. Uploading a static copy of these pages to S3
  3. Uploading a static copy of these pages to Github Pages
  4. Moving to a cheaper cloud provider

I ruled out 1, I don’t want any public facing services on my otherwise private servers. I know enough to know that I don’t know anything about securing web servers.

I think #2 and #3 are largely the same in the end. As you have probably worked out by now, I decided that Github was the one I would try. This was decided entirely on cost. S3 would have cost me a couple of pennies a month, Github was free.

I also considered spinning up a new instance in Digital Ocean or Linode (referral link, get $100 credit) which would have been about 20% cheaper for a t2.micro equivalent. Github pages are free though, and get a decent CDN behind them. WordPress on a small server is slow without doing work.

Getting the data out of WordPress

I used the Simply Static plugin for WordPress to export the pages and images to HTML. It worked pretty well, and I would recommend it. Simply Static produced a zip file with everything in. I unzipped it and copied everything to the root of a new Github repo, committed it, pushed it, and it worked.

Some tips for preparing your blog for export:

  • Disable comments on all your posts. This is a faff as you have to do it on each existing post. In the end I followed this guide: https://themeisle.com/blog/disable-comments-in-wordpress/
    See section 3 on how to remove the ability to comment on existing posts.
  • Remove all the meta links etc from the footer and sidebar. I did this through the WordPress “Appearance” -> “Customise” menu to remove widgets and links as required.

Adding new content in the future

I have zero interest in learning some new static blogging platform or writing posts in HTML or Markdown or using some automated jiggery pokery. I really like WordPress for it’s WYSIWYG writing interface.  I write about one post every two years. I intend to switch off the instance hosting WordPress until such time as I need to write a new post, then I’ll switch it on, write the post and export it using Simply Static. This will cost me a few cents for the disk storage, and zero effort.

Double helping of Pi Hole

In episode 100 of Late Night Linux I talked a little bit about trying out Pi Hole and AdGuard to replace my home grown ad blocker based on dnsmasq and a massive hosts file.

I came down in favour of Pi Hole for a couple of reasons but the deciding factor was that Pi Hole felt a bit more open and that it was built on top of dnsmasq which allowed me to reuse config for TFTP which netboots some devices which needed it.

Now that I’ve been using Pi Hole for a few months I have a much better understanding of its limitations and the big one for me is performance. Not the performance when servicing DNS requests but performance when querying the stats data, when reloading block lists and when enabling and disabling certain lists. I suspect a lot of the problems I was having is down to flaky SD cards.

I fully expect that for most people this will never be a problem, but for me it was an itch I wanted to scratch, so here’s what I did:

Through the actually quite generous Amazon Alexa AWS Credits promotion I have free money to spend on AWS services, so I spun up a t2.micro EC2 instance (1 vCPU, 1GB RAM – approx £10 a month) running Ubuntu.

I installed Pi Hole on that instance along with Wireguard which connects it back to my local network at home. I used this guide from Linode to get Wireguard set up.

The Pi Hole running in AWS hosts the large block files and is configured with a normal upstream DNS server as its upstream (I’m using Cloudflare).

Pi Hole running in AWS configured with Cloudflare as its upstream DNS

I use three Ad block lists:

Pi Hole running on a t2.micro instance is really speedy. I can reload the block list in a matter of seconds (versus minutes on the Pi) and querying the stats database no longer locks up and crashes Pi Hole’s management engine FTL.

The Pi Hole running on my LAN is configured to use the above AWS based Pi Hole as its upstream DNS server and also has a couple of additional block lists for YouTube and TikTok.

This allows me use Pi Hole on a Pi as the DHCP server on my LAN and benefit from the GUI to configure things. I can quickly and easily block YouTube when the kids have done enough and won’t listen to reason and the heavy lifting of bulk ad blocking is done on an AWS EC2 instance. The Pi on the LAN will cache a good amount of DNS and so everything whizzes along quickly.

Pi Hole on the LAN has a block list of about 3600 hosts, whereas the version running in AWS has over 1.5 million.

All things considered I’m really happy with Pi Hole and the split-load set up I have now makes it even easier to live with. I would like to see an improved Pi Hole API for enabling and disabling specific Ad lists so that I can make it easier to automate (e.g. unblock YouTube for two hours on a Saturday morning). I think that will come in time. The split-load set up also allows for easy fallback should the AWS machine need maintenance – it would be nice to have a “DNS server of last resort” in Pi Hole to make that automatic. Perhaps it already does, I should investigate.

Why not just run Pi Hole on a more powerful computer in the first place? That would be too easy.

If you fancy trying out Pi Hole in the cloud or just playing with Wireguard you can get $100 free credit with Linode with the Late Night Linux referral code: https://linode.com/latenightlinux

DNS over HTTPS in a snap

Background Story

With the recent news about the ISP UK association proposing Mozilla as “Internet villain of the year” for enabling DNS over HTTPS (and subsequently changing their mind and dropping the whole category of villain of the year. Good move I think.) I figured it was probably about time that I looked at enabling DoH at home.

Cloudflare have a suite of open source tools called cloudflared which has, among other things, a DNS over HTTPS proxy. By default it points at their 1.1.1.1 service, but you can change that if you want to. Note, at the time of writing there is a bug which seems to stop Google’s DNS service working. If you’re looking to stop people seeing your DNS traffic then Google probably isn’t the right DNS service to use anyway.

I already have dnsmasq running as my DNS server and I have quite a lot of config which I wanted to keep (e.g. adblocking) so I figured I would add cloudflared’s proxy-dns alongside dnsmasq and have dnsmasq use proxy-dns as it’s upstream server, which would in turn pass the DNS lookups to 1.1.1.1 over HTTPS. dnsmasq would then cache the results locally.

So far, so good. I’d built cloudflared on my desktop to test it, now I wanted to move it on to the Raspberry Pi, run it as a service, and ideally have a package so that I didn’t have to mess around rebuilding it in loads of places if I wanted to move to a different box.

Make a snap

Making a snap of proxy-dns would give the the package I wanted, and could allow me to run proxy-dns as a daemon with two words in the YAML. Snapcraft’s build service would build me an ARM binary, as well as loads of others, for free.

I downloaded the source for cloudflared and added three files:

  1. A snapcraft.yaml which describes how to build cloudflared and sets it to be run as a daemon
  2. A configure hook which lets me set some config options
  3. A launcher script which sets the config at run time

None of these are very complicated, as you can see. Hat-tip to Popey for help with the snapcraft.yaml.

The I pushed these back to my project on GitHub and added that project to the Snapcraft.io build service. Now, whenever I push a new change back to GitHub the snap will get rebuilt automatically and uploaded to the store! All I would need to do is a snap refresh and I’d be upgraded to the latest version. All my requirements solved in one place.

How to use the snap

If your Pi is running snapd, it’s dead easy (e.g. Ubuntu MATE or Ubuntu Core):

sudo snap install cloudflaredoh --edge

The snap is currently in the edge channel, meaning it’s not ready for the main stage just yet. Once I’ve spent a bit more time on it, I will move it to stable.

sudo snap set cloudflaredoh address=127.0.0.1
sudo snap set cloudflaredoh port=5053

Configure proxy-dns to listen on 127.0.0.1. If you want it to answer DNS queries from other computers on your network try either the IP address of the box, or just 0.0.0.0 to listen on all interfaces. It will also configure proxy-dns to listen on port 5053. If you want it to answer DNS queries from other computers on your network, use the default DNS port of 53.

sudo snap get cloudflaredoh

This will show you the currently set config options.

sudo snap restart cloudflaredoh

Restart proxy-dns and use the new config.

Now you can use something like nslookup to query the DNS server and make sure it’s doing what you expected.

10 Steps To DNS-over-HTTPS

  1. Get a Raspberry Pi
  2. Download Ubuntu Core and write it to an SD card
  3. Put the SD card in your Pi and boot it
  4. Set up the network on Ubuntu Core (tip: register for an Ubuntu One account first)
  5. sudo snap install cloudflaredoh
  6. sudo snap set cloudflaredoh address=0.0.0.0
  7. sudo snap set cloudflaredoh port=53
  8. sudo snap restart cloudflaredoh
  9. Configure your client’s DNS server as the IP address of your Pi
  10. Have a cup of tea

Update 2019-08-01

I’ve got a new Github repo set up with an improved snapcraft.yaml which pulls directly from the upstream project. I’m aiming to get this hooked up to the Snapcraft build service so that we can package the latest version automatically. More on this later. In the meantime, you can clone this and build the latest version yourself:

https://github.com/8none1/cloudflarednsproxy