Install and secure

Deploy WordPress on a VPS: Nginx, PHP, MariaDB and HTTPS

Install WordPress on an Ubuntu VPS, from the database to the Let's Encrypt certificate, with commands tested on Ubuntu 26.04 LTS.

Published on

This guide installs WordPress on an Ubuntu VPS with Nginx, PHP and MariaDB, then switches it to HTTPS with a free Let's Encrypt certificate. Allow half an hour. Every command was run on Ubuntu 26.04.1 LTS on September 27, 2026, in a test environment and then on a QuantylCloud VPS; they also work on Ubuntu 24.04 LTS, apart from the PHP version (see step 4).

The shortcut: the WordPress image

When you create your server, you can choose the catalog's WordPress image: the server starts with WordPress already installed. It is the fastest way to test. The manual installation described here leaves you in charge of every component: versions, settings, and what to look at when something breaks.

Before you start

  • an Ubuntu VPS, secured by following Secure your Linux VPS: this guide logs in with the gestion user created there;
  • a domain name, whose A DNS records for exemple.ma and www.exemple.ma point to the server's IP address. Replace exemple.ma with your domain in all the commands;
  • for a site with traffic, 2 vCPU and 4 GB of memory: a small plan is enough to start (see Create a VPS in Morocco).

Step 1 — Open the web ports

A website answers on ports 80 (HTTP) and 443 (HTTPS). Open them first in the Firewall tab of the server's page in the console, then in ufw on the machine:

sudo ufw allow 80,443/tcp

Forgetting one of the two firewalls is the first cause of an unreachable site, and of a certificate refused at step 6.

Step 2 — Install Nginx, MariaDB and PHP

sudo apt update
sudo apt install -y curl nginx mariadb-server php-fpm php-mysql php-curl php-gd php-intl php-mbstring php-xml php-zip php-imagick

Nginx serves the pages, PHP-FPM runs WordPress, MariaDB stores the content. The PHP extensions in the list are the ones WordPress asks for in its Site Health screen.

Step 3 — Create the database

First generate a strong password for the database, and write it down:

openssl rand -base64 24

Then create the database and its user, replacing MOT_DE_PASSE with the value you obtained:

sudo mysql <<'SQL'
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'MOT_DE_PASSE';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost';
SQL

On Ubuntu, sudo mysql opens the database as administrator without a password: administrator access is reserved for the server's sudo users. The wordpress user only has rights on its own database.

Step 4 — Download WordPress

Download the latest version, check its checksum, then install it:

cd /tmp
curl -fsSLO https://wordpress.org/latest.tar.gz
echo "$(curl -fsSL https://wordpress.org/latest.tar.gz.sha1)  latest.tar.gz" | sha1sum -c
tar -xzf latest.tar.gz
sudo mv wordpress /var/www/wordpress
sudo chown -R www-data:www-data /var/www/wordpress

The third command must print latest.tar.gz: OK. If not, the file is incomplete or tampered with: delete it and start again. The files belong to www-data, PHP's user: WordPress can then install its own updates, themes and plugins.

Also allow file uploads up to 64 MB, instead of the default 2 MB:

printf 'upload_max_filesize = 64M\npost_max_size = 64M\n' | sudo tee /etc/php/8.5/fpm/conf.d/99-wordpress.ini
sudo systemctl restart php8.5-fpm

8.5 is the PHP version of Ubuntu 26.04. On Ubuntu 24.04 it is 8.3: the command ls /etc/php gives you yours.

Step 5 — Configure Nginx

Create the site configuration:

sudo tee /etc/nginx/sites-available/wordpress >/dev/null <<'CONF'
server {
    listen 80;
    listen [::]:80;
    server_name exemple.ma www.exemple.ma;
    root /var/www/wordpress;
    index index.php;
    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/php-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}
CONF

Enable it in place of the default page, check it, then reload Nginx:

sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

nginx -t must answer syntax is ok and test is successful. Do not reload until it does.

