
This article provides a guide demonstrating how to setup Apache virtual hosts on Ubuntu VPS.
This guide walks you through creating multiple websites (virtual hosts) on a single Ubuntu VPS server using Apache. It covers HTTP, optional HTTPS with Let’s Encrypt, and common gotchas (and workarounds to resolve).
Before we learn how to setup Apache virtual hosts on Ubuntu VPS, let’s take a brief moment to understand Apache virtual hosts.
What are Apache Virtual Hosts?
Apache Virtual Hosts (often called vhosts) are a feature of the Apache HTTP Server that allow you to run multiple websites on a single server. Instead of needing a separate server (or IP address) for each site, you can configure Apache to “host” multiple domains and applications from one machine.
🔑 Key Concepts
- Domain-based (Name-based) Virtual Hosts
- Most common type.
- Multiple domains (e.g.,
example.com
,mysite.com
) share the same IP address. - Apache decides which website to serve based on the
Host
header sent by the browser.
- IP-based Virtual Hosts
- Each site has a unique IP address.
- Less common now (since IPv4 addresses are limited), but sometimes used for legacy apps or SSL setups before SNI (Server Name Indication).
- Port-based Virtual Hosts
- Different sites run on different ports of the same server (e.g.,
example.com:8080
vsexample.com:9090
). - Usually used for internal services rather than public websites.
- Different sites run on different ports of the same server (e.g.,
⚙️ How They Work
When a request comes in:
- The browser sends the domain name in the HTTP request (
Host
header). - Apache matches it with the
ServerName
orServerAlias
in the virtual host configuration. - Apache serves the site from the specified
DocumentRoot
(the folder containing the website’s files).
🚀 Benefits
- Host multiple domains/websites on a single server.
- Isolate websites into different directories.
- Configure separate logs, security rules, and SSL certificates per site.
- Reduce infrastructure costs by consolidating hosting.
Prerequisites
This guide assumes the following environmental prerequisites are met:
- VPS Server with fresh install of Ubuntu 24.04 LTS (Noble Numbat)
- Root-equivalent (sudo) privileges
- Basic understanding of the SSH command line
- Domain name pointed to your server’s IP address
How to Setup Apache Virtual Hosts on Ubuntu VPS (Noble Numbat) 🐧🛠️
To setup Apache virtual hosts on Ubuntu VPS, follow the steps outlined below:
Replace example.com everywhere with your actual domain.
-
Install & Verify Apache 🔧
sudo apt update sudo apt install -y apache2 apache2ctl -v # Should show Apache/2.4.x
Enable on boot and start:
sudo systemctl enable --now apache2 sudo systemctl status apache2
Open the firewall (if UFW is enabled):
sudo ufw allow 'Apache' sudo ufw status
-
Create a Document Root Per Site 🗂️
We’ll keep code under
/var/www//public_html
.sudo mkdir -p /var/www/example.com/public_html sudo chown -R $USER:www-data /var/www/example.com sudo chmod -R 750 /var/www/example.com
Drop in a quick test page:
cat <<'HTML' > /var/www/example.com/public_html/index.html <!doctype html> <html><head><meta charset="utf-8"><title>example.com</title></head> <body><h1>Hello from example.com 🎉</h1></body></html> HTML
(Repeat these steps for each site you host, e.g.,
secondsite.com
.) -
Create a Virtual Host File 📝
Apache keeps site configs in
/etc/apache2/sites-available/
. Create one per domain:sudo nano /etc/apache2/sites-available/example.com.conf
Paste this minimal, production-friendly vhost for HTTP (port 80):
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com ServerAdmin webmaster@example.com DocumentRoot /var/www/example.com/public_html <Directory /var/www/example.com/public_html> Options -Indexes +FollowSymLinks AllowOverride None Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/example.com_error.log CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined # Optional: If you later enable HTTP/2 globally #Protocols h3 h3c http/1.1 </VirtualHost>
If you rely on .htaccess (e.g., for WordPress), set
AllowOverride All
instead ofNone
and enablemod_rewrite
(next step). -
Enable Site & Common Modules ✅
# Enable the site sudo a2ensite example.com.conf # (Optional) If you’ll use .htaccess or redirects/rewrite rules sudo a2enmod rewrite # (Optional) Security and caching helpers you’ll likely want sudo a2enmod headers expires # Disable the default site to avoid collisions (optional but recommended) sudo a2dissite 000-default.conf # Check syntax and reload sudo apache2ctl configtest sudo systemctl reload apache2
Test:
curl -I http://example.com
If DNS isn’t pointed yet, you can temporarily test from your own computer by adding this line to /etc/hosts (Linux/macOS) or C:\Windows\System32\drivers\etc\hosts (Windows):
YOUR_SERVER_IP example.com www.example.com
-
Point DNS to Your Server 🌐
At your DNS provider, create A (and optional AAAA) records (full guide: How to Point a Domain to Your VPS Server):
example.com → YOUR_SERVER_IP
www.example.com → YOUR_SERVER_IP
DNS propagation can take time. You can check with:
dig +short A example.com
-
(Optional but recommended) Add HTTPS with Let’s Encrypt 🔒
On Ubuntu 24.04, the recommended method is snap:
sudo snap install core sudo snap refresh core sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/bin/certbot
Request and auto-configure SSL for Apache:
sudo certbot --apache -d example.com -d www.example.com
- Choose the redirect option so HTTP goes to HTTPS.
- Certbot sets up automatic renewal. Verify with:
sudo systemctl status snap.certbot.renew.service sudo certbot renew --dry-run
Open full HTTPS in UFW:
sudo ufw allow 'Apache Full' sudo ufw delete allow 'Apache' # optional cleanup
-
Useful Quality-of-Life Tweaks 🧰
Avoid the “could not reliably determine the server’s fully qualified domain name” warning:
echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf sudo a2enconf servername sudo systemctl reload apache2
Per-site .htaccess (if truly needed):
<Directory /var/www/example.com/public_html> AllowOverride All Require all granted </Directory>
Then:
sudo a2enmod rewrite sudo systemctl reload apache2
Force non-www (in your HTTPS vhost) via rewrite rules:
<VirtualHost *:443> # ... your SSL directives ... ServerName example.com ServerAlias www.example.com RewriteEngine On RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC] RewriteRule ^(.*)$ https://example.com/$1 [R=301,L] </VirtualHost>
-
Add Another Site (Quick Template) 🧩
Use your first config as a template:
# Document root sudo mkdir -p /var/www/secondsite.com/public_html sudo chown -R $USER:www-data /var/www/secondsite.com sudo chmod -R 750 /var/www/secondsite.com # Vhost sudo cp /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-available/secondsite.com.conf sudo nano /etc/apache2/sites-available/secondsite.com.conf # -> Change all example.com to secondsite.com and update paths # Enable & reload sudo a2ensite secondsite.com.conf sudo apache2ctl configtest sudo systemctl reload apache2
Get an SSL cert:
sudo certbot --apache -d secondsite.com -d www.secondsite.com
-
Troubleshooting 🧪
- Syntax errors:
apache2ctl configtest
shows where; fix andsystemctl reload apache2
. - Wrong site served:
Ensure the correct vhost file is enabled, has the right ServerName/ServerAlias, and the default site is disabled. List enabled sites with:a2query -s
- Permissions/403:
Confirm Apache can read the doc root:sudo -u www-data test -r /var/www/example.com/public_html/index.html && echo OK
Adjust
chown
/chmod
as needed. - DNS not pointing yet:
Use/etc/hosts
for temporary local testing (see Step 4).
- Syntax errors:
-
Housekeeping & Logs 🧹
Logs live at:
/var/log/apache2/*_access.log /var/log/apache2/*_error.log
Follow a log live:
sudo tail -f /var/log/apache2/example.com_error.log
Reload Apache after any config change:
sudo systemctl reload apache2
You’re done! 🚀
You now have clean, isolated virtual hosts on Ubuntu 24.04—easy to manage, secure with TLS, and ready to scale with more sites.
Conclusion
You now know how to setup Apache virtual hosts on Ubuntu VPS!