---
title: "How to host multiple websites on one VPS with Nginx | StreetHosting"
description: "Virtual hosts, SSL per domain and basic isolation: a guide to running multiple WordPress or static sites on a single VPS in Brazil."
url: "https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps"
type: "page"
language: "en-US"
---

VPS · 9 min · Intermediate

Published on Jun 9, 2026 · Updated on Sep 28, 2026

# Multiple websites on one VPS with Nginx

A well-configured VPS can carry several small projects. The trick is separate server blocks, a default server that rejects unknown domains, one Linux user and one PHP pool per site, and independent certificates.

By [Equipe StreetHosting](https://streethosting.com.br/en/autores#equipe-streethosting) · StreetHosting infrastructure and support team

[Network, DNS and domains](https://streethosting.com.br/en/guides/topics/networking) [Deploying and running apps](https://streethosting.com.br/en/guides/topics/deploy)

Summarize with:

[](https://chat.openai.com/?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "ChatGPT") [](https://claude.ai/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Claude") [](https://www.google.com/search?udm=50&aep=11&q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Google AI Mode") [](https://x.com/i/grok?text=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Grok") [](https://www.perplexity.ai/search/new?q=Summarize%20the%20key%20points%20of%20this%20StreetHosting%20guide%3A%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps.%20Highlight%20the%20step-by-step%20instructions%2C%20the%20prerequisites%20and%20the%20most%20common%20mistakes. "Perplexity")

Share:

[](https://x.com/intent/tweet?text=How%20to%20host%20multiple%20websites%20on%20one%20VPS%20with%20Nginx&url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps "Share on X") [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps "Share on Facebook") [](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps "Share on LinkedIn") [](https://wa.me/?text=How%20to%20host%20multiple%20websites%20on%20one%20VPS%20with%20Nginx%20https%3A%2F%2Fstreethosting.com.br%2Fen%2Fguides%2Fvps%2Fmultiple-websites-on-one-vps "Share on WhatsApp")

For agents: Copy as Markdown [.md](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps.md)

In this guide 8 sections

* [When it makes sense](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#quando-faz-sentido)
* [How Nginx picks the site](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#como-o-nginx-escolhe)
* [Nginx layout: available and enabled sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#estrutura-nginx)
* [Server blocks for PHP and static sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#server-blocks)
* [Isolation: one user and one PHP pool per site](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#isolamento)
* [DNS, SSL and security](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#ssl-e-seguranca)
* [Common errors with multiple sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#erros-comuns)
* [Limits and scaling](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#limites-e-escala)

Quick answer

To run **multiple websites on one VPS**, create one **Nginx server block** per domain in `sites-available`, enable it with a link in `sites-enabled` and add a **default\_server** block that rejects unknown domains. Give each PHP site its own Linux user and PHP-FPM pool, issue one **certificate per domain**with Certbot and point every domain's DNS at the same IP. A 4 GB Xeon VPS handles a small set of static sites or lightweight WordPress installs.

## When it makes sense[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#quando-faz-sentido)

Agencies, freelancers and makers often consolidate small client projects on one VPS to cut fixed costs. A server with ten low-traffic sites costs far less than ten separate hosting plans, and you manage a single system. It works as long as traffic and criticality allow.

The price of that saving is that the sites share CPU, memory and disk. A site that gets a spike or suffers an attack slows down its neighbors, and a broken Nginx configuration can take all of them down at once. When one site becomes the flagship, move it to its own instance before a cross-site incident happens.

## How Nginx picks the site[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#como-o-nginx-escolhe)

Every domain arrives at the same IP and the same ports. Nginx separates requests by the name the browser sends in the Host header and, over HTTPS, by the name sent at the start of the TLS handshake. It compares that name against the `server_name` of each block, in this order of priority:

| Priority | server\_name type                                             | Example                                                 |
| -------- | ------------------------------------------------------------- | ------------------------------------------------------- |
| 1        | Exact name                                                    | loja.com.br                                             |
| 2        | Leading wildcard; the longest wins                            | \*.loja.com.br                                          |
| 3        | Trailing wildcard; the longest wins                           | loja.\*                                                 |
| 4        | Regular expression; the first one in configuration order wins | \~^(www\\.)?loja\\.com\\.br$                            |
| 5        | No match: the port's default server                           | The block with default\_server, or the first one loaded |

The last row is the one that causes surprises. Without an explicit `default_server`, any domain pointed at your IP, or the IP itself typed into the browser, opens the first site loaded, which on Ubuntu is usually the first one in alphabetical order. That exposes a client's site at an address that is not theirs and confuses search engines. The fix is in the SSL and security section.

## Nginx layout: available and enabled sites[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#estrutura-nginx)

On Ubuntu, each site's configuration lives in its own file inside `/etc/nginx/sites-available/`. Nginx only loads what is linked in `/etc/nginx/sites-enabled/`. That way you disable a site by removing the link, without deleting its configuration. Name each file after its domain so you can find everything from memory:

`/etc/nginx/sites-available/ site1.com.br (WordPress) site2.com.br (static) padrao (default_server block) # enable a site sudo ln -s /etc/nginx/sites-available/site1.com.br /etc/nginx/sites-enabled/ # disable the sample site that ships with the package sudo rm /etc/nginx/sites-enabled/default # always test before reloading sudo nginx -t && sudo systemctl reload nginx`

Always run `nginx -t` before reloading. A syntax error in one site's file stops Nginx from accepting the new configuration for all of them, and a restart or a VPS reboot with that error leaves every site offline. The test catches the problem while they are still running on the previous configuration.

## Server blocks for PHP and static sites[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#server-blocks)

A WordPress site or any other PHP application in `/etc/nginx/sites-available/site1.com.br`, already pointing at the dedicated pool we will create in the next section:

`server { listen 80; server_name site1.com.br www.site1.com.br; root /var/www/site1.com.br/public; index index.php index.html; access_log /var/log/nginx/site1.com.br.access.log; error_log /var/log/nginx/site1.com.br.error.log; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm-site1.sock; } location ~ /\.(?!well-known) { deny all; } }`

A static site in `/etc/nginx/sites-available/site2.com.br` is even simpler, because it never touches PHP:

`server { listen 80; server_name site2.com.br www.site2.com.br; root /var/www/site2.com.br/public; index index.html; access_log /var/log/nginx/site2.com.br.access.log; error_log /var/log/nginx/site2.com.br.error.log; location / { try_files $uri $uri/ =404; } }`

Separate logs per site show where each error and each spike comes from, and since they live in `/var/log/nginx/` with a `.log` extension, the log rotation that ships with Ubuntu takes care of them. For a Node or Python application or a container, swap the PHP block for a `proxy_pass`, as in [Nginx as a reverse proxy on a VPS](https://streethosting.com.br/en/guides/vps/nginx-reverse-proxy-vps). The full WordPress install, with database, cache and PHP tuning, is in [WordPress on a VPS with Nginx and PHP 8.3](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx).

## Isolation: one user and one PHP pool per site[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#isolamento)

In the default install, all PHP runs as the web server user in a single pool. A vulnerable plugin on one site can read and modify the files of every other site. Basic isolation means giving each site a Linux user with no login and a PHP-FPM pool that runs as that user.

### User and permissions[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#usuario-e-permissoes)

`sudo useradd --system --user-group --home-dir /var/www/site1.com.br \ --shell /usr/sbin/nologin site1 sudo mkdir -p /var/www/site1.com.br/public sudo chown -R site1:www-data /var/www/site1.com.br sudo find /var/www/site1.com.br -type d -exec chmod 2750 {} + sudo find /var/www/site1.com.br -type f -exec chmod 640 {} +`

* **Owner site1:**the site's PHP, running as that user, reads and writes its own files, such as uploads and cache.
* **Web server group with read access:** Nginx reads CSS, images and JavaScript to serve them directly, but writes nothing.
* **No permissions for others:**the site2 user cannot even list site1's folder.
* **The 2 in 2750:**the setgid bit, which makes new files inherit the folder's group. Without it, an upload made by PHP would end up in the site1 group and Nginx could not serve it.

### One PHP-FPM pool per site[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#pool-php)

Create `/etc/php/8.3/fpm/pool.d/site1.conf`:

`[site1] user = site1 group = site1 listen = /run/php/php8.3-fpm-site1.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 30s pm.max_requests = 500`

`sudo php-fpm8.3 -t sudo systemctl reload php8.3-fpm ls -l /run/php/`

The socket belongs to the Nginx user, which is the one connecting to it, but the processes run as site1. The `ondemand` mode is what makes several sites viable on little RAM: with no visitors, the pool keeps no processes at all; they spawn on the first request and die after 30 seconds idle. `pm.max_children` caps how far one site can grow, so a spike on one does not eat the memory of the others. `pm.max_requests` recycles processes to contain memory leaks from plugins.

You can go further with `php_admin_value[open_basedir]` in the pool, restricting PHP to the site's folder. Treat it as an extra layer, not as a security boundary, and test first: some plugins read files outside the folder and break with this option. For clients who do not know each other, separate containers, as in [WordPress with Docker Compose](https://streethosting.com.br/en/guides/vps/install-wordpress-docker-vps), isolate more.

## DNS, SSL and security[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#ssl-e-seguranca)

Each domain needs A records, for the root and for www, pointing at the same VPS IP. The step by step, with dig tests, is in [pointing a domain at your VPS](https://streethosting.com.br/en/guides/vps/point-domain-to-vps). Once DNS resolves, issue one certificate per site:

`sudo certbot --nginx -d site1.com.br -d www.site1.com.br sudo certbot --nginx -d site2.com.br -d www.site2.com.br sudo certbot certificates sudo certbot renew --dry-run`

Do not bundle different clients' domains into a single certificate. Renewal validates every name on the certificate: if a client leaves and their domain stops pointing at the VPS, renewal fails for every site on that certificate. The Certbot details are in [SSL certificate with Let's Encrypt and Nginx](https://streethosting.com.br/en/guides/vps/lets-encrypt-ssl-certificate-vps).

Now the default block that rejects unknown domains, in `/etc/nginx/sites-available/padrao`:

`server { listen 80 default_server; listen 443 ssl default_server; server_name _; ssl_reject_handshake on; return 444; }`

The `return 444` closes the HTTP connection without a response, and `ssl_reject_handshake`, available since Nginx 1.19.4, refuses HTTPS for names without a block of their own, no certificate needed. Enable it with a link in `sites-enabled` and test with `curl -I http://IP_DA_VPS`, which should fail with no response.

* **Firewall:** open only 80, 443 and SSH, ideally restricted, as in [UFW on a VPS](https://streethosting.com.br/en/guides/vps/ufw-firewall-ubuntu-vps).
* **Fail2ban:** optional, against brute force on SSH and on the WordPress login.
* **Migration:** to bring an existing site over, follow [migrating WordPress to a VPS](https://streethosting.com.br/en/guides/vps/migrate-wordpress-to-vps) and create the user and the pool before copying the files.

## Common errors with multiple sites[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#erros-comuns)

Almost every problem with this setup falls into one of these rows. Always start with the error log of the affected site, which is now separate from the others.

| Symptom                                   | Likely cause                                                                             | How to fix                                                                |
| ----------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| 502 Bad Gateway on a PHP site             | The socket path in the server block does not match the pool's, or the pool did not start | Compare fastcgi\_pass with the pool's listen and check the PHP-FPM status |
| 403 Forbidden on everything               | Nginx cannot traverse the site's folder or the index file is missing                     | Check owner, group and the 2750 mode on the folders up to the site root   |
| One domain opens another site             | A name missing from server\_name, such as www, or DNS pointed somewhere else             | Review server\_name and test the name with dig                            |
| Upload works, but the image does not show | New file created without the web server group                                            | Reapply the group and the setgid bit on the site's folders                |
| Certbot fails on one domain               | The domain does not point at the VPS yet or the server\_name does not exist in any block | Confirm the A record and run Certbot again for that site only             |

To watch a site's errors in real time, use `sudo tail -f /var/log/nginx/site1.com.br.error.log` while you reload the page. To check which configuration Nginx actually loaded, with every included file, run `sudo nginx -T` and search for the domain. And to test a site before changing DNS, force the name in the request with `curl -I -H "Host: site1.com.br" http://IP_DA_VPS`.

## Limits and scaling[](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#limites-e-escala)

Monitor RAM and swap. With one user per site, it is easy to see how much each one consumes by summing the memory of the PHP processes per owner:

`ps -o user=,rss= -C php-fpm8.3 | awk '{m[$1]+=$2} END {for (u in m) printf "%s %.0f MB\n", u, m[u]/1024}' free -h`

Pools in dynamic or static mode keep idle processes consuming memory even with no visitors, which is why ondemand is the choice for small sites. When the projects together stay above 70% of RAM for a sustained period, move up a plan or split the workloads. A site that alone accounts for most of the consumption is the natural candidate for a VPS of its own.

| Set of sites                                                 | Starting plan                           | Monthly price |
| ------------------------------------------------------------ | --------------------------------------- | ------------- |
| Up to 5 lightweight WordPress sites or dozens of static ones | Xeon VPS 3 vCPU, 4 GB, 40 GB NVMe       | R$ 43.00      |
| Agency with 10 to 15 sites and a small store                 | Xeon VPS 6 vCPU, 8 GB, 80 GB NVMe       | R$ 77.00      |
| Sites with a lot of PHP outside the cache                    | Ryzen VPS 4 vCPU, 8 GB DDR5, 80 GB NVMe | R$ 118.00     |

On a [StreetHosting VPS](https://streethosting.com.br/en/vps) you get root access, a datacenter in São Paulo, Anti-DDoS included and activation within 60 seconds. When the VPS gets too small, the upgrade through the control panel charges only the prorated difference and requires a reboot, which takes every site down for a few moments, so schedule it for the early hours.

In this guide

* [When it makes sense](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#quando-faz-sentido)
* [How Nginx picks the site](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#como-o-nginx-escolhe)
* [Nginx layout: available and enabled sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#estrutura-nginx)
* [Server blocks for PHP and static sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#server-blocks)
* [Isolation: one user and one PHP pool per site](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#isolamento)
* [DNS, SSL and security](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#ssl-e-seguranca)
* [Common errors with multiple sites](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#erros-comuns)
* [Limits and scaling](https://streethosting.com.br/en/guides/vps/multiple-websites-on-one-vps#limites-e-escala)

## Frequently asked questions

How many sites fit on a 4 GB VPS?

With PHP pools in ondemand mode and page caching, 3 to 5 lightweight WordPress sites with modest traffic, or dozens of static sites. A WooCommerce store or a high-traffic site needs more RAM or a VPS of its own. Measure each site's consumption before adding the next one.

Does a hacked site affect the others?

Without isolation, yes: if every site runs as the same web server user, a vulnerable plugin on one of them gives access to the files of all of them. With one user and one PHP pool per site and folders closed to the others, the damage stays contained. For clients who do not know each other, containers or separate VPS instances isolate even further.

Do I need an extra IP per site?

No. Nginx picks the site by the name the browser sends in the Host header and, over HTTPS, by the TLS SNI extension. A single IP serves every domain, each with its own certificate.

Why does an unknown domain open one of my sites?

Because when no server\_name matches the requested name, Nginx uses the port's default server, which with no configuration is the first block loaded. Create a block with default\_server that returns 444 and rejects the TLS handshake, and only the configured domains will open a site.

One certificate for all sites or one per site?

One per site. A certificate with every domain fails its whole renewal if one of them stops pointing at the VPS, for example when a client leaves, and every site ends up with a certificate close to expiring. Kept separate, each one renews on its own and leaves without affecting the others.

Next step

See VPS plans

Root VPS in Brazil with NVMe and Anti-DDoS.

[See VPS plans](https://streethosting.com.br/en/vps)

[See Xeon VPS Xeon VPS for steady workloads, automation and long-running projects.](https://streethosting.com.br/en/vps/xeon) [See Ryzen VPS Ryzen 9 9950X VPS in São Paulo with root access, NVMe and gamer Anti-DDoS.](https://streethosting.com.br/en/vps/ryzen)

## Related guides

[VPS Beginner How to point a domain to a VPS: A, AAAA and CNAME records Your site is on the VPS, but people can only reach it by IP. DNS fixes that: an A record ties the domain to the server. Learn when to use AAAA and CNAME, how TTL controls propagation, how to test with dig and what the Cloudflare proxy does not do. 9 min Read guide](https://streethosting.com.br/en/guides/vps/point-domain-to-vps) [VPS Intermediate Host WordPress on a VPS: Nginx, PHP 8.3 and MariaDB Installing WordPress by hand, with no control panel, gives you full control over performance and security. The path is short: Nginx, PHP FPM and MariaDB on Ubuntu 24.04, a dedicated database, HTTPS and two layers of cache. 9 min Read guide](https://streethosting.com.br/en/guides/vps/host-wordpress-on-vps-nginx) [VPS Beginner SSL certificate on a VPS with Let's Encrypt and Nginx A site without the padlock loses trust and rankings. This guide shows how to issue, renew and audit a free SSL certificate on your VPS with Nginx and Certbot. 4 min Read guide](https://streethosting.com.br/en/guides/vps/lets-encrypt-ssl-certificate-vps)

[← Back to the Guide Center](https://streethosting.com.br/en/guides)
