Software & Configuration

WordPress on VPS

How to install and configure WordPress on a VPS with LEMP stack (Nginx + PHP + MariaDB)

WordPress is the most used CMS in the world. On a VPS you have full control over the environment: faster and more flexible than shared hosting.


Prerequisites

Before proceeding ensure you have:

  • Nginx installed and running
  • PHP 8.1+ with PHP-FPM
  • MariaDB/MySQL installed
  • A domain pointing to the server IP
  • Certbot for SSL

If you don't have them yet, follow the guide: LEMP Stack


1. Create database and user

mysql -u root -p
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'secure_password_here';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

2. Download and install WordPress

# Create the site directory
mkdir -p /var/www/example.com
cd /var/www/example.com

# Download WordPress
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz --strip-components=1
rm latest.tar.gz

# Set correct permissions
chown -R www-data:www-data /var/www/example.com
find /var/www/example.com -type d -exec chmod 755 {} \;
find /var/www/example.com -type f -exec chmod 644 {} \;

3. Configure Nginx

nano /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.php;

    access_log /var/log/nginx/example.com.access.log;
    error_log  /var/log/nginx/example.com.error.log;

    # Maximum upload size (align with php.ini)
    client_max_body_size 64M;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Block access to sensitive files
    location ~ /\.(ht|git) {
        deny all;
    }

    # Cache for static files
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

4. Configure PHP for WordPress

nano /etc/php/8.2/fpm/php.ini

Recommended parameters:

upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
memory_limit = 256M
max_input_vars = 3000
date.timezone = Europe/Rome
systemctl restart php8.2-fpm

5. Install SSL

certbot --nginx -d example.com -d www.example.com

6. Complete web installation

Go to https://example.com in your browser. The WordPress wizard will ask you for:

  • Database name: wordpress
  • Database user: wp_user
  • Password: the one set at step 1
  • Database host: localhost
  • Table prefix: wp_ (change it for more security, e.g. site_)

Recommended post-installation optimizations

Essential plugins

PluginPurpose
Wordfence or Solid SecuritySecurity and brute force protection
WP Super Cache or W3 Total CachePage caching
WP Mail SMTPReliable email via relay SMTP
UpdraftPlusAutomatic backups
Smush or ShortPixelImage optimization

Protect wp-login.php from brute force

# Add in the server block of Nginx
location = /wp-login.php {
    limit_req zone=one burst=5 nodelay;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

At the top of nginx.conf:

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m;

Increase memory limit in wp-config.php

nano /var/www/example.com/wp-config.php

Add before the line /* That's all, stop editing! */:

define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');

Update WordPress via WP-CLI

WP-CLI lets you manage WordPress from command line:

# Install WP-CLI
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp

# Update WordPress core
wp --path=/var/www/example.com --allow-root core update

# Update all plugins
wp --path=/var/www/example.com --allow-root plugin update --all

# Update all themes
wp --path=/var/www/example.com --allow-root theme update --all

# Backup the database
wp --path=/var/www/example.com --allow-root db export /root/backup-wp.sql

Common issues

IssueSolution
Error 500Check /var/log/nginx/error.log and PHP debug
Upload failsIncrease upload_max_filesize and client_max_body_size
SlowInstall a cache plugin and optimize images
Emails not arrivingInstall WP Mail SMTP, see Troubleshooting
Redirect loopAdd to wp-config.php: define('FORCE_SSL_ADMIN', true);

On this page