15%

Save 15% on All Hosting Services

Test your skills and get Discount on any hosting plan

Use code:

Skills
Get Started
31.10.2024

How to Configure Virtual Hosts in Nginx on Ubuntu

Configuring virtual hosts in Nginx is one of the most powerful techniques for hosting multiple websites on a single server, each with its own domain name, root directory, and independent configuration. Nginx handles this through server blocks — flexible, lightweight configuration units that define how the web server responds to requests for each domain.

Whether you're managing a personal portfolio, running client websites, or scaling a multi-tenant application, this guide provides a complete, production-ready walkthrough for setting up Nginx virtual hosts on Ubuntu. We'll cover directory structure, server block configuration, enabling sites, SSL/HTTPS setup, and troubleshooting — everything you need to go from zero to a fully functional multi-site Nginx server.

> Looking for a reliable Ubuntu server to follow along? AlexHost's VPS Hosting plans give you full root access, SSD storage, and instant deployment — perfect for this exact use case.

Table of Contents

  1. Prerequisites
  2. Set Up Directories for Each Website
  3. Create Sample HTML Content
  4. Create Virtual Host Configuration Files
  5. Enable the Virtual Hosts
  6. Test the Nginx Configuration
  7. Restart Nginx to Apply Changes
  8. Access Your Websites
  9. Enable HTTPS with Let's Encrypt (Recommended)
  10. Troubleshooting Common Issues
  11. Conclusion

Prerequisites

Before you begin, make sure the following conditions are met:

Nginx Installed on Your Server

If Nginx is not yet installed, run the following commands on your Ubuntu server:

sudo apt update
sudo apt install nginx

Verify the installation and check that the service is running:

sudo systemctl status nginx

You should see active (running) in the output. If not, start it manually:

sudo systemctl start nginx
sudo systemctl enable nginx

Domain Names Pointed to Your Server

Each virtual host requires a domain name that resolves to your server's public IP address. You'll need to create A records in your DNS settings pointing to the server's IP.

> Need a domain? Register yours through AlexHost Domain Registration and manage DNS records directly from your control panel.

For local testing purposes, you can bypass DNS entirely by editing your /etc/hosts file (covered in Step 7).

Required Permissions

You'll need sudo privileges on your Ubuntu server to create directories, edit configuration files, and manage the Nginx service.

Step 1: Set Up Directories for Each Website

Each website hosted on your server should have its own isolated directory to store web files. This separation keeps your projects organized and prevents configuration conflicts.

In this guide, we'll configure two example domains: example1.com and example2.com. Replace these with your actual domain names throughout.

Create the Web Root Directories

sudo mkdir -p /var/www/example1.com/html
sudo mkdir -p /var/www/example2.com/html

The -p flag creates all intermediate directories as needed.

Assign Correct Ownership

Grant ownership of these directories to www-data, the system user that Nginx runs as:

sudo chown -R www-data:www-data /var/www/example1.com/html
sudo chown -R www-data:www-data /var/www/example2.com/html

This ensures Nginx has the necessary read permissions to serve files from these directories.

Set Directory Permissions

sudo chmod -R 755 /var/www

The 755 permission means the owner has full read/write/execute access, while groups and other users have read and execute access — appropriate for publicly served web content.

Step 2: Create Sample HTML Content

To verify that each virtual host is working correctly, create a simple index.html file for each site.

For example1.com

echo "<h1>Welcome to Example1.com!</h1>" | sudo tee /var/www/example1.com/html/index.html

For example2.com

echo "<h1>Welcome to Example2.com!</h1>" | sudo tee /var/www/example2.com/html/index.html

These placeholder pages will confirm that Nginx is routing requests to the correct document root for each domain.

Step 3: Create Virtual Host Configuration Files

Nginx stores site configuration files in /etc/nginx/sites-available/. Each file defines a server block — the Nginx equivalent of an Apache virtual host. Enabled sites are then symlinked into /etc/nginx/sites-enabled/.

