git: Serve cgit via a Traefik IngressRoute.

Traefik's ingress-nginx provider rejects the cgit Ingress because of its
limit_req snippet.  Add an IngressRoute with the same rewrite and a
global per-host rate limit (5 r/s, burst 20) as Traefik middlewares.
The Ingress stays until ingress-nginx is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ib5d6c229380a9f181695deec0b5faa2e90d24a53
diff --git a/git/git.yaml b/git/git.yaml
index 7c69e92..884ba9b 100644
--- a/git/git.yaml
+++ b/git/git.yaml
@@ -201,6 +201,85 @@
     - git.benkard.de
     secretName: git-cgit-cgi-tls
 ---
+# Traefik route for cgit.  Traefik's ingress-nginx provider rejects the
+# Ingress above because of its snippet, and it has no global per-host rate
+# limit, so cgit gets a native IngressRoute instead.
+#
+# A crawler botnet with thousands of rotating IPs and browser user agents
+# hammers cgit; cap it at 5 r/s in total (not per client).  A single router
+# keeps the limit in one bucket (each router gets its own limiter).
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+  name: git-cgit-ratelimit
+  namespace: mulk
+spec:
+  rateLimit:
+    average: 5
+    period: 1s
+    burst: 20
+    sourceCriterion:
+      requestHost: true
+---
+# Same as the rewrite-target of the Ingress above: strip a ".git" suffix
+# from the repository name and route everything to cgit.cgi.
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+  name: git-cgit-rewrite
+  namespace: mulk
+spec:
+  replacePathRegex:
+    regex: "^/(?:(.*)[.]git(/.*)?|(.*))$"
+    replacement: "/cgit/cgit.cgi/${1}${2}${3}"
+---
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+  name: git-cgit-https-redirect
+  namespace: mulk
+spec:
+  redirectScheme:
+    scheme: https
+    permanent: true
+---
+apiVersion: traefik.io/v1alpha1
+kind: IngressRoute
+metadata:
+  name: git-cgit-cgi
+  namespace: mulk
+spec:
+  entryPoints:
+  - websecure
+  routes:
+  - kind: Rule
+    match: Host(`git.benkard.de`)
+    middlewares:
+    - name: git-cgit-ratelimit
+    - name: git-cgit-rewrite
+    services:
+    - name: git-cgit
+      port: 80
+  tls:
+    secretName: git-cgit-cgi-tls
+---
+apiVersion: traefik.io/v1alpha1
+kind: IngressRoute
+metadata:
+  name: git-cgit-cgi-http
+  namespace: mulk
+spec:
+  entryPoints:
+  - web
+  routes:
+  - kind: Rule
+    match: Host(`git.benkard.de`)
+    middlewares:
+    - name: git-cgit-https-redirect
+    services:
+    - name: git-cgit
+      port: 80
+---
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata: