Gitea Knowledge — Admin Handbuch

Channel: #gitea
Persona: Deepbit 🔧
Version: Gitea 1.25.4 auf Debian 12 (Bookworm)
DB: SQLite (/var/lib/gitea/data/gitea.db)
Config: /etc/gitea/app.ini
User: gitea (system)
Binary: /usr/local/bin/gitea


1. Architektur im Crumbforest

Internet → nginx (443) → Gitea (3000, localhost) → SQLite
                ↑                                     ↑
           TLS + Proxy                          Repos + Users
           Bot-Filter                           Webhooks

Gitea lauscht nur auf localhost:3000. nginx macht TLS und Reverse Proxy.
Kein direkter Zugang von außen auf Port 3000.

2. Service Management

# Status
systemctl status gitea

# Neustart (nach Config-Änderung)
systemctl restart gitea

# Logs
journalctl -u gitea -f
journalctl -u gitea -n 50 --no-pager

# Gitea Version
gitea --version

3. Konfiguration: app.ini

Pfad: /etc/gitea/app.ini

Kritische Sicherheits-Settings

[service]
DISABLE_REGISTRATION = true          # Keine öffentliche Registrierung
REQUIRE_SIGNIN_VIEW = true           # Repos nur fĂŒr eingeloggte User sichtbar
ENABLE_CAPTCHA = true                # Captcha bei Registrierung (falls offen)
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
SHOW_REGISTRATION_BUTTON = false     # Kein "Registrieren" Button
ENABLE_NOTIFY_MAIL = false           # Kein Mail-Versand

[openid]
ENABLE_OPENID_SIGNIN = false         # Kein OpenID
ENABLE_OPENID_SIGNUP = false

[other]
SHOW_FOOTER_VERSION = false          # Versionsnummer verstecken

Nach jeder Änderung

systemctl restart gitea

Config validieren

# PrĂŒfe ob Setting gesetzt ist
grep -A5 '\[service\]' /etc/gitea/app.ini

4. User Management

User anlegen (nur Admin)

sudo -u gitea gitea admin user create \
    --username neueruser \
    --password "sicheres_passwort" \
    --email user@crumbforest.org \
    --admin false \
    -c /etc/gitea/app.ini

User auflisten

sudo -u gitea gitea admin user list -c /etc/gitea/app.ini

User löschen

# Ohne Repos
sudo -u gitea gitea admin user delete --username USERNAME -c /etc/gitea/app.ini

# Mit Repos (purge = alles löschen)
sudo -u gitea gitea admin user delete --username USERNAME --purge -c /etc/gitea/app.ini

Wichtig: Ohne --purge schlÀgt das Löschen fehl wenn der User Repos besitzt.

User zum Admin machen

sudo -u gitea gitea admin user change-password \
    --username USERNAME --must-change-password false -c /etc/gitea/app.ini

# Oder direkt in der DB
sqlite3 /var/lib/gitea/data/gitea.db "UPDATE user SET is_admin=1 WHERE lower_name='username'"

Bulk-Delete (mit Rate-Limit Schutz)

cat spam_users.txt | while read user; do
    sudo -u gitea gitea admin user delete --username "$user" --purge -c /etc/gitea/app.ini
    sleep 2  # Rate-Limit umgehen
done

5. Repository Management

Repos auflisten

sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT r.id, u.lower_name AS owner, r.name, r.is_private
    FROM repository r
    JOIN user u ON r.owner_id = u.id
    ORDER BY u.lower_name, r.name
"

Repo-Statistiken

sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT u.lower_name AS owner, COUNT(*) AS repos, SUM(r.num_stars) AS stars
    FROM repository r
    JOIN user u ON r.owner_id = u.id
    GROUP BY u.lower_name
    ORDER BY repos DESC
"

Verwaiste Repos finden

sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT r.name, r.owner_id 
    FROM repository r
    LEFT JOIN user u ON r.owner_id = u.id
    WHERE u.id IS NULL
"

6. Datenbank

SQLite Basics

# Shell öffnen
sqlite3 /var/lib/gitea/data/gitea.db

# Tabellen anzeigen
.tables

# Schema einer Tabelle
.schema user

# Beenden
.quit

Wichtige Queries

# Alle User mit Details
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT id, lower_name, email, is_admin, num_repos,
           datetime(created_unix, 'unixepoch') AS created,
           datetime(last_login_unix, 'unixepoch') AS last_login
    FROM user WHERE type=0
    ORDER BY created_unix DESC
"

# User pro Tag (Bulk-Registrierungen erkennen)
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT date(created_unix, 'unixepoch') AS d, COUNT(*) AS c
    FROM user WHERE type=0
    GROUP BY d ORDER BY d DESC LIMIT 30
"

# User ohne Repos (Spam-Kandidaten)
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT lower_name, email, datetime(created_unix, 'unixepoch') AS created
    FROM user 
    WHERE type=0 AND is_admin=0 AND num_repos=0
    ORDER BY created_unix DESC
"

# Repos pro User
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT u.lower_name, COUNT(r.id) AS repos
    FROM user u
    LEFT JOIN repository r ON u.id = r.owner_id
    WHERE u.type=0
    GROUP BY u.lower_name
    ORDER BY repos DESC
"

Backup

# SQLite Backup (atomic)
sqlite3 /var/lib/gitea/data/gitea.db ".backup /root/gitea_backup_$(date +%Y%m%d).db"

# Oder mit borgmatic (empfohlen)
# Gitea-Daten sind in den borgmatic Pfaden enthalten:
# /var/lib/gitea/data/
# /etc/gitea/
# /opt/gitea/ (repos)