Configuration for example1.com

Create a new configuration file:

sudo nano /etc/nginx/sites-available/example1.com

Add the following server block:

server {
    listen 80;
    listen [::]:80;

    server_name example1.com www.example1.com;

    root /var/www/example1.com/html;
    index index.html index.htm;

    access_log /var/log/nginx/example1.com.access.log;
    error_log  /var/log/nginx/example1.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }
}

Save and close the file (Ctrl+X, then Y, then Enter).

Configuration for example2.com

Create a second configuration file:

sudo nano /etc/nginx/sites-available/example2.com

Add the following server block:

server {
    listen 80;
    listen [::]:80;

    server_name example2.com www.example2.com;

    root /var/www/example2.com/html;
    index index.html index.htm;

    access_log /var/log/nginx/example2.com.access.log;
    error_log  /var/log/nginx/example2.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }
}

Key Directives Explained

DirectivePurpose
listen 80Listens for incoming HTTP connections on port 80
listen [::]:80Enables IPv6 support on port 80
server_nameDefines which domain names this block handles
rootSets the document root — where website files are stored
indexSpecifies the default file to serve when a directory is requested
try_filesAttempts to serve the requested file; returns 404 if not found
access_log / error_logSeparate log files per site for easier debugging

Step 4: Enable the Virtual Hosts

Nginx activates sites by creating symbolic links from sites-available to sites-enabled. This design allows you to prepare configurations without immediately activating them.

sudo ln -s /etc/nginx/sites-available/example1.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/example2.com /etc/nginx/sites-enabled/

If you want to prevent Nginx's default placeholder page from interfering, disable it:

sudo rm /etc/nginx/sites-enabled/default

You can always re-enable it later by recreating the symlink.

Step 5: Test the Nginx Configuration

Before restarting Nginx, always validate your configuration files for syntax errors. A misconfigured file can bring down all sites on the server.

sudo nginx -t

A successful test returns:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If you see errors, Nginx will indicate the file and line number where the problem occurred. Review the relevant configuration file and correct any typos or missing semicolons before proceeding.

Step 6: Restart Nginx to Apply Changes

Once the configuration test passes, reload or restart Nginx to apply your changes:

sudo systemctl restart nginx

Alternatively, use reload for a graceful restart that doesn't interrupt active connections:

sudo systemctl reload nginx

Step 7: Access Your Websites

If DNS Is Already Configured

If your domain names are already pointing to your server's IP address via DNS A records, simply open a browser and navigate to:

  • http://example1.com
  • http://example2.com

You should see the respective "Welcome" messages you created in Step 2.

For Local Testing (Without DNS)

If you're testing locally or DNS hasn't propagated yet, you can simulate domain resolution by editing your local machine's /etc/hosts file (on Linux/macOS) or C:WindowsSystem32driversetchosts (on Windows).

Open the file with elevated privileges:

sudo nano /etc/hosts

Add the following lines, replacing YOUR_SERVER_IP with your actual server IP:

YOUR_SERVER_IP example1.com www.example1.com
YOUR_SERVER_IP example2.com www.example2.com

Save the file and test in your browser. Remember to remove these entries once your real DNS records are live.

Running websites over plain HTTP is no longer acceptable for production environments. HTTPS encrypts traffic between your server and visitors, improves SEO rankings, and is required for modern browser features. Let's Encrypt provides free, automatically renewable SSL/TLS certificates.

> Prefer a premium SSL solution? AlexHost offers trusted SSL Certificates for businesses that need extended validation or wildcard coverage.

Install Certbot

sudo apt install certbot python3-certbot-nginx

Obtain and Install SSL Certificates

Run Certbot for each domain. The --nginx plugin automatically modifies your Nginx configuration to enable HTTPS:

sudo certbot --nginx -d example1.com -d www.example1.com
sudo certbot --nginx -d example2.com -d www.example2.com

