Kahibaro
Discord Login Register

5.1.3 Virtual hosts

Why Virtual Hosts Matter

Virtual hosts let a single web server (one IP/port combination) serve multiple websites with different domain names and/or configurations. Instead of running a separate server process per site, you define multiple “virtual” servers inside one Apache or Nginx instance.

You typically use virtual hosts to:

Two dominant types:

This chapter focuses on how to define and manage virtual hosts in Apache and Nginx.


Name-Based vs IP-Based Virtual Hosts

Name-Based Virtual Hosts

Most common scenario:

Requirements:

Limitations:

IP-Based Virtual Hosts

Each virtual host has its own IP address:

Used when:

Trade-offs:

Apache Virtual Hosts

Apache uses <VirtualHost> blocks. The parent “Apache basics” chapter covers modules, configuration file locations, and reloading the service; here we focus on vhost specifics.

Core Concepts

Minimal Name-Based Virtual Host (HTTP)

Example for two HTTP sites on the same host:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example
    ErrorLog ${APACHE_LOG_DIR}/example_error.log
    CustomLog ${APACHE_LOG_DIR}/example_access.log combined
</VirtualHost>
<VirtualHost *:80>
    ServerName blog.example.com
    DocumentRoot /var/www/blog
    ErrorLog ${APACHE_LOG_DIR}/blog_error.log
    CustomLog ${APACHE_LOG_DIR}/blog_access.log combined
</VirtualHost>

Key directives:

Default Virtual Host

If a request comes to an unknown hostname on :80, Apache serves the first vhost defined for :80. You can explicitly create a “catch-all” vhost:

<VirtualHost *:80>
    ServerName default.example.local
    DocumentRoot /var/www/default
</VirtualHost>

Order in the configuration files matters for the default.

IP-Based Virtual Host in Apache

Assign different IP addresses and bind vhosts to them:

# Listen on two IPs (if not already implicit)
Listen 192.0.2.10:80
Listen 192.0.2.11:80
<VirtualHost 192.0.2.10:80>
    ServerName site1.com
    DocumentRoot /var/www/site1
</VirtualHost>
<VirtualHost 192.0.2.11:80>
    ServerName site2.com
    DocumentRoot /var/www/site2
</VirtualHost>

Ensure:

HTTPS Virtual Hosts (SNI) in Apache

Multiple HTTPS sites on the same IP/port with SNI:

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.crt
    SSLCertificateKeyFile /etc/ssl/private/example.key
</VirtualHost>
<VirtualHost *:443>
    ServerName blog.example.com
    DocumentRoot /var/www/blog
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/blog.crt
    SSLCertificateKeyFile /etc/ssl/private/blog.key
</VirtualHost>

Notes:

Per-Virtual-Host Overrides

Virtual hosts allow per-site customizations without affecting others:

Examples:

<VirtualHost *:80>
    ServerName app.example.com
    DocumentRoot /var/www/app/public
    # PHP handler or proxy config
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/app/public/$1
    # Restrict admin area by IP
    <Location "/admin">
        Require ip 203.0.113.0/24
    </Location>
    # Separate log format for this app
    CustomLog ${APACHE_LOG_DIR}/app_access.log vhost_combined
</VirtualHost>

Typical per-vhost tweaks:

Nginx Server Blocks (Virtual Hosts)

In Nginx, the equivalent of a virtual host is a server block inside the http context. The parent “Nginx basics” chapter covers overall layout and reloading; this chapter focuses on virtual host features.

Core Concepts

Minimal Name-Based Virtual Host (HTTP)

Example of two sites:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example;
    index index.html index.htm;
    access_log /var/log/nginx/example_access.log;
    error_log  /var/log/nginx/example_error.log;
}
server {
    listen 80;
    server_name blog.example.com;
    root /var/www/blog;
    index index.html;
    access_log /var/log/nginx/blog_access.log;
    error_log  /var/log/nginx/blog_error.log;
}

Key directives:

Default Server

Specify default_server on the listen line:

server {
    listen 80 default_server;
    server_name _;
    root /var/www/default;
}

This block handles requests that don’t match any server_name for listen 80.

Wildcards and Regex in `server_name`

Nginx supports:

  server {
      listen 80;
      server_name ~^(?<sub>.+)\.example\.com$;
      # $sub holds the captured subdomain
  }

Regex server names are advanced and evaluated after exact/wildcard matches; use only when necessary.

IP-Based Virtual Hosts in Nginx

Bind servers to specific IPs:

server {
    listen 192.0.2.10:80;
    server_name site1.com;
    root /var/www/site1;
}
server {
    listen 192.0.2.11:80;
    server_name site2.com;
    root /var/www/site2;
}

Again, IP addresses must be configured at the OS level and in DNS.

HTTPS Virtual Hosts (SNI) in Nginx

Multiple SSL sites on one IP using SNI:

server {
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/example;
    ssl_certificate     /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;
}
server {
    listen 443 ssl http2;
    server_name blog.example.com;
    root /var/www/blog;
    ssl_certificate     /etc/ssl/certs/blog.crt;
    ssl_certificate_key /etc/ssl/private/blog.key;
}

Nginx chooses the certificate based on the SNI hostname. You can also use a single multi-SAN or wildcard certificate across several vhosts if that suits your naming scheme.

Mixed HTTP/HTTPS Vhosts with Redirect

Common pattern: one vhost for HTTP redirect, one for HTTPS content:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}
server {
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/example;
    ssl_certificate     /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;
}

Multi-Site Management Patterns

Directory Layouts

Typical per-site layout:

Using a consistent layout makes automation and troubleshooting much easier.

Per-Site Security and Isolation

Virtual hosts share the same server process, so they are not fully isolated. You can improve separation per vhost:

For stronger isolation, consider containers or separate VMs per site, combining them with virtual hosts as needed.

Logging and Monitoring

Per-vhost logs are central to server administration:

Troubleshooting Virtual Host Issues

Common problems and how to reason about them:

  1. Wrong site is served
    • Check which vhost is the default for that IP/port
    • Confirm the Host header (e.g., with curl -H 'Host: example.com' http://IP/)
    • Verify server_name/ServerName and ServerAlias values
  2. HTTPS certificate mismatch
    • Ensure the requested hostname matches the vhost’s certificate
    • Confirm that the correct vhost is the default for 443 and SNI is enabled
    • Test with openssl s_client -connect host:443 -servername example.com
  3. New virtual host not taking effect
    • Check that its config file is included (Apache sites-enabled, Nginx include directives)
    • Validate configuration syntax before reload (e.g. Apache/Nginx test commands)
    • Reload or restart the service
  4. 404 or 403 when accessing a new site
    • Confirm DocumentRoot/root path exists and permissions are correct
    • Check per-vhost access rules and path mappings

Understanding how the server chooses a virtual host (IP/port + host name + default server behavior) is the key to systematically debugging these issues.

Views: 107

Comments

Please login to add a comment.

Don't have an account? Register now!