WordPress still powers over 40% of the web. Love it or hate it, if you host sites for clients or run your own, you need to know how to set it up properly on a modern stack.
This tutorial walks you through a clean WordPress installation on Ubuntu 24.04 using Nginx, PHP-FPM, and MariaDB — the full LEMP stack. No Docker, no control panels. Just a fast, production-ready setup you fully control.
By the end, you'll have WordPress running on Nginx with pretty permalinks, static asset caching, and a properly secured database.
Prerequisites
- An Ubuntu 24.04 VPS with at least 1 vCPU and 2 GB RAM
- SSH access to your server
- A registered domain name pointed to your server (recommended)
Step 1 — Install Nginx
Update packages and install Nginx:
sudo apt update
sudo apt install -y nginx
Enable it at boot and verify:
sudo systemctl enable nginx
sudo systemctl status nginx
You should see active (running).
Step 2 — Install MariaDB
sudo apt install -y mariadb-server
Run the security hardening script:
sudo mysql_secure_installation
Press Enter for current root password, type n for unix_socket auth, set a strong root password, then Y to everything else — removes anonymous users, disables remote root login, drops the test database, reloads privileges.
Step 3 — Create the WordPress Database
sudo mariadb
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Replace strong_password_here with an actual secure password. The utf8mb4 charset gives you full Unicode support including emojis.
Step 4 — Install PHP-FPM and Extensions
WordPress needs several PHP extensions for image processing, database access, and XML parsing:
sudo apt install -y php-fpm php-mysql php-curl php-gd php-intl php-mbstring \
php-soap php-xml php-xmlrpc php-zip php-imagick php-common
Verify PHP-FPM is running:
sudo systemctl status php8.3-fpm
Step 5 — Download and Configure WordPress
Download and extract WordPress:
cd /tmp
curl -O https://wordpress.org/latest.tar.gz
sudo tar -xzf latest.tar.gz -C /var/www/
Set ownership for Nginx:
sudo chown -R www-data:www-data /var/www/wordpress
Create the config file:
cd /var/www/wordpress
sudo -u www-data cp wp-config-sample.php wp-config.php
sudo nano /var/www/wordpress/wp-config.php
Update the database credentials:
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wpuser' );
define( 'DB_PASSWORD', 'strong_password_here' );
define( 'DB_HOST', 'localhost' );
Generate unique authentication keys by visiting https://api.wordpress.org/secret-key/1.1/salt/ and replacing the placeholder lines in wp-config.php.
⚠️ Never leave the default placeholder keys in production. They protect your login cookies and session data.
Step 6 — Configure the Nginx Server Block
Create the server block. Replace your_domain_or_ip with your actual domain or server IP:
sudo nano /etc/nginx/sites-available/wordpress
server {
listen 80;
listen [::]:80;
server_name your_domain_or_ip;
root /var/www/wordpress;
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;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
log_not_found off;
access_log off;
allow all;
}
location ~* \.(css|gif|ico|jpeg|jpg|js|png|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
What this does:
-
client_max_body_size 64M— allows media uploads up to 64 MB -
try_files— enables WordPress pretty permalinks - PHP requests routed to PHP-FPM via Unix socket
- Static assets cached for 30 days
Enable the site and remove the default config:
sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
Step 7 — Configure the Firewall
Allow HTTP traffic:
sudo ufw allow 'Nginx HTTP'
sudo ufw status
💡 After setting up SSL with Let's Encrypt, switch to
Nginx Fullto allow both HTTP and HTTPS.
Step 8 — Complete the WordPress Installation
Navigate to http://your_domain_or_ip in your browser. The WordPress installation wizard will appear. Fill in your site title, admin username (avoid "admin"), a strong password, and your email.
Click Install WordPress, then log in.
💡 First things after login: go to Settings → Permalinks → select "Post name" for SEO-friendly URLs. Then install a security plugin like Wordfence.
Step 9 — Verify and Optimize
Confirm everything works:
curl -I http://your_domain_or_ip
You should see HTTP/1.1 200 OK with X-Powered-By: PHP/8.3.
For production, consider:
-
SSL:
sudo apt install certbot python3-certbot-nginxthensudo certbot --nginx -d your_domain -
PHP tuning: Increase
memory_limitto 256M andupload_max_filesizeto 64M in/etc/php/8.3/fpm/php.ini - Caching: Install WP Super Cache or W3 Total Cache
Conclusion
You've got a clean WordPress installation running on a modern LEMP stack — Nginx, PHP-FPM 8.3, and MariaDB on Ubuntu 24.04. No bloated control panels, no shared hosting limitations. Full control.
From here: add SSL with Let's Encrypt, install your theme, and start publishing.
I'm Serdar, co-founder of Raff — affordable and reliable cloud infrastructure built to be the one platform your app needs — compute, storage, and beyond. Originally published on the Raff Technologies blog.
Top comments (0)