Why Run WordPress on a VPS Instead of Shared Hosting?

Shared hosting works well for a new website with modest traffic, but it has hard limits: you share CPU, RAM, and network resources with dozens or hundreds of other accounts. When your site grows — or when a noisy neighbour on the same server runs a resource-heavy script — your WordPress site slows to a crawl or returns 503 errors.

A VPS (Virtual Private Server) gives you dedicated, guaranteed resources, full root access to configure the server exactly how you need it, and the ability to scale independently. For businesses in Nepal running WooCommerce stores, membership sites, or news portals, a VPS is the right step up.

This guide assumes a fresh Ubuntu 22.04 or AlmaLinux 9 VPS. All commands are run as root unless stated otherwise.

Step 1: Initial Server Setup and Hardening

Before installing anything, secure the server:

# Update all packages
apt update && apt upgrade -y   # Ubuntu
# or
dnf update -y                  # AlmaLinux

# Create a non-root sudo user
adduser deploy
usermod -aG sudo deploy

# Set up SSH key auth for the new user (from your local machine)
ssh-copy-id deploy@your-vps-ip

# Then on the server, disable root SSH login
nano /etc/ssh/sshd_config
# Set: PermitRootLogin no
# Set: PasswordAuthentication no
systemctl restart sshd

# Configure UFW firewall (Ubuntu)
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Step 2: Install the LEMP Stack (Nginx + MySQL + PHP)

The LEMP stack (Linux, Nginx, MySQL/MariaDB, PHP) outperforms the traditional LAMP stack for WordPress under high concurrency. Nginx handles static files with near-zero CPU usage and manages thousands of concurrent connections efficiently.

# Ubuntu 22.04
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-intl php8.2-imagick -y

# Start and enable services
systemctl enable nginx mariadb php8.2-fpm --now

Step 3: Configure MariaDB and Create a WordPress Database

# Run the secure installation script
mysql_secure_installation

# Log in and create your WordPress database
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 WordPress

cd /var/www
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
mv wordpress yourdomain.com
chown -R www-data:www-data yourdomain.com
chmod -R 755 yourdomain.com

Step 5: Configure Nginx Virtual Host

Create /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;

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

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

    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~ /\. {
        deny all;
    }
}
# Enable the site
ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

Step 6: Install SSL with Let's Encrypt (Certbot)

apt install certbot python3-certbot-nginx -y
certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot automatically modifies your Nginx config to handle HTTPS, sets up HTTP→HTTPS redirects, and creates a cron job for certificate auto-renewal. Test renewal works: certbot renew --dry-run

Step 7: Configure WordPress wp-config.php

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

Fill in your database credentials and add unique authentication keys (generate from https://api.wordpress.org/secret-key/1.1/salt/). Also add:

define('WP_DEBUG', false);
define('DISALLOW_FILE_EDIT', true);  // Disable theme/plugin editor
define('FORCE_SSL_ADMIN', true);

Step 8: Optimise PHP-FPM for Your VPS Size

Edit /etc/php/8.2/fpm/pool.d/www.conf:

; For a 2 GB RAM VPS
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500

Also edit /etc/php/8.2/fpm/php.ini:

memory_limit = 256M
max_execution_time = 60
upload_max_filesize = 64M
post_max_size = 64M
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000

Step 9: Install a WordPress Caching Plugin

Even with Nginx, WordPress generates PHP on every request unless caching is configured. Install LiteSpeed Cache (or W3 Total Cache if on Nginx) and configure:

  • Page caching (serves HTML directly, bypassing PHP)
  • Browser caching (long cache-control headers for static assets)
  • Image lazy loading
  • CSS and JS minification and combination
  • Database object caching (consider Redis for high-traffic sites)

Step 10: Set Up Automated Backups

A VPS without automated backups is a business risk. Configure:

  1. File backup: Use rsync to a remote server or S3-compatible storage (Backblaze B2, Wasabi) nightly
  2. Database backup: mysqldump wordpress_db | gzip > /backup/db_$(date +%Y%m%d).sql.gz via cron
  3. Test restores quarterly — a backup you've never tested is not a backup you can trust

Performance Benchmark: What to Expect

On a 2 vCPU / 2 GB RAM VPS with this setup:

  • TTFB (Time to First Byte): 80–150 ms for cached pages
  • Concurrent users: 500–1,000 per minute without degradation
  • Google PageSpeed score: 85–95+ with proper image optimisation

WebsNP offers VPS hosting plans in Nepal starting at affordable monthly rates, pre-configured with the LEMP stack and WordPress-ready images. Contact us for a migration from shared hosting — we handle the entire transfer free of charge.