# Dauerhaft erreichbar machen: menumaestro.aigenius.tech

## Befund (geprüft am 07.11.2026)

| Prüfung | Ergebnis |
|---|---|
| DNS `menumaestro.aigenius.tech` → A | 187.126.21.206 ✅ zeigt auf den VPS |
| Port 80 | HTTP 308 → https://menumaestro.aigenius.tech/ ✅ |
| Port 443 | Traefik antwortet, aber **HTTP 404** für diesen Hostnamen ❌ |
| TLS-Zertifikat | `CN=TRAEFIK DEFAULT CERT` (selbstsigniert) ❌ |

**Klartext:** DNS und Traefik laufen. Es fehlt nur die **Route** — Traefik weiß
nicht, dass Anfragen für `menumaestro.aigenius.tech` an unsere Demo gehen sollen.
Und es fehlt ein **echtes Zertifikat** (aktuell selbstsigniert, Browser warnen).

## Warum ich das nicht selbst machen kann

Ich laufe in einem Docker-Container mit absichtlich engen Rechten:

- kein `/var/run/docker.sock` → ich kann keine Container verwalten
- kein SSH-Key, kein Host-Zugang
- nur `/opt/data` ist vom Host hereingereicht
- Traefik-Konfiguration liegt auf dem **Host**, nicht bei mir
- Ports 8080/2375/2376 auf dem Gateway sind zu

Die Route muss also **auf dem Host** angelegt werden — von dir. Ich liefere
dir die fertigen Bausteine dafür.

---

## Weg A (empfohlen): eigener kleiner Webserver-Container

**Vorteil:** Der Hermes-Container wird nicht angefasst. Kein Neustart, diese
Sitzung bleibt bestehen. Sauber getrennt.

**1. Prüfen, wo die Dateien auf dem Host liegen.**
Der Host hat `/dev/sda1` gemountet. Finde heraus, welcher Host-Pfad
`/opt/data` im Container entspricht:

```bash
docker inspect <hermes-container> --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'
```

Angenommen, das ergibt `/opt/hermes/data` — dann liegen die Demo-Dateien
auf dem Host unter `/opt/hermes/data/projects/gastro-ki`.

**2. `docker-compose.menumaestro.yml` neben deiner bestehenden Compose-Datei anlegen.**
Den Pfad unten anpassen (`/opt/hermes/data/projects/gastro-ki`) und den
Netzwerknamen auf das Netz setzen, in dem auch Traefik läuft
(`docker network ls` zeigt es; bei Hostinger-Hermes-Setups meist `hermes_default`
oder ähnlich).

**3. Starten:**

```bash
docker compose -f docker-compose.menumaestro.yml up -d
```

**4. Prüfen:**

```bash
docker compose -f docker-compose.menumaestro.yml ps
curl -sI https://menumaestro.aigenius.tech/verwaltung.html | head -3
```

Erwartet: `HTTP/2 200` und ein echtes Zertifikat (kein „TRAEFIK DEFAULT").

---

## Weg B: Route am bestehenden Hermes-Container ergänzen

Nur wenn du keine zweite Compose-Datei willst. Du hängst an den Hermes-Service
die Labels an und öffnest Port 8080 intern:

```yaml
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.menumaestro.rule=Host(`menumaestro.aigenius.tech`)"
      - "traefik.http.routers.menumaestro.entrypoints=websecure"
      - "traefik.http.routers.menumaestro.tls.certresolver=letsencrypt"
      - "traefik.http.services.menumaestro.loadbalancer.server.port=8080"
```

**Achtung:** Das Neuladen des Compose-Stacks **startet den Hermes-Container neu** —
also diese Sitzung und alle laufenden Prozesse (inkl. Demo) beenden sich.
Danach muss die Demo neu gestartet werden. Deshalb ist Weg A besser.

---

## Zertifikat

Traefik liefert aktuell sein selbstsigniertes Standard-Zertifikat. Für ein
echtes Zertifikat muss im Traefik-Container ein ACME/Let's-Encrypt-Resolver
konfiguriert sein, der zu dem Namen im Label passt (`certresolver=letsencrypt`
oben). Prüfen:

```bash
docker exec <traefik-container> cat /etc/traefik/traefik.yml | grep -A5 certificatesResolvers
```

Steht dort nichts von `certificatesResolvers`, muss das einmalig in der
Traefik-Konfiguration ergänzt werden:

```yaml
certificatesResolvers:
  letsencrypt:
    acme:
      email: deine@mailadresse.de
      storage: /acme.json
      httpChallenge:
        entryPoint: web
```

(`/acme.json` muss existieren und `chmod 600` haben.)

**Wichtig:** Let's Encrypt braucht Port 80 von außen erreichbar für die
HTTP-Challenge. Port 80 antwortet bereits mit 308 — das ist ein gutes Zeichen,
die Challenge sollte durchgehen.

---

## Übergangsweise: der schnelle Tunnel

Bis die Route steht, läuft die Demo über einen Cloudflare-Tunnel. Der ist
**nicht dauerhaft**: Die Adresse wechselt bei jedem Neustart, und Cloudflare
gibt keine Verfügbarkeitsgarantie.

Aktuelle Adresse steht in `URL.txt` in diesem Ordner.

Verwalten:

```bash
bash /opt/data/projects/gastro-ki/serve.sh          # starten/prüfen, idempotent
bash /opt/data/projects/gastro-ki/serve.sh status   # Zustand ansehen
```

Ein Cronjob hält den Tunnel am Leben, solange der Container läuft.
Wenn die Subdomain-Route steht, kann dieser Cronjob abgeschaltet werden.

---

## Warum kein Cloudflare-Named-Tunnel?

Das wäre die eleganteste Dauerlösung (feste Adresse, kein offener Port).
Geht aber nicht, weil die Domain `aigenius.tech` nicht bei Cloudflare liegt —
die Nameserver sind `nebula.dns-parking.com` / `aurora.dns-parking.com`
(Hostinger). Ein Named Tunnel bräuchte Cloudflare als DNS-Provider für die Zone.
