Apache VirtualHost Configuration Issue: Port-Based Virtual Hosting Not Working Correctly


2 views

When configuring multiple websites on a single CentOS 7.1 server running Apache, I encountered an unexpected behavior with port-based virtual hosting. While the first site works perfectly on port 80, the second site on port 8080 keeps redirecting to the first site when accessed via domain name, though IP:8080 works correctly.

The current httpd.conf contains these key elements:

Listen 80
Listen 8080

<VirtualHost 62.210.xx.xx:80>
    ServerName first-site.com
    ServerAlias www.first-site.com
    DocumentRoot /var/www/first-site
</VirtualHost>

<VirtualHost 62.210.xx.xx:8080>
    ServerName second-site.com
    ServerAlias www.second-site.com
    DocumentRoot /var/www/second-site
</VirtualHost>

Running apachectl -S reveals important insights:

62.210.xx.xx:8080      m.second-site.com (/etc/httpd/conf/httpd.conf:427)
62.210.xx.xx:80        is a NameVirtualHost
     default server first-site.com (/etc/httpd/conf/httpd.conf:363)
     port 80 namevhost second-site.com (/etc/httpd/conf/httpd.conf:401)

This shows that second-site.com is incorrectly being listed under port 80 name-based virtual hosts.

The fundamental issue lies in how Apache processes VirtualHost directives. When using port-based virtual hosting, you need to ensure:

  1. Each VirtualHost block explicitly declares its port
  2. The ServerName/ServerAlias directives are properly isolated per port
  3. No overlapping configurations exist between ports

Here's the proper way to configure port-based virtual hosting:

Listen 80
Listen 8080

# Default virtual host (optional)
<VirtualHost _default_:80>
    DocumentRoot /var/www/html
</VirtualHost>

# First site - Port 80
<VirtualHost *:80>
    ServerName first-site.com
    ServerAlias www.first-site.com
    DocumentRoot /var/www/first-site
    
    # Additional directives
    ErrorLog /var/log/httpd/first-site_error.log
    CustomLog /var/log/httpd/first-site_access.log combined
</VirtualHost>

# Second site - Port 8080
<VirtualHost *:8080>
    ServerName second-site.com
    ServerAlias www.second-site.com
    DocumentRoot /var/www/second-site
    
    # Additional directives
    ErrorLog /var/log/httpd/second-site_error.log
    CustomLog /var/log/httpd/second-site_access.log combined
</VirtualHost>
  • Use *:port instead of specific IP addresses unless absolutely necessary
  • Ensure all relevant ports are declared in Listen directives
  • Maintain separate log files for each virtual host
  • Remove all NameVirtualHost directives (deprecated in Apache 2.4)

After making configuration changes:

  1. Run apachectl configtest to check syntax
  2. Restart Apache: systemctl restart httpd
  3. Verify with curl -I http://second-site.com:8080
  4. Check access/error logs for each site

If issues persist:

1. Check SELinux status: sestatus
2. Verify firewall rules: firewall-cmd --list-ports
3. Test with IP address first: curl http://62.210.xx.xx:8080
4. Examine detailed debug logs: httpd -X (debug mode)

For production environments with multiple port-based virtual hosts:

  • Consider implementing a reverse proxy (Nginx, HAProxy)
  • Evaluate if port-based hosting is truly necessary vs. name-based
  • Monitor connection limits and resource usage per port

When configuring multiple websites on a CentOS 7.1 server, I encountered a puzzling behavior with Apache's VirtualHost directives. While accessing http://62.210.xx.xx:8080/ correctly served the second site, domain-based access on port 8080 kept redirecting to the first site.

Here's the relevant httpd.conf excerpt:

Listen 80
Listen 8080

# First site configuration

    ServerName first-site.com
    ServerAlias www.first-site.com
    DocumentRoot /var/www/first-site


# Second site configuration

    ServerName second-site.com
    ServerAlias www.second-site.com
    DocumentRoot /var/www/second-site

Several important findings from debug commands:

netstat -tulpn | grep httpd
tcp6       0      0 :::80                   :::*                    LISTEN      25253/httpd
tcp6       0      0 :::8080                 :::*                    LISTEN      25253/httpd

The output of apachectl -S revealed that while port 8080 was properly assigned to m.second-site.com, all other domains were somehow bound to port 80 name-based virtual hosts.

The issue stems from how Apache processes VirtualHost directives when both IP+port and name-based virtual hosts are mixed. The critical mistake was including the IP address in the VirtualHost directive while also using ServerName.

Here's the corrected configuration:

Listen 80
Listen 8080

# Default catch-all (should point to empty directory)

    DocumentRoot /var/www/default


# First site - port 80

    ServerName first-site.com
    ServerAlias www.first-site.com
    DocumentRoot /var/www/first-site


# Second site - port 8080

    ServerName second-site.com
    ServerAlias www.second-site.com
    DocumentRoot /var/www/second-site


# Additional recommendation for subdomains

    ServerName image.first-site.com
    DocumentRoot /var/www/first-site/images


# Important global setting
ServerName main-server.com

After making these changes:

  1. Run apachectl configtest to check syntax
  2. Restart Apache: systemctl restart httpd
  3. Verify with curl -v http://second-site.com:8080
  4. Check all name resolutions in /etc/hosts

For production environments:

  • Consider using separate IP addresses for critical sites
  • Implement proper firewalling for non-standard ports
  • Set up SELinux contexts correctly for non-default document roots
  • Configure proper DNS records instead of relying on /etc/hosts

If issues persist:

# Check active configuration
httpd -S

# Verify port listening
ss -tulnp | grep httpd

# Examine request processing
tail -f /var/log/httpd/access_log
tail -f /var/log/httpd/error_log