Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The most reliable design is one VPS with Nginx or Apache at the public edge, DNS records for every domain, and a separate virtual host or server block for each site. Serve static files directly, send CMS requests to isolated PHP-FPM, Apache, or container services, and keep each site’s files, database, credentials, logs, and backups separate.

This arrangement lets domains share one public IP without merging applications. Its practical limit is not a fixed site count: traffic concurrency, PHP workers, database queries, plugins or modules, cache efficiency, storage I/O, backups, and monitoring determine whether the VPS has enough headroom.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The architecture that works for mixed sites

A VPS can answer for many domains because HTTP clients send the requested hostname and the web server selects a matching name-based virtual host (Apache terminology) or server block (Nginx terminology). Apache’s documentation defines a virtual host as running more than one website on one machine. The same principle applies when all domains resolve to one IPv4 address, and it also works with IPv6 when every domain has the correct AAAA record.

Use this traffic path:

Visitor → DNS → VPS ports 80/443 → Nginx or Apache → site root or application upstream → database/cache on a private network

Static sites stop at the file server. A CMS request continues to PHP-FPM, an Apache upstream, or an application container. The proxy should be the only service exposed to the internet unless an administrative service has a deliberate, documented access policy.

What belongs in the shared edge

  • Listening on ports 80 and 443.
  • Matching the requested hostname to exactly one site configuration.
  • Serving static assets and applying cache and compression policy.
  • Terminating TLS and selecting the correct certificate.
  • Forwarding dynamic requests to the intended application service.
  • Writing access and error logs that identify the site.

What should stay behind it

  • PHP-FPM sockets or ports.
  • CMS application processes.
  • MySQL, MariaDB, PostgreSQL, Redis, and similar services.
  • Deployment tooling, management dashboards, and backup agents.

Bind those internal services to localhost or an internal container network. Do not publish database ports merely because several websites share the server.

Nginx or Apache: choose by operating model

Both servers can host multiple domains. The better choice depends on how you prefer to configure applications and how much compatibility you need with existing CMS instructions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision point Nginx Apache
Static delivery Direct file serving with lightweight server blocks Direct file serving through virtual hosts
Dynamic traffic Usually proxies to PHP-FPM, Apache, or a container Can use PHP-FPM or an integrated module, depending on the deployment
Per-directory overrides No .htaccess equivalent; rules belong in the administrator-managed configuration Can support .htaccess when enabled, which suits CMS packages that document those files
Reverse-proxy style Natural fit for several independent upstream services Can reverse-proxy too, but many teams use it primarily as the application web server
Operational trade-off Centralized, explicit configuration and reloads Familiar CMS workflows and compatibility with .htaccess-based guidance

WordPress documentation notes that many sites identified as Nginx sites are actually Apache behind Nginx as a reverse proxy. That is a valid arrangement, but it adds another layer to update and troubleshoot. Use it when an existing Apache application depends on Apache behavior while you still want Nginx at the public edge.

Choose Nginx when you want one transparent proxy configuration for static files and several application services. Choose Apache when .htaccess compatibility and established CMS procedures matter more than a proxy-first design. Do not run both by default; each additional layer increases configuration and failure points.

Give every website a separate boundary

Shared hardware does not require shared application state. Create a boundary for every site before installing the first CMS.

Separate document roots

Use a predictable path such as:

/srv/www/site-a/public
/srv/www/site-b/public
/srv/www/blog.example.net/public

Point each virtual host or server block to one root only. Never place one site’s upload directory inside another site’s root, and do not use a single generic web root with hostname-based subdirectories selected by application code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate users and permissions

Run deployment and application processes with the least privilege that still permits updates. A static site’s files can be owned by a deployment user and read by the web server. A CMS normally needs a writable uploads or files directory, but that writable area should be narrower than the entire codebase. Keep configuration files containing secrets outside public directories, and ensure private keys are readable only by the service account that needs them.

Separate logs and deployment settings

Write access and error logs per site. This makes rate spikes, broken rewrites, and abusive paths attributable to one domain rather than hidden in one undifferentiated file. Keep each site’s repository, deployment variables, scheduled jobs, and rollback instructions separate as well.

Separate databases and credentials

Give each CMS its own database and database user, even when all databases run in one database server. A compromised plugin should not automatically receive credentials for another site. Store credentials in a protected environment file or secret store, not in a publicly served configuration file or a repository.

When containers are worth adding

Docker Compose defines multi-container applications in YAML, including services, networks, and volumes. A useful pattern is one front proxy, one application service per CMS, and a database or cache service attached only to that CMS’s internal network. Containers provide stronger process and dependency separation and make a deployment repeatable, but they do not replace patching, least-privilege permissions, or backups. A vulnerable application in a container can still expose data reachable from its network.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
services:
cms_a:
image: your-cms-image
networks: [site_a_net]
volumes:
- site_a_files:/var/www/html
db_a:
image: your-database-image
networks: [site_a_net]
volumes:
- site_a_db:/var/lib/database
networks:
site_a_net:
internal: true
volumes:
site_a_files:
site_a_db:

The example is a pattern rather than a drop-in production file: pin image versions, set passwords through secrets, define health checks, and document the persistent paths before deploying.

