From dc083ddf1a92074963f59441804ebdebad3653dc Mon Sep 17 00:00:00 2001 From: root Date: Wed, 20 May 2026 03:34:42 -0500 Subject: [PATCH] feat(gitea): add Anubis anti-crawler sidecar Anubis (https://anubis.techaro.lol) is a lightweight proof-of-work challenge that protects web services from AI crawlers and scrapers. Changes: - Add Anubis as an extraContainers sidecar in the Gitea HelmRelease - Listens on :8080, proxies to Gitea at http://localhost:3000 - DIFFICULTY=4 (default; tune up to increase challenge strength) - SERVE_ROBOTS_TXT=true (Anubis manages robots.txt) - OG_PASSTHROUGH=true (OpenGraph bots pass through for link previews) - Signs challenges with ED25519 key from 'anubis-key' secret - Add anubis port (8080) to Gitea service via additionalPorts - Update Ingress to route to the 'anubis' port instead of 'http' - Add anubis-secret.yaml placeholder with creation instructions One-time setup required before applying: kubectl create secret generic anubis-key \ --namespace gitea \ --from-literal=ED25519_PRIVATE_KEY_HEX=$(openssl rand -hex 32) --- manifests/gitea/anubis-secret.yaml | 23 ++++++++++++++ manifests/gitea/chart.yaml | 51 ++++++++++++++++++++++++++++++ manifests/gitea/ingress.yaml | 3 +- manifests/gitea/kustomization.yaml | 1 + 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 manifests/gitea/anubis-secret.yaml diff --git a/manifests/gitea/anubis-secret.yaml b/manifests/gitea/anubis-secret.yaml new file mode 100644 index 0000000..dc1eab9 --- /dev/null +++ b/manifests/gitea/anubis-secret.yaml @@ -0,0 +1,23 @@ +# Secret for Anubis ED25519 signing key. +# Create with: +# kubectl create secret generic anubis-key \ +# --namespace gitea \ +# --from-literal=ED25519_PRIVATE_KEY_HEX=$(openssl rand -hex 32) +# This file is a placeholder so kustomization knows the secret must exist. +# The secret is NOT managed here to avoid storing the key in git. +# +# If using external-secrets or agenix, replace this comment block with +# the appropriate ExternalSecret / SealedSecret manifest. +apiVersion: v1 +kind: Secret +metadata: + name: anubis-key + namespace: gitea + annotations: + # Managed manually — do not overwrite with kustomize apply + kustomize.toolkit.fluxcd.io/prune: disabled +type: Opaque +# data is intentionally empty; populate via: +# kubectl create secret generic anubis-key --namespace gitea \ +# --from-literal=ED25519_PRIVATE_KEY_HEX=$(openssl rand -hex 32) \ +# --dry-run=client -o yaml | kubectl apply -f - diff --git a/manifests/gitea/chart.yaml b/manifests/gitea/chart.yaml index 9aa3a56..bc1729f 100644 --- a/manifests/gitea/chart.yaml +++ b/manifests/gitea/chart.yaml @@ -47,6 +47,12 @@ spec: type: LoadBalancer port: 32222 nodePort: 32222 + # Anubis sidecar port — ingress routes here; Anubis proxies to :3000 + additionalPorts: + - name: anubis + port: 8080 + targetPort: 8080 + protocol: TCP gitea: admin: @@ -119,6 +125,51 @@ spec: cpu: "100m" memory: "2Gi" + # Anubis anti-crawler sidecar + # Anubis listens on :8080 and proxies to Gitea at http://localhost:3000 + # Ingress is updated to route to the anubis port instead of http + extraContainers: + - name: anubis + image: ghcr.io/techarohq/anubis:latest + imagePullPolicy: Always + env: + - name: BIND + value: ":8080" + - name: DIFFICULTY + value: "4" + - name: ED25519_PRIVATE_KEY_HEX + valueFrom: + secretKeyRef: + name: anubis-key + key: ED25519_PRIVATE_KEY_HEX + - name: METRICS_BIND + value: ":9090" + - name: SERVE_ROBOTS_TXT + value: "true" + - name: TARGET + value: "http://localhost:3000" + - name: OG_PASSTHROUGH + value: "true" + - name: OG_EXPIRY_TIME + value: "24h" + resources: + limits: + cpu: "750m" + memory: "256Mi" + requests: + cpu: "250m" + memory: "256Mi" + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + strategy: type: RollingUpdate rollingUpdate: diff --git a/manifests/gitea/ingress.yaml b/manifests/gitea/ingress.yaml index 9ce31de..c9b7a21 100644 --- a/manifests/gitea/ingress.yaml +++ b/manifests/gitea/ingress.yaml @@ -8,7 +8,8 @@ spec: service: name: gitea-release-http port: - name: http + # Route through Anubis anti-crawler sidecar instead of directly to Gitea + name: anubis tls: - hosts: - gitea diff --git a/manifests/gitea/kustomization.yaml b/manifests/gitea/kustomization.yaml index a66546d..8ee13ec 100644 --- a/manifests/gitea/kustomization.yaml +++ b/manifests/gitea/kustomization.yaml @@ -7,3 +7,4 @@ resources: - ingress.yaml - secrets.yaml - dump-cronjob.yaml + - anubis-secret.yaml