How to Create Virtual Host

How to Create Virtual Host Creating a virtual host is a fundamental skill for web administrators, developers, and system engineers who manage multiple websites on a single server. Whether you’re running a personal blog, a portfolio site, or a business with several web applications, virtual hosts allow you to serve different domains or subdomains from the same physical machine—each with its own con

Oct 30, 2025 - 10:20
Oct 30, 2025 - 10:20
 0

How to Create Virtual Host

Creating a virtual host is a fundamental skill for web administrators, developers, and system engineers who manage multiple websites on a single server. Whether you’re running a personal blog, a portfolio site, or a business with several web applications, virtual hosts allow you to serve different domains or subdomains from the same physical machine—each with its own configuration, content, and security settings. This tutorial provides a comprehensive, step-by-step guide to setting up virtual hosts on both Apache and Nginx web servers, along with best practices, real-world examples, and essential tools to ensure reliability, scalability, and performance.

Virtual hosting eliminates the need for multiple physical servers, reducing hardware costs and simplifying maintenance. It enables efficient resource allocation, secure isolation between sites, and seamless domain-based routing. Understanding how to create virtual hosts is not just a technical task—it’s a strategic advantage for anyone managing web infrastructure.

Step-by-Step Guide

Understanding Virtual Hosting Types

Before configuring a virtual host, it’s critical to understand the two primary types: name-based and IP-based virtual hosting.

Name-based virtual hosting is the most common method. It relies on the Host header sent by the client’s browser to determine which website to serve. Multiple domains can share the same IP address, making it ideal for most modern deployments where public IP addresses are limited and costly.

IP-based virtual hosting assigns a unique IP address to each website. This method is less common today due to IPv4 address exhaustion, but it’s still necessary in scenarios requiring SSL certificates without Server Name Indication (SNI) support, such as legacy systems or specific compliance requirements.

For the purposes of this guide, we’ll focus primarily on name-based virtual hosting, as it applies to the vast majority of use cases.

Prerequisites

Before beginning, ensure you have the following:

  • A server running Linux (Ubuntu, CentOS, Debian, or similar)
  • Root or sudo access
  • A web server installed: Apache or Nginx
  • Domain names pointed to your server’s IP address via DNS A records
  • Basic command-line familiarity

Verify your server’s IP address by running:

curl -4 icanhazip.com

Confirm your web server is installed and running:

sudo systemctl status apache2   

For Apache on Ubuntu/Debian

sudo systemctl status nginx

For Nginx on any Linux

If not installed, install Apache with:

sudo apt update && sudo apt install apache2

Or Nginx with:

sudo apt update && sudo apt install nginx

Configuring Virtual Hosts on Apache

Apache uses configuration files located in /etc/apache2/sites-available/ for virtual hosts. Enabled sites are symlinked from /etc/apache2/sites-enabled/.

Step 1: Create a Directory for Your Website

Create a dedicated directory for your site’s files. For example, for a site called example.com:

sudo mkdir -p /var/www/example.com/html

Set appropriate ownership and permissions:

sudo chown -R $USER:$USER /var/www/example.com/html

sudo chmod -R 755 /var/www/example.com

Step 2: Create a Sample Index File

Create a basic HTML file to test your configuration:

nano /var/www/example.com/html/index.html

Add the following content:

<!DOCTYPE html>

<html>

<head>

<title>Welcome to example.com</title>

</head>

<body>

<h1>Success! The example.com virtual host is working.</h1>

</body>

</html>

Step 3: Create the Virtual Host Configuration File

Create a new configuration file in the sites-available directory:

sudo nano /etc/apache2/sites-available/example.com.conf

Insert the following configuration:

<VirtualHost *:80>

ServerAdmin webmaster@example.com

ServerName example.com

ServerAlias www.example.com

DocumentRoot /var/www/example.com/html

ErrorLog ${APACHE_LOG_DIR}/error.log

CustomLog ${APACHE_LOG_DIR}/access.log combined

<Directory /var/www/example.com/html>

Options Indexes FollowSymLinks

AllowOverride All

Require all granted

</Directory>

</VirtualHost>

Key directives explained:

  • ServerName: The primary domain name.
  • ServerAlias: Additional domain names that should also serve this site (e.g., www variant).
  • DocumentRoot: The directory where website files are stored.
  • AllowOverride All: Enables .htaccess files for per-directory configuration (useful for WordPress, Laravel, etc.).
  • Require all granted: Grants access to the directory (replaces older Apache 2.2 syntax).

Step 4: Enable the Virtual Host

