# Traefik CRD middleware for rate limiting apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: rate-limit namespace: honeydue spec: rateLimit: average: 100 burst: 200 period: 1m --- # Security headers apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: security-headers namespace: honeydue spec: headers: frameDeny: true contentTypeNosniff: true # browserXssFilter removed (audit L7): it emits the deprecated # X-XSS-Protection header, which can itself introduce XSS in legacy # browsers. Modern browsers ignore it. referrerPolicy: "strict-origin-when-cross-origin" customResponseHeaders: X-Content-Type-Options: "nosniff" X-Frame-Options: "DENY" # HSTS: 2-year max-age + preload (audit L5/CODE-L3). After this is # live on api/admin/app, submit myhoneydue.com to hstspreload.org. Strict-Transport-Security: "max-age=63072000; includeSubDomains; preload" # Cross-origin isolation (audit F9). COEP (require-corp) is omitted — # it commonly breaks third-party embeds; add only after testing. Cross-Origin-Opener-Policy: "same-origin" Cross-Origin-Resource-Policy: "same-origin" # Content-Security-Policy is intentionally NOT set here — the Go API # sets a CSP in internal/router/router.go that permits Google Fonts # for the landing page. Two CSP headers would intersect and break it. # admin and web apps set their own CSP via Next.js middleware. Permissions-Policy: "camera=(), microphone=(), geolocation=()" X-Permitted-Cross-Domain-Policies: "none" --- # Cloudflare IP allowlist (restrict origin to Cloudflare only) # https://www.cloudflare.com/ips-v4 and /ips-v6 # Update periodically: curl -s https://www.cloudflare.com/ips-v4 && curl -s https://www.cloudflare.com/ips-v6 apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: cloudflare-only namespace: honeydue spec: ipAllowList: sourceRange: # Cloudflare IPv4 ranges - 173.245.48.0/20 - 103.21.244.0/22 - 103.22.200.0/22 - 103.31.4.0/22 - 141.101.64.0/18 - 108.162.192.0/18 - 190.93.240.0/20 - 188.114.96.0/20 - 197.234.240.0/22 - 198.41.128.0/17 - 162.158.0.0/15 - 104.16.0.0/13 - 104.24.0.0/14 - 172.64.0.0/13 - 131.0.72.0/22 # Cloudflare IPv6 ranges - 2400:cb00::/32 - 2606:4700::/32 - 2803:f800::/32 - 2405:b500::/32 - 2405:8100::/32 - 2a06:98c0::/29 - 2c0f:f248::/32 --- # Admin basic auth — additional auth layer for admin panel # Secret created by 02-setup-secrets.sh from config.yaml credentials apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: admin-auth namespace: honeydue spec: basicAuth: secret: admin-basic-auth realm: "honeyDue Admin" --- # Strict rate limit for auth endpoints (audit F10 / LIVE-L12). # Applied via the honeydue-api-auth Ingress to login / register / # forgot-password / reset-password / join-with-code. depth: 2 makes the # limiter key on the real client IP rather than the Cloudflare edge IP # (request path: client -> Cloudflare -> Traefik). This is the edge half; # the per-account lockout in the Go app is the robust half. apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth-rate-limit namespace: honeydue spec: rateLimit: average: 5 burst: 10 period: 1m sourceCriterion: ipStrategy: depth: 2