Step 6 — Switch to HTTPS with Let's Encrypt

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d exemple.ma -d www.exemple.ma

Certbot asks for an email address, for expiry notices, and for you to accept Let's Encrypt's terms. It obtains the certificate, adds it to Nginx's configuration and from now on redirects all HTTP traffic to HTTPS. Renewal is automatic: the certificate lasts three months, and a scheduled task renews it before it expires.

In testing, we obtained the certificate from Let's Encrypt's test authority, without going over the Internet. Against the real Let's Encrypt, two more conditions apply: your DNS records must already point to the server, and port 80 must be open in both firewalls. If certbot fails, it is almost always one of the two.

Step 7 — Finish the installation in the browser

Open https://exemple.ma: the WordPress setup wizard starts. Choose the language, then enter the database created in step 3: name wordpress, username wordpress, your password, and localhost as the address. Then give the site a title, an administration username that is neither gestion nor your domain name, and a long password.

The wizard writes the wp-config.php file, which contains the database password, readable by all the server's users. We saw this in testing. Close it off:

sudo chmod 640 /var/www/wordpress/wp-config.php

Step 8 — Send the site's emails

As it stands, WordPress cannot send email: in testing, the “Lost your password?” link answered that the email could not be sent. Password resets, notifications and contact forms depend on it. The solution is to route emails through an SMTP server: the one from your business mailbox, or the one from an email delivery service. It gives you a server address, a port (usually 587), a username and a password.

Create the following file, replacing the server, username, password and sender address with your own:

sudo mkdir -p /var/www/wordpress/wp-content/mu-plugins
sudo tee /var/www/wordpress/wp-content/mu-plugins/smtp.php >/dev/null <<'PHP'
<?php
// Envoi des emails de WordPress par SMTP.
add_action('phpmailer_init', function ($mail) {
    $mail->isSMTP();
    $mail->Host       = 'smtp.exemple.ma';
    $mail->Port       = 587;
    $mail->SMTPSecure = 'tls';
    $mail->SMTPAuth   = true;
    $mail->Username   = 'site@exemple.ma';
    $mail->Password   = 'MOT_DE_PASSE_SMTP';
    $mail->setFrom('site@exemple.ma', 'Mon site');
});
PHP
sudo chown -R www-data:www-data /var/www/wordpress/wp-content/mu-plugins
sudo chmod 640 /var/www/wordpress/wp-content/mu-plugins/smtp.php

A file in the mu-plugins folder is loaded automatically by WordPress: it cannot be deactivated by mistake from the dashboard and survives theme changes. It contains a password, hence the last command. If you prefer a settings screen, an SMTP plugin from the official directory does the same job.

To check, log out, click “Lost your password?” on the login page and enter your username: the email should arrive within a minute. Your SMTP provider also tells you which DNS records to add to your domain so that these emails do not end up in spam.

What next?

  • Updates. WordPress, themes and plugins are updated from the dashboard. Nginx, PHP and MariaDB are updated by Ubuntu's automatic updates if you followed the securing guide.
  • Backups. Enable the daily backup option from the server's page, or keep your own: the database and the /var/www/wordpress/wp-content folder.
  • Plugins. Each one is code that runs on your server: install few, from the official directory, and remove the ones you no longer use.

Frequently asked questions

Which plan should I choose for a WordPress site?

The smallest plan is enough for a showcase site or to get started. For a site with traffic, a shop or several heavy plugins, aim for 2 vCPU and 4 GB of memory.

Is the HTTPS certificate paid?

No. Let's Encrypt issues free certificates, valid for three months, and certbot renews them automatically before they expire.

Why won't certbot get a certificate?

Almost always for one of two reasons: the domain's DNS records do not yet point to the server, or port 80 is closed in the console firewall or in ufw.

Can you install WordPress for me?

Yes: the catalog's WordPress image delivers a server with WordPress already installed, and our team can also handle the setup. Write to us from the contact page.