When configuring Apache to serve both HTTP (port 80) and HTTPS (port 443) under the same VirtualHost, we encounter a fundamental protocol conflict. The SSL Engine directives (SSLEngine on, certificate paths) cause errors when processing plain HTTP requests. Here's why this happens:
# This causes port 80 to fail
SSLEngine on
SSLCertificateFile /path/to/cert.crt
SSLCertificateKeyFile /path/to/key.key
The correct approach involves creating separate VirtualHost blocks for each protocol while maintaining the same DocumentRoot and other configurations:
ServerName mysite.co.uk
DocumentRoot /var/www/mysite/public
# Other HTTP-only configurations
# Redirect specific paths to HTTPS
Redirect permanent https://mysite.co.uk/secure-area
ServerName mysite.co.uk
DocumentRoot /var/www/mysite/public
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/apache2/crts/mysite.crt
SSLCertificateKeyFile /etc/apache2/crts/mysite.key
SSLCertificateChainFile /etc/apache2/crts/DigiCertCA.crt
# HTTPS-only configurations
For a site that needs partial SSL, consider these implementation patterns:
# Option 1: Directory-based SSL
SSLEngine on
# ... SSL config ...
SSLRequireSSL
# Option 2: Environment variable detection
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure-area
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
When implementing dual-port serving, remember these optimization tips:
- Use KeepAlive carefully - different timeouts for HTTP/HTTPS
- Configure separate logging for each protocol
- Consider HTTP/2 for HTTPS connections
# HTTP/2 configuration example
Protocols h2 http/1.1
H2Direct on
Watch for these frequent problems:
- Certificate path permissions (Apache user needs read access)
- Port conflicts (verify nothing else is using 80/443)
- Mixed content warnings (ensure assets load properly)
# Diagnostic commands
sudo apachectl configtest
sudo netstat -tulnp | grep ':443'
sudo tail -f /var/log/apache2/error.log
When configuring Apache to handle both HTTP and HTTPS traffic on standard ports (80/443) within the same VirtualHost, developers often encounter SSL engine conflicts. The fundamental issue arises because SSL directives automatically configure the host for HTTPS-only operation, breaking HTTP access.
The proper approach requires creating separate VirtualHost declarations while maintaining configuration DRY principles:
# Base configuration for both protocols
Define SHARED_CONFIG {
ServerAdmin webmaster@localhost
ServerName mysite.co.uk
DocumentRoot /var/www/mysite/public
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
}
# HTTP VirtualHost
Use SHARED_CONFIG
# Non-SSL specific directives
# HTTPS VirtualHost
Use SHARED_CONFIG
SSLEngine on
SSLCertificateFile /etc/apache2/crts/mysite.crt
SSLCertificateKeyFile /etc/apache2/crts/mysite.key
SSLCertificateChainFile /etc/apache2/crts/DigiCertCA.crt
# Modern SSL configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
For complex scenarios requiring protocol-specific logic:
# Conditional content based on protocol
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^/secure-path(.*) https://%{HTTP_HOST}/secure-path$1 [R=301,L]
RewriteCond %{HTTPS} on
RewriteRule ^/non-secure-path(.*) http://%{HTTP_HOST}/non-secure-path$1 [R=301,L]
When serving mixed content:
- Enable HTTP/2 for HTTPS connections:
Protocols h2 http/1.1
- Implement HSTS carefully:
Header always set Strict-Transport-Security "max-age=63072000"
- Use separate log files for protocol analysis
# Verify configuration
apachectl configtest
# Check listening ports
ss -tulnp | grep apache
# Debug SSL handshake
openssl s_client -connect mysite.co.uk:443 -servername mysite.co.uk -status