How to Set Up a WordPress Site on a VPS from Scratch (LEMP Stack 2025)

How to Set Up a WordPress Site on a VPS from Scratch (LEMP Stack 2025)

Running WordPress on shared hosting means competing for server resources with hundreds of other sites. Move to a VPS and you get dedicated resources, complete control over your stack, and the ability to configure your server for exactly your site’s needs. The result is a faster, more reliable WordPress site β€” often at the same or lower cost than managed WordPress hosting.

This guide covers a complete WordPress installation on Ubuntu using the LEMP stack (Linux, Nginx, MariaDB, PHP) β€” the most performant open-source web stack for WordPress in 2025.

Why LEMP Instead of LAMP?

LAMP uses Apache; LEMP uses Nginx. For WordPress specifically, Nginx outperforms Apache because:

  • Nginx handles static files (images, CSS, JS) significantly faster
  • Lower memory footprint β€” critical on modest VPS plans
  • Better handling of concurrent connections
  • FastCGI caching support for dramatic PHP performance gains

Requirements

  • Ubuntu VPS 22.04 or 24.04 LTS (KVM, minimum 1 GB RAM)
  • A domain name with DNS pointing to your VPS IP
  • Root or sudo access via SSH

πŸ’‘ VPS.DO Tip: VPS.DO’s USA VPS 500SSD plan (2 vCPU, 4 GB RAM, 500 GB SSD) comfortably hosts 10–30 WordPress sites. View Plans β†’


Step 1: Update the System

sudo apt update && sudo apt upgrade -y

Step 2: Install Nginx

sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

Step 3: Install MariaDB

sudo apt install mariadb-server -y
sudo systemctl enable mariadb
sudo mysql_secure_installation

Follow the prompts: set a root password, remove anonymous users, disallow remote root login, remove test database.

Create the WordPress Database

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

Step 4: Install PHP 8.3 with FPM

sudo apt install php8.3-fpm php8.3-mysql php8.3-xml php8.3-mbstring \
  php8.3-curl php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath \
  php8.3-imagick php8.3-redis -y

Tune PHP for WordPress

sudo nano /etc/php/8.3/fpm/php.ini
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
max_input_vars = 3000
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
sudo systemctl restart php8.3-fpm

Step 5: Download and Configure WordPress

cd /var/www
sudo wget https://wordpress.org/latest.tar.gz
sudo tar -xzf latest.tar.gz
sudo mv wordpress yourdomain.com
sudo chown -R www-data:www-data yourdomain.com
sudo find yourdomain.com/ -type d -exec chmod 755 {} \;
sudo find yourdomain.com/ -type f -exec chmod 644 {} \;

Create wp-config.php

sudo cp /var/www/yourdomain.com/wp-config-sample.php /var/www/yourdomain.com/wp-config.php
sudo nano /var/www/yourdomain.com/wp-config.php

Update these values:

define( 'DB_NAME', 'wordpress_db' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'StrongPassword123!' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );

// Security keys β€” generate at https://api.wordpress.org/secret-key/1.1/salt/
define('AUTH_KEY',         'paste-unique-phrase-here');
// ... (paste all 8 keys)

Step 6: Configure Nginx Server Block

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

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

    # PHP processing
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Block sensitive files
    location ~ /\.(ht|git|env)              { deny all; }
    location = /xmlrpc.php                  { deny all; }
    location ~* /wp-config.php              { deny all; }

    # Static file caching
    location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff2|svg)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
        log_not_found off;
    }

    # Gzip
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;

    access_log /var/log/nginx/yourdomain.com.access.log;
    error_log  /var/log/nginx/yourdomain.com.error.log;
}
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 7: Install Free SSL Certificate

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
sudo certbot renew --dry-run

Visit https://yourdomain.com β€” you’ll see the WordPress installation wizard. Complete it to finish setup. βœ…


Step 8: Install Redis for Object Caching

sudo apt install redis-server -y
sudo systemctl enable redis-server

Add to wp-config.php:

define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_CACHE', true);

Install the Redis Object Cache plugin from the WordPress plugin directory and enable it. Database queries per page drop from 30–50 to under 10. βœ…


Step 9: Essential WordPress Security Settings

Disable file editing in WordPress admin

Add to wp-config.php:

define('DISALLOW_FILE_EDIT', true);

Limit login attempts

Install the Limit Login Attempts Reloaded plugin β€” essential for blocking brute-force attacks on wp-login.php.

Force HTTPS for admin and logins

define('FORCE_SSL_ADMIN', true);

Change the default database table prefix

In wp-config.php, change:

$table_prefix = 'wp83hx_'; // Use a random string, not 'wp_'

Step 10: Recommended WordPress Plugins for VPS Hosting

Plugin Purpose
Redis Object Cache Database query caching via Redis
WP Rocket / LiteSpeed Cache Full-page caching and performance
Wordfence Security Firewall and malware scanner
UpdraftPlus Automated backups to remote storage
ShortPixel / Imagify Automatic image compression
Limit Login Attempts Reloaded Block brute-force login attacks

Final Thoughts

A WordPress site on a LEMP VPS is faster, more flexible, and more cost-effective than managed WordPress hosting for any technically capable site owner. With Nginx, PHP 8.3 with OPcache, MariaDB, and Redis all configured and tuned, your site will load quickly, handle traffic spikes, and stay secure.

VPS.DO’s USA and Hong Kong VPS plans give you the dedicated resources and full root access to implement this complete stack β€” starting at $20/month.

Related articles:

Fast β€’ Reliable β€’ Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!