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.
If you would rather not manage a server, Arianet hosting is a simpler option for a single WordPress site.
Prerequisites
- A cloud server or VPS with Ubuntu 24.04, at least 1 GB of RAM, and a sudo user (first SSH login and hardening)
- A domain with an A record (and AAAA, if any) pointing to the server
- Ports 80 and 443 open in the cloud firewall and ufw
Replace example.com with your domain in the commands.
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:
| Field | Value |
|---|---|
| Database name | wordpress |
| Username | wpuser |
| Password | the password from step 3 |
| Database host | localhost |
| Table prefix | wp_ (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
| Error | Fix |
|---|---|
502 Bad Gateway | The socket path in fastcgi_pass does not match the PHP version. Check ls /run/php/ and fix the path. |
Error establishing a database connection | Wrong database name, user or password in wp-config.php, or MariaDB is down: systemctl status mariadb. |
413 Request Entity Too Large | client_max_body_size in Nginx is too small. |
The uploaded file exceeds the upload_max_filesize directive | Do step 6 and restart php8.3-fpm. |
| WordPress asks for FTP details to install plugins | Files are not owned by www-data; run the chown from step 4 again. |
| WordPress emails do not arrive | Use 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
- Snapshots, backups and restore
- Arianet cloud load balancer in front of two web servers
- Swap, timezone and hostname
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.