7. Nginx Reverse Proxy

Typische Config

server {
    listen 443 ssl http2;
    server_name git.crumbforest.org;

    ssl_certificate /etc/letsencrypt/live/git.crumbforest.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.crumbforest.org/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Git ĂŒber HTTP: große Uploads erlauben
        client_max_body_size 100M;
    }
}

Registrierungs-Versuche im Log finden

grep "user/sign_up\|user/register" /var/log/nginx/access.log | \
    awk '{print $1}' | sort | uniq -c | sort -rn | head -20

8. Spam-Erkennung & Forensik

Schnell-Check

# Gibt es verdÀchtige User?
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT lower_name, email, website
    FROM user WHERE type=0
      AND (email LIKE '%@topcompanygroup.com'
        OR website LIKE '%:3000%'
        OR website LIKE '%:30000%'
        OR website LIKE '%rentry.co%')
"

Automatisiert

# gitea_ninja.sh installiert unter /root/
gitea_ninja.sh --analyze    # Read-only Analyse
gitea_ninja.sh --harden     # Config prĂŒfen
gitea_ninja.sh --report     # Markdown fĂŒr Vektor

Typische Spam-Merkmale

Signal Bewertung
0 Repos, 0 Commits ⚠ VerdĂ€chtig (wenn nicht frisch registriert)
Gleiche Email-Domain bei >5 Usern ❌ Spam
Profil-Website auf Port 3000/30000 ❌ Spam (externe Gitea-Instanzen)
>3 Registrierungen am gleichen Tag ⚠ Bulk-Registrierung
Kein Login nach Registrierung ⚠ Bot

9. Gitea Update

# 1. Backup
sqlite3 /var/lib/gitea/data/gitea.db ".backup /root/gitea_pre_update.db"
cp /etc/gitea/app.ini /etc/gitea/app.ini.bak

# 2. Download neue Version
wget -O /tmp/gitea https://dl.gitea.com/gitea/VERSION/gitea-VERSION-linux-amd64
chmod +x /tmp/gitea

# 3. Service stoppen
systemctl stop gitea

# 4. Binary ersetzen
cp /usr/local/bin/gitea /usr/local/bin/gitea.old
mv /tmp/gitea /usr/local/bin/gitea

# 5. Starten
systemctl start gitea

# 6. PrĂŒfen
gitea --version
systemctl status gitea

# 7. Nach Update: Sicherheits-Settings prĂŒfen!
gitea_ninja.sh --harden

10. Webhooks fĂŒr den Wald

Repo-Push → Vector Collector triggern

# In Gitea: Repository → Settings → Webhooks → Add Webhook
# URL: http://127.0.0.1:5001/api/webhook/gitea
# Content-Type: application/json
# Events: Push

Webhook-Log prĂŒfen

sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT id, repo_id, url, last_status,
           datetime(updated_unix, 'unixepoch') AS updated
    FROM webhook
    ORDER BY updated_unix DESC
"

11. Troubleshooting

Gitea startet nicht

# Logs prĂŒfen
journalctl -u gitea -n 50 --no-pager

# HĂ€ufige Ursachen:
# 1. Port 3000 belegt
ss -tlnp | grep 3000

# 2. Berechtigungen
ls -la /var/lib/gitea/data/gitea.db
# Muss gitea:gitea gehören

# 3. Config-Fehler
gitea doctor check -c /etc/gitea/app.ini

Git Clone schlÀgt fehl

# 503 vom Proxy? → Gitea ĂŒberlastet oder Rate-Limit
# Lösung: sleep zwischen Clones
for repo in repo1 repo2 repo3; do
    git clone https://git.crumbforest.org/branko/$repo.git
    sleep 1  # Gitea atmen lassen
done

"Repository does not exist"

# PrĂŒfe ob Repo-Daten noch auf Disk liegen
ls /opt/gitea/data/gitea-repositories/branko/

# PrĂŒfe DB
sqlite3 /var/lib/gitea/data/gitea.db "
    SELECT name, is_empty FROM repository WHERE lower_name='reponame'
"

12. Wichtige Pfade

Pfad Inhalt
/etc/gitea/app.ini Hauptkonfiguration
/var/lib/gitea/data/gitea.db SQLite Datenbank
/var/lib/gitea/data/ Gitea Daten (Avatare, Attachments, LFS)
/opt/gitea/data/gitea-repositories/ Git Bare Repos (oder /var/lib/gitea/repositories/)
/usr/local/bin/gitea Binary
/var/log/nginx/access.log Nginx Zugriffs-Log
/root/gitea_ninja.sh Spam-Forensik Tool
/root/gitea-forensics/ Forensik Reports

13. Crumbforest-spezifisch

Vector Collector braucht Clone-Zugriff

# vector-collector-nullfeld.sh klont alle Repos
# Bei REQUIRE_SIGNIN_VIEW=true braucht der Collector Auth:
git clone https://USER:TOKEN@git.crumbforest.org/branko/REPO.git

# Token erstellen: Gitea → User Settings → Applications → Generate Token
# Oder: .netrc Datei
echo "machine git.crumbforest.org login branko password TOKEN" >> ~/.netrc
chmod 600 ~/.netrc

Neues Repo → Vektor Pipeline

1. Repo in Gitea erstellen
2. Content pushen
3. REPO_MAP in forest_seed.py erweitern
4. forest_seed --repo NeuesRepo
5. → Chunks im Vektor, Persona kann antworten

Erstellt: 30.03.2026 — Aus echtem Angriff gelernt.
Gitea 1.25.4 · Debian 12 · Der Wald schĂŒtzt sich selbst. đŸ„·đŸŒČ