Echo Reverse Proxy Setup
Introduction
When deploying Echo web applications to production environments, you'll often need to set up a reverse proxy. A reverse proxy sits in front of your Echo application server and forwards client requests to your application. This setup provides several benefits:
- Security: The reverse proxy acts as a shield for your application server
- Load balancing: Distribute traffic across multiple application instances
- SSL/TLS termination: Handle HTTPS connections at the proxy level
- Caching: Improve performance by caching responses
- Path-based routing: Route requests to different services based on URL paths
This guide will walk you through setting up various reverse proxy configurations for your Echo application.
Prerequisites
Before we begin, ensure you have:
- A working Echo application
- Access to a server where you'll deploy your application
- Basic understanding of networking concepts
- Administrative privileges to configure the proxy server
Common Reverse Proxy Options
Nginx
Nginx is one of the most popular reverse proxy servers due to its performance and flexibility.
Basic Nginx Configuration
Here's a simple Nginx configuration to proxy requests to your Echo application:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:1323;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
In this configuration:
proxy_pass
specifies the address of your Echo application (assuming it runs on port 1323)- The
proxy_set_header
directives ensure that important HTTP headers are forwarded to your application - WebSocket connections are properly handled with the
Upgrade
andConnection
headers
Enabling HTTPS
To add HTTPS support with Nginx:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:1323;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Apache
Apache HTTP Server is another popular option for setting up a reverse proxy.
Basic Apache Configuration
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyPass / http://localhost:1323/
ProxyPassReverse / http://localhost:1323/
# Forward headers
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "80"
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Enabling HTTPS with Apache
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
ProxyPreserveHost On
ProxyPass / http://localhost:1323/
ProxyPassReverse / http://localhost:1323/
# Forward headers
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Traefik
Traefik is a modern HTTP reverse proxy and load balancer designed for microservices.
Basic Traefik Configuration (Docker Compose)
version: '3'
services:
traefik:
image: traefik:v2.5
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
echo-app:
image: your-echo-app-image
labels:
- "traefik.enable=true"
- "traefik.http.routers.echo.rule=Host(`example.com`)"
- "traefik.http.routers.echo.entrypoints=web"
- "traefik.http.services.echo.loadbalancer.server.port=1323"
Configuring Your Echo Application for Proxy Awareness
When running behind a reverse proxy, your Echo application needs to be aware of it to properly handle client information. Here's how to configure your Echo application:
package main
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
// Trust X-Forwarded-* headers
e.IPExtractor = echo.ExtractIPFromXFFHeader()
e.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
Skipper: middleware.DefaultSkipper,
}))
// Your routes and handlers
e.GET("/", func(c echo.Context) error {
// The client's real IP will be available through c.RealIP()
return c.String(200, "Hello from Echo behind a proxy!")
})
e.Logger.Fatal(e.Start(":1323"))
}
The middleware.Proxy
middleware helps your Echo application properly interpret forwarded headers such as X-Forwarded-For
, X-Forwarded-Proto
, etc.
Load Balancing Multiple Echo Instances
For high-traffic applications, you might want to run multiple instances of your Echo application and distribute the load between them.
Nginx Load Balancing
upstream echo_backend {
server localhost:1323;
server localhost:1324;
server localhost:1325;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://echo_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Handling WebSockets
Echo supports WebSocket connections, and your reverse proxy needs to be configured to forward these connections properly.
WebSocket Configuration for Nginx
server {
listen 80;
server_name example.com;
location /ws {
proxy_pass http://localhost:1323;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400; # Enable longer connections for WebSockets
}
location / {
# Regular HTTP configuration as shown earlier
proxy_pass http://localhost:1323;
# Other proxy settings...
}
}
Testing Your Reverse Proxy Setup
After setting up your reverse proxy, it's important to test that everything is working correctly:
- HTTP/HTTPS access: Verify that you can access your application through the proxy
- Header forwarding: Check that headers like
X-Forwarded-For
are being passed correctly - WebSocket connections: Test that WebSocket connections work if your app uses them
- Path-based routing: If you have multiple services, verify that routing works correctly
You can use tools like curl
to test your setup:
# Test regular HTTP access
curl -v http://example.com/
# Test if X-Forwarded headers are passed (check your application logs)
curl -v http://example.com/headers
# For WebSocket testing, you can use a tool like websocat
websocat ws://example.com/ws
Common Issues and Troubleshooting
Headers Not Being Forwarded
If your Echo application isn't receiving the correct client IP:
- Verify that your proxy configuration includes the
X-Forwarded-For
header - Ensure Echo is configured to trust proxy headers (using the
middleware.Proxy
middleware)
Connection Timeouts
For long-running connections like WebSockets:
- Increase the
proxy_read_timeout
in Nginx - For Apache, adjust
ProxyTimeout
directive
SSL/TLS Certificate Issues
If you're having TLS problems:
- Verify certificate paths in your proxy configuration
- Check certificate validity with
openssl verify -CAfile /path/to/ca.pem /path/to/cert.pem
- Ensure certificate permissions are correct
Real-World Example: Complete Setup with Docker Compose
Here's a complete example of an Echo application with Nginx reverse proxy using Docker Compose:
version: '3'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./certs:/etc/nginx/certs
depends_on:
- echo-app
echo-app:
build: ./echo-app
expose:
- "1323"
environment:
- PORT=1323
With a corresponding nginx.conf
:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
location / {
proxy_pass http://echo-app:1323;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Summary
Setting up a reverse proxy for your Echo application is an important step in deploying to production. In this guide, we've covered:
- Basic reverse proxy concepts and benefits
- Configuration examples for Nginx, Apache, and Traefik
- How to enable HTTPS
- Load balancing multiple Echo instances
- WebSocket support
- Troubleshooting common issues
By following these practices, you can create a secure, scalable, and robust deployment architecture for your Echo applications.
Additional Resources
- Official Echo Documentation
- Nginx Documentation
- Apache HTTP Server Documentation
- Traefik Documentation
- Let's Encrypt - For free SSL certificates
Exercises
- Set up a basic Echo application and configure Nginx as a reverse proxy for it.
- Implement HTTPS using a self-signed certificate or Let's Encrypt.
- Create a Docker Compose configuration that runs multiple instances of your Echo application with load balancing.
- Implement a WebSocket endpoint in your Echo application and verify it works through your reverse proxy.
- Configure path-based routing to serve both an Echo API and a static website from the same domain.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)