[traefik] Remove broken rewrite-body plugin and all rybbit/anti-AI injection

The rewrite-body Traefik plugin (both packruler/rewrite-body v1.2.0 and
the-ccsn/traefik-plugin-rewritebody v0.1.3) silently fails on Traefik
v3.6.12 due to Yaegi interpreter issues with ResponseWriter wrapping.
Both plugins load without errors but never inject content.

Removed:
- rewrite-body plugin download (init container) and registration
- strip-accept-encoding middleware (only existed for rewrite-body bug)
- anti-ai-trap-links middleware (used rewrite-body for injection)
- rybbit_site_id variable from ingress_factory and reverse_proxy factory
- rybbit_site_id from 25 service stacks (39 instances)
- Per-service rybbit-analytics middleware CRD resources

Kept:
- compress middleware (entrypoint-level, working correctly)
- ai-bot-block middleware (ForwardAuth to bot-block-proxy)
- anti-ai-headers middleware (X-Robots-Tag: noai, noimageai)
- All CrowdSec, Authentik, rate-limit middleware unchanged

Next: Cloudflare Workers with HTMLRewriter for edge-side injection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-04-17 12:41:17 +00:00
parent b24545ffdb
commit b034c868db
29 changed files with 32 additions and 197 deletions

View file

@ -58,10 +58,6 @@ variable "root_domain" {
default = "viktorbarzin.me"
type = string
}
variable "rybbit_site_id" {
default = null
type = string
}
variable "custom_content_security_policy" {
type = string
default = null
@ -237,12 +233,8 @@ resource "kubernetes_ingress_v1" "proxied-ingress" {
var.exclude_crowdsec ? null : "traefik-crowdsec@kubernetescrd",
local.effective_anti_ai ? "traefik-ai-bot-block@kubernetescrd" : null,
local.effective_anti_ai ? "traefik-anti-ai-headers@kubernetescrd" : null,
local.effective_anti_ai ? "traefik-strip-accept-encoding@kubernetescrd" : null,
local.effective_anti_ai ? "traefik-anti-ai-trap-links@kubernetescrd" : null,
var.protected ? "traefik-authentik-forward-auth@kubernetescrd" : null,
var.allow_local_access_only ? "traefik-local-only@kubernetescrd" : null,
var.rybbit_site_id != null ? "traefik-strip-accept-encoding@kubernetescrd" : null,
var.rybbit_site_id != null ? "${var.namespace}-rybbit-analytics-${var.name}@kubernetescrd" : null,
var.custom_content_security_policy != null ? "${var.namespace}-custom-csp-${var.name}@kubernetescrd" : null,
], var.extra_middlewares)))
"traefik.ingress.kubernetes.io/router.entrypoints" = "websecure"
@ -282,33 +274,6 @@ resource "kubernetes_ingress_v1" "proxied-ingress" {
}
}
# Rybbit analytics middleware (rewrite-body plugin with content-type filtering) - created per service when rybbit_site_id is set
resource "kubernetes_manifest" "rybbit_analytics" {
count = var.rybbit_site_id != null ? 1 : 0
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "rybbit-analytics-${var.name}"
namespace = var.namespace
}
spec = {
plugin = {
traefik-plugin-rewritebody = {
rewrites = [{
regex = "</head>"
replacement = "<script src=\"https://rybbit.viktorbarzin.me/api/script.js\" data-site-id=\"${var.rybbit_site_id}\" defer></script></head>"
}]
monitoring = {
types = ["text/html"]
}
}
}
}
}
}
# Custom CSP headers middleware - created per service when custom_content_security_policy is set
resource "kubernetes_manifest" "custom_csp" {
count = var.custom_content_security_policy != null ? 1 : 0

View file

@ -145,7 +145,6 @@ module "ingress" {
name = "budget-${var.name}"
tls_secret_name = var.tls_secret_name
dns_type = "proxied"
rybbit_site_id = "3e6b6b68088a"
extra_annotations = var.homepage_annotations
}

View file

@ -112,7 +112,6 @@ module "ingress" {
full_host = "viktorbarzin.me"
dns_type = "proxied"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "da853a2438d0"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Blog"
@ -130,5 +129,4 @@ module "ingress-www" {
service_name = "blog"
full_host = "www.viktorbarzin.me"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "da853a2438d0"
}

View file

@ -128,7 +128,7 @@ resource "helm_release" "crowdsec" {
repository = "https://crowdsecurity.github.io/helm-charts"
chart = "crowdsec"
values = [templatefile("${path.module}/values.yaml", { homepage_username = var.homepage_username, homepage_password = var.homepage_password, DB_PASSWORD = var.db_password, ENROLL_KEY = var.enroll_key, SLACK_WEBHOOK_URL = var.slack_webhook_url, mysql_host = var.mysql_host, postgresql_host = var.postgresql_host })]
values = [templatefile("${path.module}/values.yaml", { homepage_username = var.homepage_username, homepage_password = var.homepage_password, DB_PASSWORD = var.db_password, ENROLL_KEY = var.enroll_key, SLACK_WEBHOOK_URL = var.slack_webhook_url, mysql_host = var.mysql_host, postgresql_host = var.postgresql_host })]
timeout = 1200
wait = true
wait_for_jobs = true
@ -256,13 +256,12 @@ resource "kubernetes_service" "crowdsec-web" {
}
module "ingress" {
source = "../../../../modules/kubernetes/ingress_factory"
dns_type = "proxied"
dns_type = "proxied"
namespace = kubernetes_namespace.crowdsec.metadata[0].name
name = "crowdsec-web"
protected = true
tls_secret_name = var.tls_secret_name
exclude_crowdsec = true
rybbit_site_id = "d09137795ccc"
}
# CronJob to import public blocklists into CrowdSec

View file

@ -102,7 +102,6 @@ module "ingress" {
namespace = kubernetes_namespace.cyberchef.metadata[0].name
name = "cc"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "7c460afc68c4"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "CyberChef"

View file

@ -385,7 +385,6 @@ module "ingress" {
namespace = kubernetes_namespace.dawarich.metadata[0].name
name = "dawarich"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "0abfd409f2fb"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Dawarich"

View file

@ -1004,15 +1004,13 @@ resource "kubernetes_service" "phpmyadmin" {
}
}
module "ingress" {
source = "../../../../modules/kubernetes/ingress_factory"
dns_type = "proxied"
namespace = kubernetes_namespace.dbaas.metadata[0].name
name = "pma"
tls_secret_name = var.tls_secret_name
protected = true
extra_annotations = {}
rybbit_site_id = "942c76b8bd4d"
custom_content_security_policy = "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval' https://rybbit.viktorbarzin.me"
source = "../../../../modules/kubernetes/ingress_factory"
dns_type = "proxied"
namespace = kubernetes_namespace.dbaas.metadata[0].name
name = "pma"
tls_secret_name = var.tls_secret_name
protected = true
extra_annotations = {}
}
@ -1514,7 +1512,6 @@ module "ingress-pgadmin" {
name = "pgadmin"
tls_secret_name = var.tls_secret_name
protected = true
rybbit_site_id = "7cef78e30485"
}

View file

@ -390,8 +390,6 @@ module "calibre_ingress" {
"gethomepage.dev/widget.password" = local.calibre_homepage_credentials["calibre-web"]["password"]
"gethomepage.dev/pod-selector" = ""
}
rybbit_site_id = "17a5c7fbb077"
custom_content_security_policy = "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://rybbit.viktorbarzin.me"
}
# Stacks - Anna's Archive Download Manager
@ -501,7 +499,6 @@ module "stacks_ingress" {
service_name = "annas-archive-stacks"
tls_secret_name = var.tls_secret_name
protected = true
rybbit_site_id = "ce5f8aed6bbb"
extra_annotations = {
"gethomepage.dev/enabled" = "false"
}
@ -650,7 +647,6 @@ module "audiobookshelf_ingress" {
namespace = kubernetes_namespace.ebooks.metadata[0].name
name = "audiobookshelf"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "b38fda4285df"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Audiobookshelf"

View file

@ -169,11 +169,10 @@ module "tls_secret" {
module "ingress" {
source = "../../modules/kubernetes/ingress_factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
namespace = kubernetes_namespace.f1-stream.metadata[0].name
name = "f1"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "7e69786f66d5"
exclude_crowdsec = true
extra_annotations = {
"gethomepage.dev/enabled" = "true"

View file

@ -281,7 +281,6 @@ module "ingress" {
name = "frigate"
tls_secret_name = var.tls_secret_name
protected = true
rybbit_site_id = "0d4044069ff5"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Frigate"

View file

@ -125,5 +125,4 @@ module "ingress" {
name = "highlights-immich"
tls_secret_name = var.tls_secret_name
service_name = "immich-frame"
rybbit_site_id = "602167601c6b"
}

View file

@ -674,13 +674,12 @@ resource "kubernetes_service" "immich-machine-learning" {
module "ingress-immich" {
source = "../../modules/kubernetes/ingress_factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
namespace = kubernetes_namespace.immich.metadata[0].name
name = "immich"
service_name = "immich-server"
port = 2283
tls_secret_name = var.tls_secret_name
rybbit_site_id = "35eedb7a3d2b"
skip_default_rate_limit = true
extra_middlewares = ["traefik-immich-rate-limit@kubernetescrd"]
anti_ai_scraping = false

View file

@ -263,7 +263,6 @@ module "ingress" {
name = "mail"
service_name = "roundcubemail"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "082f164faa7d"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Roundcube Mail"

View file

@ -225,7 +225,6 @@ module "ingress" {
namespace = kubernetes_namespace.navidrome.metadata[0].name
name = "navidrome"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "8a3844ff75ba"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Navidrome"

View file

@ -96,7 +96,6 @@ module "ingress" {
name = "networking-toolbox"
tls_secret_name = var.tls_secret_name
protected = true
rybbit_site_id = "50e38577e41c"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Networking Toolbox"

View file

@ -221,7 +221,6 @@ module "ingress" {
name = "nextcloud"
tls_secret_name = var.tls_secret_name
port = 8080
rybbit_site_id = "5a3bfe59a3fe"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Nextcloud"

View file

@ -369,7 +369,6 @@ module "ingress" {
service_name = "ollama-ui"
tls_secret_name = var.tls_secret_name
port = 80
rybbit_site_id = "e73bebea399f"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Ollama"

View file

@ -247,5 +247,4 @@ module "ingress" {
# gethomepage.dev/weight: 10 # optional
# gethomepage.dev/instance: "public" # optional
}
rybbit_site_id = "be6d140cbed8"
}

View file

@ -130,8 +130,7 @@ module "ingress" {
host = "pb"
dns_type = "proxied"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "3ae810b0476d"
custom_content_security_policy = "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval' https://rybbit.viktorbarzin.me"
custom_content_security_policy = "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "PrivateBin"

View file

@ -331,7 +331,6 @@ module "ingress" {
name = "wrongmove"
service_name = "realestate-crawler-ui"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "edee05de453d"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Wrongmove"

View file

@ -37,10 +37,6 @@ variable "max_body_size" {
variable "extra_annotations" {
default = {}
}
variable "rybbit_site_id" {
default = null
type = string
}
variable "custom_content_security_policy" {
default = null
type = string
@ -143,8 +139,6 @@ resource "kubernetes_ingress_v1" "proxied-ingress" {
"traefik-crowdsec@kubernetescrd",
var.protected ? "traefik-authentik-forward-auth@kubernetescrd" : null,
var.strip_auth_headers ? "traefik-strip-auth-headers@kubernetescrd" : null,
var.rybbit_site_id != null ? "traefik-strip-accept-encoding@kubernetescrd" : null,
var.rybbit_site_id != null ? "${var.namespace}-rybbit-analytics-${var.name}@kubernetescrd" : null,
var.custom_content_security_policy != null ? "${var.namespace}-custom-csp-${var.name}@kubernetescrd" : null,
], var.extra_middlewares)))
"traefik.ingress.kubernetes.io/router.entrypoints" = "websecure"
@ -186,33 +180,6 @@ resource "kubernetes_ingress_v1" "proxied-ingress" {
}
}
# Rybbit analytics middleware (rewrite-body plugin with content-type filtering) - created per service when rybbit_site_id is set
resource "kubernetes_manifest" "rybbit_analytics" {
count = var.rybbit_site_id != null ? 1 : 0
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "rybbit-analytics-${var.name}"
namespace = var.namespace
}
spec = {
plugin = {
traefik-plugin-rewritebody = {
rewrites = [{
regex = "</head>"
replacement = "<script src=\"https://rybbit.viktorbarzin.me/api/script.js\" data-site-id=\"${var.rybbit_site_id}\" defer></script></head>"
}]
monitoring = {
types = ["text/html"]
}
}
}
}
}
}
# Custom CSP headers middleware - created per service when custom_content_security_policy is set
resource "kubernetes_manifest" "custom_csp" {
count = var.custom_content_security_policy != null ? 1 : 0

View file

@ -26,7 +26,7 @@ module "tls_secret" {
# https://pfsense.viktorbarzin.me/
module "pfsense" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "pfsense"
external_name = "pfsense.viktorbarzin.lan"
tls_secret_name = var.tls_secret_name
@ -47,14 +47,13 @@ module "pfsense" {
"gethomepage.dev/widget.fields" = "[\"load\", \"memory\", \"temp\", \"disk\"]"
"gethomepage.dev/widget.wan" = "vtnet0"
}
depends_on = [kubernetes_namespace.reverse-proxy]
rybbit_site_id = "b029580e5a7c"
depends_on = [kubernetes_namespace.reverse-proxy]
}
# https://nas.viktorbarzin.me/
module "nas" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "nas"
external_name = "nas.viktorbarzin.lan"
port = 5001
@ -62,7 +61,6 @@ module "nas" {
backend_protocol = "HTTPS"
max_body_size = "0m"
depends_on = [kubernetes_namespace.reverse-proxy]
rybbit_site_id = "1e11f8449f7d"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Synology NAS"
@ -76,7 +74,7 @@ module "nas" {
# https://files.viktorbarzin.me/
module "nas-files" {
source = "./factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
name = "files"
external_name = "nas.viktorbarzin.lan"
port = 5001
@ -92,7 +90,7 @@ module "nas-files" {
# https://idrac.viktorbarzin.me/
module "idrac" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "idrac"
external_name = "idrac.viktorbarzin.lan"
port = 443
@ -114,7 +112,7 @@ module "idrac" {
# TODO: Not working yet
module "tp-link-gateway" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "gw"
external_name = "gw.viktorbarzin.lan"
port = 443
@ -148,8 +146,7 @@ module "truenas" {
# "gethomepage.dev/widget.enablePools" : "true"
# "gethomepage.dev/pod-selector" : ""
}
depends_on = [kubernetes_namespace.reverse-proxy]
rybbit_site_id = "b66fbd3cb58a"
depends_on = [kubernetes_namespace.reverse-proxy]
}
# https://r730.viktorbarzin.me/
@ -174,7 +171,7 @@ module "r730" {
# https://proxmox.viktorbarzin.me/
module "proxmox" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "proxmox"
external_name = "proxmox.viktorbarzin.lan"
port = 8006
@ -182,7 +179,6 @@ module "proxmox" {
backend_protocol = "HTTPS"
max_body_size = "0" # unlimited
depends_on = [kubernetes_namespace.reverse-proxy]
rybbit_site_id = "190a7ad3e1c7"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Proxmox"
@ -217,14 +213,14 @@ module "docker-registry-ui" {
# https://registry.viktorbarzin.me/ (Docker CLI push/pull endpoint)
module "docker-registry-cli" {
source = "./factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
name = "registry"
external_name = "docker-registry.viktorbarzin.lan"
port = 5050
backend_protocol = "HTTPS"
tls_secret_name = var.tls_secret_name
protected = false # Docker CLI uses htpasswd, NOT Authentik
max_body_size = "0" # unlimited - Docker layers can be large
protected = false # Docker CLI uses htpasswd, NOT Authentik
max_body_size = "0" # unlimited - Docker layers can be large
depends_on = [kubernetes_namespace.reverse-proxy]
extra_annotations = {
# Skip rate-limit (Docker push/pull generates many rapid requests)
@ -237,7 +233,7 @@ module "docker-registry-cli" {
# https://valchedrym.viktorbarzin.me/
module "valchedrym" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "valchedrym"
external_name = "valchedrym.viktorbarzin.lan"
tls_secret_name = var.tls_secret_name
@ -303,14 +299,13 @@ resource "kubernetes_manifest" "ha_sofia_rate_limit" {
module "ha-sofia" {
source = "./factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
name = "ha-sofia"
external_name = "ha-sofia.viktorbarzin.lan"
port = 8123
tls_secret_name = var.tls_secret_name
depends_on = [kubernetes_namespace.reverse-proxy]
protected = false
rybbit_site_id = "590fc392690a"
skip_global_rate_limit = true
extra_middlewares = [
"reverse-proxy-ha-sofia-rate-limit@kubernetescrd",
@ -328,7 +323,7 @@ module "ha-sofia" {
# https://music-assistant.viktorbarzin.me/
module "music-assistant" {
source = "./factory"
dns_type = "non-proxied"
dns_type = "non-proxied"
name = "music-assistant"
external_name = "ha-sofia.viktorbarzin.lan"
port = 8095
@ -364,7 +359,7 @@ module "ha-london" {
# https://london.viktorbarzin.me/
module "london" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "london"
external_name = "openwrt-london.viktorbarzin.lan"
port = 443
@ -388,7 +383,7 @@ module "london" {
}
module "pi-lights" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "pi"
external_name = "ha-london.viktorbarzin.lan"
port = 5000
@ -416,7 +411,7 @@ module "pi-lights" {
module "mbp14" {
source = "./factory"
dns_type = "proxied"
dns_type = "proxied"
name = "mbp14"
external_name = "mbp14.viktorbarzin.lan"
port = 4020

View file

@ -548,7 +548,6 @@ module "ingress" {
name = "rybbit"
service_name = "rybbit-client"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "3c476801a777"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Rybbit"

View file

@ -163,7 +163,6 @@ module "ingress" {
name = "send"
tls_secret_name = var.tls_secret_name
port = 1443
rybbit_site_id = "c1b8f8aa831b"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Send"

View file

@ -128,7 +128,6 @@ module "ingress" {
namespace = kubernetes_namespace.stirling-pdf.metadata[0].name
name = "stirling-pdf"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "a55ac54ec749"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Stirling PDF"

View file

@ -53,12 +53,9 @@ resource "helm_release" "traefik" {
"set -e; ",
"STORAGE=/plugins-storage; ",
"mkdir -p \"$STORAGE/archives/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin\"; ",
"mkdir -p \"$STORAGE/archives/github.com/the-ccsn/traefik-plugin-rewritebody\"; ",
"wget -q -T 30 -O \"$STORAGE/archives/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/v1.4.2.zip\" ",
"\"https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/archive/refs/tags/v1.4.2.zip\"; ",
"wget -q -T 30 -O \"$STORAGE/archives/github.com/the-ccsn/traefik-plugin-rewritebody/v0.1.3.zip\" ",
"\"https://github.com/the-ccsn/traefik-plugin-rewritebody/archive/refs/tags/v0.1.3.zip\"; ",
"printf '{\"github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin\":\"v1.4.2\",\"github.com/the-ccsn/traefik-plugin-rewritebody\":\"v0.1.3\"}' ",
"printf '{\"github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin\":\"v1.4.2\"}' ",
"> \"$STORAGE/archives/state.json\"; ",
"echo \"Plugins pre-downloaded successfully\"",
])]
@ -170,10 +167,6 @@ resource "helm_release" "traefik" {
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
version = "v1.4.2"
}
traefik-plugin-rewritebody = {
moduleName = "github.com/the-ccsn/traefik-plugin-rewritebody"
version = "v0.1.3"
}
}
}

View file

@ -253,33 +253,8 @@ resource "kubernetes_manifest" "middleware_immich_rate_limit" {
depends_on = [helm_release.traefik]
}
# Strip Accept-Encoding header so backends send uncompressed responses.
# Used alongside rewrite-body plugin (rybbit analytics) which fails to
# decompress certain gzip responses (flate: corrupt input before offset 5).
# Also used by anti-AI trap links rewrite-body middleware.
resource "kubernetes_manifest" "middleware_strip_accept_encoding" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "strip-accept-encoding"
namespace = kubernetes_namespace.traefik.metadata[0].name
}
spec = {
headers = {
customRequestHeaders = {
"Accept-Encoding" = ""
}
}
}
}
depends_on = [helm_release.traefik]
}
# Re-compress responses to clients after rewrite-body plugin has modified them.
# Applied at websecure entrypoint level (outermost), so the response path is:
# backend rewrite-body modifies uncompressed HTML compress gzips client.
# Compress responses to clients at the entrypoint level (outermost).
# Applied at websecure entrypoint so all responses get compressed.
# Uses includedContentTypes (whitelist) instead of excludedContentTypes:
# - Only compresses text-based types that benefit from compression
# - Binary types (images, video, zip) are never compressed (no wasted CPU)
@ -368,36 +343,6 @@ resource "kubernetes_manifest" "middleware_anti_ai_headers" {
depends_on = [helm_release.traefik]
}
# Inject hidden trap links before </body> to catch AI scrapers
# Links are CSS-hidden and aria-hidden so humans never see them
resource "kubernetes_manifest" "middleware_anti_ai_trap_links" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "anti-ai-trap-links"
namespace = kubernetes_namespace.traefik.metadata[0].name
}
spec = {
plugin = {
traefik-plugin-rewritebody = {
lastModified = true
rewrites = [{
regex = "</body>"
replacement = "<div style=\"position:absolute;left:-9999px;height:0;overflow:hidden\" aria-hidden=\"true\"><a href=\"https://poison.viktorbarzin.me/article/training-data-2024-research-corpus\">Research Archive</a><a href=\"https://poison.viktorbarzin.me/article/dataset-export-machine-learning-v3\">Dataset Export</a><a href=\"https://poison.viktorbarzin.me/article/nlp-benchmark-evaluation-results\">Benchmark Results</a><a href=\"https://poison.viktorbarzin.me/article/web-crawl-index-2024-archive\">Web Index</a><a href=\"https://poison.viktorbarzin.me/article/text-corpus-english-dump\">Text Corpus</a></div></body>"
}]
monitoring = {
types = ["text/html"]
methods = ["GET"]
}
}
}
}
}
depends_on = [helm_release.traefik]
}
# Retry middleware for transient backend failures (502/503 during restarts)
resource "kubernetes_manifest" "middleware_retry" {
manifest = {

View file

@ -190,7 +190,6 @@ module "ingress" {
"gethomepage.dev/widget.url" = "http://uptime-kuma.uptime-kuma.svc.cluster.local"
"gethomepage.dev/widget.slug" = "infra"
}
rybbit_site_id = "8fef77b1f7fe"
}
# CronJob for daily SQLite backups # no longer needed as we're using the mysql

View file

@ -193,7 +193,6 @@ module "ingress" {
namespace = kubernetes_namespace.vaultwarden.metadata[0].name
name = "vaultwarden"
tls_secret_name = var.tls_secret_name
rybbit_site_id = "b8fc85e18683"
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Vaultwarden"