global log stdout format raw local0 maxconn 100000 tune.http.logurilen 4096 tune.ssl.default-dh-param 2048 ssl-default-bind-options no-tlsv10 no-tlsv11 ssl-default-server-options no-tlsv10 no-tlsv11 # --- CROWDSEC SPOA START --- tune.bufsize 65536 lua-prepend-path /usr/lib/crowdsec-haproxy-spoa-bouncer/lua/?.lua tune.lua.bool-sample-conversion normal lua-load /usr/lib/crowdsec-haproxy-spoa-bouncer/lua/crowdsec.lua setenv CROWDSEC_BAN_TEMPLATE_PATH /var/lib/crowdsec-haproxy-spoa-bouncer/html/ban.html setenv CROWDSEC_CAPTCHA_TEMPLATE_PATH /var/lib/crowdsec-haproxy-spoa-bouncer/html/captcha.html # --- CROWDSEC SPOA END --- defaults log global mode http option httplog timeout client 300s timeout server 300s timeout connect 5s default-server init-addr libc,none resolvers docker resolve-prefer ipv4 # --- CROWDSEC SPOA START --- option http-buffer-request # --- CROWDSEC SPOA END --- resolvers docker parse-resolv-conf resolve_retries 3 timeout resolve 1s timeout retry 1s hold valid 10s # -------- HTTP -> HTTPS -------- frontend fe_http bind :80 mode http # --- CROWDSEC SPOA START --- filter spoe engine crowdsec config /usr/local/etc/haproxy/crowdsec.cfg acl body_within_limit req.body_size -m int le 51200 http-request send-spoe-group crowdsec crowdsec-http-body if body_within_limit || !{ req.body_size -m found } http-request send-spoe-group crowdsec crowdsec-http-no-body if !body_within_limit { req.body_size -m found } # --- CROWDSEC SPOA END --- http-request redirect scheme https code 301 unless { ssl_fc } # -------- HTTPS (SNI) ---------- frontend fe_https bind :443 ssl crt /etc/haproxy/certs alpn h2,http/1.1 mode http option forwardfor header X-Forwarded-For if-none # Сохраняем request-phase поля в txn.*, потому что log-format выполняется на response-phase http-request set-var(txn.host) req.hdr(Host),lower http-request set-var(txn.path) path http-request set-var(txn.method) method log-format "%{+json}o %(client_ip)ci %(client_port)cp %(frontend_name)ft %(backend_name)b %(server_name)s %(host)[var(txn.host)] %(method)[var(txn.method)] %(path)[var(txn.path)] %(status_code)ST %(bytes_read)B %(time_to_receive)TR %(time_waiting)Tw %(time_to_connect)Tc %(time_server_response)Tr %(time_active)Ta %(termination_state)tsc %(request_line)r %(sni)[ssl_fc_sni]" http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-For %[src] http-request set-header X-Forwarded-Port 443 http-request set-header X-Forwarded-Host %[req.hdr(host)] http-request set-header Host %[req.hdr(host)] http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" http-response set-header X-Content-Type-Options "nosniff" http-response set-header X-Frame-Options "SAMEORIGIN" http-response set-header Referrer-Policy "strict-origin-when-cross-origin" # --- CROWDSEC SPOA START --- filter spoe engine crowdsec config /usr/local/etc/haproxy/crowdsec.cfg acl body_within_limit req.body_size -m int le 51200 http-request send-spoe-group crowdsec crowdsec-http-body if body_within_limit || !{ req.body_size -m found } http-request send-spoe-group crowdsec crowdsec-http-no-body if !body_within_limit { req.body_size -m found } http-request set-header X-Crowdsec-Remediation %[var(txn.crowdsec.remediation)] http-request redirect code 302 location %[url] if { var(txn.crowdsec.remediation) -m str "allow" } { var(txn.crowdsec.redirect) -m found } http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "captcha" } http-request lua.crowdsec_handle if { var(txn.crowdsec.remediation) -m str "ban" } http-after-response set-header Set-Cookie %[var(txn.crowdsec.captcha_cookie)] if { var(txn.crowdsec.captcha_status) -m found } { var(txn.crowdsec.captcha_cookie) -m found } http-after-response set-header Set-Cookie %[var(txn.crowdsec.captcha_cookie)] if { var(txn.crowdsec.captcha_cookie) -m found } !{ var(txn.crowdsec.captcha_status) -m found } # --- CROWDSEC SPOA END --- # Keycloak passthrough acl host_sso hdr(host) -i sso.zk-tech.info # OnlyOffice engine acl host_of hdr(host) -i of.zk-tech.info # Jellyfin acl host_jellyfin hdr(host) -i jf.zk-tech.info # NextCloud acl host_nc hdr(host) -i nc.zk-tech.info # Immich acl host_immich hdr(host) -i im.zk-tech.info # Firefly III acl host_firefly hdr(host) -i ff.zk-tech.info # Obsidian + CouchDB acl host_obsidian hdr(host) -i ob.zk-tech.info # Speedtest acl host_speedtest hdr(host) -i st.zk-tech.info # WUD + docker-socket-proxy acl host_wud hdr(host) -i wud.zk-tech.info acl allowed_wud src 172.19.0.0/16 # Arr stack (media server) acl host_sonarr hdr(host) -i sr.zk-tech.info acl host_radarr hdr(host) -i rr.zk-tech.info acl host_qb hdr(host) -i qb.zk-tech.info acl host_prowl hdr(host) -i pr.zk-tech.info # Torrserver acl host_torrserv hdr(host) -i ts.zk-tech.info # Matrix (synapse, elements acl host_matrix hdr(host) -i mr.zk-tech.info acl path_synapse path_beg -i /_matrix /_synapse/client acl path_wellknown path_beg -i /.well-known/matrix # MAS acl host_mas hdr(host) -i ms.zk-tech.info # Rackula SSO acl host_rk hdr(host) -i rk.zk-tech.info # Zabbix SSO acl host_zb hdr(host) -i zb.zk-tech.info # WikiJS acl host_wiki hdr(host) -i wiki.zk-tech.info # mailcow web + sogo + EAS acl host_mailcow hdr(host) -i mail.zk-tech.info autodiscover.zk-tech.info autoconfig.zk-tech.info # Enable admin from home network acl mc_admin_path path_beg -i /admin acl mc_admin_allowed src 172.19.0.0/16 http-request deny if host_mailcow mc_admin_path !mc_admin_allowed # Grafana local acl host_grafana hdr(host) -i gr.zk-tech.info # Gitea acl host_gitea hdr(host) -i git.zk-tech.info # Wishlist APP acl host_wishlist hdr(host) -i wish.zk-tech.info # PrivateBin acl host_privatebin hdr(host) -i pb.zk-tech.info # Vaultwarden acl host_vaultwarden hdr(host) -i vw.zk-tech.info # Deny access to WUD http-request deny if host_wud !allowed_wud # Immich backend use_backend bk_immich if host_immich # Keycloak backend use_backend bk_keycloak if host_sso use_backend bk_jellyfin if host_jellyfin use_backend bk_nextcloud if host_nc use_backend bk_onlyoffice if host_of use_backend bk_firefly if host_firefly use_backend bk_obsidian if host_obsidian use_backend bk_speedtest if host_speedtest use_backend bk_wud if host_wud # Arr stack backends use_backend be_sonarr if host_sonarr use_backend be_radarr if host_radarr use_backend be_qb if host_qb use_backend be_prowl if host_prowl # Torrserver backend use_backend bk_torr if host_torrserv # MAS redirection # Matrix Auth (MAS compat) - ОБЯЗАТЕЛЬНО ПЕРЕД path_synapse acl path_matrix_auth path_reg -i ^/_matrix/client/(v1|v3|r0)/(login|logout|refresh)(/.*)?$ # (опционально) если хочешь, чтобы запросы регистрации тоже обрабатывал MAS (иначе будут 403/404 от Synapse) # acl path_matrix_register path_reg -i ^/_matrix/client/(v1|v3|r0)/register(/.*)?$ use_backend bk_matrix_mas if host_matrix path_matrix_auth # use_backend bk_matrix_mas if host_matrix path_matrix_register # Matrix (Synapse, Element) use_backend bk_matrix_synapse if host_matrix path_synapse use_backend bk_matrix_synapse if host_matrix path_wellknown use_backend bk_matrix_element if host_matrix #MAS use_backend bk_matrix_mas if host_mas # Rackula Backend use_backend bk_rackula_sso if host_rk # Zabbix Backend use_backend bk_zabbix if host_zb # Wiki backend use_backend bk_wiki if host_wiki # mailcow backend use_backend bk_mailcow if host_mailcow # Grafana Backend use_backend be_grafana if host_grafana # Gitea backend use_backend bk_gitea if host_gitea # Wishlist backend use_backend bk_whishlist if host_wishlist # PricateBin backend use_backend bk_privatebin if host_privatebin # Vaultwarden backend use_backend bk_vaultwarden if host_vaultwarden default_backend bk_404 # -------- HTTP backends -------- backend bk_keycloak mode http option httpchk GET /realms/zk-tech/.well-known/openid-configuration http-request set-header X-Forwarded-Proto https server keycloak keycloak:8080 check resolvers docker resolve-prefer ipv4 inter 5s fall 4 rise 2 # OnlyOffice backend bk_onlyoffice option httpchk http-check send meth GET uri /healthcheck ver HTTP/1.1 hdr Host of.zk-tech.info http-check expect status 200 http-check expect string true http-response del-header X-Frame-Options http-response set-header Content-Security-Policy "frame-ancestors 'self' https://nc.zk-tech.info" timeout connect 5s timeout server 1h server oods onlyoffice-docs:80 check resolvers docker resolve-prefer ipv4 inter 5s fall 4 rise 2 # Jellyfin backend bk_jellyfin option httpchk GET /health http-check expect string Healthy http-request set-header X-Forwarded-Host %[req.hdr(host)] http-request set-header X-Forwarded-Server %[req.hdr(host)] http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Port %[dst_port] http-request set-header X-Real-IP %[src] server jellyfin-server 172.19.0.18:8096 check inter 5s fall 4 rise 2 # --- Бэкенд Immich --- backend bk_immich mode http balance roundrobin option httpchk GET /.well-known/immich http-check expect status 200 timeout check 5s server immich01 172.19.0.16:2283 check resolvers docker resolve-prefer ipv4 inter 5s fall 4 rise 2 #Nextcloud backend bk_nextcloud balance uri option httpchk GET /status.php http-check expect status 200 timeout connect 5s timeout server 600s server nc1 nextcloud:80 check resolvers docker resolve-prefer ipv4 init-addr libc,none inter 5s fall 4 rise 2 # Firefly III backend bk_firefly mode http # option httplog option httpclose option forwardfor except 127.0.0.1 # заголовки для корректной работы за прокси http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] # при желании можно добавить health-check: # option httpchk GET /login server firefly_iii 172.19.0.15:8051 check # Obsidian + CouchDB backend bk_obsidian mode http # option httplog option httpclose option forwardfor except 127.0.0.1 # option httpchk GET / # http-check expect status 200 server couchdb-obsidian couchdb-obsidian:5984 check # Speedtest backend bk_speedtest mode http # option httplog option httpclose option forwardfor except 127.0.0.1 # option httpchk GET / # http-check expect status 200 server openspeedtest openspeedtest:3000 check # WUD backend bk_wud mode http option httpchk GET / http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] server wud wud:3000 check # Arr stack Sonarr backend be_sonarr mode http option httpclose option forwardfor except 127.0.0.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] option httpchk GET / server sonarr 172.19.0.16:8989 check # Arr stack Radarr backend be_radarr mode http option httpclose option forwardfor except 127.0.0.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] option httpchk GET / server radarr 172.19.0.16:7878 check # Arr stack qbittorrent backend be_qb mode http option httpclose option forwardfor except 127.0.0.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] #option httpchk GET / server qbittorrent 172.19.0.16:8085 check # Arr stack Prowlarr backend be_prowl mode http option httpclose option forwardfor except 127.0.0.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] option httpchk GET / server prowlarr 172.19.0.16:9696 check # Torrserver for multimedia backend bk_torr mode http option httpclose option forwardfor except 127.0.0.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] option httpchk GET / server prowlarr 172.19.0.16:8090 check # Matrix (synapse, Element, MAS) backend bk_matrix_synapse server synapse matrix-synapse:8008 check backend bk_matrix_element server element matrix-element-web:80 check backend bk_matrix_mas server mas matrix-mas:8080 check backend bk_404 mode http http-request deny deny_status 404 # Rackula with auth backend bk_rackula_sso http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(Host)] http-request set-header X-Forwarded-Port 443 server oauth2proxy oauth2-proxy-rackula:4180 check # Zabbix backend backend bk_zabbix mode http option httpchk GET /index.php http-check expect status 200 server zabbix-web zabbix-web-nginx-pgsql:8080 check # WikiJS backend backend bk_wiki mode http server wikijs wikijs:3000 check # Crowdsec Backend backend crowdsec-spoa mode tcp server spoa crowdsec-spoa-bouncer:9000 check # mailcow web + sogo + EAS backend bk_mailcow option forwardfor http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } server mailcow 172.19.0.15:8085 check # Grafana backend be_grafana mode http option httpchk GET /api/health http-check expect status 200 http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-Port 443 http-request set-header X-Forwarded-Host %[req.hdr(Host)] server grafana grafana:3000 check resolvers docker resolve-prefer ipv4 init-addr libc,none # Gitea backend bk_gitea mode http option httpchk GET /api/healthz http-check expect status 200 http-request set-header Host %[req.hdr(Host)] http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-For %[src] http-request set-header X-Real-IP %[src] server gitea gitea:3000 check # Wishlist backend bk_whishlist mode http # option httpchk GET /api/healthz # http-check expect status 200 http-request set-header Host %[req.hdr(Host)] http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-For %[src] http-request set-header X-Real-IP %[src] server wishlist 172.19.0.16:3280 # PrivateBin backend bk_privatebin mode http option forwardfor http-request set-header Host %[req.hdr(Host)] http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-For %[src] http-request set-header X-Real-IP %[src] server privatebin privatebin:8080 check # Vaultwarden backend bk_vaultwarden mode http option forwardfor option http-keep-alive http-request set-header X-Real-IP %[src] http-request set-header X-Forwarded-Proto https http-request set-header X-Forwarded-Port 443 option httpchk GET /alive http-check expect status 200 timeout tunnel 1h server vaultwarden vaultwarden:80 check # TEST string