commit 78c5ad051b84f12b499fc99e6974107ff3e4d20e Author: root Date: Mon Sep 28 19:14:40 2026 +0300 Initial infrastructure configuration diff --git a/stacks/haproxy/conf/crowdsec.cfg b/stacks/haproxy/conf/crowdsec.cfg new file mode 100644 index 0000000..03716f3 --- /dev/null +++ b/stacks/haproxy/conf/crowdsec.cfg @@ -0,0 +1,28 @@ +[crowdsec] + +spoe-agent crowdsec-agent + messages crowdsec-tcp + groups crowdsec-http-body crowdsec-http-no-body + option var-prefix crowdsec + option set-on-error error + timeout hello 200ms + timeout idle 55s + timeout processing 500ms + use-backend crowdsec-spoa + log global + +spoe-message crowdsec-tcp + args id=unique-id src-ip=src src-port=src_port + event on-client-session + +spoe-message crowdsec-http-body + args remediation=var(txn.crowdsec.remediation) id=unique-id method=method path=path query=query version=req.ver headers=req.hdrs body=req.body url=url ssl=ssl_fc src-ip=src src-port=src_port + +spoe-message crowdsec-http-no-body + args remediation=var(txn.crowdsec.remediation) id=unique-id method=method path=path query=query version=req.ver headers=req.hdrs url=url ssl=ssl_fc src-ip=src src-port=src_port + +spoe-group crowdsec-http-body + messages crowdsec-http-body + +spoe-group crowdsec-http-no-body + messages crowdsec-http-no-body diff --git a/stacks/haproxy/conf/haproxy.cfg b/stacks/haproxy/conf/haproxy.cfg new file mode 100644 index 0000000..744cd01 --- /dev/null +++ b/stacks/haproxy/conf/haproxy.cfg @@ -0,0 +1,413 @@ +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 diff --git a/stacks/haproxy/conf/haproxy.cfg.bak b/stacks/haproxy/conf/haproxy.cfg.bak new file mode 100644 index 0000000..4718ff9 --- /dev/null +++ b/stacks/haproxy/conf/haproxy.cfg.bak @@ -0,0 +1,369 @@ +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 + # 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 + + 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.16: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 diff --git a/stacks/haproxy/docker-compose.yml b/stacks/haproxy/docker-compose.yml new file mode 100644 index 0000000..77f5e80 --- /dev/null +++ b/stacks/haproxy/docker-compose.yml @@ -0,0 +1,71 @@ +services: + haproxy: + image: haproxy:3.4.0-alpine + container_name: haproxy + user: "0:0" + cap_add: + - NET_BIND_SERVICE + ports: + - "80:80" + - "443:443" + volumes: + - /srv/nfs/infra/haproxy/conf:/usr/local/etc/haproxy:ro + - /srv/nfs/infra/haproxy/certs:/etc/haproxy/certs:ro + - /srv/nfs/infra/haproxy/logs:/var/log/haproxy + + # SPOA Lua/Templates (выдаются spoa-bouncer, читаются haproxy) + - /srv/nfs/infra/haproxy/crowdsec/lua:/usr/lib/crowdsec-haproxy-spoa-bouncer/lua:ro + - /srv/nfs/infra/haproxy/crowdsec/templates:/var/lib/crowdsec-haproxy-spoa-bouncer/html:ro + networks: + - interdock + depends_on: + - crowdsec + - crowdsec_spoa_bouncer + restart: unless-stopped + + crowdsec: + image: crowdsecurity/crowdsec:latest + container_name: crowdsec + restart: unless-stopped + env_file: + - /srv/nfs/infra/haproxy/.env + ports: + - "127.0.0.1:8087:8087" + environment: + COLLECTIONS: "crowdsecurity/haproxy" + GID: "${DOCKER_GID}" + volumes: + # CrowdSec persist -> NFS + - /srv/nfs/infra/haproxy/crowdsec/data:/var/lib/crowdsec/data/ + - /srv/nfs/infra/haproxy/crowdsec/config:/etc/crowdsec/ + + # acquisition + #- /srv/nfs/infra/haproxy/crowdsec/acquis.d:/etc/crowdsec/acquis.d:ro + + # docker logs datasource + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: + - interdock + + crowdsec_spoa_bouncer: + image: crowdsecurity/spoa-bouncer:latest + container_name: crowdsec-spoa-bouncer + restart: unless-stopped + env_file: + - /srv/nfs/infra/haproxy/.env + depends_on: + - crowdsec + environment: + CROWDSEC_URL: "http://crowdsec:8080/" + LISTEN_TCP: "0.0.0.0:9000" + CROWDSEC_KEY: "${BOUNCER_KEY_SPOA}" + volumes: + # SPOA bouncer пишет lua/templates в NFS, haproxy читает их + - /srv/nfs/infra/haproxy/crowdsec/lua:/usr/lib/crowdsec-haproxy-spoa-bouncer/lua/ + - /srv/nfs/infra/haproxy/crowdsec/templates:/var/lib/crowdsec-haproxy-spoa-bouncer/html/ + networks: + - interdock + +networks: + interdock: + external: true