
Running more than one website on a single server is a common task for small website operations. With Nginx server blocks for multiple domains, you can host many sites on one machine without confusion. This guide walks you through the full setup, from the first domain to HTTPS and safety rules. No fancy words. Just clear steps.
What You’ll Learn: Nginx Server Blocks for Multiple Domains
By the end of this guide, you will know how to run many websites on one server. You will learn the safe way to add each new domain. You will also learn how to protect every site with HTTPS.
Who This Guide Is For
This guide fits beginners who run a small VPS or cloud server. If you can log into a Linux terminal and run basic commands, you are ready. Students, hobbyists, and junior site admins will find the steps easy to follow.
What You’ll Build by the End
You will build a working Nginx setup that serves:
- Two static HTML sites on different domains
- One application site using a reverse proxy
- HTTPS on every domain
- A safe default block that rejects unknown requests
Static Sites, Reverse Proxies, and HTTPS
A static site shows files stored on disk. A reverse proxy passes traffic to a running app, like Node.js or Docker. HTTPS adds a lock icon in the browser. Nginx server blocks for multiple domains handle all three jobs with one config style.
Prerequisites Before Configuring Nginx Server Blocks
Before you write any config, gather your tools. Missing one piece will cause errors later.
Server and Domain Requirements
- A Linux server (Ubuntu 22.04/24.04 or Debian 12 works well)
- Root or sudo access
- Nginx installed:
sudo apt install nginx - At least two domain names you own
DNS Records and Firewall Checklist
Point each domain to your server IP with an A record. Open ports 80 and 443 in your firewall:
sudo ufw allow 80sudo ufw allow 443sudo ufw allow 22
Identify Your Nginx Configuration Layout (Debian/Ubuntu vs. RHEL/Generic)
| Distro | Sites Folder | Enabled Folder |
|---|---|---|
| Debian/Ubuntu | /etc/nginx/sites-available/ | /etc/nginx/sites-enabled/ |
| RHEL/Alma/Generic | /etc/nginx/conf.d/ | (same folder) |
This guide uses the Debian layout. RHEL users just skip the symlink step.
Step 1 — Create Your First Nginx Server Block for a Static Domain
Think of a server block like a name tag. Each domain gets its own tag so Nginx knows where to send traffic.
Set Up the Website Document Root
Create a folder for your site files:
sudo mkdir -p /var/www/site1.example.com/htmlsudo chown -R $USER:$USER /var/www/site1.example.com/html- Add a test file:
echo "<h1>Hello Site 1</h1>" > /var/www/site1.example.com/html/index.html
Write the Server Block Configuration File
Create a new file at /etc/nginx/sites-available/site1.example.com with this content:
server {
listen 80;
server_name site1.example.com www.site1.example.com;
root /var/www/site1.example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
The server_name line tells Nginx which domain this block handles.
Enable the Site and Reload Nginx
Link the file into the enabled folder and test:
sudo ln -s /etc/nginx/sites-available/site1.example.com /etc/nginx/sites-enabled/sudo nginx -t— this checks your syntaxsudo systemctl reload nginx
Verify the Domain Is Serving Correctly
Open your browser or run curl http://site1.example.com. You should see “Hello Site 1”. If not, check DNS with dig site1.example.com.
Step 2 — Add a Second Domain with Nginx Server Blocks Safely
Adding a second domain is the same pattern. The key is to avoid small copy-paste traps.
Avoid Common Copy-Paste Mistakes
When you copy a server block, change these values:
server_name— must match the new domainroot— must point to a new folderaccess_loganderror_log— give each site its own log file
Forgetting one of these is the top cause of “wrong site shows up” bugs.
Configure a Unique Server Name and Root Path
Create /etc/nginx/sites-available/site2.example.com:
server {
listen 80;
server_name site2.example.com www.site2.example.com;
root /var/www/site2.example.com/html;
index index.html;
access_log /var/log/nginx/site2.access.log;
error_log /var/log/nginx/site2.error.log;
location / {
try_files $uri $uri/ =404;
}
}
Test Locally with Host Headers Before DNS Propagation
DNS can take hours. Test early with curl:
curl -H "Host: site2.example.com" http://YOUR_SERVER_IP
This sends the right Host header so Nginx picks the correct server block. You can also edit /etc/hosts on your laptop for browser testing.
Step 3 — Configure Nginx Server Blocks for Application Domains (Reverse Proxy)
Not every site is just files. Apps like Node.js, Python, or Docker run on a port. Nginx server blocks for multiple domains can forward traffic to them.
Static Site vs. Reverse Proxy Server Block Differences
| Feature | Static Block | Reverse Proxy Block |
|---|---|---|
| Content source | Files on disk | Running app |
| Key directive | root | proxy_pass |
| Port used | 80/443 only | 80/443 plus app port |
Example: Proxying to a Node.js or Docker Application
Assume your app listens on localhost:3000. Create a block like this:
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The proxy_set_header lines pass real visitor info to your app.
Upstream Health Checks and Error Handling
For better reliability, define an upstream block and add error handling:
upstream app_backend {
server 127.0.0.1:3000;
}
server {
server_name app.example.com;
location / {
proxy_pass http://app_backend;
proxy_next_upstream error timeout http_502 http_503;
proxy_connect_timeout 5s;
}
}
This helps Nginx retry or show a friendly error when the app is slow.
Step 4 — Secure All Nginx Server Blocks with HTTPS
HTTPS is a must in 2026. Free certificates from Let’s Encrypt make this easy for every server block.
Install Certbot and Issue SSL Certificates
sudo apt install certbot python3-certbot-nginx- Run:
sudo certbot --nginx -d site1.example.com -d www.site1.example.com - Follow the prompts. Certbot edits your server block and adds port 443 settings.
- Repeat for site2 and app domains.
Force HTTP-to-HTTPS Redirect in Each Server Block
Certbot adds this for you, but you should understand it:
server {
listen 80;
server_name site1.example.com;
return 301 https://$host$request_uri;
}
This sends every HTTP visitor to the secure URL.
Set Up Automatic Certificate Renewal
Certbot installs a timer. Check it with:
sudo systemctl status certbot.timer
Test a dry run: sudo certbot renew --dry-run. Certs renew every 60–90 days with no action from you.
Step 5 — Define a Default Catch-All Server Block for Security
A default block is a safety net. It handles requests that don’t match any real domain.
Why a Default Server Block Matters
Without a default, Nginx picks the first block it finds. Bots scanning your IP could see a site you didn’t mean to show. A catch-all block stops that.
Configure the Catch-All Block to Reject Unknown Hosts
Create /etc/nginx/sites-available/default-catchall:
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
return 444;
}
Code 444 closes the connection with no reply. Enable it, test with nginx -t, and reload.
Troubleshooting Nginx Server Blocks for Multiple Domains
Problems happen. Here is how to find them fast.
DNS and Network Layer Issues
- Use
dig yourdomain.comto check A records - Use
ping yourdomain.comto confirm the IP - Wait up to 24 hours for DNS to spread worldwide
Nginx Configuration and Routing Errors
- Run
sudo nginx -tafter every change - Check the error log:
sudo tail -f /var/log/nginx/error.log - Look for typos in
server_nameandrootpaths - Make sure the file is linked in
sites-enabled
TLS Certificate Problems
- Run
sudo certbot certificatesto list active certs - Check that the domain in the cert matches
server_name - Renew with
sudo certbot renewif expired
Essential Diagnostic Commands (nginx -t, curl, dig, ss)
| Command | Use |
|---|---|
| nginx -t | Test config syntax |
| curl -I domain | Check HTTP headers |
| dig domain | Check DNS records |
| ss -tlnp | List listening ports |
| tail -f error.log | Watch live errors |
Operational Best Practices for Managing Multiple Nginx Server Blocks
Good habits save hours of pain. Follow these rules as your site list grows.
Backup Configuration Before Every Change
Before editing any block, copy the folder:
sudo cp -r /etc/nginx /etc/nginx.bak.$(date +%F)
If a change breaks things, you can restore fast.
Per-Site Logging and Log Rotation
Give each domain its own log files. This makes debugging simple. Use logrotate to keep logs small. A basic config in /etc/logrotate/nginx-sites:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
}
Safe Reload Workflow and Rollback Plan
- Backup current config
- Edit the server block
- Run
sudo nginx -t - If the test passes, run
sudo systemctl reload nginx - If the test fails, fix the error or restore the backup
- Visit the site to confirm it still works
FAQ: Common Questions About Nginx Server Blocks for Multiple Domains
Q: How many domains can one server handle?
A: Hundreds, if your traffic is light. The real limit is RAM and CPU, not Nginx itself.
Q: Do I need a separate IP for each domain?
A: No. Nginx uses the Host header to pick the right server block. One IP is enough.
Q: Why does my second domain show the first site?
A: Usually a typo in server_name, or the file is not linked in sites-enabled. Run nginx -t and reload.
Q: Can I use wildcards in server_name?
A: Yes. server_name *.example.com; matches any subdomain. Useful for customer sites.
Q: Should I use one block per domain or group them?
A: One block per domain is cleaner. It is easier to read, edit, and debug.
Final Production Checklist for Nginx Server Blocks
Before you go live, check every box:
- All domains point to the server IP via DNS
- Each domain has its own folder under
/var/www/ - Every server block has a unique
server_nameandroot nginx -tpasses with no errors- Ports 80 and 443 are open in the firewall
- HTTPS is active on every domain via Certbot
- HTTP traffic redirects to HTTPS
- A default catch-all block rejects unknown hosts
- Each site has its own access and error log
- A recent config backup is stored off-server
- You tested each domain in a browser and with curl
With this checklist done, your Nginx server blocks for multiple domains are ready for real traffic. Keep learning, keep testing, and your small website operations will grow with confidence.
