How to Install WordPress on a VPS (2026): LEMP Stack Guide
The short version: To install WordPress on a VPS, build a LEMP stack on Ubuntu 24.04: install Nginx, MariaDB, and PHP 8.3-FPM, create a WordPress database and user, drop WordPress in the web root, write an Nginx server block, then run Certbot for free SSL. Add Redis as an object cache for speed. Plan on 30 to 45 minutes.
We run this exact stack on production sites hosted on Hetzner Cloud, and the steps below are the cleaned-up version of what we type on a fresh server. Every command is real, copy-pasteable, and correct for Ubuntu 24.04 LTS. We use the LEMP stack (Linux, Nginx, MariaDB, PHP) rather than LAMP because Nginx with PHP-FPM uses less RAM and serves static files faster on a small VPS, which is what most people are starting from.
What you need before you start
- An Ubuntu 24.04 LTS VPS with at least 2 GB RAM. We use a Hetzner CX22 (4 GB) for this guide. A 1 GB instance works with swap, but 2 GB is the realistic floor for comfortable WordPress.
- Root or sudo SSH access. If you have not hardened the box yet (new sudo user, SSH keys, UFW, fail2ban), do that first with our VPS setup guide. This walkthrough assumes a secured server.
- A registered domain with an A record pointing at your VPS IP. SSL will not issue until DNS resolves to the server, so set this up early and let it propagate.
- An SSH client. The built-in terminal on macOS or Linux, or a client like PuTTY on Windows.
Through the rest of this guide, replace example.com with your real domain and swap the placeholder passwords for strong, unique values. We use deploy as the sudo user from our setup guide.
Step 1: Update the server and install Nginx
Start by refreshing the package index and installing the latest security updates, then install Nginx. If you followed our setup guide you already have UFW running, so allow the web ports too.
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx
sudo ufw allow 'Nginx Full'
sudo systemctl enable --now nginx
The Nginx Full profile opens ports 80 and 443. Visit http://your-server-ip in a browser and you should see the default Nginx welcome page. That confirms the web server is reachable before we point a domain at it.
Step 2: Install and secure MariaDB
MariaDB is the database WordPress stores every post, setting, and user in. It is a drop-in replacement for MySQL and is what most Linux distributions ship. Install it, then run the hardening script.
sudo apt install -y mariadb-server
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
The mysql_secure_installation script asks a short series of questions. Answer them this way:
- Switch to unix_socket authentication? Press Enter to keep the default (you log in as root via sudo).
- Change the root password? Yes, and set a strong one you save in a password manager.
- Remove anonymous users? Yes.
- Disallow root login remotely? Yes.
- Remove the test database? Yes.
- Reload privilege tables now? Yes.
Those defaults remove the obvious attack surface that ships out of the box. Confirm the server is up with sudo systemctl status mariadb.
Step 3: Create the WordPress database and user
WordPress should never connect as the MySQL root user. Create a dedicated database and a dedicated user that has rights only on that one database. Log in to the database shell first.
sudo mariadb
At the MariaDB [(none)]> prompt, run these statements. Replace the password with your own strong value.
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'StrongDbPassword_Change_Me';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
The utf8mb4 character set is important: it lets WordPress store emoji and the full range of Unicode without corrupting content. Note the three values you just set (database wordpress, user wp_user, and the password); you will paste them into the config file shortly.
Step 4: Install PHP 8.3-FPM and extensions
Ubuntu 24.04 ships PHP 8.3, which is the version we run in production. Install PHP-FPM (the process manager Nginx talks to) plus the extensions WordPress and the common plugins expect.
sudo 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-imagick php8.3-intl
sudo systemctl enable --now php8.3-fpm
Confirm the service is listening on its socket with sudo systemctl status php8.3-fpm. While you are here, raise two defaults that block real-world WordPress uploads. Edit the FPM config:
sudo sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 64M/' /etc/php/8.3/fpm/php.ini
sudo sed -i 's/^post_max_size = .*/post_max_size = 64M/' /etc/php/8.3/fpm/php.ini
sudo systemctl restart php8.3-fpm That bumps the upload limit to 64 MB so media uploads and plugin installs do not fail silently on the defaults.
Step 5: Download and configure WordPress
Pull the latest WordPress, extract it into the web root, and set ownership so Nginx and PHP can read and write the files.
cd /tmp
curl -O https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
sudo mkdir -p /var/www/example.com
sudo cp -a /tmp/wordpress/. /var/www/example.com/
sudo chown -R www-data:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \; Now create the config file from the sample and open it.
sudo cp /var/www/example.com/wp-config-sample.php /var/www/example.com/wp-config.php
sudo nano /var/www/example.com/wp-config.php Set the three database lines to match what you created in Step 3:
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'StrongDbPassword_Change_Me' );
define( 'DB_HOST', 'localhost' ); WordPress also needs unique secret keys (the salts). Do not invent your own. Generate a fresh set and paste them over the placeholder block in the file:
curl -s https://api.wordpress.org/secret-key/1.1/salt/
That command prints eight define() lines. Replace the matching placeholder block in wp-config.php with the generated lines, save, and exit. The salts encrypt session cookies, so unique values per install matter.
Step 6: Write the Nginx server block
Nginx needs a server block that points at the WordPress directory, hands PHP requests to the PHP-FPM socket, and routes pretty permalinks through index.php. Create the file:
sudo nano /etc/nginx/sites-available/example.com
Paste this configuration, replacing example.com with your domain:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
client_max_body_size 64M;
}
Enable the site by linking it into sites-enabled, test the configuration for syntax errors, then reload Nginx.
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
The nginx -t step is the one most people skip and then wonder why the reload failed. Always run it. If it reports syntax is ok, visit http://example.com and you should land on the WordPress installer.
Step 7: Install free SSL with Certbot
Serving WordPress over plain HTTP in 2026 is a non-starter: browsers flag it, and login credentials travel in the clear. Certbot issues a free Let's Encrypt certificate and rewrites your Nginx block to serve HTTPS, all in one command.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com Certbot asks for an email (for expiry warnings) and whether to redirect HTTP to HTTPS. Choose the redirect. It edits your server block, reloads Nginx, and installs a systemd timer that renews the certificate automatically before it expires. Confirm renewal works with a dry run:
sudo certbot renew --dry-run
Certificates last 90 days and renew on their own, so once the dry run passes you do not touch SSL again. Your site now answers on https://example.com.
Step 8: Add a Redis object cache
Redis is an in-memory store that caches the results of repeated database queries. On a busy site, or anything with logged-in users or WooCommerce, it cuts page generation time noticeably. Install the server and the PHP extension.
sudo apt install -y redis-server php8.3-redis
sudo systemctl enable --now redis-server
sudo systemctl restart php8.3-fpm
Tell WordPress to use Redis by adding one line to wp-config.php above the line that reads /* That's all, stop editing! */:
define( 'WP_REDIS_HOST', '127.0.0.1' ); Then finish the WordPress installer in the browser (set your site title, admin user, and password), log in to the dashboard, and install the free Redis Object Cache plugin. Under Settings, Redis, click Enable Object Cache. The status should flip to "Connected." That last step is what actually wires WordPress to the Redis server you just installed.
Common mistakes and quick fixes
- 502 Bad Gateway after the Nginx reload. The
fastcgi_passsocket path does not match your PHP version. Confirm the socket withls /run/php/and make sure the server block points at the exact filename (for examplephp8.3-fpm.sock). - "Error establishing a database connection." The credentials in
wp-config.phpdo not match what you created in Step 3, or you forgotFLUSH PRIVILEGES. Re-check the database name, user, and password character for character. - Certbot fails to issue the certificate. DNS is not resolving to the server yet, or port 80 is blocked. Verify with
dig example.comthat the A record returns your VPS IP, and confirm UFW allows Nginx Full. - Permalinks return 404 on every page except the homepage. The
try_filesdirective is missing or the site was not reloaded. Thelocation /block above handles this; reload Nginx after editing. - White screen after enabling a plugin. Usually a missing PHP extension. Re-run the Step 4 install line and restart
php8.3-fpm. Check/var/log/nginx/error.logfor the exact missing module.
Skip the manual work
Everything above is worth doing once so you understand your own stack. But if you would rather never SSH into a server or edit an Nginx block, a managed host does all of this for you. Cloudways layers managed updates, server hardening, free SSL, daily backups, and a one-click WordPress plus cache stack on top of providers like DigitalOcean and Vultr. You pick the size, it provisions a tuned LEMP install in about four minutes, and you never touch a config file. We use the hybrid affiliate program; the price you pay is the same.
If you want the simplest possible path with a bundled domain, Hostinger offers a one-click WordPress install on its VPS and shared plans and registers a free domain in year one. It is the easiest on-ramp for a first site. We are a Hostinger affiliate; the link tracks the signup and your price does not change.
Prefer the hands-on route at the lowest possible cost? That is what we run. A Hetzner CX22 at EUR 4.50/mo hosts this exact LEMP stack with room to spare. Hetzner runs a mutual-credit referral: you get EUR 20 in account credit after spending EUR 10, and we get EUR 10 in credit after that. It is not a one-way commission, and your price is the same. If you would rather use a host we do not earn from, DigitalOcean and Vultr both run this guide unchanged; we do not earn a commission there, and the steps are identical.
FAQ
How long does it take to install WordPress on a VPS by hand?
About 30 to 45 minutes the first time, including securing the server. Once you have done it a few times it is closer to 15 minutes. The slowest parts are waiting on DNS to point at the VPS and running mysql_secure_installation carefully. If you do not want to touch a config file at all, a managed host like Cloudways or a one-click installer like Hostinger gets you a live WordPress site in about 5 minutes.
Should I use Nginx (LEMP) or Apache (LAMP) for WordPress?
For a single WordPress site on a small VPS, Nginx (the LEMP stack) uses less RAM and serves static files faster under load, which matters on a 1 to 2 GB instance. Apache is friendlier if you rely on .htaccess rules from plugins, since Nginx needs those rules translated into the server block. For most people running their own VPS, Nginx with PHP-FPM is the leaner, faster default.
What PHP version should WordPress run in 2026?
PHP 8.3 is the sweet spot in 2026: it is fast, fully supported, and compatible with current WordPress core and the major plugins. PHP 8.4 also works with up-to-date WordPress, but some older plugins lag behind on the newest release, so 8.3 is the safer production choice. Avoid anything older than 8.1, which is past its security support window.
Is a 1 GB VPS enough to run WordPress?
A 1 GB VPS runs a small WordPress site if you add swap and enable caching, but it is tight once you stack plugins like Elementor or WooCommerce. We recommend 2 GB RAM as the realistic floor for a comfortable LEMP WordPress install, which is what the Hetzner CX22 (4 GB) or Hostinger KVM 2 (2 GB) give you for a few dollars a month.
Do I need to install Redis to run WordPress on a VPS?
No, WordPress runs fine without Redis. Redis is an optional object cache that stores repeated database query results in memory, which cuts page generation time on dynamic, logged-in, or WooCommerce traffic. For a low-traffic blog it is a small win. For a busy site or a store it is one of the cheapest performance upgrades you can make on a VPS.
How do I get a free SSL certificate for WordPress on a VPS?
Use Certbot with Let's Encrypt. After your Nginx server block is live on port 80, install Certbot and the Nginx plugin and run certbot --nginx for your domain. It issues a free certificate, rewrites your server block to serve HTTPS, and sets up automatic renewal via a systemd timer, so the certificate refreshes every 60 to 90 days without you touching it.
When should I use a managed host instead of installing WordPress myself?
Use a managed host when your time is worth more than the markup, or when you bill clients for hosting. Cloudways layers managed updates, server hardening, free SSL, daily backups, and a one-click WordPress stack on top of providers like DigitalOcean and Vultr, so you never edit a config file. Hostinger offers a one-click WordPress install on its VPS and shared plans. Self-installing is the right call when you want full control of the stack and the lowest possible bill.
Related Guides
- Best Cheap VPS Hosting (2026), the ranked list of providers to run this stack on.
- How to Set Up a VPS, the security hardening (sudo user, SSH keys, UFW, fail2ban) you should do before this install.
- How to Migrate WordPress to Cloudways, move an existing site to managed hosting without downtime.
- Cheap Cloudways Alternatives, managed-hosting options if Cloudways pricing does not fit.