Enable the site using the a2ensite command:

sudo a2ensite example.com.conf

Disable the default site if not needed:

sudo a2dissite 000-default.conf

Step 5: Test Configuration and Restart Apache

Always test your configuration before restarting:

sudo apache2ctl configtest

If the output says Syntax OK, restart Apache:

sudo systemctl restart apache2

Configuring Virtual Hosts on Nginx

Nginx stores virtual host configurations in /etc/nginx/sites-available/, with enabled sites symlinked to /etc/nginx/sites-enabled/.

Step 1: Create a Directory for Your Website

Same as with Apache:

sudo mkdir -p /var/www/example.com/html

Set ownership and permissions:

sudo chown -R $USER:$USER /var/www/example.com/html

sudo chmod -R 755 /var/www/example.com

Step 2: Create a Sample Index File

Use the same index.html file created earlier:

nano /var/www/example.com/html/index.html

Step 3: Create the Server Block Configuration

Create a new configuration file:

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

Add the following configuration:

server {

listen 80;

server_name example.com www.example.com;

root /var/www/example.com/html;

index index.html;

location / {

try_files $uri $uri/ =404;

}

access_log /var/log/nginx/example.com.access.log;

error_log /var/log/nginx/example.com.error.log;

}

Key directives explained:

  • listen 80;: Specifies the port to listen on.
  • server_name: The domain(s) this block serves.
  • root: The document root directory.
  • index: Default file to serve when directory is requested.
  • try_files: Attempts to serve the requested file; if not found, returns a 404.
  • access_log and error_log: Custom log files for monitoring.

Step 4: Enable the Site

Create a symbolic link to the sites-enabled directory:

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

Remove the default configuration if it’s not needed:

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

Step 5: Test and Reload Nginx

Test the configuration for syntax errors:

sudo nginx -t

If successful, reload Nginx to apply changes:

sudo systemctl reload nginx

Configuring DNS Records

Virtual hosts rely on DNS to route traffic correctly. Ensure your domain’s A record points to your server’s public IP address.

Log in to your domain registrar’s control panel (e.g., GoDaddy, Namecheap, Cloudflare) and create an A record:

  • Name: @ (for root domain) or www
  • Type: A
  • Value: Your server’s IP address
  • TTL: 3600 seconds (or default)

Wait for DNS propagation—this can take up to 48 hours, though usually completes within minutes to a few hours.

Verify DNS resolution using:

dig example.com +short

or

nslookup example.com

Testing Your Virtual Host

Once DNS propagates and the server is restarted, open your browser and navigate to http://example.com. You should see your sample index page.

If you see a default page or an error:

  • Check your web server logs: sudo tail -f /var/log/apache2/error.log or sudo tail -f /var/log/nginx/error.log
  • Verify file permissions: ls -la /var/www/example.com/html/
  • Ensure the correct configuration file is enabled
  • Confirm firewall allows HTTP traffic: sudo ufw allow 'Apache Full' or sudo ufw allow 'Nginx Full'

Best Practices

Use Separate Directories for Each Site

Never store multiple websites in the same document root. Isolating each site’s files under its own directory—such as /var/www/site1.com and /var/www/site2.com—enhances security, simplifies backups, and reduces the risk of cross-site contamination.

Implement Proper File Permissions

Web server processes (e.g., www-data for Apache, nginx for Nginx) should have read access to files but not write access unless necessary. Avoid setting permissions to 777. Use:

sudo chown -R $USER:www-data /var/www/example.com

sudo chmod -R 644 /var/www/example.com/html/

sudo chmod 755 /var/www/example.com/

This grants ownership to your user, group ownership to the web server, and restricts write access to the owner only.

Enable Logging for Each Virtual Host

Always configure separate access and error logs per virtual host. This enables granular monitoring, troubleshooting, and analytics. Avoid using global logs for multiple sites—it becomes impossible to isolate issues.

Use ServerAlias for Common Variants

Always include www as a ServerAlias if your site uses it. Users may type either version. Redirecting one to the other (e.g., www to non-www or vice versa) is a separate step but should be planned.

Implement HTTPS with Let’s Encrypt

After establishing a working HTTP virtual host, secure it with TLS. Use Certbot to automate SSL certificate issuance from Let’s Encrypt:

sudo apt install certbot python3-certbot-apache   

For Apache

sudo apt install certbot python3-certbot-nginx

For Nginx

sudo certbot --apache -d example.com -d www.example.com

or

sudo certbot --nginx -d example.com -d www.example.com

