Haproxy http/https on single port

I do a lot of web development and prefer spinning up my development app/site/enviroment on one of my home server(s) within the confines of my homenet/homelab (without ever exposing site/app to the internet).

It works just dandy for http, however – im not satisfied with just http (even if this is a dev environment) – and neither should you.

Many critical applications such as financial processing may require https in all environments and there is sometimes just no way around that (and we really shouldn’t try finding these ways – let’s just set it up with https, it’s not that complicated).

Caveats with http/https in development environment

Per official convention port 80 is for http and port 443 is for https. But then you probably have more then 1 application you’re working on that requires https. Like many more.

For that reason I don’t like to ever rely on port 443 ever being available on my dev server (even if it is). I tend to favor running dev applications on a single high port (>1024) that would then accept both http & https.

And guess what – you can configure haproxy to do just that.

Configure haproxy to process http/https on a high non-well known port

I tend to run single haproxy instance per dev site – for separation of concerns.

For example – haproxy configuration below will listen on port 31703 for http and https requests in TCP mode, then will differentiate between http and https and redirect all http requests to https.

    # Settings under global define process-wide security and performance tunings that affect HAProxy at a low level.

    # Max number of connections haproxy will accept
    maxconn 1024

    # Logging to stdout  preferred when running as a container.
    log stdout format raw local0

    # Only TLS version 1.2 and newer is allowed:
    ssl-default-bind-options ssl-min-ver TLSv1.2

    # Defaults here
    # As your configuration grows, using a defaults section will help reduce duplication. 
    # Its settings apply to all of the frontend and backend sections that come after it. 
    # You’re still free to override those settings within the sections that follow.
    # this updates different proxies (frontend, backend, and listen sections) to send messages 
    # to the loggign mechanism/server(s) configured in the global section
    log global

    # Will enable more verbose HTTP logging
    # Enable http logging format to incldue more details logs
    option	httplog

    # Enable HTTP connection closing on the server side but support keep-alive with clients
    # (This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side)
    option  http-server-close
    # option 	httpclose
    # Don't use httpclose and http-server-close, httpclose will disable keepalive on the client side

    # Expect HTTP layer 7, rather than load-balance at layer 4 
    mode    http
    # A connection on which no data has been transferred will not be logged (such as monitor probes)
    option	dontlognull

    # Various response timeouts
    timeout connect 5s
    timeout client 20s
    timeout server 45s

frontend fe-wp-combined
    mode tcp
    bind *:31703
    tcp-request inspect-delay 2s
    tcp-request content accept if HTTP
    tcp-request content accept if { req.ssl_hello_type 1 }
    use_backend be-wp-recirc-http if HTTP
    default_backend be-wp-recirc-https

backend be-wp-recirc-http
    mode tcp
    server loopback-for-http abns@wp-haproxy-http send-proxy-v2

backend be-wp-recirc-https
    mode tcp
    server loopback-for-https abns@wp-haproxy-https send-proxy-v2

frontend fe-wp-https
    mode http
    bind abns@wp-haproxy-https accept-proxy ssl crt /certs/example.com/fullkeychain.pem alpn h2,http/1.1
    # whatever you need todo for HTTPS traffic
    default_backend be-wp-real

frontend fe-wp-http
    mode http
    bind abns@wp-haproxy-http accept-proxy

    # Redirect HTTP to HTTPS
    redirect scheme https code 301 if !{ ssl_fc }

backend be-wp-real
    mode http
    balance roundrobin

    # Enable insertion of the X-Forwarded-For header to requests sent to servers
    option forwardfor

    # Send these request to check health
    option httpchk
    http-check send meth HEAD uri / ver HTTP/1.1 hdr Host haproxy.local

    # remove the Server header from responses
    http-response del-header Server

    server wp-backend1 bytepursuits-varnish:80 check
    http-request set-header x-client-ip %[src]
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }

Now – in example above we are redirecting HTTP to HTTPS:

frontend fe-wp-http
    mode http
    bind abns@wp-haproxy-http accept-proxy

    # Redirect HTTP to HTTPS
    redirect scheme https code 301 if !{ ssl_fc }

However – you can change this block to following if you prefer to serve both HTTP and HTTPS on a a single port (I typically prefer to redirect):

frontend fe-wp-http
    mode http
    bind abns@wp-haproxy-http accept-proxy

    # Backend 
    default_backend be-wp-real

2 thoughts on “Haproxy http/https on single port”

Leave a Comment