Guide e tutorial

Installare WordPress su uno stack LEMP (Nginx, PHP 8.3, MariaDB)

Pubblicato il 5 settembre 2023 · 14 min di lettura

Questo articolo è disponibile in francese e inglese.

Prerequisites

An Ubuntu 24.04 VPS with at least 2 vCPUs and 2 GB of RAM, a domain name whose A record points to the server's IP, and root SSH access (or sudo). Update the system first:

apt update && apt upgrade -y

Step 1 — Install Nginx and MariaDB

apt install -y nginx mariadb-server
systemctl enable --now nginx mariadb
mysql_secure_installation

Answer "yes" to everything: remove anonymous users, disallow remote root login, drop the test database. Pick a strong MariaDB root password.

Step 2 — Install PHP 8.3-FPM

Ubuntu 24.04 ships PHP 8.3 out of the box — no third-party PPA needed:

apt install -y php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring \
  php8.3-xml php8.3-zip php8.3-intl php8.3-imagick php8.3-bcmath
systemctl enable --now php8.3-fpm

Step 3 — Tune php.ini for WordPress

Edit /etc/php/8.3/fpm/php.ini and adjust these values:

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300

Apply with systemctl reload php8.3-fpm. The upload cap must stay consistent with Nginx's client_max_body_size, set in step 6.

Step 4 — Create the database

mariadb
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'AVeryStrongPassword!';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Never use the MariaDB root account in wp-config.php: a dedicated user limits the blast radius of a credential leak.

Step 5 — Download WordPress

mkdir -p /var/www/example.com
cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
cp -r wordpress/* /var/www/example.com/
chown -R www-data:www-data /var/www/example.com
chmod -R u=rwX,go=rX /var/www/example.com

Generate the configuration file:

cd /var/www/example.com
cp wp-config-sample.php wp-config.php
curl -s https://api.wordpress.org/secret-key/1.1/salt/ > /tmp/salts.txt

Edit wp-config.php: fill in DB_NAME, DB_USER, DB_PASSWORD, replace the eight security keys block with the contents of /tmp/salts.txt, then add:

define('FS_METHOD', 'direct');
define('DISABLE_WP_CRON', true);

FS_METHOD prevents the FTP credential prompt on every plugin update. DISABLE_WP_CRON stops scheduled tasks from firing on every page view — we replace it with a real system cron in step 8.

Step 6 — Nginx server block

Create /etc/nginx/sites-available/example.com:

server {
    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;
    }
}

Enable the site and validate the configuration:

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

Step 7 — HTTPS with Let's Encrypt

apt install -y certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com

Certbot rewrites the server block for HTTPS and installs a systemd timer that renews the certificate automatically — check it with systemctl list-timers certbot.

Step 8 — System cron for WP-Cron

By default WordPress triggers its cron on every page load: unpredictable, and expensive under traffic spikes. With DISABLE_WP_CRON active, schedule execution every five minutes:

crontab -u www-data -e
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1

Step 9 — Finish the installation

Open https://example.com, pick the language and create the administrator account — never use "admin" as the username. Under Settings → Permalinks, select "Post name": the server block's try_files already handles rewrites, no .htaccess needed.

Verification

  • systemctl status nginx mariadb php8.3-fpm — all three services active.
  • curl -I https://example.com — a 200 response over HTTPS.
  • WordPress "Site Health" tool: no critical warnings.

Troubleshooting

  • 502 Bad Gateway: PHP-FPM stopped or wrong socket — compare ls /run/php/ with the fastcgi_pass directive, then read journalctl -u php8.3-fpm.
  • "Error establishing a database connection": test the credentials manually with mariadb -u wp_user -p wordpress.
  • Uploads rejected: upload_max_filesize, post_max_size and client_max_body_size must be consistent on both sides.
  • White screen: set WP_DEBUG to true in wp-config.php and check wp-content/debug.log.

Going further

Install WP-CLI to manage the site from the command line:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp

On a high-traffic site, add an object cache: the php8.3-redis package, a local Redis server, and the "Redis Object Cache" plugin. Repetitive queries will stop hitting MariaDB.

Keep the whole stack patched with apt update && apt upgrade -y — PHP and MariaDB security fixes land in Ubuntu's repositories throughout the 24.04 lifecycle. A weekly wp plugin update --all && wp core update through WP-CLI closes the most exploited attack surface of any WordPress site.

Tutorial passo passo scritti dai nostri ingegneri, testati sulla nostra infrastruttura.

GLOBALCLOUDHOSTING →