Author SHA1 Message Date
klaatu aa4afea341 chore(gitea/anubis): remove anubis-secret from kustomization
buildbot/nix-eval Build done. (1 warning)
buildbot/nix-build Build done.
2026-05-21 06:05:54 +00:00
klaatu b12731a100 chore(gitea/anubis): remove anubis-secret.yaml, no manual secret needed
buildbot/nix-eval Build done.
2026-05-21 06:05:42 +00:00
klaatu ce2c9c76a7 chore(gitea/anubis): remove ED25519 secret env var, Anubis auto-generates key
buildbot/nix-eval Build done.
2026-05-21 06:05:34 +00:00
root dc083ddf1a 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)
2026-05-20 03:34:42 -05:00
5 changed files with 67 additions and 91 deletions
+25 -23
View File
@@ -13,23 +13,25 @@
includes = [ "config.local" ]; includes = [ "config.local" ];
enableDefaultConfig = false; enableDefaultConfig = false;
settings = matchBlocks =
let let
nas = { nas = {
User = "admin"; user = "admin";
}; };
owned = { owned = {
User = "greg"; user = "greg";
}; };
in in
{ {
inherit nas; inherit nas;
"*" = { "*" = {
DynamicForward = [ "10240" ]; dynamicForwards = [ { port = 10240; } ];
ServerAliveInterval = 60; serverAliveInterval = 60;
extraOptions = {
LogLevel = "error"; LogLevel = "error";
SetEnv = { TERM = "xterm-256color"; }; SetEnv = "TERM=xterm-256color";
};
}; };
"10.42.1.4" = lib.hm.dag.entryBefore [ "10.42.*" ] nas; "10.42.1.4" = lib.hm.dag.entryBefore [ "10.42.*" ] nas;
@@ -39,46 +41,46 @@
"chronicles.thehellings.lan" = lib.hm.dag.entryBefore [ "*.thehellings.lan" ] nas; "chronicles.thehellings.lan" = lib.hm.dag.entryBefore [ "*.thehellings.lan" ] nas;
gh = { gh = {
User = "git"; user = "git";
Hostname = "github.com"; hostname = "github.com";
}; };
"src" = { "src" = {
User = "git"; user = "git";
Hostname = "jeremiah.shire-zebra.ts.net"; hostname = "jeremiah.shire-zebra.ts.net";
Port = 32222; port = 32222;
}; };
srcpub = { srcpub = {
User = "git"; user = "git";
Hostname = "src.thehellings.com"; hostname = "src.thehellings.com";
Port = 2222; port = 2222;
}; };
ivr = { ivr = {
User = "git"; user = "git";
Hostname = "gitlab.com"; hostname = "gitlab.com";
}; };
"ivr.thehellings.lan" = lib.hm.dag.entryBefore [ "ivr" ] { "ivr.thehellings.lan" = lib.hm.dag.entryBefore [ "ivr" ] {
User = "gregory.hellings"; user = "gregory.hellings";
}; };
"*.thehellings.lan" = owned; "*.thehellings.lan" = owned;
"10.42.*" = owned; "10.42.*" = owned;
"host.crosswire.org crosswire" = { "host.crosswire.org crosswire" = {
Hostname = "host.crosswire.org"; hostname = "host.crosswire.org";
User = "ghellings"; user = "ghellings";
}; };
fedpeople = { fedpeople = {
Hostname = "fedorapeople.org"; hostname = "fedorapeople.org";
User = "greghellings"; user = "greghellings";
}; };
"src.fedoraproject.org pkgs.fedoraproject.org" = { "src.fedoraproject.org pkgs.fedoraproject.org" = {
User = "greghellings"; user = "greghellings";
}; };
"127.*" = { "127.*".extraOptions = {
PubkeyAcceptedAlgorithms = "+ssh-rsa"; PubkeyAcceptedAlgorithms = "+ssh-rsa";
HostkeyAlgorithms = "+ssh-rsa"; HostkeyAlgorithms = "+ssh-rsa";
}; };
+15 -41
View File
@@ -1,4 +1,4 @@
{ config, ... }: { ... }:
let let
srcDomain = "src.thehellings.com"; srcDomain = "src.thehellings.com";
@@ -6,23 +6,15 @@ let
in in
{ {
greg.proxies."${srcDomain}" = { greg.proxies."${srcDomain}" = {
target = "http://unix:${config.services.anubis.instances.git.settings.BIND}"; target = "https://gitea.shire-zebra.ts.net";
ssl = true; ssl = true;
genAliases = false; genAliases = false;
extraConfig = '' extraConfig = ''
#proxy_ssl_verify off; proxy_ssl_verify off;
#proxy_ssl_server_name on; proxy_ssl_server_name on;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Http-Version $server_protocol;
proxy_set_header User-Agent $http_user_agent;
client_max_body_size 100000m; client_max_body_size 100000m;
#proxy_set_header Host $host;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-Forwarded-Proto $scheme;
#proxy_set_header X-Forwarded-Ssl on;
# Ultimate AI Block List v1.7 20250924 # Ultimate AI Block List v1.7 20250924
# https://perishablepress.com/ultimate-ai-block-list/ # https://perishablepress.com/ultimate-ai-block-list/
@@ -95,22 +87,18 @@ in
networking.firewall.allowedTCPPorts = [ sshPort ]; networking.firewall.allowedTCPPorts = [ sshPort ];
services = { systemd.services = {
anubis = { haproxy = {
instances = { after = [
git = { "network-online.target"
enable = true; ];
settings = { wants = [
BIND = "/run/anubis/anubis-git/anubis.sock"; "network-online.target"
COOKIE_DOMAIN = "thehellings.com"; ];
SERVE_ROBOTS_TXT = true;
TARGET = "https://gitea.shire-zebra.ts.net/";
};
};
}; };
}; };
haproxy = { services.haproxy = {
enable = true; enable = true;
config = '' config = ''
global global
@@ -131,18 +119,4 @@ in
server git-zeke zeke.shire-zebra.ts.net:32222 server git-zeke zeke.shire-zebra.ts.net:32222
''; '';
}; };
};
systemd.services = {
haproxy = {
after = [
"network-online.target"
];
wants = [
"network-online.target"
];
};
};
users.users.nginx.extraGroups = [ config.users.groups.anubis.name ];
} }
+10 -11
View File
@@ -47,6 +47,12 @@ spec:
type: LoadBalancer type: LoadBalancer
port: 32222 port: 32222
nodePort: 32222 nodePort: 32222
# Anubis sidecar port — ingress routes here; Anubis proxies to :3000
additionalPorts:
- name: anubis
port: 8080
targetPort: 8080
protocol: TCP
gitea: gitea:
admin: admin:
@@ -133,16 +139,14 @@ spec:
value: "4" value: "4"
- name: METRICS_BIND - name: METRICS_BIND
value: ":9090" value: ":9090"
- name: POLICY_FNAME
value: "/etc/anubis/policy.yaml"
- name: SERVE_ROBOTS_TXT - name: SERVE_ROBOTS_TXT
value: "true" value: "true"
- name: TARGET - name: TARGET
value: "http://localhost:3000" value: "http://localhost:3000"
volumeMounts: - name: OG_PASSTHROUGH
- name: anubis-policy value: "true"
mountPath: /etc/anubis - name: OG_EXPIRY_TIME
readOnly: true value: "24h"
resources: resources:
limits: limits:
cpu: "750m" cpu: "750m"
@@ -161,11 +165,6 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
extraVolumes:
- name: anubis-policy
configMap:
name: anubis-policy
strategy: strategy:
type: RollingUpdate type: RollingUpdate
rollingUpdate: rollingUpdate:
+2 -1
View File
@@ -8,7 +8,8 @@ spec:
service: service:
name: gitea-release-http name: gitea-release-http
port: port:
name: http # Route through Anubis anti-crawler sidecar instead of directly to Gitea
name: anubis
tls: tls:
- hosts: - hosts:
- gitea - gitea
+2 -2
View File
@@ -15,8 +15,8 @@ spec:
storage: |- storage: |-
MINIO_ACCESS_KEY_ID={{ .minio_nas1_key }} MINIO_ACCESS_KEY_ID={{ .minio_nas1_key }}
MINIO_SECRET_ACCESS_KEY={{ .minio_nas1_secret }} MINIO_SECRET_ACCESS_KEY={{ .minio_nas1_secret }}
#minio_key: "{{ .minio_nas1_key }}" minio_key: "{{ .minio_nas1_key }}"
#minio_secret: "{{ .minio_nas1_secret }}" minio_secret: "{{ .minio_nas1_secret }}"
secretStoreRef: secretStoreRef:
name: bitwarden-login name: bitwarden-login
kind: ClusterSecretStore kind: ClusterSecretStore