Plan capacity without inventing a site count

There is no honest universal answer to “How many sites can a 2 GB or 4 GB VPS handle?” Official guidance for the components above publishes no general site-count statistic. A lightly visited static site may consume almost no CPU while idle; one busy CMS can exhaust memory or database I/O by itself.

Workload signal Why it matters What to measure
Static traffic Mostly file reads and network throughput Bandwidth, cache hit rate, disk latency, and open connections
PHP or application concurrency Each active worker consumes memory and CPU Worker utilization, queue time, request latency, and out-of-memory events
Database activity Queries and indexes can become the bottleneck before the web server Query latency, locks, buffer usage, and storage I/O
Plugins or modules Extensions add background jobs, queries, and attack surface Slow requests, scheduled-task duration, and error rates after updates
Backups and scans Maintenance jobs compete for CPU, memory, and disk Backup duration, snapshot space, and I/O contention during the job
Logging and monitoring Verbose logs can fill a small disk Disk usage, retention, and alert delivery

Start with measured usage, leave headroom for bursts and maintenance, then scale vertically or split workloads when contention appears. A sensible split is to move the noisiest database or highest-traffic CMS to another VPS while leaving low-traffic static sites on the original server.

Prepare the VPS before adding domains

  1. Patch the operating system. Apply security updates, set the correct time zone, and enable automatic security updates when your distribution supports them.
  2. Create an administrative path. Use a non-root administrator with key-based SSH, restrict SSH access with a firewall policy, and keep a documented recovery account.
  3. Install the edge server. Install Nginx or Apache, enable its service at boot, and verify that a default page is reachable before adding custom sites.
  4. Install the runtime. Add the PHP version and extensions required by each CMS, or prepare the application containers. Do not assume that one CMS’s requirements suit another.
  5. Create storage and service accounts. Make the per-site directories, ownership rules, log paths, and database users before copying application files.
  6. Set a firewall. Allow inbound TCP 80 and 443. Allow SSH only from the addresses or access method you deliberately maintain. Keep database and cache ports private.

Connect DNS to the VPS

For every hostname, create an A record pointing to the VPS’s IPv4 address. Add an AAAA record only when the server is correctly configured for IPv6 and the firewall permits it. Include the bare domain and the intended subdomains; a record for www does not automatically cover the apex domain.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Create the A and, if applicable, AAAA records at the authoritative DNS provider.
  2. Wait until public resolvers return the VPS address. Check both the apex name and every www or CMS subdomain you plan to serve.
  3. Make the hostname list in the DNS records match the names in the web-server configuration exactly.
  4. Keep the old server online until the new records resolve consistently and the new site has passed testing.

DNS propagation is not a signal that the application is ready. Test the origin directly with the hostname, inspect which virtual host answered, and confirm that an unknown hostname does not expose the wrong site’s files.

Configure name-based sites

Static site with Nginx

Create one server block per domain, with a unique root and log files:

server {
listen 80;
server_name example.net www.example.net;
root /srv/www/example.net/public;
index index.html;
access_log /var/log/nginx/example.net.access.log;
error_log /var/log/nginx/example.net.error.log;
location / {
try_files $uri $uri/ =404;
}
}

Enable the file according to your distribution’s layout, validate the complete configuration, and gracefully reload Nginx. Use a separate block for every domain rather than adding unrelated roots to one block.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

CMS requests through Nginx

A PHP CMS needs a front controller rule and a PHP-FPM upstream. The exact socket path depends on the installed PHP version, so use the path supplied by your distribution:

location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}

Do not copy this socket name blindly. Confirm it exists, restrict direct access to sensitive files, and test permalinks, uploads, and administrator login after reloading.

Virtual host with Apache

An Apache virtual host follows the same isolation rule:

<VirtualHost *:80>
ServerName example.net
ServerAlias www.example.net
DocumentRoot /srv/www/example.net/public
ErrorLog ${APACHE_LOG_DIR}/example.net-error.log
CustomLog ${APACHE_LOG_DIR}/example.net-access.log combined
<Directory /srv/www/example.net/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

Enable only the override behavior your CMS actually needs. If you use Nginx in front of Apache, make Apache listen on a private address or port and configure Nginx to proxy only the intended hostnames.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Enable HTTPS for every hostname

Open inbound ports 80 and 443, confirm DNS resolves, and then obtain certificates with Certbot’s Nginx or Apache plugin. Certbot can request a certificate and optionally install the web-server changes.

  1. Install Certbot and the plugin matching Nginx or Apache.
  2. Request a certificate for every name the site serves, for example the apex and www hostname.
  3. Choose the plugin installation mode if you want Certbot to edit the active server configuration, or use certificate-only mode when you maintain the TLS configuration yourself.
  4. Test HTTPS in a browser and with a command-line request. Check that the certificate names match the hostname and that HTTP redirects to HTTPS only after the HTTPS virtual host works.
  5. Verify the scheduled renewal job. Run a dry-run renewal test, then validate the web-server configuration and perform a graceful reload after a real renewal.

