🛡️ Gitea Bot Protection - Lessons Learned
"Das Problem wird bestimmt vielen auf die Füße fallen"
❌ Warum v1 (deploy-bot-protection.sh) uncool war:
Problem 1: Falsche Datei
Script bearbeitete: git.crumbforest.org
Aber nginx nutzt: git.crumbforest.org.conf
= Script änderte falsche Datei, nichts passierte
Problem 2: Multiline Return Statements
# Das funktioniert NICHT:
return 200 "Line 1
Line 2
Line 3";
# Nginx Syntax Error!
Problem 3: Gitea kämpfen statt mit Gitea arbeiten
Versuch: robots.txt in nginx location block
Reality: Gitea fängt /robots.txt ab und gibt 404
= Gitea HAT eigene robots.txt Funktion!
= Nutze die statt dagegen zu kämpfen!
Problem 4: Zu komplex
- 300+ Zeilen Code
- Viele Annahmen über File-Struktur
- Komplexe sed/awk Magie
- Schwer zu debuggen
= Uncool!
✅ Warum v2 (deploy-gitea-bot-protection.sh) cool ist:
Fix 1: Findet die richtige Config
# Versucht alle gängigen Namen:
- git.crumbforest.org
- git.crumbforest.org.conf
- gitea
- gitea.conf
# Checked ob git.crumbforest.org drin steht
# = Funktioniert immer!
Fix 2: Arbeitet MIT Gitea
# In /etc/gitea/app.ini:
[other]
ROBOTS_TXT = User-agent: GPTBot\nDisallow: /
= Gitea's EIGENE robots.txt Funktion!
= Kein Kampf mit nginx location blocks
= Funktioniert IMMER!
Fix 3: Simple Rate Limiting
# Keine komplexen if-Blocks in location
# Sondern: Eine Zone, eine Zeile
limit_req zone=$gitea_rate_limit_zone burst=10 nodelay;
= Einfach, lesbar, funktioniert
Fix 4: Robuste Checks
# Pre-flight:
- Ist Gitea installiert?
- Existiert app.ini?
- Ist nginx da?
# Post-flight:
- nginx -t (config valid?)
- curl robots.txt (funktioniert?)
- Rollback wenn Fehler
= Kann nicht kaputt gehen!
🔧 Installation (v2):
# 1. Script downloaden
wget https://git.crumbforest.org/.../deploy-gitea-bot-protection.sh
# ODER: Aus diesem Repo
# 2. Ausführbar machen
chmod +x deploy-gitea-bot-protection.sh
# 3. Als root ausführen
sudo ./deploy-gitea-bot-protection.sh
# 4. Fertig!
🐛 Troubleshooting:
"robots.txt gibt immer noch 404"
# Check 1: Ist [other] Section in app.ini?
grep -A 2 "\[other\]" /etc/gitea/app.ini
# Sollte zeigen:
# [other]
# ROBOTS_TXT = ...
# Check 2: Wurde Gitea neu gestartet?
sudo systemctl restart gitea
# Check 3: Ist Gitea wirklich auf Port 3000?
ss -tlnp | grep 3000
# Check 4: Test direkt gegen Gitea (ohne nginx)
curl http://localhost:3000/robots.txt
"Rate limiting funktioniert nicht"
# Check 1: Ist die Config-Datei da?
ls -la /etc/nginx/conf.d/gitea-rate-limits.conf
# Check 2: Ist nginx config valid?
sudo nginx -t
# Check 3: Sind die Zones geladen?
sudo nginx -T | grep "limit_req_zone"
# Check 4: Monitoring
tail -f /var/log/nginx/error.log | grep "limiting requests"
# Wenn OpenAI crawlt und limit erreicht:
# [error] limiting requests, excess: 5.123 by zone "gitea_openai"
"Script findet nginx config nicht"
# Manuell suchen:
find /etc/nginx -name "*git*"
# Welche wird wirklich geladen?
sudo nginx -T | grep "git.crumbforest.org"
# Symlink checken:
ls -la /etc/nginx/sites-enabled/ | grep git
# Falls nicht gefunden:
# → Script anpassen mit richtigem Pfad
# → Oder manuell deployen (siehe Manual Deploy unten)
"Nginx reload failed"
# Check syntax error:
sudo nginx -t
# Check logs:
sudo journalctl -u nginx -n 50
# Rollback zum Backup:
BACKUP_DIR="/root/bot-protection-backup-XXXXXXXX" # Vom Script Output
sudo cp $BACKUP_DIR/nginx.backup /etc/nginx/sites-available/git.crumbforest.org.conf
sudo systemctl reload nginx
🔧 Manual Deploy (Fallback):
Falls Script komplett fehlschlägt:
Schritt 1: Gitea robots.txt
sudo nano /etc/gitea/app.ini
Am Ende hinzufügen:
[other]
ROBOTS_TXT = User-agent: GPTBot\nDisallow: /\n\nUser-agent: ChatGPT-User\nDisallow: /\n\nUser-agent: *\nAllow: /
Speichern und Gitea neu starten:
sudo systemctl restart gitea
curl http://localhost:3000/robots.txt # Test!
Schritt 2: Rate Limiting
sudo nano /etc/nginx/conf.d/gitea-rate-limits.conf
Inhalt:
# Rate Limit Zones
limit_req_zone $binary_remote_addr zone=gitea_openai:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=gitea_general:10m rate=100r/m;
# OpenAI Detection
geo $is_openai {
default 0;
74.7.227.0/24 1;
74.7.242.0/24 1;
74.7.243.0/24 1;
}
# Select Zone
map $is_openai $rate_zone {
default "gitea_general";
1 "gitea_openai";
}
In nginx site config (git.crumbforest.org.conf):
sudo nano /etc/nginx/sites-available/git.crumbforest.org.conf
In location / Block (vor proxy_pass):
location / {
limit_req zone=$rate_zone burst=10 nodelay;
proxy_pass http://localhost:3000;
# ... rest
}
Test und reload:
sudo nginx -t
sudo systemctl reload nginx
📊 Monitoring nach Deploy:
# 1. Live OpenAI Requests
tail -f /var/log/nginx/access.log | grep "74.7.227"
# 2. Rate Limit Hits
tail -f /var/log/nginx/error.log | grep "limiting requests"
# 3. Gitea Status
systemctl status gitea
# 4. robots.txt Fetches
grep "robots.txt" /var/log/nginx/access.log | tail -20
# 5. Morgen: waldwächter-analyzer.sh nochmal laufen
./waldwächter-analyzer.sh
# Sollte zeigen: MASSIV weniger OpenAI Traffic!
🎯 Erwartete Resultate:
Vorher:
OpenAI (74.7.227.14): 47,329 requests/Tag
= Alle 2 Sekunden ein Request!
= Crawlt ALLES (jeden Commit, jeden Branch)
Nachher:
OpenAI: MAX 5 requests/Minute
= 7,200 requests/Tag
= 85% REDUKTION! 🎉
robots.txt zeigt: Disallow: /
= Bots die respektieren (Googlebot, etc) stoppen komplett
= Bots die nicht respektieren (manche) werden rate-limited
💡 Für andere Gitea Instanzen:
Dieses Problem betrifft JEDEN der:
- Gitea öffentlich hosted
- Nginx als Reverse Proxy nutzt
- Von AI Crawlern gecrawlt wird
Die Lösung:
1. NICHT in nginx robots.txt bauen
2. SONDERN Gitea's app.ini nutzen
3. Rate Limiting in nginx (einfach)
4. Test, deploy, monitor
Das Script funktioniert für:
- Ubuntu/Debian
- Standard Gitea Installation
- Nginx als Reverse Proxy
- LetsEncrypt SSL
Anpassungen nötig für:
- Andere Distros (Paths können abweichen)
- Apache statt Nginx
- Andere Proxy-Setups
📝 License & Credits:
Script: MIT + CKL + HHL
Von: waldwächter Team / Crumbforest
Für: Alle die das gleiche Problem haben werden
"Steal it smart!"
🐛 Bug Reports:
Falls Script bei dir nicht funktioniert:
- Run mit debug:
bash -x ./deploy-gitea-bot-protection.sh 2>&1 | tee debug.log
- Share debug.log + diese Info:
- OS Version (
cat /etc/os-release) - Nginx Version (
nginx -v) - Gitea Version (
gitea --version) -
Config paths (
find /etc/nginx -name "*git*") -
Öffne Issue oder PR mit Fix!
🌲 waldwächter says: Viel Erfolg! Und: Der Wald schützt zurück!