Linux VPS

Host multiple websites on Nginx with server blocks and PHP-FPM

Configure Nginx server blocks to host several PHP websites on one VPS, each with its own PHP-FPM pool and user, pretty permalinks, security rules and free HTTPS.

IntermediateLinux VPS3 min read

Nginx server blocks are the Nginx equivalent of Apache virtual hosts: each block serves one website based on the requested domain. Pair each site with its own PHP-FPM pool and Linux user and a problem on one site cannot touch the others. This guide sets up two PHP sites on one Nginx server.

Before you start

  • A Linux VPS with Nginx and PHP-FPM installed (see the LEMP stack guide).
  • Domains pointing to the server.
  • Root or sudo access.

Create a user and folder per site

sudo useradd -m -s /usr/sbin/nologin site1
sudo mkdir -p /var/www/site1.com/public
sudo chown -R site1:site1 /var/www/site1.com
sudo chmod 750 /var/www/site1.com

Let Nginx read the files by adding its user to the site group: sudo usermod -aG site1 www-data (the user is nginx on AlmaLinux). Repeat for site2.

Create a PHP-FPM pool per site

  1. Copy the default pool: on Ubuntu the pools live in /etc/php/8.3/fpm/pool.d/, on AlmaLinux in /etc/php-fpm.d/. Create site1.conf:
    [site1]
    user = site1
    group = site1
    listen = /run/php/site1.sock
    listen.owner = www-data
    listen.group = www-data
    pm = ondemand
    pm.max_children = 10
    pm.process_idle_timeout = 30s
    php_admin_value[open_basedir] = /var/www/site1.com:/tmp

    On AlmaLinux use nginx for the listen owner and group and a socket path like /run/php-fpm/site1.sock.

  2. Restart PHP-FPM: sudo systemctl restart php8.3-fpm (or php-fpm).

Create the server block

  1. Create /etc/nginx/sites-available/site1.com (AlmaLinux: /etc/nginx/conf.d/site1.com.conf):
    server {
        listen 80;
        server_name site1.com www.site1.com;
        root /var/www/site1.com/public;
        index index.php index.html;
    
        access_log /var/log/nginx/site1.access.log;
        error_log  /var/log/nginx/site1.error.log;
    
        client_max_body_size 64m;
    
        location / {
            try_files $uri $uri/ /index.php?$args;
        }
    
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass unix:/run/php/site1.sock;
        }
    
        location ~ /\.(?!well-known) {
            deny all;
        }
    
        location ~* \.(css|js|jpg|jpeg|png|gif|webp|svg|woff2?)$ {
            expires 30d;
            access_log off;
        }
    }
  2. Enable it on Ubuntu: sudo ln -s /etc/nginx/sites-available/site1.com /etc/nginx/sites-enabled/.
  3. Test and reload: sudo nginx -t && sudo systemctl reload nginx.

The try_files line gives WordPress and most PHP frameworks pretty URLs. The dot-file rule blocks access to .git, .env and similar files.

Add HTTPS

sudo certbot --nginx -d site1.com -d www.site1.com

Set a default server

Requests for unknown domains go to the first server block. Add a catch-all that closes the connection so random hostnames do not show one of your sites:

server {
    listen 80 default_server;
    server_name _;
    return 444;
}

What to check afterwards

  • Each domain shows its own site.
  • ps aux | grep php-fpm shows workers running as site1 and site2 when the sites are busy.
  • https://site1.com/.env returns 403.

Troubleshooting

  • File not found / "Primary script unknown": wrong root or SCRIPT_FILENAME, or PHP-FPM cannot read the files.
  • 502 Bad Gateway: socket path mismatch or the pool failed to start – check journalctl -u php8.3-fpm.
  • 403 on the site: Nginx's user cannot traverse the site folder; check group membership and folder permissions.
  • SELinux (AlmaLinux): run sudo restorecon -Rv /var/www; allow writes for uploads with the httpd_sys_rw_content_t context.

FAQ: Nginx server blocks

Does Nginx support .htaccess?

No. Rewrite rules go into the server block, which is faster because Nginx doesn't read files on every request.

Why use a separate PHP-FPM pool per site?

Each site runs as its own user, so a hacked site cannot read or modify the others, and you can limit resources per site.

How many sites can one Nginx server host?

As many as RAM and CPU allow; Nginx itself handles thousands of server blocks.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.