WordPress Production Setup with Nginx, PHP-FPM, and Redis Cache
- Author :Liam K.
- Date :July 02, 2026
- Time :30 minutes
WordPress powers over 40% of the web, but a default installation on shared hosting is far from production-ready. Running WordPress on your own Linux server with Nginx, PHP-FPM, MariaDB, and Redis gives you full control over performance, security, and scaling. This guide walks through a complete production stack — from database creation to Redis object caching, SSL, security hardening, and wp-cron optimization.
The target architecture handles thousands of daily visitors on a modest VPS (4 CPU, 8 GB RAM). Redis eliminates repeated database queries for options, transients, and post meta. Nginx serves static files directly and caches FastCGI responses for anonymous visitors. PHP-FPM is tuned to prevent memory exhaustion under traffic spikes.
Stack Overview
- Nginx — reverse proxy, static file serving, FastCGI cache, TLS termination
- PHP-FPM 8.3 — PHP process manager with tuned worker pool
- MariaDB 11 — database with InnoDB buffer pool sizing
- Valkey/Redis — persistent object cache via Redis Object Cache plugin
- Certbot — Let's Encrypt SSL with auto-renewal
Prerequisites
- Ubuntu 22.04+ or Debian 12 VPS with 4 GB+ RAM
- Domain with DNS A record pointing to the server
- SSH access with sudo privileges
Step 1: Install Nginx, PHP-FPM, and MariaDB
sudo apt update
sudo apt install -y nginx mariadb-server \
php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring \
php8.3-xml php8.3-zip php8.3-intl php8.3-redis php8.3-imagick
sudo systemctl enable nginx mariadb php8.3-fpm
sudo mysql_secure_installationStep 2: Create Database and User
sudo mysql <<'SQL'
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'REPLACE_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
SQLStep 3: Install WordPress
sudo mkdir -p /var/www/wordpress
cd /tmp
curl -LO https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz
sudo cp -r wordpress/* /var/www/wordpress/
sudo chown -R www-data:www-data /var/www/wordpress
sudo find /var/www/wordpress -type d -exec chmod 755 {} \;
sudo find /var/www/wordpress -type f -exec chmod 644 {} \;Step 4: Configure wp-config.php
sudo cp /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php
# Generate salts: https://api.wordpress.org/secret-key/1.1/salt/
# Add to wp-config.php:
define('DB_NAME', 'wordpress');
define('DB_USER', 'wp_user');
define('DB_PASSWORD', 'REPLACE_STRONG_PASSWORD');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
[...]Step 5: Nginx Virtual Host with FastCGI Cache
sudo tee /etc/nginx/sites-available/wordpress.conf >/dev/null <<'EOF'
fastcgi_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=WP:100m inactive=60m max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
listen 80;
server_name blog.example.com;
return 301 https://$host$request_uri;
}
[...]Step 6: Install Valkey and Redis Object Cache Plugin
sudo apt install -y valkey
sudo systemctl enable --now valkey
# Install plugin via WP-CLI:
cd /var/www/wordpress
sudo -u www-data wp plugin install redis-cache --activate
sudo -u www-data wp redis enableStep 7: Tune PHP-FPM for WordPress
# /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 30
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
php_admin_value[memory_limit] = 256M
[...]Step 8: Replace wp-cron with System Cron
WordPress built-in cron runs on every page load, adding latency. Disable it in wp-config.php (done in Step 4) and schedule it via system cron instead.
sudo tee /etc/cron.d/wordpress >/dev/null <<'EOF'
*/5 * * * * www-data curl -s https://blog.example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
EOFStep 9: Security Hardening
- Block
xmlrpc.php— common DDoS and brute-force vector. - Rate-limit
wp-login.php— max 5 requests per minute per IP. - Install Fail2ban or CrowdSec for automated IP banning.
- Keep WordPress core, themes, and plugins updated via WP-CLI cron.
- Disable file editing:
define('DISALLOW_FILE_EDIT', true); - Use unique table prefix — not the default
wp_.
Step 10: Verify Performance
# Check Redis object cache:
sudo -u www-data wp redis status
# Check FastCGI cache headers:
curl -I https://blog.example.com/
# Look for X-FastCGI-Cache: HIT on second request
# Load test (from another machine):
ab -n 1000 -c 50 https://blog.example.com/Production Checklist
- Enable Redis object cache and verify hit rate above 90%.
- Configure automated backups for database and
/var/www/wordpress. - Set up Uptime Kuma or similar for availability monitoring.
- Review Nginx and PHP slow logs weekly for performance regressions.
- Test restore from backup quarterly.
"WordPress at scale is not about plugins — it is about caching layers, cron discipline, and a stack you control end to end."
Technical Author

System administrator and technical writer specializing in server infrastructure, security and deployment. Creating comprehensive guides to help you master server administration.