diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9feaf3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +# Secrets — NEVER commit +.env +.env.local +.env.*.local +*.key +*.pem +*.p12 +*.pfx +secrets/ +credentials/ + +# Backups and dumps +*.sql +*.sql.gz +*.tar.gz +*.tar.xz +backups/ +dumps/ + +# Runtime data that shouldn't be in version control +data/ +volumes/ +storage/ +acme.json + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.venv/ +venv/ +env/ +.Python +pip-log.txt +.coverage +.pytest_cache/ + +# Node +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +dist/ +build/ +.next/ +.astro/ + +# IDE / Editor +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# OS +.DS_Store +.AppleDouble +.LSOverride +Thumbs.db +ehthumbs.db +Desktop.ini + +# Temporary +*.tmp +*.bak +*.orig +.#* +#*# diff --git a/Agent.md b/Agent.md new file mode 100644 index 0000000..090c6ae --- /dev/null +++ b/Agent.md @@ -0,0 +1,99 @@ +# Agent Briefing — electric-horses-infra + +Du bist ein AI-Agent der an der Infrastructure-as-Code-Ablage von Electric Horses / Richter & Zech arbeitet. + +## Was ist dieses Repo? +**Die versionierte Beschreibung unserer Hetzner-Cloud-Infrastruktur.** +Alles was wir auf Servern laufen lassen (docker-compose-Stacks, Configs, Scripts) ist hier abgebildet — ohne Secrets. Das Repo ist kein Deploy-Mechanismus (wir ziehen nicht automatisch aus Git auf die Server), sondern die **Wahrheit-von-gestern**: was aktuell läuft. + +Wenn Server A und dieses Repo unterschiedliche Inhalte zeigen, ist entweder ein Commit noch offen ODER die AI hat manuell am Server gearbeitet und das Repo nicht nachgezogen — letzteres ist ein Bug und muss nachgeholt werden. + +## Vor jeder Aktion +1. **Lies `README.md`** — die aktuellen Regeln +2. **Lies `Agent.md`** im betroffenen Stack-Ordner (z.B. `stacks/forgejo/Agent.md`) falls vorhanden +3. **Verstehe den aktuellen Zustand** — `git log --oneline -20` zeigt die letzten Aktionen + +## Konventionen + +### Commit-Messages +- Auf Deutsch ODER Englisch, konsistent pro Commit +- Konventioneller Prefix (feat / fix / docs / refactor / chore) +- Referenz auf OpenProject wenn anwendbar: `Refs OP#1234` +- Kurz und konkret, Detail in Commit-Body + +Beispiele: +``` +feat(forgejo): add backup cron script + +Refs OP#1119 +``` + +``` +fix(eh-search): tighten substring match to 3+ chars + +Fixes the "ze" noise issue where 2-char queries matched +in unrelated words. Brand-prefix matches still work. + +Refs OP#1112 +``` + +### Secrets — NIEMALS committen +- `.env` immer gitignored +- `.env.example` mit Platzhaltern ist OK +- Wenn du echte Credentials brauchst: sie leben auf dem Server in `/opt//.env` +- API-Tokens, Passwörter, Zertifikate: **nie** ins Repo, auch nicht in Comments + +### Docker-Compose-Files +- Spiegeln 1:1 den Stand auf dem Server +- Image-Tags sind gepinnt (nicht `:latest`) für Reproduzierbarkeit +- Environment-Variablen immer via `env_file` oder `environment:` mit `${VAR}` Syntax — nie hardcoded + +### Docs +- Architektur-Beschreibungen in `docs/architecture/` +- ADRs in `docs/adr/-.md` mit fortlaufender Nummer +- Runbooks in `docs/runbooks/.md` +- Markdown-Diagramme mit Mermaid (rendert im Forgejo-Web-UI) + +## Verbindung zur realen Infrastruktur + +| Stack | Server | Pfad auf Server | Dieses Repo | +|---|---|---|---| +| forgejo | ai-apps (10.0.0.8) | `/opt/ai-apps/forgejo/` | `stacks/forgejo/` | +| eh-search | ai-apps (10.0.0.8) | `/opt/ai-apps/eh-search/` | `stacks/eh-search/` | +| (weitere kommen in folgenden Commits) | + +**Workflow bei Änderungen:** +1. AI macht Änderung auf dem Server (`docker-compose.yml` anpassen, restart) +2. AI committet die identische Änderung in dieses Repo +3. User reviewt den Commit im Forgejo Web-UI +4. Bei Problemen: Rollback via `git revert` + manuelles Neudeployen auf dem Server + +## Zugang zu Servern während der Arbeit +- `ssh ai-apps` — Hetzner cx22, Private 10.0.0.8, Public 91.98.226.44 +- `ssh pegasus` — Hetzner cx33, Private 10.0.0.10 (kein Public IPv4) +- `ssh webmin-kronos` — Hetzner cx32 mit sudo, DNS + Apache Proxy +- `ssh authentik-sso` — Hetzner, Private 10.0.0.7, SSO + +Lokale Doku mit Credentials: `/Users/benjaminweinlich/Library/Mobile Documents/com~apple~CloudDocs/AI/IT & Infrastruktur/` (nicht in diesem Repo — das Repo ist public!) + +## Dieses Repo ist PUBLIC +Das bedeutet: +- **Nichts** was schützenswert wäre commiten (keine Passwörter, interne Kundendaten, Fahrzeug-VINs außer öffentlich dokumentierten Musterdaten) +- Die README + ADRs können gern "Marketing-tauglich" sein — sie zeigen nach außen wie wir denken und bauen +- Für sensiblere Details ein privates Repo nutzen (evtl. zukünftig `electric-horses-infra-private`) + +## OpenProject +- **Projekt:** www.electric-horses.de Relaunch (ID 33) +- **Relevante Phasen:** + - M6: Site Search (abgeschlossen) + - M7: Operations & Documentation Foundation + - M7.1: Forgejo Deployment (#1119) — abgeschlossen + - M7.2: Erstes Infra-Repo (dieses Repo!) + - M7.3+: ADRs/Runbooks spiegeln, Mirror zu GitHub, etc. + +## Related External Docs +Außerhalb dieses Repos lebt Doku in: +- `/Users/benjaminweinlich/Library/Mobile Documents/com~apple~CloudDocs/AI/IT & Infrastruktur/` + - `Forgejo/` — ADRs + Runbooks für den Forgejo-Stack (werden in M7.3 hier hin gespiegelt) + - `Authentik/howto-oauth2-provider.md` — Template für OIDC-Integrationen + - `Hetzner/ai-apps-stacks.md` — Cloud-Inventory diff --git a/README.md b/README.md index 6783260..38bfb24 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,54 @@ # electric-horses-infra -Infrastructure as Code — docker-compose Stacks, Configs, Architektur-Docs und ADRs für die Electric Horses / Richter & Zech Hetzner-Cloud-Infrastruktur. \ No newline at end of file +**Infrastructure as Code** für Electric Horses / Richter & Zech. + +Dieses Repository enthält die versionierten Docker-Compose-Stacks, Reverse-Proxy-Configs, Architektur-Dokumentation und Architecture Decision Records (ADRs) für unsere Hetzner-Cloud-Infrastruktur. + +## Was lebt hier? + +``` +electric-horses-infra/ +├── Agent.md # AI-Briefing für jede Session +├── README.md # diese Datei +├── .gitignore # was NICHT commitet wird +│ +├── stacks/ # Docker-Compose Stacks (1:1 was auf den Servern läuft) +│ ├── forgejo/ # code.sdda.eu — dieses Git-Hosting +│ └── eh-search/ # electric-horses.de Site-Search +│ +└── docs/ # Dokumentation + └── architecture/ # Topologie-Snapshots, Stack-Inventories +``` + +**Konvention:** Jeder Stack-Ordner spiegelt den Stack auf dem tatsächlichen Server — aber ohne Secrets. Die `.env` mit echten Werten lebt auf dem Server (mode 600), hier ist nur die `.env.example` als Template. + +## Was gehört hier REIN + +- `docker-compose.yml` Dateien +- `Dockerfile`s +- Nginx-Configs +- Python / Shell Scripts die Teil der Infra sind +- SQL-Migrationen / Schema-Dumps (nicht Datenbank-Inhalte!) +- `.env.example` mit Platzhaltern +- Markdown-Dokumentation, Diagramme (Mermaid), ADRs, Runbooks + +## Was gehört hier NICHT REIN + +- **Niemals** echte `.env` Dateien, Passwörter, API-Keys, Zertifikate +- Runtime-Daten (Datenbank-Inhalte, Git-Repos im Git-Repo, uploaded files) +- Build-Artefakte (`node_modules/`, `dist/`, `__pycache__/`) +- Logs +- Backup-Dumps mit Nutzerdaten (DSGVO) + +Wenn du unsicher bist: Lass es lieber raus. Es ist einfacher eine fehlende Datei nachzureichen als ein Secret aus der Git-History zu entfernen. + +## Mitarbeit + +**Du als Human:** Du schreibst Wünsche und Feedback in Claude-Code / OpenProject, reviewst Commits im Web-UI (code.sdda.eu). + +**Die AI:** Liest `Agent.md` am Sessionstart, macht Änderungen in bestehenden Stacks, committet mit Referenzen auf OpenProject-Work-Packages (`Refs OP#1234`). + +## OpenProject Referenz +- **Parent-Phase:** M7 Operations & Documentation Foundation (#1118) +- **Repo-Setup:** M7.2 (dieser Commit) +- Nachschauen: https://openproject.sdda.eu/projects/www-dot-electric-horses-dot-de-relaunch/