sodcalculator

10 Tech How-To

Apache Virtual Hosts on Ubuntu: Step-by-Step Setup

Guide 10-35735 · Updated · Step by step

Setting up Apache virtual hosts on Ubuntu lets you host multiple websites on a single server, each with its own domain name and document root. This guide walks you through creating a directory structure, configuring virtual host files, enabling them, and testing the result. You’ll need a running Ubuntu server (20.04 or newer) with Apache installed and sudo access.

What You’ll Need

  • Ubuntu server (20.04 LTS or later) with a non-root sudo user.
  • Apache2 installed (sudo apt install apache2).
  • Domain names (or test domains) pointing to your server’s IP, or you can edit your local /etc/hosts file for testing.

Step-by-Step

  1. Create the directory structure. For each site, create a directory under /var/www/. For example, for example.com and test.com:
    sudo mkdir -p /var/www/example.com/public_html
    sudo mkdir -p /var/www/test.com/public_html
  2. Set ownership and permissions. Give your user ownership so you can edit files without sudo, and set the correct permissions:
    sudo chown -R $USER:$USER /var/www/example.com/public_html
    sudo chown -R $USER:$USER /var/www/test.com/public_html
    sudo chmod -R 755 /var/www
  3. Create a test page for each site. Add an index.html file to each directory so you can verify the virtual host works. For example:
    echo "<h1>Welcome to Example.com!</h1>" | tee /var/www/example.com/public_html/index.html
    echo "<h1>Welcome to Test.com!</h1>" | tee /var/www/test.com/public_html/index.html
  4. Copy the default configuration file. Apache uses configuration files in /etc/apache2/sites-available/. Copy the default file to create a new one for each site:
    sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf
    sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/test.com.conf
  5. Edit the virtual host files. Open the first file with a text editor (e.g., nano):
    sudo nano /etc/apache2/sites-available/example.com.conf

    Update the ServerAdmin email, add ServerName and ServerAlias, and change the DocumentRoot to the new directory. A minimal configuration looks like:

    <VirtualHost *:80>
        ServerAdmin admin@example.com
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public_html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>

    Save and exit. Repeat for the second site, adjusting the domain and paths.

  6. Enable the virtual host files. Use a2ensite to enable each site:
    sudo a2ensite example.com.conf
    sudo a2ensite test.com.conf
  7. Disable the default site (optional but recommended). To avoid conflicts, disable the default site:
    sudo a2dissite 000-default.conf
  8. Test the configuration. Before restarting Apache, check for syntax errors:
    sudo apache2ctl configtest

    You should see Syntax OK. If not, fix the errors before continuing.

  9. Restart Apache. Apply the changes:
    sudo systemctl restart apache2
  10. Test the virtual hosts. If your domains are live, visit them in a browser. If you’re testing locally, edit your /etc/hosts file to point the domains to your server’s IP (e.g., 127.0.0.1 example.com), then visit http://example.com and http://test.com. Each should show the corresponding test page.

Common Mistakes

  • Forgetting to enable the site. Creating a config file in sites-available does nothing until you run a2ensite.
  • Wrong DocumentRoot path. A typo in the path leads to a 404 or a generic Apache page.
  • Not using ServerName. Without it, Apache may route requests to the first virtual host, causing wrong sites to load.
  • Not disabling the default site. If the default site is still enabled, it can catch requests that don’t match any ServerName.
  • Forgetting to restart Apache. Changes only take effect after a reload or restart.

Tips

  • Use sudo systemctl reload apache2 instead of restart for minor changes; it’s faster and less disruptive.
  • Keep each site’s logs separate by setting ErrorLog and CustomLog to files like ${APACHE_LOG_DIR}/example.com-error.log.
  • For HTTPS, later add a virtual host on port 443 and use Let’s Encrypt with certbot.
  • Use sudo apache2ctl -S to list all virtual hosts and verify their configuration.
  • If you have many sites, consider using a wildcard ServerAlias like *.example.com for subdomains.

Troubleshooting

  • Site shows default Apache page. This usually means the virtual host isn’t being used. Check that the site is enabled (a2ensite) and that the ServerName matches the domain you’re visiting. Also ensure the default site is disabled.
  • 404 Not Found. The DocumentRoot path is wrong or the index file is missing. Check the directory exists and contains the file.
  • Permission denied. Apache may not have read access to the document root. Ensure the directory permissions are 755 and files are 644, and that the ownership is correct (usually www-data for the group, but your user can own it).
  • Syntax errors after editing. Run sudo apache2ctl configtest to see the exact error. Common issues are missing closing tags or typos in paths.
  • Domain not resolving. If you’re testing locally, edit /etc/hosts to map the domain to your server IP. For production, check your DNS records.
  • Port 80 already in use. If another service is using port 80, Apache won’t start. Check with sudo netstat -tulpn | grep :80 and stop the conflicting service or change Apache’s port.

Frequently Asked Questions

Can I use virtual hosts with IP-based instead of name-based hosting?

Yes, but name-based virtual hosts (using ServerName) are the default and more common. IP-based hosting requires each site to have a unique IP address, which is rare on a single server.

How do I set up a virtual host for a subdomain?

Create a new virtual host file with a ServerName like sub.example.com and point its DocumentRoot to a separate directory. Enable it with a2ensite and restart Apache.

What is the difference between sites-available and sites-enabled?

sites-available holds all configuration files, even inactive ones. sites-enabled contains symlinks to the active configurations. The a2ensite and a2dissite commands manage these symlinks.

Can I run multiple sites on different ports?

Yes, you can specify a different port in the <VirtualHost> tag, e.g., <VirtualHost *:8080>. You’ll also need to add a Listen 8080 directive in ports.conf.

How do I redirect all traffic to HTTPS?

After setting up SSL with Let’s Encrypt, you can add a redirect in the port 80 virtual host: Redirect permanent / https://example.com/. Alternatively, use the certbot --apache command to automate this.

Why does my second site show the first site’s content?

This usually happens when the ServerName is missing or incorrect in the second virtual host. Apache then falls back to the first virtual host. Double-check the ServerName and that the site is enabled.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →