haproxy how to process /.well-known before any redirects?

Solution 1:

I'm afraid it is not possible to process use_backend before redirect statements. I believe HAPROXY evaluates redirects after it receives the entire HTTP request from the client and chooses a backend only after it discovers that the client will not be redirected.

You do not need to modify every redirect rule in order to add additional exclusion paths. You can use an unique ACL instead. For example, this configuration snippet would work:

acl noredirects path -m reg ^/.well-known/acme-challenge/
acl noredirects path -m beg /static/ /images/ /css/
acl noredirects req.hdr(host) -i httpsite.example.com
redirect prefix https://a.test if ! noredirects { req.hdr(host) -m reg ^a\.test(?::.*)?$ }
use_backend certbot_80 if noredirects

You can also process redirections on a backend. For example:

frontend http *:80
    acl certbot  path -m beg /.well-known/acme-challenge/
    acl httpsite path -m beg /public/
    use_backend certbot_80 if certbot
    use_backend httpbackend if httpsite
    default_backend redirector

backend redirector
    redirect prefix https://a.test if { req.hdr(host) -m reg ^a\.test(?::.*)?$ }
    redirect prefix https://b.test if { req.hdr(host) -m reg ^b\.test(?::.*)?$ }

backend httpbackend
    server httpserver httpserver.example.com:80

Solution 2:

With a modern HAProxy (tested with 2.2 LTS), the syntax is intuitive:

frontend http *:80
    acl path_certbot path_beg /.well-known/acme-challenge/
    http-request redirect scheme https unless { ssl_fc } || path_certbot
    use_backend certbot_80 if path_certbot
    default_backend std_backend

backend certbot
    server certbot localhost:80

backend std_backend
  • the first line creates a named condition (path_certbot) that is true it the url starts with /.well-known/acme-challenge/
  • the second line redirects (with a HTTP/302) all the incoming requests to https, unless the request was already https, or the path_certbot condition is activated