Certbot automatically modifies your virtual host configuration to redirect HTTP to HTTPS and sets up automatic renewal.

Optimize Performance with Caching and Compression

Enable Gzip compression and browser caching in your virtual host configuration to improve load times:

For Apache, add to your virtual host:

<IfModule mod_deflate.c>

AddOutputFilterByType DEFLATE text/html text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript

</IfModule>

<IfModule mod_expires.c>

ExpiresActive on

ExpiresByType text/html "access plus 1 day"

ExpiresByType image/jpg "access plus 1 month"

ExpiresByType image/jpeg "access plus 1 month"

ExpiresByType image/png "access plus 1 month"

ExpiresByType text/css "access plus 1 week"

ExpiresByType application/javascript "access plus 1 week"

</IfModule>

For Nginx, add to your server block:

gzip on;

gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

expires 30d;

add_header Cache-Control "public, immutable";

Limit Access When Necessary

For staging or admin areas, restrict access by IP address:

Apache:

<Directory /var/www/example.com/admin>

Require ip 192.168.1.0/24

Require ip 203.0.113.5

</Directory>

Nginx:

location /admin/ {

allow 192.168.1.0/24;

allow 203.0.113.5;

deny all;

}

Regularly Monitor and Rotate Logs

Log files can grow large. Use logrotate to manage them automatically:

sudo nano /etc/logrotate.d/example.com

Add:

/var/log/nginx/example.com.access.log /var/log/nginx/example.com.error.log {

daily

missingok

rotate 14

compress

delaycompress

notifempty

create 640 nginx adm

sharedscripts

postrotate

[ -f /var/run/nginx.pid ] && kill -USR1 cat /var/run/nginx.pid

endscript

}

Tools and Resources

Essential Command-Line Tools

  • curl – Test HTTP responses and headers: curl -I http://example.com
  • dig and nslookup – Verify DNS propagation
  • netstat or ss – Check which ports are listening: ss -tuln
  • tail – Monitor logs in real time: tail -f /var/log/nginx/error.log
  • apache2ctl and nginx -t – Validate configuration syntax

