Saltar al contenido
Ubuntu / Linux

Host Multiple WordPress Sites on One Ubuntu LEMP Server

For each site: create a server block, a database and database user, unpack WordPress into its own folder, set ownership to www-data, enable the block and add a Let’s Encrypt certificate.

Probado en Ubuntu 24.04 LTS, Nginx 1.24, PHP 8.3, MySQL 8.0

One well-tuned server can host many WordPress sites. Each site gets its own folder, Nginx server block, database and database user, so a problem on one doesn’t spill into the others. Replace example.com with your domain throughout, and repeat steps 1–6 for each site.

Before you start

  • A LEMP stack: sudo apt install nginx mysql-server 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 unzip
  • The domain’s A record pointing at the server
  • A sudo user

Step 1 – Create the server block

Terminal
sudo nano /etc/nginx/sites-available/example.com.conf
/etc/nginx/sites-available/example.com.conf
server {n    listen 80;n    listen [::]:80;n    server_name example.com www.example.com;n    root /var/www/example.com;n    index index.php index.html;nn    client_max_body_size 64m;nn    location / {n        try_files $uri $uri/ /index.php?$args;n    }nn    location ~ u005c.php$ {n        include snippets/fastcgi-php.conf;n        fastcgi_pass unix:/run/php/php8.3-fpm.sock;n    }nn    # Never run PHP from uploads, never serve hidden filesn    location ~* ^/wp-content/uploads/.*u005c.php$ { deny all; }n    location ~ /u005c.(?!well-known) { deny all; }n    location = /xmlrpc.php { deny all; }nn    location = /favicon.ico { log_not_found off; access_log off; }n    location = /robots.txt  { log_not_found off; access_log off; }n}

Using another PHP version? Change php8.3-fpm.sock to match (ls /run/php/). The Nginx Server Block Generator writes this file for you, HTTPS included.

Step 2 – Create the database and user

Terminal
sudo mysql
MySQL
CREATE DATABASE example_wp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;nCREATE USER 'example_user'@'localhost' IDENTIFIED BY 'a-long-random-password';nGRANT ALL PRIVILEGES ON example_wp.* TO 'example_user'@'localhost';nFLUSH PRIVILEGES;nEXIT;

Use a different database and user for every site, and a long random password – the Password Generator can make one.

Step 3 – Download WordPress into the site folder

Terminal
cd /tmpnwget https://wordpress.org/latest.tar.gzntar -xzf latest.tar.gznsudo mkdir -p /var/www/example.comnsudo cp -a /tmp/wordpress/. /var/www/example.com/nrm -rf /tmp/wordpress /tmp/latest.tar.gz

Step 4 – Configure wp-config.php

Terminal
cd /var/www/example.comnsudo cp wp-config-sample.php wp-config.phpnsudo nano wp-config.php

Set DB_NAME, DB_USER and DB_PASSWORD, replace the salt lines with fresh ones from api.wordpress.org/secret-key, and change $table_prefix from wp_ to something unique such as ex7_.

Step 5 – Set ownership and enable the site

Terminal
sudo chown -R www-data:www-data /var/www/example.comnsudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/nsudo nginx -t u0026u0026 sudo systemctl reload nginx

Step 6 – Add HTTPS with Let’s Encrypt

Terminal
sudo apt install certbot python3-certbot-nginxnsudo certbot u002du002dnginx u002du002dredirect -d example.com -d www.example.com

Certbot edits the server block for HTTPS and renews the certificate automatically.

Step 7 – Run the WordPress installer

Open https://example.com, choose a language, then create the administrator account – use a unique username, not “admin”.

Isolate sites further

For stronger separation give each site its own PHP-FPM pool running as its own Linux user (a file in /etc/php/8.3/fpm/pool.d/ with user = example and its own socket). A compromised plugin on one site then can’t read the others’ files.

Inder Kochar

Escrito por

Inder Kochar

Ingeniero de sistemas y redes – Documento las soluciones que aplico con mis clientes, probadas en sistemas reales. ¿Atascado con algo parecido?

Seguir leyendo

Haga una pregunta o comparta su solución

Su correo no se publica. Los comentarios se moderan – por favor, cíñase al tema.