Last Updated: May 12, 2026
Configuring Nginx on a Vultr VPS correctly can cut your WordPress TTFB from 400 ms to under 80 ms. This step-by-step guide walks you through a production-grade Nginx stack — from provisioning a fresh Vultr High Frequency Compute instance to tuning every layer for maximum throughput. You’ll end up with a WordPress site capable of handling 2,000+ concurrent requests on a $24/month VPS.
Prerequisites
- A Vultr account with a High Frequency Compute instance (2 vCPU / 4 GB RAM minimum recommended, Ubuntu 22.04 LTS)
- A registered domain with DNS pointed to your Vultr instance IP
- SSH access and basic Linux command-line familiarity
- WordPress installed (this guide assumes a fresh WordPress install or migration)
Step 1: Provision and Harden Your Vultr VPS
Deploy a new High Frequency Compute instance from the Vultr dashboard. Choose Ubuntu 22.04 LTS, select NVMe SSD storage, and enable IPv6. After provisioning, SSH in and update the system:
ssh root@YOUR_SERVER_IP
apt update && apt upgrade -y
apt install -y ufw fail2ban curl wget unzip
Configure the firewall to allow only necessary ports:
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose
Create a non-root sudo user for daily operations:
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
Step 2: Install Nginx and PHP 8.3-FPM
Install Nginx from the official repository to get the latest stable release with HTTP/3 support:
apt install -y nginx
systemctl enable nginx
systemctl start nginx
# Install PHP 8.3 FPM and required WordPress extensions
apt install -y software-properties-common
add-apt-repository ppa:ondrej/php -y
apt update
apt install -y 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-bcmath php8.3-imagick php8.3-redis
systemctl enable php8.3-fpm
systemctl start php8.3-fpm
Verify both services are running:
systemctl status nginx
systemctl status php8.3-fpm
Step 3: Install MariaDB and Create a WordPress Database
MariaDB 10.11 outperforms MySQL 8.0 on most WordPress read-heavy workloads by 15–25% in sysbench benchmarks:
apt install -y mariadb-server
mysql_secure_installation
# Create database
mysql -u root -p
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD_HERE';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Tune MariaDB for your VPS RAM. Edit /etc/mysql/mariadb.conf.d/50-server.cnf:
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_type = 0
max_connections = 100
tmp_table_size = 64M
max_heap_table_size = 64M
systemctl restart mariadb
Step 4: Configure PHP-FPM for High Performance
Edit the FPM pool configuration at /etc/php/8.3/fpm/pool.d/www.conf. For a 4 GB RAM VPS:
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
php_admin_value[memory_limit] = 256M
php_admin_value[max_execution_time] = 300
systemctl restart php8.3-fpm
Step 5: Configure Nginx for WordPress
Create the site configuration at /etc/nginx/sites-available/yourdomain.com. This configuration includes FastCGI caching, Gzip compression, and security headers:
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m use_temp_path=off;
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourdomain.com;
index index.php index.html;
# SSL
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000" always;
# Gzip
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
# FastCGI Cache
set $skip_cache 0;
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") { set $skip_cache 1; }
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; }
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 60m;
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
fastcgi_cache_lock on;
add_header X-FastCGI-Cache $upstream_cache_status;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { allow all; log_not_found off; access_log off; }
location ~ /\.ht { deny all; }
}
mkdir -p /var/cache/nginx
ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
Step 6: Install SSL with Certbot and Redis Object Cache
Free SSL via Let’s Encrypt plus Redis caching will dramatically reduce database queries per page load:
# SSL Certificate
apt install -y certbot python3-certbot-nginx
certbot --nginx -d yourdomain.com -d www.yourdomain.com
systemctl reload nginx
# Redis
apt install -y redis-server
systemctl enable redis-server
systemctl start redis-server
# Configure Redis
sed -i 's/# maxmemory-policy noeviction/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf
echo "maxmemory 256mb" >> /etc/redis/redis.conf
systemctl restart redis-server
Install the Redis Object Cache WordPress plugin and add to wp-config.php:
define('WP_CACHE_KEY_SALT', 'yourdomain.com_');
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
Troubleshooting Common Issues
| Error | Cause | Fix |
|---|---|---|
| 502 Bad Gateway | PHP-FPM socket not running or wrong socket path | systemctl restart php8.3-fpm; verify socket path matches Nginx config |
| White screen of death | PHP memory_limit too low or plugin conflict | Set memory_limit = 256M in FPM pool; enable WP_DEBUG temporarily |
| Nginx config test fails | Syntax error in nginx.conf | nginx -t to see exact line; check for missing semicolons |
| SSL certificate error | Port 80 blocked by UFW or domain not pointing to server IP | ufw allow 80; verify DNS A record with dig yourdomain.com |
| High TTFB (>200ms) | FastCGI cache not warming or Redis not connected | Check X-FastCGI-Cache: HIT header; run redis-cli ping |
Expected Outcome & Success Criteria
After completing this guide, your WordPress site on Vultr should achieve:
- TTFB: Under 80 ms for cached pages, under 200 ms for uncached
- Google PageSpeed Insights: 90+ score on Performance (desktop)
- Concurrent connections: 2,000+ handled gracefully with
ab -n 5000 -c 200 https://yourdomain.com/ - Cache hit rate: >85% (visible via
X-FastCGI-Cache: HITheader in browser DevTools)
Verify your configuration is correct:
nginx -t && systemctl reload nginx
curl -I https://yourdomain.com | grep -E "X-FastCGI|Cache-Control|Strict"
Frequently Asked Questions
Do I need Nginx or Apache for WordPress on Vultr?
Nginx is preferred for WordPress on Vultr VPS for most workloads. It handles concurrent connections more efficiently than Apache’s prefork model, uses less RAM, and the FastCGI caching setup described here is highly effective for WordPress performance.
What is TTFB and why does it matter?
Time to First Byte (TTFB) measures how long it takes the server to start sending a response after receiving a request. Google uses TTFB as a Core Web Vitals signal. A TTFB under 200 ms is considered good; under 100 ms is excellent.
How many PHP-FPM workers do I need?
For a 4 GB RAM VPS, pm.max_children = 50 is a safe starting point assuming each PHP worker uses ~40–60 MB RAM. Monitor with php-fpm8.3 -t and adjust based on ps aux | grep php memory usage under load.
Can I use this setup with WooCommerce?
Yes, with minor adjustments. WooCommerce cart and checkout pages must bypass FastCGI cache (the config above handles this via cookie detection). For WooCommerce stores with 1,000+ products, increase innodb_buffer_pool_size to 2 GB on a 4 GB RAM VPS.
How do I update Nginx safely on Vultr Ubuntu?
Run apt update && apt upgrade -y. Nginx upgrades via apt are safe and perform a graceful reload automatically. Always run nginx -t before reloading to validate config syntax.



