Skip to main content

Install WordPress on a VPS with LEMP

WordPress on your own server means full control over resources, plugins and the PHP version, without the limits of shared hosting. In this tutorial you install WordPress on the LEMP stack: Linux (Ubuntu), Engine-X (Nginx), MariaDB and PHP-FPM.

tip

If you would rather not manage a server, Arianet hosting is a simpler option for a single WordPress site.

Prerequisites​

Replace example.com with your domain in the commands.

Ubuntu 22.04

Ubuntu 24.04 ships PHP 8.3 and Ubuntu 22.04 ships PHP 8.1. On 22.04 replace 8.3 with 8.1 in paths and service names (for example php8.1-fpm and /run/php/php8.1-fpm.sock).

1. Install Nginx, MariaDB and PHP​

sudo apt update
sudo apt install -y nginx mariadb-server \
php-fpm php-mysql php-curl php-gd php-intl php-mbstring php-xml php-zip php-imagick
sudo ufw allow 'Nginx Full'

Check the PHP version and services:

php -v
systemctl is-active php8.3-fpm mariadb nginx

2. Secure MariaDB​

sudo mariadb-secure-installation

On Ubuntu the database root user logs in through the OS socket and needs no password. Press Enter for the current password, answer n to Switch to unix_socket authentication and Change the root password (socket login is already active), and answer Y to the remaining questions (remove anonymous users, disallow remote root login, remove the test database, reload privileges).

3. Create the database and user​

Replace the password with a strong one:

sudo mariadb <<'SQL'
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'CHANGE-ME-strong-password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
SQL

4. Download WordPress​

cd /tmp
curl -LO 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 {} \;

www-data ownership lets WordPress create wp-config.php and install plugins and updates without FTP.

5. Configure Nginx​

sudo tee /etc/nginx/sites-available/example.com > /dev/null <<'EOF'
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

root /var/www/example.com;
index index.php index.html;
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.3-fpm.sock;
}

location ~ /\.ht {
deny all;
}

location ~* \.(css|js|gif|ico|jpe?g|png|svg|webp|woff2?)$ {
expires 30d;
access_log off;
}
}
EOF

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

6. PHP upload size​

PHP's default upload limit is 2 MB. Match it to client_max_body_size above:

sudo tee /etc/php/8.3/fpm/conf.d/99-wordpress.ini > /dev/null <<'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 120
EOF
sudo systemctl restart php8.3-fpm

7. SSL certificate​

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com --redirect --agree-tos -m you@example.com

Details and automatic renewal are in Nginx and a free Let's Encrypt certificate.

8. Install from the browser​

Open https://example.com, pick a language and enter the database details:

FieldValue
Database namewordpress
Usernamewpuser
Passwordthe password from step 3
Database hostlocalhost
Table prefixwp_ (or any prefix)

WordPress creates wp-config.php with random security keys. Then enter the site title, an admin username (not admin), a strong password and your email.

Final check​

curl -sI https://example.com | head -n 1         # HTTP/2 200 or HTTP/1.1 200
curl -sI https://example.com/wp-login.php | head -n 1
sudo -u www-data test -w /var/www/example.com/wp-content && echo writable

In the WordPress dashboard, Tools → Site Health should show no critical issues.

Common errors​

ErrorFix
502 Bad GatewayThe socket path in fastcgi_pass does not match the PHP version. Check ls /run/php/ and fix the path.
Error establishing a database connectionWrong database name, user or password in wp-config.php, or MariaDB is down: systemctl status mariadb.
413 Request Entity Too Largeclient_max_body_size in Nginx is too small.
The uploaded file exceeds the upload_max_filesize directiveDo step 6 and restart php8.3-fpm.
WordPress asks for FTP details to install pluginsFiles are not owned by www-data; run the chown from step 4 again.
WordPress emails do not arriveUse an SMTP plugin with an email service on port 587 or 465. On an Arianet VPS port 25 is closed by default.

Maintenance​

  • Take a snapshot before updating WordPress core, themes or important plugins.
  • Back up the database regularly: sudo mariadb-dump wordpress | gzip > wordpress-$(date +%F).sql.gz
  • Attach a separate volume for large media libraries.

Next steps​

Create your server​

Run WordPress on your own server with dedicated resources. In the Arianet panel, create a cloud server (Cloud server / Cloud Computing → New server) or a VPS with Ubuntu 24.04, and protect your site with automatic backups.