Configuration Validation Tools

  • Apache Config Test – Built-in: sudo apache2ctl configtest
  • Nginx Config Test – Built-in: sudo nginx -t
  • SSL Labs (https://ssllabs.com) – Test SSL/TLS configuration strength
  • GTmetrix – Analyze page speed and optimization
  • Redirect Checker (https://redirect-checker.org) – Verify HTTP to HTTPS redirects

Automation and Management Tools

  • Certbot – Automates SSL certificate issuance and renewal
  • Ansible – Automate server provisioning and virtual host deployment across multiple servers
  • Webmin – Web-based GUI for managing Apache/Nginx virtual hosts (useful for non-CLI users)
  • Portainer – For Docker-based deployments, manage containers hosting websites
  • Cloudflare – Use as a reverse proxy for caching, security, and DNS management

Template Repositories and Code Examples

For rapid deployment, use open-source templates:

These repositories provide production-ready configurations, Dockerfiles, and automation scripts that can be customized for your environment.

Real Examples

Example 1: Hosting Multiple WordPress Sites on One Server

Suppose you’re managing three WordPress sites: blog.com, store.com, and portfolio.com. Each requires its own database and document root.

For each site:

  1. Create directory: /var/www/blog.com/html
  2. Download WordPress: wget https://wordpress.org/latest.tar.gz
  3. Extract and move files to the directory
  4. Create a MySQL database and user for each site
  5. Configure wp-config.php with unique database credentials
  6. Set up a virtual host for each domain
  7. Enable SSL with Certbot

Each site operates independently. If one site is compromised, the others remain unaffected. Backups can be automated per site using rsync or mysqldump.

Example 2: Development, Staging, and Production Environments

Use subdomains to separate environments:

  • dev.example.com – Developer testing
  • staging.example.com – QA and client review
  • www.example.com – Production

Each subdomain has its own virtual host, pointing to a different directory:

/var/www/dev.example.com/html

/var/www/staging.example.com/html

/var/www/www.example.com/html

Use environment-specific configuration files (e.g., wp-config.php with different database connections) and restrict access to dev/staging via IP whitelisting.

Example 3: Reverse Proxy for Node.js Applications

Many modern applications run on Node.js, Python (Django/Flask), or Ruby on Rails. These are not HTTP servers by default. Use Nginx as a reverse proxy to route traffic to them.

Example: Running a Node.js app on port 3000.

Virtual host configuration:

server {

listen 80;

server_name app.example.com;

location / {

proxy_pass http://localhost:3000;

proxy_http_version 1.1;

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection 'upgrade';

proxy_set_header Host $host;

proxy_cache_bypass $http_upgrade;

}

}

Start your Node.js app:

node server.js

Now app.example.com serves your application through Nginx, with benefits like SSL termination, caching, and load balancing.

Example 4: Multi-Tenant SaaS Application

A SaaS product might serve thousands of customers under subdomains: customer1.yourapp.com, customer2.yourapp.com.

Use a wildcard virtual host:

Apache:

<VirtualHost *:80>

ServerName yourapp.com

ServerAlias *.yourapp.com

DocumentRoot /var/www/yourapp.com/html

<Directory /var/www/yourapp.com/html>

AllowOverride All

Require all granted

</Directory>

</VirtualHost>

Nginx:

server {

listen 80;

server_name yourapp.com *.yourapp.com;

root /var/www/yourapp.com/html;

index index.php;

location / {

try_files $uri $uri/ /index.php?$query_string;

}

}

Use application-level routing (e.g., Laravel’s multi-tenancy packages or custom middleware) to serve different content based on the subdomain.

FAQs

What is the difference between a virtual host and a subdomain?

A virtual host is a server configuration that tells the web server how to respond to requests for a specific domain or subdomain. A subdomain is a part of a domain name, such as blog.example.com. You can use a virtual host to serve a subdomain, but not all virtual hosts are subdomains—some serve root domains like example.com.

Can I host multiple websites on a single IP address?

Yes, using name-based virtual hosting. This is the standard method for most websites today. As long as each domain resolves to the same IP, the web server uses the Host header to determine which site to serve.

Why is my virtual host not loading?

Common causes include:

  • DNS not propagating (check with dig)
  • Incorrect file permissions
  • Misspelled ServerName or DocumentRoot
  • Configuration not enabled (e.g., missing symlink in sites-enabled)
  • Firewall blocking port 80
  • Web server not restarted after configuration change

Do I need a static IP address to create a virtual host?

Yes. Virtual hosts require a fixed IP address so DNS records can point reliably to your server. Dynamic IP addresses (common in home networks) will cause your sites to become unreachable when the IP changes.

Can I create virtual hosts on Windows?

Yes, but it’s less common. Apache and Nginx both run on Windows. The configuration process is similar, but file paths use backslashes (e.g., C:\Apache24\htdocs\example.com). For production environments, Linux is strongly recommended due to stability, performance, and tooling support.

How do I redirect HTTP to HTTPS automatically?

For Apache, add this inside your virtual host block:

<VirtualHost *:80>

ServerName example.com

ServerAlias www.example.com

Redirect permanent / https://example.com/

</VirtualHost>

For Nginx:

server {

listen 80;

server_name example.com www.example.com;

return 301 https://example.com$request_uri;

}

How often should I renew SSL certificates?

Let’s Encrypt certificates expire every 90 days. Use Certbot’s automated renewal system:

sudo certbot renew --dry-run

Add a cron job to run this weekly:

sudo crontab -e

Add:

0 12 * * * /usr/bin/certbot renew --quiet

Can I use virtual hosts with Docker?

Absolutely. Use tools like nginx-proxy or traefik to automatically generate virtual host configurations based on Docker container labels. This enables dynamic, containerized hosting without manual server configuration.

What happens if two virtual hosts have the same ServerName?

Apache and Nginx will use the first matching configuration they find. This can lead to unexpected behavior. Always ensure each ServerName is unique. Use wildcard domains (e.g., *.example.com) intentionally and avoid overlapping configurations.

Conclusion

Creating a virtual host is a powerful and essential skill for managing modern web infrastructure. Whether you’re hosting a single blog or dozens of enterprise applications, virtual hosts enable you to efficiently utilize server resources, maintain clear separation between sites, and scale your web presence with confidence.

This guide has walked you through the complete process—from setting up directories and configuration files to securing your sites with HTTPS and optimizing performance. You’ve learned how to configure both Apache and Nginx, implemented best practices for security and maintainability, explored real-world use cases, and gained access to tools that automate and simplify ongoing management.

Remember: virtual hosting is not just about technical configuration—it’s about architecture. Each virtual host you create should be treated as an independent service with its own lifecycle, backups, monitoring, and security posture. By following the practices outlined here, you ensure that your infrastructure remains robust, scalable, and secure.

As web technologies evolve, the principles of virtual hosting remain foundational. Mastering this skill empowers you to take full control of your hosting environment, reduce dependency on third-party platforms, and build systems that are resilient, efficient, and future-proof.