Keep certificate and private-key permissions restricted. If a certificate covers several domains, list every covered name in your inventory and renew it as one unit. A failed renewal should trigger an alert before the existing certificate expires.

Back up files, databases, and configuration independently

A website is not recoverable from its document root alone. Back up these components separately:

  • Static assets and CMS uploads.
  • Application code and deployment manifests.
  • Database dumps, with credentials stored outside the dump location.
  • Nginx or Apache configuration, enabled-site links, and TLS automation settings.
  • Docker Compose files, image version records, and persistent volumes when containers are used.
  • Scheduled jobs, environment variables, and a map of DNS records.

Keep at least one copy away from the VPS. Encrypt backups, restrict access, retain several historical points, and rehearse restoration to a clean host. A backup that has never been restored is an assumption, not a recovery plan.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Operate many sites without losing track

Use a per-site deployment checklist

  • Build or pull the release artifact.
  • Run database migrations for that site only.
  • Deploy files atomically, such as by switching a release symlink.
  • Set ownership and writable-directory permissions.
  • Clear the appropriate application cache.
  • Check the homepage, a representative dynamic page, login, forms, uploads, and scheduled tasks.
  • Keep the previous release available for rollback.

Monitor shared bottlenecks

Watch memory pressure, swap activity, CPU saturation, disk utilization, inode usage, storage latency, PHP-FPM queues, database connections, certificate expiry, and HTTP error rates. Alert per hostname so one failing CMS does not hide behind an apparently healthy aggregate metric.

Control scheduled jobs

Stagger backups, CMS cron tasks, image processing, search indexing, and security scans. Running every site’s heavy job at the same minute can create a false capacity problem. Record which user runs each job and where its output is logged.

Keep configuration reviewable

Store server blocks, virtual hosts, Compose files, and deployment scripts in version control. Validate configuration before reloads. A failed syntax check should stop the deployment rather than take every domain offline.

Architecture choices compared

Pattern Isolation Operational effort Best fit Main risk
One Nginx edge, host-managed static sites and PHP-FPM pools Separate roots and pools; shared kernel and host Moderate Teams wanting explicit, fast configuration A host-level mistake can affect every site
One Apache edge with virtual hosts Separate roots and virtual hosts Moderate CMS installations that rely on Apache conventions Loose .htaccess or permissions can expose files or consume resources
Nginx edge proxying Apache applications Separate edge and application layers Higher Existing Apache applications needing a proxy front end Two configurations and logs must agree
Nginx or Apache edge with Docker Compose sites Separate processes, networks, and volumes Higher initially, repeatable later Multiple CMS versions or teams needing reproducible deployments Container and image maintenance can be neglected
Control-panel or automation-managed virtual hosts Depends on the tool’s user and service model Lower for repetitive setup Operators prioritizing guided provisioning Generated configuration may be less transparent during incidents

Troubleshoot by following the request path

Symptom Likely cause First checks
The wrong website appears DNS points elsewhere, or the hostname is missing from the matching block Resolve the hostname, inspect the active configuration, and test the exact Host header
502 or 504 from the proxy PHP-FPM, Apache, or a container is stopped or unreachable Check service status, socket or upstream address, permissions, and application logs
Permalinks return 404 Front-controller rewrite is absent or overrides are disabled Check Nginx try_files or Apache rewrite and override settings
HTTPS certificate mismatch The TLS block lacks a hostname or DNS still reaches the old server Inspect certificate names, DNS answers, and the selected 443 server block
Uploads fail The writable directory has wrong ownership, quota, or insufficient disk Check effective service user, permissions, inode and disk usage, and CMS limits
All sites slow down together Shared CPU, memory, database, storage, or backup contention Compare resource graphs with request latency and pause or reschedule heavy jobs
Renewal fails Port 80 is blocked, DNS changed, or the web-server configuration is invalid Run a renewal dry run, validate configuration, and inspect the Certbot log

When to split sites across VPSs

Move a site or service when measurements show sustained contention, not simply because the server hosts a certain number of domains. Split workloads when one CMS needs a different PHP or database version, when a noisy neighbor repeatedly consumes the shared pool, when a customer or team requires administrative isolation, or when maintenance windows cannot be coordinated.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical migration keeps DNS TTLs low before the change, copies files and a recent database dump, tests the new origin through a temporary hostname, freezes writes for the final database export, switches DNS, and watches logs and error rates. Keep the old origin available until caches expire and rollback criteria are met.

Final implementation checklist

  • Every domain has correct A and, where used, AAAA records.
  • Each hostname maps to one documented server block or virtual host.
  • Static roots, CMS code, uploads, logs, databases, and credentials are separated.
  • Only ports 80 and 443 are publicly reachable by default.
  • Dynamic services are reachable only from the edge or their private container network.
  • HTTPS certificates cover every served name and renewal has been dry-run tested.
  • Configuration validation and graceful reloads are part of deployment.
  • Files, databases, proxy configuration, and service definitions have independent backups.
  • A restoration rehearsal has produced a working site on a clean location.
  • Monitoring measures per-site errors as well as shared CPU, memory, storage, and database pressure.
  • Capacity decisions use observed workload and reserved headroom rather than a guessed site count.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.