This episode explains how to serve multiple domains from a single NGINX using server blocks, complete with the listen and server_name directives, the root vs alias difference, index, and error_page.

One NGINX server can serve many websites at the same time. This concept is called a virtual host or server block. This Episode 3 teaches you how to build a static web server and separate several different domains within a single NGINX installation.
By the end of this episode, you'll be able to build a static web file structure, define multiple server blocks for different domains, understand when to use root and when to use alias, and handle custom error pages. All examples are run directly on a real server.
A server block is a server context inside http. Each block defines how NGINX responds to requests for a specific combination of port, IP, and domain name. When a request arrives, NGINX matches it to the most appropriate server block based on the listen and server_name directives.
The location for server block files on Ubuntu is typically /etc/nginx/sites-available/, with a symlink created to /etc/nginx/sites-enabled/. On other distributions like RHEL, just put the file in /etc/nginx/conf.d/.
The listen directive determines the address and port a server block listens on:
server {
listen 80;
listen [::]:80;
}
server {
listen 443 ssl default_server;
server_name _;
}listen 80; listens on IPv4, listen [::]:80; listens on IPv6. The default_server parameter marks the server block as the fallback destination when no server_name matches. The key point: there can only be one default_server per address and port combination.
server_name determines which domain the block serves. There are three patterns:
server_name example.com; — matches the host name exactly.server_name *.example.com; — matches subdomains like api.example.com.server_name ~^(?<user>.+)\.example\.net$; — complex patterns with named captures.server {
listen 80;
server_name example.com www.example.com;
root /var/www/example;
}If you use a wildcard like *.example.com, make sure you also have a DNS record pointing *.example.com at the server's IP.
root and alias determine how the file path is combined with the URI, and the difference is often confusing:
root /var/www/site; — the URI is appended directly: a request for /blog/halo looks up /var/www/site/blog/halo.alias /var/www/files; — the part of the URI that matched the location is replaced: location /assets/ with alias /var/www/files/ makes a request for /assets/x.png look up /var/www/files/x.png.server {
listen 80;
server_name example.com;
root /var/www/site;
location /assets/ {
alias /var/www/assets/;
}
}The practical rule: use root at the server level for the document root, and alias when the directory on the server doesn't mirror the public URI structure.
index determines which file NGINX looks for when a request points at a directory:
server {
listen 80;
server_name example.com;
root /var/www/site;
index index.html index.htm;
}NGINX will try index.html first, then index.htm.
error_page points error requests at a specific file without changing the status code:
server {
listen 80;
server_name example.com;
root /var/www/site;
error_page 404 /404.html;
location = /404.html {
internal;
}
}Important requirement: the file used as an error_page target must be accessed internally. The internal; directive prevents users from accessing that file directly.
A complete example of two websites on one server. Create a directory for each domain, then write the configuration file:
server {
listen 80;
server_name example.com;
root /var/www/example;
index index.html;
error_page 404 /404.html;
}
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
index index.html;
error_page 404 /404.html;
}Save it at /etc/nginx/conf.d/example.com.conf, test with nginx -t, then reload:
sudo nginx -t
sudo nginx -s reloadFinally, verify that each domain responds with the correct content.
Episode 3 completed the static web server foundation: you can define multiple server blocks in one NGINX, choose a block based on listen and server_name, distinguish root from alias, and configure index and error_page.
Key takeaways:
listen 80 default_server; marks the fallback block for an address and port.server_name can be exact, wildcard, or regex.root appends the URI to the path; alias replaces the location prefix.index sets the default file, error_page handles error pages.nginx -t before reloading.In the next episode we'll deep dive into location block matching and priority rules — the five location syntax types from exact match to prefix, and NGINX's priority order for picking the most appropriate location for a URI.