Follow the interactive prompts. Certbot will:

  1. Verify domain ownership via HTTP challenge
  2. Obtain a signed certificate from Let's Encrypt
  3. Automatically update your Nginx server block to listen on port 443
  4. Configure HTTP-to-HTTPS redirection

Verify Auto-Renewal

Let's Encrypt certificates expire every 90 days. Certbot installs a systemd timer to handle renewals automatically. Test it with:

sudo certbot renew --dry-run

If the dry run completes without errors, your certificates will renew automatically without any manual intervention.

What Your Updated Server Block Will Look Like

After Certbot runs, your configuration will be automatically updated to something like this:

server {
    listen 443 ssl;
    server_name example1.com www.example1.com;

    root /var/www/example1.com/html;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/example1.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        try_files $uri $uri/ =404;
    }
}

server {
    listen 80;
    server_name example1.com www.example1.com;
    return 301 https://$host$request_uri;
}

Troubleshooting Common Issues

Even with careful configuration, issues can arise. Here are the most common problems and how to resolve them:

502 Bad Gateway

This typically means Nginx cannot communicate with a backend service (e.g., PHP-FPM or a Node.js app). Verify the upstream service is running and that the socket/port in your configuration is correct.

403 Forbidden

Usually a permissions issue. Check that www-data owns the web root and that file permissions are set correctly:

sudo chown -R www-data:www-data /var/www/example1.com
sudo chmod -R 755 /var/www/example1.com

404 Not Found

Verify that the root directive in your server block points to the correct directory and that index.html exists at that path.

Wrong Site Loading

If visiting example1.com loads example2.com's content, check that:

  • Each server_name directive is unique and correct
  • Symlinks in sites-enabled are valid: ls -la /etc/nginx/sites-enabled/
  • The default site is disabled if it conflicts

Nginx Fails to Start After Config Change

Always run sudo nginx -t before restarting. Review the error output carefully — it will point to the exact file and line causing the issue.

Checking Logs

Per-site logs (configured in Step 3) are your best debugging resource:

sudo tail -f /var/log/nginx/example1.com.error.log
sudo tail -f /var/log/nginx/example1.com.access.log

Advanced Considerations

Hosting PHP Applications

If your sites run PHP (e.g., WordPress, Laravel), you'll need to install PHP-FPM and add a fastcgi_pass directive to your server block:

location ~ .php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

Using a Control Panel

Managing Nginx virtual hosts manually via the command line is powerful but time-consuming at scale. If you prefer a graphical interface, consider AlexHost's VPS with cPanel or explore the full range of VPS Control Panels to find the right fit for your workflow.

Scaling Beyond a Single VPS

As your traffic grows, a single VPS may not be sufficient. For high-traffic, resource-intensive workloads, consider upgrading to Dedicated Servers for guaranteed resources, full hardware isolation, and maximum performance.

Conclusion

You've now successfully configured Nginx virtual hosts on Ubuntu, enabling your server to host multiple independent websites simultaneously. Here's a summary of what was accomplished:

  • Created isolated web root directories for each domain with correct ownership and permissions
  • Wrote clean, production-ready server block configurations with separate access and error logs
  • Enabled virtual hosts using Nginx's symlink-based sites-available / sites-enabled pattern
  • Validated and reloaded the Nginx configuration safely
  • Secured each site with HTTPS using free Let's Encrypt certificates via Certbot

This setup is efficient, scalable, and follows Nginx best practices. Whether you're hosting two sites or twenty, the same pattern applies — simply repeat the process for each additional domain.

For the best results, pair this configuration with a fast, reliable hosting environment. AlexHost's VPS Hosting plans are optimized for Linux workloads, come with full root access, and are backed by 24/7 technical support — giving you the ideal foundation for running Nginx in production.

15%

Save 15% on All Hosting Services

Test your skills and get Discount on any hosting plan

Use code:

Skills
Get Started