global lua-load /etc/haproxy/cors/cors.lua log /dev/log local0 log /dev/log local1 notice log 127.0.0.1 local2 log-send-hostname chroot /var/lib/haproxy pidfile /var/run/haproxy.pid stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners stats timeout 30s maxconn 30000 user haproxy group haproxy daemon # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # An alternative list with additional directives can be obtained from # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy #ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS #ssl-default-bind-options no-sslv3 tune.ssl.default-dh-param 2048 # intermediate configuration ssl-default-bind-curves X25519:prime256v1:secp384r1 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:DHE-RSA-CHACHA20-POLY1305 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 ssl-min-ver TLSv1.2 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:DHE-RSA-CHACHA20-POLY1305 ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 600s timeout server 600s timeout http-request 5s option http-buffer-request http-errors kitties errorfile 400 /etc/haproxy/http-cat-errors/400.http errorfile 403 /etc/haproxy/http-cat-errors/403.http errorfile 408 /etc/haproxy/http-cat-errors/408.http errorfile 500 /etc/haproxy/http-cat-errors/500.http errorfile 502 /etc/haproxy/http-cat-errors/502.http errorfile 503 /etc/haproxy/http-cat-errors/503.http errorfile 504 /etc/haproxy/http-cat-errors/504.http userlist admin-ghost group is-admin user admin password $5$ITvxQNSy4YoUQdNm$p/2D8ey05ZI3KC2gpRun4OKNsomFS8xJnNd0M4P0zeB # $5$... (générez avec: printf "votrepassword" | mkpasswd --method=sha-256 --stdout) #frontend http_in # bind *:80 # maxconn 500 # http-request track-sc0 src table per_ip_rates # http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 } # http-request silent-drop if { sc_http_req_rate(0) gt 100 } # acl acl_letsencrypt path_beg /.well-known/acme-challenge/ # # redirect scheme https if !acl_letsencrypt !{ ssl_fc } # use_backend be_letsencrypt if acl_letsencrypt #frontend smtp_front # bind *:587 # mode tcp # option tcplog # default_backend smtp_back #backend smtp_back # mode tcp # server postfix_server 192.168.1.17:587 check frontend https bind *:443,[::]:443 ssl crt /etc/haproxy/ssl/ strict-sni alpn http/1.1 #bind *:443,[::]:443 ssl crt /etc/haproxy/ssl/ strict-sni alpn h2,http/1.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-For %[src] http-request set-header X-Forwarded-For %[src] http-request track-sc0 src table per_ip_rates http-request silent-drop if { sc_http_req_rate(0) gt 100 } # config httpcats errorfiles kitties http-response return status 400 default-errorfiles if { status 400 } http-response return status 401 default-errorfiles if { status 401 } http-response return status 403 default-errorfiles if { status 403 } http-response return status 404 default-errorfiles if { status 404 } http-response return status 408 default-errorfiles if { status 408 } http-response return status 500 default-errorfiles if { status 500 } http-response return status 502 default-errorfiles if { status 502 } http-response return status 503 default-errorfiles if { status 503 } http-response return status 504 default-errorfiles if { status 504 } ## config antiDDOS # Suivi du taux de requêtes par IP stick-table type ip size 1m expire 10m store http_req_rate(10s) http-request track-sc0 src # ACL pour whitelister ton domaine n8n acl n8n_domain hdr_end(host) -i gyozamancave.fr # Whitelist IP perso (optionnel) acl my_ip src 82.67.3.126 acl my_lan1 src 192.168.1.0/24 acl my_lan2 src 192.168.2.0/24 # Autoriser ton domaine (ou ton IP) à passer sans rate-limit http-request allow if n8n_domain http-request allow if my_ip http-request allow if my_lan1 http-request allow if my_lan2 # Appliquer la rate-limit globale pour le reste http-request deny deny_status 429 if { sc0_http_req_rate gt 100 } # BEGIN CORS #capture request header origin len 128 #chttp-response set-header Access-Control-Allow-Origin "*" #chttp-response set-header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization, JSNLog-RequestId, activityId, applicationId, applicationUserId, channelId, senderId, sessionId" #chttp-response set-header Access-Control-Max-Age 3628800 #chttp-response set-header Access-Control-Allow-Methods "GET, DELETE, OPTIONS, POST, PUT" # END CORS # Redirection 301 pour links.billisdead.com acl is_billisdead hdr(host) -i links.billisdead.com http-request redirect code 301 location https://links.mrteddybear.fr/@billisdead.com if is_billisdead acl cms-host hdr(host) -i mrteddybear.fr acl links-host hdr(host) -i links.mrteddybear.fr acl cms2-host hdr(host) -i billisdead.com acl mattermost-host hdr(host) -i mattermost.gyozamancave.fr acl nextcloud-host hdr(host) -i nextcloud.gyozamancave.fr acl funkwhale-host hdr(host) -i funkwhale.gyozamancave.fr acl wiki-host hdr(host) -i wiki.gyozamancave.fr acl hass-host hdr(host) -i hass.gyozamancave.fr acl postiz-host hdr(host) -i postiz.gyozamancave.fr acl stats-host hdr(host) -i stats.gyozamancave.fr acl n8n-host hdr(host) -i n8n.gyozamancave.fr acl homegit-host hdr(host) -i homegit.gyozamancave.fr #acl boudoir-assets path_beg /assets/ #acl path_og path_beg /og/ acl boudoir-host hdr(host) -i ledigitalboudoir.com use_backend cms if cms-host use_backend links-mtb if links-host use_backend cms2 if cms2-host use_backend mattermost if mattermost-host use_backend nextcloud if nextcloud-host use_backend funkwhale if funkwhale-host use_backend wiki if wiki-host use_backend hass-backend if hass-host use_backend postiz-backend if postiz-host use_backend stats-backend if stats-host use_backend n8n-backend if n8n-host use_backend homegit-backend if homegit-host #use_backend boudoir-assets-backend if path_og #use_backend boudoir-assets-backend if boudoir-assets use_backend boudoir-backend if boudoir-host #backend boudoir-assets-backend # mode http # En-têtes HTTPS corrects pour Directus # http-request set-header X-Forwarded-Proto https # http-request set-header X-Forwarded-Host ledigitalboudoir.com # http-request set-header X-Forwarded-For %[src] # Route principale OG : # https://ledigitalboudoir.com/og/.jpg # → /assets/?format=jpg&width=1200&height=630&fit=contain&bg=black # http-request replace-path ^/og/(.*)\.jpg$ /assets/\1?format=jpg&width=1200&height=630&fit=contain&bg=black # Variante cache-busting (ex: .../og/-v2.jpg) # http-request replace-path ^/og/(.*)-v[0-9]+\.jpg$ /assets/\1?format=jpg&width=1200&height=630&fit=contain&bg=black # Cache long (1 semaine) # http-response set-header Cache-Control public,max-age=604800,immutable # Autoriser uniquement assets/uploads # acl allowed_assets path_beg /assets/ /uploads/ # http-request deny unless allowed_assets # Serveur Directus interne # server directus 192.168.1.107:8055 check #backend boudoir-backend # server boudoir 192.168.1.57:2368 backend boudoir-backend acl ghost_path path_beg /ghost/ acl is_whitelisted src 82.67.3.126/32 acl is_lan src 192.168.1.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_lan2 src 192.168.2.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_whitelisted_full src 82.67.3.126/32 192.168.1.0/24 192.168.2.0/24 # Combine acl admin_auth http_auth_group(admin-ghost) is-admin # Deny /ghost/ hors IP white http-request deny if ghost_path !is_whitelisted_full server boudoir 192.168.1.57:2368 check #backend boudoir-backend # server boudoir 192.168.1.107:31723 check backend homegit-backend server homegit 192.168.1.70:3000 backend stats-backend server stats 192.168.1.49:3000 backend n8n-backend mode http option forwardfor server n8n 192.168.1.56:5678 backend links-mtb #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-For %[src] mode http #option forwardfor server links 192.168.1.18:32508 check ssl verify none backend hass-backend server hass 192.168.1.18:30250 mode http # option forwardfor # http-request add-header X-Forwarded-Proto https # http-request add-header X-Forwarded-Port 443 backend cms #server cms 192.168.1.101:80 acl ghost_path path_beg /ghost/ acl is_whitelisted src 82.67.3.126/32 acl is_lan src 192.168.1.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_lan2 src 192.168.2.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_whitelisted_full src 82.67.3.126/32 192.168.1.0/24 192.168.2.0/24 # Combine acl admin_auth http_auth_group(admin-ghost) is-admin # Deny /ghost/ hors IP white http-request deny if ghost_path !is_whitelisted_full server cms 192.168.1.250:2369 backend cms2 #mode http acl ghost_path path_beg /ghost/ acl is_whitelisted src 82.67.3.126/32 acl is_lan src 192.168.1.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_lan2 src 192.168.2.0/24 # Plage LAN (adaptez 192.168.1.0/24 si précis) acl is_whitelisted_full src 82.67.3.126/32 192.168.1.0/24 192.168.2.0/24 # Combine acl admin_auth http_auth_group(admin-ghost) is-admin # Deny /ghost/ hors IP white http-request deny if ghost_path !is_whitelisted_full server ghost_server 192.168.1.55:2368 backend mattermost server mattermost 192.168.1.112:8065 backend be_letsencrypt server letsencrypt 127.0.0.1:9080 #server letsencrypt 127.0.0.1:10001 backend wiki server wiki 192.168.1.18:32149 backend postiz-backend mode http balance source http-request add-header X-Forwarded-Proto https if { ssl_fc } # stickiness stick-table type ip size 50k expire 30m stick on src http-reuse safe cookie SERVERID insert indirect nocache default-server inter 10s fastinter 500 fall 2 rise 2 # force https acl http ssl_fc,not http-request redirect scheme https if http http-response set-header Strict-Transport-Security max-age=15552000 option ssl-hello-chk server postiz 192.168.1.18:32133 backend nextcloud # health checking is DISABLED mode http balance source http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Real-IP %[src] http-request set-header X-Forwarded-For %[src] http-request set-header Host %[req.hdr(host)] # stickiness stick-table type ip size 50k expire 30m stick on src http-reuse safe cookie SERVERID insert indirect nocache default-server inter 10s fastinter 500 fall 2 rise 2 # force https acl http ssl_fc,not http-request redirect scheme https if http http-response set-header Strict-Transport-Security max-age=15552000 option ssl-hello-chk server nextcloud 192.168.1.13:5080 #ssl verify none option http-server-close option httpclose option forwardfor http-request set-header Connection "upgrade" if { hdr(Upgrade) -i WebSocket } backend funkwhale 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-For %[src] option forwardfor #http-request set-header X-Forwarded-Port %[dst_port] #http-request add-header X-Forwarded-Proto https if { ssl_fc } #http-response add-header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline': img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:; worker-src 'self';" #http-response add-header Referrer-Policy strict-origin-when-cross-origin #http-response add-header X-Frame-Options SAMEORIGIN #server funkwhale 192.168.1.12:5002 server funkwhale 192.168.1.108:5002 backend per_ip_rates #stick-table type ip size 1m expire 10m store http_req_rate(10s) # Define a stick-table to track request rates per IP stick-table type ip size 1m expire 10m store http_req_rate(10s) # Track all requests by source IP http-request track-sc0 src # Whitelist IP: 82.67.3.126 (bypass rate limiting) acl is_whitelisted_ip src 82.67.3.126 acl is_whitelisted_lan1 src 192.168.1.0/24 acl is_whitelisted_lan2 src 192.168.2.0/24 # Whitelist domain: *.gyozamancave.fr (bypass rate limiting) acl is_whitelisted_domain hdr_end(host) -i gyozamancave.fr # Apply rate limiting (10 req/10s) unless whitelisted #http-request deny deny_status 429 if !is_whitelisted_ip !is_whitelisted_domain { sc0_http_req_rate(per_ip_rates) gt 10 } http-request deny deny_status 429 if !is_whitelisted_ip !is_whitelisted_lan1 !is_whitelisted_lan2 !is_whitelisted_domain { sc0_http_req_rate gt 10 }