Skip to content

Updating A Static’d WordPress Site

Static’d? Static-ified? Enstaticed?


Previously, I “un-multisite’d” a few WordPress blogs I had running on Strider’s Virtual Multiblog (VMB). I used a plugin called Simply Static which worked well. However, there were a couple of things I realised I needed to do to the site, but since it was now static, I couldn’t update the few things using WordPress.


 wanted to do a couple of things but the most important thing was to put a notice on each page noting that the site was archived, read-only and wouldn’t be receicing udpates in the form of new posts or comments (being a good netizen). Removing the comment forms too would make that much more obvious.

Off the top of my head, I figured I had a couple of options:

  • update the static files using some kind of mass-edit tool (sed, emacs, vi etc)
  • host a temporary development instance of the WordPress site, then re-export it with Simply Static again

I figured the latter would be moderately easier as Simply Static worked well, plus spinning up a quick wordpress dev instance isn’t too hard. Looking back, I should have gone with the first option. I could have probably done the job two or three times over, rather than it taking most of the day to do (along with searching for car insurance, which is a very separate topic but equally if not more perplexing).

For anyone else wanting to hide comment forms, you can use the following custom CSS:

/* override.css */
div#respond { display: none; }


I had everything I needed already:

  • a backup of the site files (you have backups, right?)
  • a backup of the WordPress database (you do have backups, right?)
  • somewhere to host the site – I have a Docker host which I use to self-host some services

Setting Up The Test Site

Docker Setup

I figured I could use the WordPress Docker image to host the site temporarily. I was able to get it up and running with a minor modification to the docker-compose.yml file to use traefik to give me a nice URL which was not needed, but I thought I would refresh my memory of it.

I’m glad I did, as I ran into a minor issue causing the site to not be resolvable through traefik (see ‘Issues’ section) which needed a tweak to fix.

Importing WordPress Database

It’s pretty straightforward. My SQL dumps include all tables, but all I needed was the particular one:

$ grep -A 999999999999999 "Current Database: \`wordpress\`" all-dbs.sql > wp.sql
$ docker exec -i wpdb mysql -u root -p [password] < wp.sql

Thanks to this ServerFault answer for the tip.

Using PHP & Nginx

Unfortunately, while the WordPress image gave me the setup wizard (as expected), once I brought in the database and files I got the dreaded “white screen of death (WSOD)” and couldn’t get any useful information as to why, so I switched over to a php + nginx combo.

The guide at JonsDocs on nginx and php was very helpful. I ended up with a slightly different php-dockerfile (and changed context to a subdirectory) and dropped things that I didn’t need (php logging, composer, fancy URL schemes). Note that I used the php:7.4-fpm image, not the 8 branch which was current at time of writing as that was causing complaints like:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function WP_Widget::__construct(),

When I used the standard off-the-shelf php image, WordPress complained that it didn’t have the mysql extension (there is a guide to what sort of environment WP needs, including PHP extensions), so I had to build one. I used php7.4, and borrowed from the JonsDocs guide for the dockerfile:

# php-dockerfile
FROM php:7.4-fpm

RUN apt-get update && \
    apt-get install -y zip curl libcurl3-dev libzip-dev libpng-dev libonig-dev libxml2-dev

RUN docker-php-ext-install curl gd mbstring mysqli xml dom zip

Note: Make sure you don’t try to build an already-included module (like json), or you’ll run into an error there!


Installing shared extensions:     /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
cp: cannot stat 'modules/*': No such file or directory
make: *** [Makefile:87: install-modules] Error 1

Site Access

Obviously all the references in the site’s database were to the actual domain. To get around that and keep the site live, I used the time-honoured trick of pointing to the development site in my /etc/hosts, and adding a corresponding traefik label for the site name. Make sure you have the site subdomain if applicable- I had to switch from bare domain to www.

This was enough to get the site working! I was able to install the Simply Static plugin, and… it didn’t work. Didn’t do anything. At first I thought it was a permission issue as the diagnostics page complained it didn’t have read or write accesss to the output directory, which is a fair enough complaint. However, even after fixing that it still didn’t do anything.

Nothing in the activity log.

Nothing in the output directory.

Nothing in nginx/php logs.


I tried a bunch of things- reinstalling the plugin, installing the plugin from the VPS itself, installing the plugin via git clone and rolling back to an earlier version. Other wild things that I would never do live, like giving global recursive read/write access to the entire wordpress directory in case there was another odd permission / ownership issue (note: please, for the love of Yggdrasil, don’t randomly futz with overly-permissive permissions on live sites). I updated other plugins, I updated WordPress. I wasn’t far from losing my sanity when I had a realisation.

On the diagnostics page, one of the checks is that WordPress can talk to itself, and indeed my site reported it could talk to itself on its internal docker IP quite happily. But the gears in my head finally turned and it clicked- I was seeing nothing in the access logs because the dev site was (probably) trying to make requests to the live site. I had bypassed DNS by adding an entry in /etc/hosts, but that was local to me.

The solution was to add the mapping of IP-sitename (of the nginx container service and ‘real’ domain respectively) of the development site to the containers’ /etc/hosts.

Once I did that I saw actual activity in Simply Static’s activity log. I regained some semblance of sanity, though it wasn’t to last… car insurance.

After the export was concluded I was able to rsync the files to the VPS hosting the live version of the site, change the root directive in the nginx config file, and the updated version is live!


Minor Issue 1: Traefik Complained `No such service: wordpress@docker’

tl;dr: docker-compose services are not the same as traefik services

This one, like many minor issues, are on me for not fully remembering how traefik labels work. the docker-compose.yml file specifies services, made of images which have volumes, environment values, network definitions, whatever you have in your docker-compose ‘unit’. Those services are not the same as traefik services!

I had to add an extra label to create a traefik service (loadbalancer) to stop it complaining and link up to the service:

      - "traefik.enable=true"
      - ""
      - "traefik.http.routers.wpdev.rule=Host(`www.sitename.tld`)"
      - "traefik.http.routers.wpdev.service=wordpressdev"
      - ""
      - "traefik.http.routers.wpdev.tls=false"

Minor Issue 2: WordPress complains ‘Error establishing a database connection’

This cropped up a a couple of times. Things to check:

  • you have containers on the same network- I added a wpdevnet network as by adding the frontend to the traefik network, I had inadvertently split it from the database
  • check credentials match
  • check wp-config is up-to-date
  • make sure your database user has access to the wordpress database (see eg SHOW GRANTS)

Minor Issue 3: MariaDB / MySQL complains about ‘Incorrect definition of table mysql.column_stats: expected column’

I was getting repeated errors in the console from the mariadb container:

wpdb       | 2023-09-04 14:33:49 1911 [ERROR] Incorrect definition of table mysql.column_stats: expected column 'histogram' at position 10 to have type longblob, found type varbinary(255).
wpdb       | 2023-09-04 14:33:49 1912 [ERROR] Incorrect definition of table mysql.column_stats: expected column 'hist_type' at position 9 to have type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB'), found type enum('SINGL E_PREC_HB','DOUBLE_PREC_HB').

Turns out this is an upgrade issue. You can update it by using the mysql_update tool (works for mariadb too):

docker exec -i wpdb mysql_upgrade -u root -p

Changing wpdb for your database container name.

1 thought on “Updating A Static’d WordPress Site”

  1. Pingback: Fixing Site Issues (Multiblog, Default Site, & Speed) – Rob's Blog

Tell us what's on your mind