feat(gitea): add Anubis anti-crawler sidecar
buildbot/nix-eval Build done. (1 warning)
buildbot/nix-build Build done.

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)
This commit is contained in:
root
2026-05-20 03:34:42 -05:00
parent 75e71f9ce9
commit dc083ddf1a
4 changed files with 77 additions and 1 deletions
+23
View File
@@ -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 -
+51
View File
@@ -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:
+2 -1
View File
@@ -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
+1
View File
@@ -7,3 +7,4 @@ resources:
- ingress.yaml
- secrets.yaml
- dump-cronjob.yaml
- anubis-secret.yaml