How to host a WordPress site on your own VPS
WordPress runs a large share of the web, and a VPS lets you host it with full control and without paying for a managed plan. It is a manageable project if you take it in stages: a web server, PHP, a database, WordPress itself and HTTPS. This guide uses nginx, PHP-FPM and MariaDB, a combination often called a LEMP stack, on Ubuntu.
You are taking on the work of keeping it updated and backed up. If you would rather not, a managed WordPress plan is a fair choice. If you want the control, read on.
Before you start
- An Ubuntu VPS with a sudo user and basic security done. See How to create a non-root user with sudo and Basic security for a new VPS.
- A domain pointed at the server, as in Point your domain to your server.
- At least 1 GB of memory for a small site, and more for a busy one. See What the CPU, memory and disk numbers on your server mean.
- Ports 80 and 443 open in the firewall. See Set up a firewall on your VPS with UFW.
Step 1: install the software
sudo apt update
sudo apt install nginx mariadb-server php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl
Ubuntu installs the current PHP version for your release. Find the exact version, which you need for the socket path later:
ls /run/php/
You will see a file such as php8.3-fpm.sock.
Step 2: create the database
Secure MariaDB first, following How to install and secure MariaDB on Ubuntu. Then:
sudo mysql
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Step 3: download WordPress
cd /tmp
curl -LO https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
sudo mkdir -p /var/www/mysite
sudo cp -a wordpress/. /var/www/mysite/
sudo chown -R www-data:www-data /var/www/mysite
Always download from the official WordPress site.
Step 4: configure WordPress
Copy the sample config and edit it:
cd /var/www/mysite
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php
Set DB_NAME, DB_USER and DB_PASSWORD to the values from step 2, and DB_HOST to localhost. Replace the placeholder security keys with fresh random ones. WordPress offers a page that generates them, at https://api.wordpress.org/secret-key/1.1/salt/. Then restrict the file, since it holds your database password:
sudo chmod 640 wp-config.php
Step 5: configure nginx
Create /etc/nginx/sites-available/mysite:
server {
listen 80;
listen [::]:80;
server_name mydomain.net www.mydomain.net;
root /var/www/mysite;
index index.php;
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;
}
Use the socket name from step 1, and your own domain. The client_max_body_size line allows larger uploads, such as images. Enable it, test and reload:
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
More on this layout is in How to host several websites on one VPS with nginx server blocks.
Step 6: add HTTPS
sudo certbot --nginx -d mydomain.net -d www.mydomain.net
See Set up an SSL certificate (HTTPS). Then visit your domain and complete the WordPress installer in the browser, choosing the admin username and a strong password.
Step 7: keep it secure and healthy
WordPress is a popular target, so attention to the basics matters:
- Update everything: WordPress, themes and plugins. Most hacked sites run outdated plugins. Turn on automatic updates for minor releases, and check weekly for the rest.
- Remove what you do not use. Delete unused themes and plugins instead of just deactivating them.
- Use strong, unique passwords and two-factor authentication for admin accounts.
- Limit login attempts with a plugin, or block repeat offenders with Fail2ban.
- Install plugins only from trusted sources.
- Keep file permissions tight. Files should be readable by the web server, and only what must be writable, such as
wp-content/uploads, should be. - Back up the files and the database on a schedule, and test restores. See How to back up your VPS with rsync and The 3-2-1 backup rule.
Speed
A few simple things help a lot: enable PHP's opcache, which is on by default in recent versions, use a caching plugin, compress images before uploading and keep plugins few. If the server runs out of memory, see the section on swap in How to add swap space to your VPS.
Troubleshooting
| Problem | Likely cause |
|---|---|
| "Error establishing a database connection" | Wrong credentials in wp-config.php, or MariaDB stopped |
| 502 Bad Gateway | PHP-FPM not running, or the socket path is wrong. See How to fix nginx 502 and 504 errors |
| 403 or 404 on pages | Permalinks need the try_files line above |
| Cannot upload files | Folder ownership, or client_max_body_size too small |
| White screen | A plugin error. Check the nginx and PHP logs |
Still stuck? Open a ticket on Discord - run /ticket in any channel, pick a department, and include your Server ID or Invoice ID so we can jump straight in.