Convert working nginx to haproxy 1.6


#1

I have the following nginx config that works perfectly fine and I need to convert it to haproxy config:

map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}

upstream app {
server localhost:5000;
}

upstream websocket {
server localhost:5000;
}

server {
listen 80 default_server;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
ssl_certificate /etc/nginx/ssl/domain.com/2018/ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/domain.com/2018/domain.key;
ssl_dhparam /etc/nginx/ssl/domain.com/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
ssl_session_cache shared:TLS:2m;
ssl_stapling on;
ssl_stapling_verify on;

server_name domain.com;
root /home/deploy/rails/appUI/current/public/;
try_files $uri/index.html $uri @app;
expires $expires;

location /cable {
    proxy_pass http://websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection Upgrade;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-Proto https;
	proxy_redirect off;
    }

location @app {
    proxy_pass http://app;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    }

client_max_body_size 4G;

}

As you can see there is the application (app) and a websocket both running on the same port. The above works perfectly fine in nginx. I have tried to build an haproxy config but the app breaks as follows:

global
log 127.0.0.1 local1 notice
maxconn 2000
user haproxy
group haproxy
spread-checks 5
stats socket /var/run/haproxy.sock mode 0600 level admin
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers AES128+EECDH:AES128+EDH
ssl-default-bind-options no-sslv3 no-tls-tickets force-tlsv12

defaults http_proxies
mode http
timeout http-request 5s
option http-server-close
option forwardfor
option redispatch
option allbackups
option httplog
option log-separate-errors
log global
retries 3
cookie SERVERID insert nocache
maxconn 20000
timeout connect 5s
timeout client 1150s
timeout server 1180s
default-server inter 15s fastinter 10s downinter 20s
errorfile 503 /etc/haproxy/errors/503.http

frontend HTTP
bind *:80
redirect scheme https code 301 if { hdr(Host) -i domain.com } !{ ssl_fc }
default_backend webservers

frontend HTTPS
bind *:443 ssl crt /etc/nginx/ssl/domain.com/2018/domain.pem
http-response set-header Cache-Control no-cache,\ max-age=0
acl is_websocket hdr(Upgrade) -i WebSocket
acl is_websocket_server hdr_end(host) -i domain.com
use_backend websock if is_websocket is_websocket_server
default_backend webservers

backend webservers
timeout server 30s
option httpchk HEAD / HTTP/1.1\r\nHost:\ domain.com
server server1 10.131.74.88:5000 check

backend websock
timeout server 30s
option httpchk HEAD / HTTP/1.1\r\nHost:\ domain.com
server server1 10.131.74.88:5000 check

With the haproxy config it looks like ‘broken CSS’. Could anyone pls help me.
Regards


#2

Your httpchk could be wrong for websockets, and you should expect a 101, not a 200 (default).

Have a look at this: https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy/