haproxyconf-2022/etc/haproxy/haproxy.cfg

289 lines
11 KiB
INI

# Inspired by https://gist.github.com/haproxytechblog/dc5c3b5e2801d36b79e00f07b2309c14
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
node my-hostname
server-state-file /var/lib/haproxy/server_state.txt
maxconn 60000
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# generated 2021-05-03, Mozilla Guideline v5.6, HAProxy 2.2, OpenSSL 1.1.1d, intermediate configuration
# https://ssl-config.mozilla.org/#server=haproxy&version=2.2&config=intermediate&openssl=1.1.1d&guideline=5.6
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/ssl/dhparam-haproxy
ssl-dh-param-file /etc/ssl/dhparam-haproxy
defaults
log global
mode http
option httplog
option dontlognull
option log-separate-errors
option httpclose
option abortonclose
option http-server-close
option redispatch
timeout connect 5s
timeout client 300s
timeout server 300s
timeout queue 60s
timeout http-request 15s
load-server-state-from-file global
maxconn 50000
# Default options for "server" directive in backends
default-server maxconn 2000 on-error fail-check slowstart 60s inter 5s fastinter 1s downinter 1s weight 100 fall 3 rise 2
http-errors boost-default-errors
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
resolvers local_dns
parse-resolv-conf
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 30s
hold refused 30s
hold nx 30s
hold timeout 30s
hold valid 10s
hold obsolete 30s
userlist example-dev_team
user dev1 insecure-password ItyecpotHeHagAcukfoGrynPeawdEyb2
user dev2 insecure-password 8owEkecharhiedyarOwcebcheimeObBa
listen stats
mode http
# Bind with SSL externaly
bind *:8080 ssl crt /etc/haproxy/ssl/
# Bind without SSL locally
bind 127.0.0.1:8081
acl stats_access_ips src -f /etc/haproxy/stats_access_ips
acl stats_admin_ips src -f /etc/haproxy/stats_admin_ips
stats enable
stats refresh 10s
stats uri /
stats show-legends
stats show-node
stats admin if stats_admin_ips
stats http-request deny if !stats_access_ips
http-request set-log-level silent
frontend external
bind 0.0.0.0:80,:::80
bind 0.0.0.0:443,:::443 ssl strict-sni alpn h2,http/1.1 crt /etc/haproxy/ssl
option forwardfor
errorfiles boost-default-errors
# Reject the request at the TCP level if source is in the denylist
tcp-request connection reject if { src -f /etc/haproxy/deny_ips }
# Remove a possible x-forwarded-for header already present
http-request del-header x-forwarded-for if { req.hdr(x-forwarded-for) -m found }
# Store the Host header in lowercase, to speedup ACL later
http-request set-var(req.hdr_host) req.hdr(host),lower
# Capture host header in logs
http-request capture var(req.hdr_host) len 32
# Is the request coming for the server itself (stats…)
acl self var(req.hdr_host) -m str my-hostname my-hostname.domain.tld
acl munin var(req.hdr_host) -m str munin
# List of IP that will not go the maintenance backend
acl maintenance_ips src -f /etc/haproxy/maintenance_ips
# Detect Let's Encrypt challenge requests
acl letsencrypt path_dir -i /.well-known/acme-challenge
# Determine if the request is routable to Varnish
acl varnish_available nbsrv(varnish) gt 0
acl varnish_detected res.hdr(X-Varnish) -m found
acl varnish_http_verb method GET HEAD PURGE
http-request set-header X-Forwarded-Port %[dst_port]
# Set header if not coming from Varnish
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
http-request set-header X-Forwarded-Proto https if { ssl_fc }
# BEGIN HTTP tagging
acl xid_req_exists req.hdr(x-request-id) -m found
http-request set-var(txn.xid) req.hdr(x-request-id) if xid_req_exists
http-request set-var(txn.xid) uuid() unless xid_req_exists
http-request capture var(txn.xid) len 64
http-request set-header x-request-id %[var(txn.xid)] unless xid_req_exists
acl xid_res_exists res.hdr(x-request-id) -m found
http-after-response set-header x-request-id %[var(txn.xid)] unless xid_res_exists
http-request set-header x-boost-step1 "haproxy-external"
http-response set-header x-boost-step1 "haproxy-external; ssl-frontend" if { ssl_fc }
http-response set-header x-boost-step1 "haproxy-external; no-ssl-frontend" if !{ ssl_fc }
http-response set-header x-boost-server my-hostname
# Debug: Enable this to add a full log line in the response
### http-response add-header X-Haproxy-Log-external "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
# END HTTP tagging
# Global maintenance mode (### -> uncomment)
### use_backend maintenance unless maintenance_ips
use_backend local if self
use_backend local if munin
# "letsencrypt" must stay after "local"
use_backend letsencrypt if letsencrypt
# BEGIN frontend_external section for site 'example'
acl example_com_domains var(req.hdr_host) -m str example.com
acl example_com_domains2 var(req.hdr_host) -m str example.org www.example.org
# Redirect to HTTPS without Let's Encrypt certificate
### http-request redirect scheme https code 301 if example_com_domains !{ ssl_fc }
# Redirect to HTTPS with Let's Encrypt certificate (exclude LE challenge from redirection)
### http-request redirect scheme https code 301 if example_com_domains !{ ssl_fc } !letsencrypt
# Redirect a domain to another without Let's encrypt certificate
### http-request redirect prefix https://example-to.org code 301 if { var(req.hdr_host) -m str example-from.org }
# Redirect a domain to another with a Let's encrypt certificate (exclude Let's Enrypt challenge from redirection)
### http-request redirect prefix https://example-to.org code 301 if { var(req.hdr_host) -m str example-from.org } !letsencrypt
# HSTS (31536000 seconds = 1 year)
### http-response set-header Strict-Transport-Security max-age=31536000 if example_com_domains
# custom directives, all conditionned by at least the "example_com_domains" ACL
### http-request deny if example_com_domains { src 1.2.3.4 }
# routing directives, all conditionned by (at least) the "example_com_domains" ACL
# Maintenance mode (### -> uncomment BUT define example_com_maintenance_ips acl before)
### use_backend example_com_maintenance if example_com_domains !example_com_maintenance_ips !maintenance_ips
# Use Varnish if available
use_backend varnish if example_com_domains varnish_available varnish_http_verb
# … or use normal backend
use_backend example_com if example_com_domains
# END frontend_external section for site 'example'
default_backend goto_internal
# This is used as a fallback to go to the internal frontend
# This is not supposed to happen
backend goto_internal
server haproxy-internal /run/haproxy-frontend-default.sock send-proxy-v2
# This frontend is only used when returning from varnish
frontend internal
bind /run/haproxy-frontend-default.sock user root mode 666 accept-proxy
option forwardfor
# Check URL (used by Varnish)
monitor-uri /haproxycheck
# Store the Host header in lowercase, to speedup ACL later
http-request set-var(req.hdr_host) req.hdr(host),lower
# Capture host header in logs
http-request capture var(req.hdr_host) len 32
acl varnish_from hdr(X-Varnish) -m found
acl forwarded_proto hdr(x-forwarded-proto) -m found
# Keep header if present and coming from Varnish
http-request set-header X-Forwarded-Proto %[hdr(x-forwarded-proto)] if forwarded_proto varnish_from
# BEGIN HTTP tagging
http-request set-header x-boost-step3 "haproxy-internal"
http-response set-header x-boost-step3 "haproxy-internal; ssl-backend" if { ssl_bc }
http-response set-header x-boost-step3 "haproxy-internal; no-ssl-backend" if !{ ssl_bc }
# Debug: Enable this to add a full log line in the response
### http-response add-header X-Haproxy-Log-Internal "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
# END HTTP tagging
# BEGIN frontend_internal section for site 'example'
acl example_com_domains var(req.hdr_host) -m str example.com
# routing directives, all conditionned by (at least) the "example_com_domains" ACL
use_backend example_com if example_com_domains
# END frontend_internal section for site 'example'
backend varnish
option httpchk HEAD /varnishcheck
server varnish_sock /run/varnish.sock check observe layer7 maxconn 3000 inter 1s send-proxy-v2
# BEGIN backend section for site 'example'
backend example_com
errorfile 503 /etc/haproxy/sites/example/maintenance.http
server example-hostname 1.2.3.4:443 check observe layer4 ssl verify none
backend example_com_maintenance
http-request set-log-level silent
errorfile 503 /etc/haproxy/sites/example/maintenance.http
# END backend section for site 'example'
backend letsencrypt
# Use this if the challenge is managed locally
server localhost 127.0.0.1:81 send-proxy-v2 maxconn 10
# Use this if the challenge is managed remotely
### server my-certbot-challenge-manager 192.168.2.1:80 maxconn 10
backend local
option httpchk HEAD /haproxy-check
server localhost 127.0.0.1:81 send-proxy-v2 maxconn 10
backend maintenance
http-request set-log-level silent
errorfile 503 /etc/haproxy/errors/maintenance.http