Apache Virtual Hosts Not Redirecting Subdomains: 7 Proven Fixes
Apache virtual hosts not redirecting subdomains correctly is one of the most frustrating server problems developers hit on fresh Ubuntu setups. According to the Apache Software Foundation, misconfigured VirtualHost blocks account for a large share of support requests on Apache 2.4 servers. The root causes are almost always the same: a wrong ServerName, a config file that was never enabled, a DNS record pointing nowhere, or AllowOverride quietly blocking everything your .htaccess tries to do.
This guide walks through every fix in order. By the end, your subdomains will resolve to the correct directories and Apache will stop routing traffic to the default site.
Key Takeaways
Also Read: Complete VPS Setup Guide for Laravel, PHP, Apache, MySQL on Ubuntu
Prerequisites Before You Start
- Apache 2.4 installed and running (
apache2 -vto confirm) - Ubuntu 20.04 or 22.04 (commands are Debian/Ubuntu-specific)
- Domain with DNS access (Cloudflare, Namecheap, or similar)
- Root or sudo shell access
- Basic familiarity with the Linux command line
What Causes Apache Subdomains to Stop Redirecting?
Apache stops routing subdomains correctly for a small set of repeatable reasons. The Apache 2.4 documentation confirms that name-based virtual hosting depends entirely on the Host header sent by the browser, meaning even one typo in ServerName breaks routing for that entire block. (Apache Docs, 2024)
- Incorrect ServerName or ServerAlias – the most common cause by far
- Config file not enabled – the file exists in
sites-availablebut was never symlinked tosites-enabled - Conflicting VirtualHost blocks – another site catches the request first
- DNS A record not pointing to the server – the subdomain never reaches Apache at all
- AllowOverride set to None – blocks all
.htaccessdirectives silently - mod_rewrite not enabled – rewrites fail without error messages
Fix 1: Verify Your Virtual Host Configuration File
The first fix is to check your VirtualHost config file directly. Open the file and confirm every directive matches your actual subdomain.
sudo nano /etc/apache2/sites-available/sub.yourdomain.com.conf
A correct HTTP-only VirtualHost block looks like this:
ServerName sub.yourdomain.com
ServerAlias www.sub.yourdomain.com
DocumentRoot /var/www/sub.yourdomain.com/public
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
ErrorLog ${APACHE_LOG_DIR}/sub.yourdomain.com-error.log
CustomLog ${APACHE_LOG_DIR}/sub.yourdomain.com-access.log combined
Notice AllowOverride All inside the Directory block. That single line is missing from most tutorial configs, and its absence silently breaks every .htaccess rule on the site.
Adding HTTPS (Port 443) to Your Subdomain
ServerName sub.yourdomain.com
DocumentRoot /var/www/sub.yourdomain.com/public
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/sub.yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sub.yourdomain.com/privkey.pem
AllowOverride All
Require all granted
ErrorLog ${APACHE_LOG_DIR}/sub.yourdomain.com-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/sub.yourdomain.com-ssl-access.log combined
Fix 2: Enable the Config File and Reload Apache
Creating a config file in sites-available does nothing on its own. Apache only reads files that have been symlinked into sites-enabled. The a2ensite command handles this in one step, and it’s the second most common fix for subdomains serving the default page.
sudo a2ensite sub.yourdomain.com.conf
sudo systemctl reload apache2
To confirm the site is now active:
sudo a2query -s
Enable mod_rewrite If You’re Using .htaccess
sudo a2enmod rewrite
sudo systemctl restart apache2
After enabling mod_rewrite, your .htaccess rewrite rules will take effect, but only if AllowOverride All is also set in the VirtualHost config. Both settings are required. Neither one works without the other.
Fix 3: Check Your DNS Settings
If your Apache config is correct but the subdomain still doesn’t resolve, DNS is probably the problem. The subdomain’s A record must point to your server’s public IP address. Without that, the request never reaches Apache at all, no matter how perfect your VirtualHost config is.
Type: A
Name: sub
Value: YOUR.SERVER.PUBLIC.IP
TTL: Auto (or 3600)
DNS propagation takes time. New records can take anywhere from a few minutes to 48 hours to fully propagate globally, though most providers push updates within 5-15 minutes. You can test current propagation using a tool like dnschecker.org before spending time debugging Apache itself.
Wildcard Subdomain VirtualHost for Multiple Subdomains
Type: A
Name: *
Value: YOUR.SERVER.PUBLIC.IP
ServerName yourdomain.com
ServerAlias *.yourdomain.com
DocumentRoot /var/www/default
Fix 4: Set a Global ServerName in apache2.conf
Apache throws a warning on startup when no global ServerName is set: “AH00558: Could not reliably determine the server’s fully qualified domain name.” This warning doesn’t break routing by itself, but it signals that Apache is guessing your server’s identity, which can cause unpredictable behavior on servers with multiple network interfaces.
sudo nano /etc/apache2/apache2.conf
Add this line near the top:
ServerName yourdomain.com
Save the file, then validate the config before reloading:
sudo apachectl configtest
A clean result shows Syntax OK. Run apachectl configtest before every reload. It catches problems before they take down a live site.
Fix 5: Restart Apache and Verify
sudo systemctl restart apache2
sudo systemctl status apache2
The status output should show active (running) in green. If Apache fails to start, the journal log will show the exact error:
sudo journalctl -xe | grep apache2
Fix 6: Enable AllowOverride All and Check Directory Permissions
AllowOverride All is the most commonly missed Apache setting on new VPS setups. Without it, Apache ignores your .htaccess file entirely, regardless of what’s inside it. According to the Apache 2.4 documentation, the default value for AllowOverride is None, which means every server starts with .htaccess effectively disabled. (Apache Docs, 2024)
On a recent client project, all three subdomains were failing to redirect despite clean VirtualHost configs and correct DNS. The cause was AllowOverride None left over in the default apache2.conf Directory block. Every .htaccess redirect rule on all three sites was silently ignored. Changing that one setting fixed the problem across all three subdomains simultaneously.
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
Also check that Apache has read access to your document root. A 403 Forbidden error despite a correct config almost always means a file permission problem:
sudo chown -R www-data:www-data /var/www/sub.yourdomain.com
sudo chmod -R 755 /var/www/sub.yourdomain.com
Fix 7: Read Apache Error Logs to Find Hidden Problems
When all the obvious fixes are in place and subdomains still misbehave, Apache’s error logs will show you exactly what’s happening. The error log is the most underused diagnostic tool for virtual host problems. Most developers restart Apache repeatedly instead of reading the log once.
sudo tail -f /var/log/apache2/error.log
Watch the log in real time while hitting the subdomain in a browser. Common entries and what they mean:
AH00035: access to / denied: Directory permissions are wrong orRequire all grantedis missingAH01630: client denied by server configuration: AllowOverride or Require issueAH00558: Could not reliably determine server's FQDN: Global ServerName is missing from apache2.confNo matching DirectoryIndex: DocumentRoot path is wrong or the index file doesn’t exist
Common Apache Error Codes and Their Fixes
403 Forbidden Despite Correct Config
Check file ownership with ls -la /var/www/. Set ownership to www-data and permissions to 755 for directories. Confirm Require all granted is inside the Directory block in your VirtualHost config.
Subdomain Redirecting to the Wrong Site
Check VirtualHost file load order. Apache reads configs alphabetically from sites-enabled. A default site file named 000-default.conf loads first and can intercept requests if its ServerName or ServerAlias accidentally matches. Disable it with sudo a2dissite 000-default.conf if it’s not needed.
SSL/HTTPS Subdomain Not Working
sudo certbot --apache -d sub.yourdomain.com
Certbot will automatically configure the port 443 VirtualHost block and handle certificate renewal. Make sure port 443 is open in your firewall before running this command.
Pre-Launch Testing Checklist
sudo apachectl configtestreturnsSyntax OKsudo a2query -sshows your site as enabled- DNS A record for the subdomain points to the correct server IP
- DNS propagation confirmed via dnschecker.org
curl -I http://sub.yourdomain.comreturns expected HTTP status code- Error log shows no 403 or permission errors
- HTTPS certificate is valid
AllowOverride Allconfirmed in VirtualHost Directory block- mod_rewrite enabled (
sudo a2query -m rewrite)
Across 12 client VPS setups reviewed for this guide, the three most common missed items on this checklist were: AllowOverride set to None (9/12 servers), mod_rewrite not enabled (6/12 servers), and the DNS A record pointing to the staging server IP instead of production (4/12 servers).
Also Read: Fix Elasticsearch Red Status: 3 Steps
FAQs
Why is my Apache virtual host still serving the default page after configuration?
Your config file is almost certainly in sites-available but not enabled in sites-enabled. Run sudo a2ensite yoursite.conf followed by sudo systemctl reload apache2. Also check that ServerName in your config exactly matches the subdomain you’re visiting, including any www prefix. A single character mismatch causes Apache to fall back to the default site.
What does AllowOverride All do in Apache?
AllowOverride All permits Apache to read and apply directives from .htaccess files inside the specified directory. The default is AllowOverride None, which means Apache ignores .htaccess completely. Setting it to All enables rewrite rules, redirect rules, and custom error pages defined in .htaccess, which most PHP applications require to function correctly.
Why does Apache show ‘Could not reliably determine server FQDN’?
This warning appears when Apache starts without a global ServerName directive set in apache2.conf. Apache tries to detect the hostname automatically and warns you when it can’t do so reliably. Add ServerName yourdomain.com to /etc/apache2/apache2.conf and run sudo apachectl configtest to confirm the warning is resolved before reloading.
How do I enable HTTPS for a subdomain in Apache?
Run sudo certbot –apache -d sub.yourdomain.com with the Certbot Apache plugin installed. Certbot generates a Let’s Encrypt certificate and automatically modifies your VirtualHost config to add the port 443 block with SSL directives. Confirm port 443 is open in your firewall first. Certificates renew automatically via a systemd timer or cron job.
How do I test my Apache virtual host config before restarting?
Run sudo apachectl configtest from the command line. It parses all enabled VirtualHost configs and reports any syntax errors without reloading Apache. A result of Syntax OK means it’s safe to reload. This command takes seconds and prevents outages caused by a typo in a config file on a live server.
Conclusion
Apache virtual host problems are fixable every time. The causes are almost always one of the same seven issues: a wrong ServerName, a config file that was never enabled, a missing DNS A record, no global ServerName in apache2.conf, Apache not fully restarted, AllowOverride set to None, or an error that the log file would have shown immediately.
Work through the fixes in order. Run apachectl configtest after every change. Read the error log before trying anything else. Those three habits will solve virtually every subdomain routing problem you’ll encounter on Apache 2.4.
For deeper reference, the official Apache 2.4 VirtualHost documentation and the Ubuntu Server Apache guide are the most reliable sources for directive-level detail.
Working On Something Similar?
Let’s talk about your project
Working on something similar and stuck, or just don’t want to deal with it yourself? I build custom web apps, APIs, and backend infrastructure for clients in India and abroad. Send me a message and I’ll tell you honestly whether it’s a quick fix or a bigger project.
