WordPressWordPressVPSNginxSSLLinux

Deploying WordPress on a VPS with Nginx, PHP-FPM, and Let's Encrypt

Step-by-step guide to deploying a production-ready WordPress site on a Linux VPS with Nginx, PHP-FPM, MariaDB, and free SSL via Certbot.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

May 26, 2026 10 min read

Managed WordPress hosting is convenient but expensive at scale and limited in control. A VPS — Virtual Private Server — gives you root access, predictable pricing, and the freedom to configure your stack exactly as needed. The combination of Nginx as the web server, PHP-FPM for processing PHP, MariaDB as the database, and Let's Encrypt for free SSL certificates is the modern standard for self-hosted WordPress. This guide walks through a complete production deployment on Ubuntu 22.04, from provisioning the server to serving your first HTTPS request. Each step is production-appropriate, not just a quick demo setup.

Initial Server Setup and Security Hardening

After provisioning your VPS, log in as root and create a non-root sudo user: `adduser deploy && usermod -aG sudo deploy`. Copy your SSH public key to the new user's authorized_keys: `mkdir /home/deploy/.ssh && cp ~/.ssh/authorized_keys /home/deploy/.ssh/`. Set correct permissions and ownership. Disable root SSH login by editing `/etc/ssh/sshd_config` — set `PermitRootLogin no` and `PasswordAuthentication no`, then restart SSH. Install UFW firewall and allow only SSH, HTTP, and HTTPS: `ufw allow OpenSSH && ufw allow 'Nginx Full' && ufw enable`. This baseline prevents brute-force attacks and limits your attack surface before you install anything else.

Installing Nginx, PHP-FPM, and MariaDB

Update packages and install the stack: `apt update && apt install nginx mariadb-server php8.2-fpm php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring php8.2-xml php8.2-zip php8.2-imagick -y`. Run `mysql_secure_installation` to set the root database password, remove anonymous users, and disable remote root login. Create the WordPress database: `CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'strong_password'; GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost'; FLUSH PRIVILEGES;`. PHP-FPM runs as a pool of workers; the default pool configuration at `/etc/php/8.2/fpm/pool.d/www.conf` is adequate for starting out but should be tuned based on available RAM.

Configuring Nginx for WordPress

Create an Nginx server block at `/etc/nginx/sites-available/yourdomain.com`. Key configuration elements include setting the root to your WordPress directory, enabling `try_files` for WordPress permalink support (`try_files $uri $uri/ /index.php?$args`), passing PHP requests to PHP-FPM via the socket (`fastcgi_pass unix:/run/php/php8.2-fpm.sock`), and blocking direct access to sensitive files like `wp-config.php` and `.htaccess`. Set `client_max_body_size 64M` to allow plugin and theme uploads. Enable gzip compression with `gzip_types` covering text/html, text/css, application/javascript, and image types. Link the config to sites-enabled and test with `nginx -t` before reloading.

Installing WordPress and wp-config Setup

Download WordPress to your web root: `cd /var/www && wget https://wordpress.org/latest.tar.gz && tar xzf latest.tar.gz && mv wordpress yourdomain.com`. Set ownership: `chown -R www-data:www-data /var/www/yourdomain.com`. Copy wp-config-sample.php to wp-config.php and fill in database credentials. Use the WordPress secret key generator to populate the AUTH_KEY, SECURE_AUTH_KEY, and related constants. Add `define('FS_METHOD', 'direct')` to avoid FTP prompts for file operations. Set `define('WP_DEBUG', false)` for production and optionally configure `define('WP_CACHE', true)` if you plan to use object caching. Ensure the uploads directory is writable by the web server.

Obtaining SSL with Certbot and Let's Encrypt

Install Certbot: `apt install certbot python3-certbot-nginx -y`. Run `certbot --nginx -d yourdomain.com -d www.yourdomain.com`. Certbot automatically modifies your Nginx config to add SSL directives, set up HTTP to HTTPS redirects, and configure the certificate paths. It also installs a systemd timer that auto-renews certificates before they expire — verify with `systemctl status certbot.timer`. After obtaining the certificate, your Nginx config will include SSL on port 443 with the Let's Encrypt certificate, a redirect block on port 80, and the HSTS header. Test renewal without actually renewing using `certbot renew --dry-run` to confirm the automated process will work when the certificate is near expiry.

Performance Tuning and Monitoring

For a production WordPress site, enable PHP OPcache by adding `opcache.enable=1` and `opcache.memory_consumption=128` to your PHP ini. Install Redis for object caching: `apt install redis-server php8.2-redis -y` and configure WordPress to use it with the Redis Object Cache plugin. For Nginx, enable FastCGI caching to serve cached HTML pages without hitting PHP at all for anonymous visitors. Set up log rotation for Nginx and PHP-FPM logs to prevent disk exhaustion. Monitor server health with `htop` for real-time resource usage and configure email alerts for high CPU or memory usage using a monitoring tool like Netdata or a simple cron job that emails you when disk usage crosses 80%.

Share this article

All posts
#WordPress#VPS#Nginx#SSL#Linux
Abdur Razzak — Full Stack Web Developer

Free Consultation

Got a Project Idea? Let's Talk.