WIUNIX ACADEMY
Install WordPress on Nginx with a privacy-safe FastCGI cache
Page 2 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.
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
LET’S BUILD
Check identity and database exposure
Back in the server shell, enter the password only at the interactive prompt. If 3306 is public, stop and correct MariaDB binding/network policy first; this site needs no public database port.
Record the printed @@socket and compare it with DB_HOST in the selected configuration panel. If they differ, use the actual local socket path there; do not expose TCP to work around a socket mismatch.
WordPress server, Bash, existing sudo administrator.
mariadb -u wp_site -p wordpress -e 'SELECT DATABASE(), CURRENT_USER();'
sudo mariadb -e 'SELECT @@bind_address, @@socket;'
sudo ss -lntp 'sport = :3306'
Database is wordpress, identity is wp_site@localhost, listener remains local.
LET’S BUILD
Verify WordPress before installing files
The archive contains architecture-independent PHP code. HTTPS and both checksums must pass before extraction/copy. SHA1 comes from the official release endpoint; SHA256 was calculated from that validated archive during this review and is not an upstream signature. Neither protects against a compromised publisher. Recheck the official release archive before reusing this pinned version later. Root owns code; only uploads is writable by the dedicated PHP identity.
WordPress server, Bash, existing sudo administrator.
(
set -euo pipefail
umask 077
work=$(mktemp -d)
cd "$work"
curl --proto '=https' --proto-redir '=https' -fL --connect-timeout 10 --max-time 180 -o wordpress-7.1.4.tar.gz https://wordpress.org/wordpress-7.1.4.tar.gz
curl --proto '=https' --proto-redir '=https' -fL --connect-timeout 10 --max-time 60 -o wordpress.sha1 https://wordpress.org/wordpress-7.1.4.tar.gz.sha1
[ "$(tr -d '\r\n ' < wordpress.sha1)" = b175879c4fb2d35300f9abe1153da9b543a35a2b ]
printf '%s %s\n' b175879c4fb2d35300f9abe1153da9b543a35a2b wordpress-7.1.4.tar.gz | sha1sum --check --strict -
printf '%s %s\n' 881e53a4681ff2cd911651b11cccdede5ae477ddf0765af5d6a1a8b219a1d835 wordpress-7.1.4.tar.gz | sha256sum --check --strict -
tar -xzf wordpress-7.1.4.tar.gz
sudo test ! -e /var/www/wordpress
sudo test ! -L /var/www/wordpress
sudo useradd --system --user-group --no-create-home --shell /usr/bin/nologin wp-php
sudo install -d -o root -g root -m 0755 /var/www/wordpress
sudo rsync -a --chown=root:root wordpress/ /var/www/wordpress/
sudo find /var/www/wordpress -type d -exec chmod 0755 {} +
sudo find /var/www/wordpress -type f -exec chmod 0644 {} +
sudo install -d -o wp-php -g http -m 0755 /var/www/wordpress/wp-content/uploads
printf 'Retained verified download: %s\n' "$work"
)
SHA1 and SHA256 report OK, absent destination is populated, verified download retained.
Open the dedicated PHP pool
The stock www pool may remain in this single-site lab; this host never uses its socket. Do not disable another site’s pool. Save the next panel using nano (Ctrl+O, Enter, Ctrl+X).
WordPress server, Bash, existing sudo administrator.
(
set -euo pipefail
sudo nano /etc/php/php-fpm.d/wordpress.conf
)
Check succeeds; stop on an error before continuing.
LET’S BUILD
Run PHP with a dedicated Unix identity
The dedicated pool uses wp-php and a http:http 0660 Unix socket at /run/php-fpm/wordpress.sock. Do not copy the stock www pool ACL users into this new pool: listen.owner/group are the intended access control. Validate the complete configuration before first start.
File contents; save in the named file, not the shell.
[wordpress]
user = wp-php
group = wp-php
listen = /run/php-fpm/wordpress.sock
listen.owner = http
listen.group = http
listen.mode = 0660
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
pm.max_requests = 500
chdir = /var/www/wordpress
security.limit_extensions = .php
php_admin_value[upload_max_filesize] = 16M
php_admin_value[post_max_size] = 16M
php_admin_value[memory_limit] = 128M
php_admin_flag[display_errors] = off
php_admin_flag[log_errors] = on
Dedicated wp-php pool defines the www-data-owned 0660 socket.
LET’S BUILD
Review exposure and host security before starting the site
Inspect the existing nftables/provider policy with its owner before starting. Preserve SSH and allow inbound80/tcp and443/tcp only as needed; keep3306 and FPM private. This guide does not install/enable/flush a firewall or invent an Arch/Manjaro default policy. Stop until the actual active policy is configured. Do not disable AppArmor or service sandboxing to hide access failures.
Fresh dedicated Linux VM, existing sudo administrator.
(
set -euo pipefail
command -v nft >/dev/null || { echo 'Inspect the actual active firewall with its owner; STOP' >&2; exit 1; }
sudo nft list ruleset
sudo ss -lntup
)
The check succeeds; stop and diagnose any failure.
LET’S BUILD
Validate FPM before its first start
This is the first start of the fresh dedicated FPM service. Validate the complete selected-version configuration before unmasking and starting it; record the exact socket owner/mode. Later restarts interrupt all pools of that version.
WordPress server, Bash, existing sudo administrator.
(
set -euo pipefail
sudo php-fpm -t
sudo systemctl unmask php-fpm.service
sudo systemctl enable --now php-fpm.service
systemctl is-active php-fpm
sudo stat -c '%U:%G %a %n' /run/php-fpm/wordpress.sock
)
FPM validates and starts; socket is http:http 660.