← Start of tutorial

WIUNIX ACADEMY

Install WordPress on Nginx with a privacy-safe FastCGI cache

Page 7 of 8. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu 26.10Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment4 editable values

Invalidate without deleting active cache files

No purge API/module is assumed. For urgent changes disable cache or remove the public URL BEFORE changing its privacy, then select a never-used generation in the next panel and validate/reload. This invalidates the whole small site, not one URL. Old files are unreachable by new keys and expire by inactive/size controls. Never revert to an old generation. Normal WordPress publication does not trigger this cache invalidation; content can remain until its actual upstream/fallback TTL. In staging, change the marker to PUBLIC_CACHE_MARKER_V2, rotate generation, then repeat the anonymous test using the new marker and require the old content absent.

Bash

WordPress server, Bash, existing sudo administrator.

sudo nano /etc/nginx/sites-available/wordpress
How do I know it worked?

Check succeeds; stop on an error before continuing.

Rotate the cache generation

Replace the existing key line, never add a duplicate. Use a never-used generation, then the earlier guarded validation/reload panel.

Nginx · /etc/nginx/sites-available/wordpress (existing PHP location)

File contents; save in the named file, not the shell.

# Replace the previous key directive with this NEW generation:
fastcgi_cache_key "$scheme|$request_method|$host|$request_uri|wp-v2";
How do I know it worked?

Check succeeds; stop on an error before continuing.

Retain the site while disabling caching

If a user sees another user’s content, disable caching immediately with the next line and the earlier guarded reload. Also invalidate existing outer CDN/distributed copies through their owning workflow and investigate the exposure. Keep WordPress files, database, uploads, accounts and certificates. Do not delete active cache directories.

Bash

WordPress server, Bash, existing sudo administrator.

sudo nano /etc/nginx/sites-available/wordpress
How do I know it worked?

Check succeeds; stop on an error before continuing.

27

LET’S BUILD

Return to direct PHP without deleting data

Replace the cache-selection line only; keep the zone while references remain. After validation/reload, body/session tests must still pass, with X-WP-Cache absent rather than HIT/BYPASS. Correct the policy and use a fresh generation before re-enabling. Existing cache files can expire normally.

Nginx · /etc/nginx/sites-available/wordpress (existing PHP location)

File contents; save in the named file, not the shell.

# In the PHP location, replace WORDPRESS with off:
fastcgi_cache off;
How do I know it worked?

WordPress works through PHP; cache off, all site data retained.

28

LET’S BUILD

Back up before controlled maintenance

Optional maintenance: first suspend editorial/plugin/schema changes and uploads through your existing maintenance access process. The dump is transaction-consistent for InnoDB, but does not synchronize uploaded files or non-transactional plugin tables. File comparison fails safely if the tree changes. This is not an atomic online whole-site backup; use a maintenance window or your established consistent backup workflow. Original files/data stay in place. Local checksums/read-back/comparison do NOT prove SQL restorability. Before destructive retirement/migration, restore into an ISOLATED recovery environment, verify login/content/uploads, and keep an encrypted off-host copy using your existing backup system. Never restore-test over the live database. Plan administrator-controlled core/theme/plugin updates from official sources, then repeat privacy tests.

Bash

WordPress server, Bash, existing sudo administrator.

sudo sh -eu <<'BACKUP'
umask 077
install -d -m 0700 /root/academy-backups
backup=$(mktemp -d /root/academy-backups/wordpress-XXXXXXXX)
mariadb-dump --single-transaction --quick --databases wordpress > "$backup/wordpress.sql"
test -s "$backup/wordpress.sql"
tar -C / -cpf "$backup/wordpress-files.tar" var/www/wordpress etc/nginx/sites-available/wordpress etc/nginx/conf.d/wordpress-cache.conf etc/php/8.5/fpm/pool.d/wordpress.conf
cd "$backup"
sha256sum wordpress.sql wordpress-files.tar > SHA256SUMS
sha256sum -c SHA256SUMS
tar -tf wordpress-files.tar >/dev/null
tar -C / -df wordpress-files.tar
printf 'Verified local files and dump: %s\n' "$backup"
BACKUP
How do I know it worked?

Root-only archive/dump pass local checks; original data retained. SQL restore remains a separate required recovery test.

Diagnose the failing boundary

Keep private logs and cookies local. Each disclosure has separate executable diagnostics.

How do I know it worked?

Check succeeds; stop on an error before continuing.

PHP returns 502

Compare actual socket, selected service and permissions; restart does not fix a wrong path.

Bash
sudo nginx -t
sudo systemctl status php8.5-fpm --no-pager
sudo journalctl -u php8.5-fpm -n 50 --no-pager
sudo stat /run/php/wordpress.sock
sudo -u www-data test -w /run/php/wordpress.sock
Database connection fails

Check local authentication, schema grants and file readability without printing secrets.

Bash
sudo systemctl status mariadb --no-pager
sudo journalctl -u mariadb -n 50 --no-pager
mariadb -u wp_site -p wordpress -e 'SELECT 1;'
sudo -u wp-php test -r /var/www/wordpress/wp-config.php
No HIT or wrong body

Disable cache first for wrong content. Cookies/queries/Set-Cookie/private/no-store can correctly prevent storage. Check disk/inodes, never suppress headers to force HIT. This request may warm the public URL.

Bash
sudo nginx -t
sudo df -h /var/cache/nginx/wordpress
sudo df -i /var/cache/nginx/wordpress
sudo du -sh /var/cache/nginx/wordpress
curl -sS --connect-timeout 5 --max-time 20 -D - -o /dev/null https://blog.example.com/sample-page/
TLS or renewal fails

Compare DNS, challenge reachability and matching certificate. Repair the cause, do not bypass certificate checks.

Bash
getent ahosts blog.example.com
sudo nginx -t
sudo certbot certificates
sudo journalctl -u nginx -n 50 --no-pager
Explore all tutorials ↗