Running a static site in Microsoft Azure using WordPress for content management

Image by @edgarraw / Unsplash.com

I’m currently running my blog (the one you’re reading, thanks!) in Azure, Microsoft’s cloud platform. For the longest of times — which is maybe five years — I ran multiple WordPress sites in Azure using the PaaS offering. This includes the Azure Marketplace-based template, that provisions a Web App and MySQL database with a few simple clicks.

I also had our company website, e-commerce services and a few different blogs on this same setup — all on separate Web App Plans and in a few different Azure regions.

Back in the day hosting WordPress on Azure meant you had to resort to using ClearDB’s MySQL hosting. Your website would run on Azure, and for database services, it would connect to another (supposedly, I never had enough interest to find out) Azure subscription that was maintained and managed by ClearDB. This introduced plenty of challenges. It was often unreliable, and it wasn’t cheap, as ClearDB kept ramping up the prices. Someone had also made it extremely hard to back up your data should you want to migrate elsewhere.

Today, WordPress is again available on Azure using Azure Database for MySQL as the backend. I migrated this blog to a native Azure platform about two years ago. And then the problems started.

The performance was a constant struggle for me. Page load times or the Time-To-First-Byte (TTFB) would occasionally peak at 30 seconds. I thought this was just my poorly written warm-up scripts that sometimes caused additional friction and latency. I used Application Insights to provide more insights and started seeing a pattern of slugginess that was hard to pinpoint to any specific service.

I had better luck with a Linux-hosted App Plan, but even with the Standard S1 tier, it was slow. At times loading WordPress admin interface took over 30 seconds.

Thinking outside the box

As WordPress grew more and more unreliable when hosted in Azure, I contemplated moving back to a Virtual Machine-based solution. I feared that the additional time to maintain, patch, monitor, and backup of the VM would be too much, so I wasn’t enthusiastic about going that route in Azure.

At home, I have a beefy workstation running Windows 10 Pro for Workstations, and I have Hyper-V enabled for local virtualization. I use this mainly for running quick tests with Linux and Windows, and I also backup VMs images to my Synology NAS.

I spun up a Windows Server 2019 as a local VM, and started searching for the latest WordPress installation instructions. I came upon XAMPP, a free deployment and managing tool for running Apache, MySQL (or MariaDB), PHP and Perl. It’s available for Windows, Linux, and macOS.

It installed without a hassle, and has a semi-proper control panel.

I used the fantastic All-In-One WordPress plugin to export all my content from the Azure-hosted (PaaS) WordPress, and then I used the same plugin to import content to my VM running XAMPP.

I now had a locally running WordPress running, and the production site was still running in Azure, although it was very slow. The local WordPress was blazingly fast – pages would load in 1-2 seconds, and this was on a VM with only 8 GB of RAM and two cores!

This got me thinking – what if I maintained my local WordPress with XAMPP, and generated static pages for publishing? These static pages I could then host on an Azure Web App or in Azure Storage. It would also help me secure my solution as I wouldn’t have to worry too much about WordPress security issues or unpatched plugins.

Generating static pages

I found two plugins for generating static pages. WP2Static and Simply Static. Despite my heroic efforts I couldn’t get Simply Static to work under XAMPP – the generator kept receiving 401 errors, so I gave up on Simply Static after two hours of fighting.

WP2Static worked on the first try. It’s almost magical. First, you configure the settings and then let it run.

WP2Static settings

I generate all content and dump it in a local directory within the VM. I then use secure FTP to upload content to my blog at https://jussiroine.com.

One of the neat features in WP2Static is the ability to tweak the content – such as hiding cruft:

I can also rename directories such as ‘WP-Uploads’ to ‘uploads’ or something else.

Azure configuration

I opted to run my static pages in a Web App, instead of using the Azure Storage static website. I reasoned that this way, I would still have an escape route ‘back’ to a proper WordPress solution if my bold approach would fail.

I have a Web App with one instance and the service plan is set to Standard S1. This provides me with 100 Azure Compute Units, 1.75 GB of RAM and it costs about 38 €/month. Despite traffic growing ten-fold in the past 6 months, the site seems fast and reliable.

I’m also using Application Insights to track the server-side telemetry. Response times are amazing – on average, 12.91 ms (for the past 30 days)!

Cost-wise I am averaging 38 to 40 € monthly, and this is mostly for the App Service Plan for Standard S1. Storage costs me less than 2 €, and bandwidth is less than 1 €.

Performance issues

I’m running my VM from a semi-fast NVMe SSD, yet generating static pages takes between 10 and 15 minutes each time. Admittedly the amount of static content to generate is in the thousands, but I still felt WP2Static, and XAMPP could have been faster.

I spent a few evenings trying to optimize WordPress. Tweaking configuration files, Windows settings, and Hyper-V settings had negligible effect. WP2Static still took about 9 to 10 minutes to generate the static pages.

Then I recalled my performance issues with Azure on a Windows host. The PHP compiler in XAMPP is mod_php by default. I found several sources (see here) that suggested that switching to FastCGI would yield better performance.

I followed these instructions to do the switch from mod_php to FastCGI. After a reboot of the VM, WP2Static now runs in 5-6 minutes, down from the original 10-15 minutes!

Publishing process

As I mentioned before, the process is straight-forward:

  1. Author a new post
  2. Test locally that everything looks good at https://localwp/
  3. Generate static pages with WP2Static
  4. Test locally against the static version at https://localwp/static/
  5. Upload static files to Azure Storage
  6. Test in the cloud at https://jussiroine.com/

After authoring a post the steps from 2 to 6 take about 10 minutes. WP2Static takes 5-6 minutes, and the rest goes to manually initiate the FTP upload.

I could automate this easily but currently, when publishing about 2 articles each week I haven’t bothered with anything too fancy, as it works great like this too.

In closing

There’s plenty to optimize in my setup. I could run the VM in Azure, especially with the Burstable series a VM like this would be very affordable. As I’m using a Web App to serve out my static pages, I can later add a CDN, Traffic Manager and added high availability and georeplication if needed.

I’m also using Web App deployment slots to test ‘releases’ of static pages, if I feel there’s further need for testing. This could be automated, as Deployment Center supports Dropbox and other mediums for delivering the assets for testing.

I’ve been running this setup now for about six months and I’m immensely happy how cheap, reliable and flexible the setup is!