This guide walks you through setting up Nginx and HAProxy as reverse proxies for WebSocket proxying, including handling both ws and wss connections. The example will use the GoLang WebSocket implementation.
Prerequisites:
To follow this guide, you’ll need:
- A Linux server with sudo privileges
- Nginx and HAProxy installed on the server
- Go installed on the server
Part I: Setting up the Go WebSocket Server
Let’s start by creating a simple WebSocket server in Go. This example uses the gorilla/websocket package, which you can install with go get.
package main
import (
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func handleConnections(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a websocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println(err)
return
}
defer ws.Close()
// Simple echo back
for {
// Read in a new message as JSON and map it to a Message object
var msg string
err := ws.ReadJSON(&msg)
if err != nil {
fmt.Println(err)
break
}
fmt.Println("Received:", msg)
err = ws.WriteJSON("Echo: " + msg)
if err != nil {
fmt.Println(err)
break
}
}
}
func main() {
http.HandleFunc("/ws", handleConnections)
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("Failed to start server:", err)
return
}
}
This code creates a simple WebSocket server that echoes any message it receives. Save this file as main.go.
To start your WebSocket server, use the go run command:
go run main.go
Your server is now listening on port 8080. Test it using a WebSocket client by connecting to ws://your-server-ip:8080/ws.
Part II: Setting up Nginx
First, we will configure Nginx as a reverse proxy for the WebSocket connections.
Update the Nginx configuration file, usually found at /etc/nginx/nginx.conf or /etc/nginx/sites-available/default, and add a new server block for your WebSocket server:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
}
}
}
This configuration tells Nginx to pass any requests at http://your-server-ip/ws to your WebSocket server at localhost:8080. The Upgrade and Connection headers allow the WebSocket protocol to function correctly. The proxy_read_timeout is set to a day to prevent Nginx from closing the connection prematurely.
After updating the configuration, verify it with the following:
sudo nginx -t
If the configuration is correct, reload Nginx:
sudo systemctl reload nginx
You can now connect to your WebSocket server through Nginx at ws://your-server-ip/ws.
Part III: Enabling SSL for wss connections
You must enable SSL on your server for wss (WebSocket Secure) connections. You can get a free SSL certificate from Let’s Encrypt. Install the Certbot software and get a certificate:
sudo apt-get install certbot python-certbot-nginx
sudo certbot --nginx -d your-domain.com
This will automatically update your Nginx configuration to handle HTTPS connections and set up a cron job to renew the certificate automatically.
After installing the SSL certificate, you can connect securely to your WebSocket server at wss://your-server-ip/ws.
Part IV: Setting up HAProxy
HAProxy can also act as a reverse proxy for WebSocket connections. This can be useful for load balancing, failover, and other advanced scenarios.
To use HAProxy, first, install it:
sudo apt-get install haproxy
Update the HAProxy configuration file, usually found at /etc/haproxy/haproxy.cfg, and add a new frontend and backend for your WebSocket server:
frontend http_front
bind *:80
default_backend ws_back
backend ws_back
balance roundrobin
server ws1 localhost:8080 check
This configuration tells HAProxy to listen on port 80 and to balance the load between the servers listed in the ws_back backend. In this case, there’s only one server: localhost:8080.
After updating the configuration, check it with the following command:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
If the configuration is correct, restart HAProxy:
sudo systemctl restart haproxy
You can now connect to your WebSocket server through HAProxy at ws://your-server-ip/ws.
Part V: Enabling SSL for HAProxy
Like with Nginx, you must enable SSL on HAProxy to handle wss connections. You can reuse the same certificate that you got for Nginx. Add a new bind directive in your frontend part with the path to the certificate and private key:
frontend http_front
bind *:80
bind *:443 ssl crt /etc/letsencrypt/live/your-domain.com/fullchain.pem privkey /etc/letsencrypt/live/your-domain.com/privkey.pem
default_backend ws_back
After updating the configuration, check it and restart HAProxy as before.
You can now connect securely to your WebSocket server through HAProxy at wss://your-server-ip/ws.
Conclusion
This guide showed you how to set up Nginx and HAProxy as reverse proxies for WebSocket proxying and how to enable both ws and wss connections. This setup can help serve WebSocket connections from a Go server, with the added benefits of SSL security and load balancing.