When working with WebSocket connections behind Apache2, the main issue stems from how mod_proxy handles HTTP upgrade requests. By default, Apache2 treats WebSocket connections as regular HTTP requests, stripping crucial headers like Upgrade
and Connection
that are essential for WebSocket protocol negotiation.
You'll need to ensure these modules are enabled:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
sudo systemctl restart apache2
Method 1: Using ProxyPass with wss://
For secure WebSocket connections:
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule /(.*) ws://backend-server:8080/$1 [P,L]
ProxyPass / ws://backend-server:8080/
ProxyPassReverse / ws://backend-server:8080/
ProxyPass /wss/ ws://backend-server:8080/
ProxyPassReverse /wss/ ws://backend-server:8080/
</VirtualHost>
Method 2: Path-based WebSocket Routing
For applications where WebSocket endpoints are under specific paths:
<Location "/ws/">
ProxyPass ws://backend-server:8080/ws/
ProxyPassReverse ws://backend-server:8080/ws/
ProxyPassReverseCookieDomain backend-server yourdomain.com
</Location>
After applying changes, test with these commands:
apachectl configtest
systemctl reload apache2
- Connection drops after 60 seconds: Add
ProxyTimeout 3600
to your config - Headers not being forwarded: Use
ProxySet
to preserve headers - Mixed content warnings: Ensure consistent http/https schemes
For complex setups requiring header manipulation:
<Location "/custom-ws/">
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set Origin "https://yourdomain.com"
ProxyPass ws://backend-server:8080/custom-ws/
ProxyPassReverse ws://backend-server:8080/custom-ws/
</Location>
When trying to proxy WebSocket connections through Apache2, many developers encounter a frustrating issue: Apache's mod_proxy
treats WebSocket traffic as regular HTTP, stripping away essential headers like Upgrade
and Connection
. This breaks the WebSocket handshake protocol.
Ensure these modules are enabled:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo systemctl restart apache2
Here's a complete VirtualHost configuration for WebSocket proxying:
<VirtualHost *:80>
ServerName yourdomain.com
# WebSocket configuration
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule /(.*) "ws://backend-server:8080/$1" [P,L]
# Regular HTTP proxy
ProxyPass / http://backend-server:8080/
ProxyPassReverse / http://backend-server:8080/
# WebSocket-specific proxy
ProxyPass /ws/ ws://backend-server:8080/ws/
ProxyPassReverse /ws/ ws://backend-server:8080/ws/
</VirtualHost>
- The
ProxyPass
directive withws://
protocol is crucial for WebSocket support - Apache 2.4.47+ is recommended as it has improved WebSocket support
- Timeout settings may need adjustment:
ProxyTimeout 3600
If connections fail, check these common issues:
- Verify headers are being passed through with
curl -v
- Check Apache error logs:
tail -f /var/log/apache2/error.log
- Test backend WebSocket server directly to isolate the issue
For complex setups, consider:
# Using LocationMatch for specific paths
<LocationMatch "/ws/.+">
ProxyPass ws://backend-server:8080/ws/
ProxyPassReverse ws://backend-server:8080/ws/
</LocationMatch>
You might also want to add these headers for better compatibility:
# Add these inside your VirtualHost or Location directive
RequestHeader set Upgrade "websocket"
RequestHeader set Connection "Upgrade"