I think you want ACL-driven "stats scope" statements, which don't
exist to the best of my knowledge.
In your case, rather than open a bunch of different ports, I'd give
people different FQDNs to hit, and point a wildcard DNS record at a
single port 80. (Well, a :443 with TLS, if I were doing it, but you're
using :80 in your example)
DNS: *.haproxy-stats.example.com -> IP_ADDRESS
--------------------
frontend stats
bind IP_ADDRESS:80
mode http
option httplog
compression algo gzip
use_backend stats-foo if { hdr(host) foo.haproxy-stats.example.com }
use_backend stats-bar if { hdr(host) bar.haproxy-stats.example.com }
default_backend always_returns_400
defaults for-stats-backends-in-effect-until-next-defaults-section
mode http
option httplog
stats enable
stats uri /haproxystats
stats refresh 60s
stats show-legends
stats scope .
backend stats-foo
stats scope foo-frontend-1
stats scope foo-backend-2
stats auth user1:password1
backend stats-bar
stats scope bar-frontend-1
stats scope bar-frontend-2
stats scope bar-backend-3
stats auth user2:password2
defaults reset-defaults-disable-stats
<rest of config>
--------------------
(typed but not tested ...)
Yes, this isn't too different from what you proposed :-) Note the use
of the multiple "defaults" section to move as much common config out
of the individual backends.
You might also find userlists handy:
https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#3.4
They'll let you make the "stats auth" definitions a fair bit cleaner,
moving the user/passwords lists elsewhere in your configuration file.
HTH,
J