When running multiple services on non-standard ports (like 9090-9094), accessing them through standard HTTP/HTTPS ports (80/443) with clean URLs becomes essential for production environments. The key is to use Apache's reverse proxy capabilities without exposing the actual ports externally.
For this setup, you'll need to ensure these modules are enabled:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_connect
sudo a2enmod ssl # For HTTPS services
Here's a production-ready configuration for both HTTP and HTTPS services:
ServerName mydomain.com
ServerAlias www.mydomain.com
# App1 (HTTPS backend)
ProxyPass /app1 https://localhost:9090/
ProxyPassReverse /app1 https://localhost:9090/
ProxyPreserveHost On
# App2 (HTTPS backend)
ProxyPass /app2 https://localhost:9091/
ProxyPassReverse /app2 https://localhost:9091/
# App3 (HTTP backend)
ProxyPass /app3 http://localhost:9092/
ProxyPassReverse /app3 http://localhost:9092/
# Security headers
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
ErrorLog ${APACHE_LOG_DIR}/proxy-error.log
CustomLog ${APACHE_LOG_DIR}/proxy-access.log combined
If any of your services use WebSockets, add these directives:
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /app1/(.*) wss://localhost:9090/$1 [P,L]
For SSL backends, you might need to add SSL verification skipping (only for development):
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
If you encounter 502 errors, check these:
- Verify the backend service is running
- Check SELinux/apparmor permissions
- Test connectivity with
curl -v http://localhost:9090
- Review Apache error logs
For production environments, consider adding these proxy parameters:
ProxyTimeout 300
ProxyBadHeader Ignore
ProxyIOBufferSize 8192
Many developers running local services on non-standard ports face a common challenge: exposing these services through clean URLs without port numbers. While services might be accessible via https://domain.com:9090
, we want them available at https://domain.com/appName
for better usability.
The most elegant solution is using Apache's ProxyPass
directive. This creates reverse proxy rules that map paths to backend services. Here's how to implement it:
ServerName www.mydomain.com
# Enable proxy modules (if not already loaded)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
# Basic security settings
ProxyRequests Off
Require all granted
# SSL service mapping
ProxyPass /app1 https://localhost:9090/
ProxyPassReverse /app1 https://localhost:9090/
# Non-SSL service mapping
ProxyPass /app3 http://localhost:9092/
ProxyPassReverse /app3 http://localhost:9092/
ServerName www.mydomain.com
SSLEngine on
# Your SSL certificate configuration here
# SSL service mapping
ProxyPass /app2 https://localhost:9091/
ProxyPassReverse /app2 https://localhost:9091/
1. Ensure required Apache modules are enabled:
sudo a2enmod proxy proxy_http proxy_connect
sudo systemctl restart apache2
2. For SSL services, the backend connection will maintain encryption even if your frontend connection is non-SSL.
For more complex scenarios, consider these additional parameters:
# With timeout settings
ProxyPass /app1 https://localhost:9090/ timeout=600 keepalive=On
# With path preservation
ProxyPass /app1/ https://localhost:9090/
ProxyPassReverse /app1/ https://localhost:9090/
# With connection pooling
ProxySet connectiontimeout=5 timeout=30
If you encounter 502 errors, check:
- The backend service is running
- SELinux/apparmor isn't blocking connections
- Firewall allows localhost connections between ports
- Apache error logs (
/var/log/apache2/error.log
)
Example debug command:
curl -v http://localhost:9090