I didn’t take notes on how I was building willangley.org in 2019, because I was only planning to build it once; I planned to deal with things going wrong with backups, and things going right with in-place capacity upgrades.
Now it’s prompting me to upgrade, from Ubuntu 18.04 LTS to Ubuntu 20.04 LTS. It’s sometimes necessary to rebuild servers when an in place upgrade doesn’t work, so I might need to build this twice after all; restoring to before a failed upgrade is likely to bring you to a state where the upgrade will fail again ?.
This is a good reminder to figure out what I did and write it down, even if I don’t upgrade immediately.
ℹ Info
Although I’ve published my notes here, I’ve also kept a copy off the system in Bear so I can get to them if willangley.org is broken.
Development environment
I’ve been using Local to run WordPress on my machine since before I knew if I’d go live with a WordPress site, or how I’d serve it if I did.
I don’t develop PHP at work any more and lean heavily on an editor (usually either Sublime Text or Visual Studio Code) to remind me what I’m looking at, and this makes them work well.
I’ve tried to make my site portable between both my server and Local.
Server
I mostly followed the 2019 version of Hosting WordPress Yourself, with some exceptions that follow below.
Machine
willangley.org runs on a single DigitalOcean Basic droplet, with DigitalOcean backups taking weekly snapshots on the server.
PHP
I’m using PHP 7.2, since it’s packaged with Ubuntu, rather than adding a PPA to get a more modern version.
I’ve also added several extensions to PHP to get one plugin or another working. Running dpkg -l | grep php
says I’ve got: php-common php-igbinary php-imagick php-intl php-pear php-redis php7.2-bcmath php7.2-cli php7.2-common php7.2-curl php7.2-dev php7.2-fpm php7.2-gd php7.2-imap php7.2-intl php7.2-json php7.2-mbstring php7.2-mysql php7.2-opcache php7.2-readline php7.2-soap php7.2-xml php7.2-xmlrpc php7.2-zip pkg-php-tools
installed now, and will likely need them again on a new server too. (Some, but not all, of them are installed by the base PHP install.)
SSH
I followed the guide , set up an SSH key pair, and turned off passwords.
Since then I’ve installed Tailscale on the server, and firewalled off SSH from most of the Internet. Then Jetpack complained, so I opened up SSH back up for their IP address ranges only.
This firewall is applied at the DigitalOcean Networking level, rather than running on the droplet. It’ll apply to my new server automatically when I add it to the web-serving
firewall group.
DNS
DNS for my domain lives on Google Domains, but my server lives in DigitalOcean.
In Google Domains, I have an NS
record for do.willangley.org
that delegates them to DigitalOcean, and I have A
records for @
and www
that point directly to the IP address of my server in DigitalOcean.
In DigitalOcean, I have an NS
record for DigitalOcean, and an A
record for the server running willangley.org.
I’d been trying to avoid troubleshooting mail forwarding for @willangley.org by moving as little as possible, because I use a @willangley.org address as a login for some services. But this split setup is seeming like a mistake in hindsight and I’ll likely back it out.
Monitoring
Is set up through the DigitalOcean agent. CPU looks good,
memory meh but probably fine.
Object Cache
I skipped using Redis initially, then came back when I installed the AMP plugin and it asked for an object cache.
I used WP Redis instead of Redis Object Cache like the tutorial recommended, because I wanted to use Redis on a Unix domain socket and Redis Object Cache doesn’t support that. Unix domain sockets mean one less thing to manage passwords and firewall rules for.
Page Cache
I set up WP Super Cache for page caching, instead of handling caching in nginx and using Nginx Cache like the tutorial recommended.
I can’t remember why I did this but it might’ve had something to do with using Local for development instead of a copy of the server.
I ignored the part about sending email from a WordPress plugin. This makes a lot of sense if you’re hosting WordPress for clients, and want them to get WordPress emails and you to get system emails.
But I’m not; I want both WordPress and system emails to go to me. So I followed the Sending email with SendGrid instructions to send mail from Postfix instead.
Backups
I ignored the part about tarball backups, and signed up for Jetpack backups instead.
Since I was already planning to use other Jetpack features this made sense to me. It still largely does, although it’s never fit in super well with Local (protip: Local will create a database for you when it’s creating a site, but the .sql
script that Jetpack Backups gives you expects not to have this. Drop the tables in phpMyAdmin, then run the script, and things will work cleanly) and iterating on my theme a few weeks ago didn’t seem to prompt real-time backups.
Automatic security updates
I’ve configured unattended-upgrades
to perform security updates and to restart automatically. I did not request a specific reboot time, since I’d rather have brief downtime than run an old kernel for a day until the time arrives again.
Additionally, I’ve set it to use minimal steps to avoid blocking shutdown, and to mail me on upgrades.
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Mail "root";
Code language: PHP (php)
This reminds me that my server is taking care of itself, and if something goes wrong I’ll hopefully have an email with the bad upgrade in my inbox before an email from Jetpack downtime monitoring telling me that things are broken.
WordPress build
I did this locally first, rather than starting with wp-cli
on the server, and copied it over later. I’ve got some plugins with config settings in them, and a customized theme, that both seemed easier to develop this way than across the Internet.
The smallest Basic droplet is powerful enough to serve a pretty good amount of traffic, but Visual Studio Code Remote Development will bring it to its knees in a hurry.
I disabled comments before serving my site. This isn’t a permanent decision – I think they can add value – but I’m only going to think about enabling them if I get to blogging regularly enough I think I’ll be able to sustain a community.
Jetpack is enabled. I’m actively using Anti-Spam (on the contact form only), Backups, Brute Force Login Protection, Contact Form, Downtime Monitoring, Image Optimization, Scan, and Stats.
Automatic updates are turned for WordPress, plugins, and themes too.
Planning to build on 20.04
Now that I’ve poked at this a bit I’m pretty sure it’ll translate to the new version of Hosting WordPress Yourself, Set Up a DigitalOcean Virtual Server for WordPress on Ubuntu 20.04.
Even though 18.04 will be supported for another two and a half years, I’m hoping to go to 20.04 sooner. WordPress is already recommending PHP 7.4, and I’d rather upgrade than spend time getting backports working.
But this time I’ll write down what I’m doing so I don’t have to reverse engineer it all over again when 22.04 comes out.