How to Combine HTTP and HTTPS in a Single Apache VirtualHost Configuration Without Duplication


4 views

Managing duplicate VirtualHost configurations in Apache for HTTP and HTTPS can become messy, especially when dealing with complex setups. The ideal solution would allow maintaining a single configuration block while handling both protocols appropriately.

Apache provides several approaches to handle this scenario without configuration duplication:


    ServerName example.com
    DocumentRoot /var/www/html
    
    
        SSLEngine on
        SSLCertificateFile /path/to/cert.pem
        SSLCertificateKeyFile /path/to/key.pem
        SSLCertificateChainFile /path/to/chain.pem
    
    
    # Common configuration for both protocols
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

For more complex scenarios where complete separation is preferred, you can use includes:

# Main configuration file

    ServerName example.com
    Include /etc/apache2/sites-available/common.conf
    
    
        Include /etc/apache2/sites-available/ssl.conf
    
  • Test configuration with apachectl configtest before reloading
  • HTTP/2 requires explicit SSL configuration
  • Some rewrite rules may need protocol-specific conditions
  • Consider HSTS headers for HTTPS-only sites

Here's a complete production-ready example with redirects:


    ServerName example.com
    ServerAlias www.example.com
    
    DocumentRoot /var/www/example
    
    # SSL Configuration
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
        Header always set Strict-Transport-Security "max-age=63072000"
    
    
    # Force HTTPS redirect
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    # Common configuration
    
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    

Managing separate VirtualHost configurations for HTTP and HTTPS in Apache can become messy, especially when dealing with complex setups. Many administrators find themselves maintaining nearly identical configurations in two separate blocks, which violates the DRY (Don't Repeat Yourself) principle and increases the chances of configuration drift.

The most elegant solution is to use Apache's IfDefine directive combined with the SSL variable that Apache sets automatically when SSL is enabled:


    ServerName example.com
    DocumentRoot /var/www/html
    
    
        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/example.com.crt
        SSLCertificateKeyFile /etc/ssl/private/example.com.key
        SSLCertificateChainFile /etc/ssl/certs/example.com.ca-bundle
    
    
    # Common configuration for both protocols
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    # Additional directives...

Another approach is to check for the SSL module's presence:


    ServerName example.com
    
    
        SSLEngine on
        # SSL configuration here
    
    
    # Shared configuration

When using this approach:

  • Make sure to include both ports (*:80 *:443) in the VirtualHost declaration
  • All non-SSL directives will apply to both HTTP and HTTPS connections
  • For more granular control, you might still need separate VirtualHosts
  • Test your configuration with apachectl configtest before reloading

If you need to redirect HTTP to HTTPS while keeping a single VirtualHost:


    ServerName example.com
    
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    
        SSLEngine on
        # SSL configuration
    

While this unified approach reduces configuration complexity, be aware that:

  • All requests (HTTP and HTTPS) will go through the same VirtualHost processing
  • Conditional checks add minimal overhead
  • For high-traffic sites, separate VirtualHosts might be preferable