---
name: live-mongodb
description: Connect to the live (production) MongoDB via chisel tunnel and perform read/write operations. Use this skill when you need to inspect or update live data directly in the production database.
---

# Live MongoDB Access via Chisel Tunnel

## Overview

Die Produktions-MongoDB läuft auf dem Server aus `PRODUCTION_SERVER` in `.env`. Der Zugang erfolgt über einen **Chisel-Tunnel**, der den Remote-MongoDB-Port auf localhost mapped. Damit kann man dann entweder über `mongosh`, `mongodump`/`mongorestore`, oder den **MongoDB MCP Server** auf die Live-Daten zugreifen.

## Umgebungsvariablen (aus .env)

| Variable                 | Beschreibung                                    |
| ------------------------ | ----------------------------------------------- |
| `PRODUCTION_SERVER`      | Produktionsserver (z.B. `dock4.basehosts.de`)   |
| `PRODUCTION_TIBI_PREFIX` | DB-Prefix auf Produktion (z.B. `tibi`)          |
| `TIBI_NAMESPACE`         | Projekt-Namespace                               |
| **Live DB Name**         | = `${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}` |
| Chisel-Port (Remote)     | `10987` — Chisel-Server auf dem Produktionshost |

## Schritt 1: Chisel-Tunnel starten

Das Chisel-Passwort muss vom User bereitgestellt werden. Tunnel starten:

```bash
# Passwort vom User erfragen oder aus Umgebung nehmen
read -s -p "Chisel-Passwort: " CHISEL_PASSWORD

# Tunnel starten (mappt remote mongo:27017 → localhost:27017)
chisel client --auth "coder:${CHISEL_PASSWORD}" \
  http://${PRODUCTION_SERVER}:10987 \
  27017:mongo:27017 &

# Kurz warten, bis der Tunnel steht
sleep 3
```

**WICHTIG:** Der lokale Docker-Mongo-Container muss gestoppt sein oder auf einem anderen Port laufen, da der Tunnel Port 27017 lokal belegt. Falls der lokale Container läuft:

```bash
# Lokales MongoDB stoppen (belegt sonst Port 27017)
docker compose -f docker-compose-local.yml stop mongo
```

Alternativ kann der Tunnel auf einen anderen lokalen Port gemappt werden:

```bash
chisel client --auth "coder:${CHISEL_PASSWORD}" \
  http://${PRODUCTION_SERVER}:10987 \
  37017:mongo:27017 &
# → erreichbar unter mongodb://localhost:37017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}
```

## Schritt 2: Verbinden

### Option A: mongosh (interaktiv)

```bash
mongosh "mongodb://localhost:27017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}"
```

### Option B: MongoDB MCP Server (für Copilot)

Den MongoDB MCP über die Umgebungsvariable `MDB_MCP_CONNECTION_STRING` auf die Live-DB umleiten.

**Temporär für eine Session** – in `.vscode/mcp.json` eine zweite Server-Config eintragen:

```jsonc
{
    "servers": {
        "mongodb-live": {
            "command": "npx",
            "args": ["-y", "mongodb-mcp-server@latest"],
            "type": "stdio",
            "env": {
                "MDB_MCP_CONNECTION_STRING": "mongodb://localhost:27017/${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}",
                "MDB_MCP_READ_ONLY": "false",
                "MDB_MCP_TELEMETRY": "disabled",
            },
        },
    },
}
```

> **Achtung:** `MDB_MCP_READ_ONLY=false` erlaubt Schreiboperationen! Nach getaner Arbeit den Server wieder entfernen oder auf `true` setzen.

### Option C: Einmalige Kommandos via Terminal

```bash
DB_NAME="${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE}"

# Dokument suchen
mongosh "mongodb://localhost:27017/$DB_NAME" \
  --eval 'db.content.findOne({path: "/"})'

# Feld updaten
mongosh "mongodb://localhost:27017/$DB_NAME" \
  --eval 'db.content.updateOne({path: "/"}, {$set: {"title": "Neuer Titel"}})'
```

## Schritt 3: Tunnel beenden

```bash
killall chisel
```

Falls der lokale Mongo-Container vorher gestoppt wurde, wieder starten:

```bash
docker compose -f docker-compose-local.yml start mongo
```

## Sicherheitsregeln

1. **Immer zuerst lesen, dann schreiben.** Vor jedem Update das betroffene Dokument mit `find`/`findOne` inspizieren.
2. **Backup vor Bulk-Updates.** Bei Massenänderungen vorher ein `mongodump` machen:
    ```bash
    mongodump --uri="mongodb://localhost:27017" \
      --db=${PRODUCTION_TIBI_PREFIX}_${TIBI_NAMESPACE} \
      --collection=<collection> \
      --gzip --archive=backup-<collection>-$(date +%Y%m%d-%H%M%S).gz
    ```
3. **User muss Chisel-Passwort liefern.** Das Passwort niemals hardcoden oder in Dateien speichern.
4. **Updates immer bestätigen lassen.** Vor jeder Schreiboperation dem User die geplante Query zeigen und explizit nach Bestätigung fragen.
5. **Nach getaner Arbeit Tunnel schließen** und ggf. `mongodb-live` MCP-Server aus der Config entfernen.
6. **Kein Drop/Delete von Collections** ohne explizite User-Anweisung.
7. **SSR-Cache leeren nach Datenänderungen.** Wenn Daten in Collections geändert werden, die auf der Website gerendert werden (z.B. `content`, `navigation`), muss der SSR-Cache invalidiert werden, damit die Änderungen sichtbar werden. Dazu die `ssr`-Collection leeren:
    ```bash
    mongosh "mongodb://localhost:27017/$DB_NAME" \
      --eval 'db.ssr.deleteMany({})'
    ```
    Siehe auch den Skill `tibi-ssr-caching` für Details zur Cache-Invalidierung über die API.

## Wichtige Collections

| Collection   | Beschreibung                    |
| ------------ | ------------------------------- |
| `content`    | CMS-Inhaltsseiten (Pagebuilder) |
| `navigation` | Navigationsstruktur             |
| `medialib`   | Medien-Bibliothek               |
| `ssr`        | SSR-Cache                       |

> Weitere Collections je nach Projekt — siehe `api/collections/` für die aktuelle Liste.

## Typische Anwendungsfälle

### Content-Eintrag inspizieren

```js
db.content.findOne({ path: "/" })
```

### Navigation aktualisieren

```js
db.navigation.updateOne({ type: "header", language: "de" }, { $set: { "elements.0.name": "Neues Label" } })
```

### Dokument-Struktur inspizieren

```js
// Schema einer Collection anschauen
db.content.findOne()

// Alle Felder eines Dokuments auflisten
Object.keys(db.content.findOne())
```

## Fehlerbehebung

- **"Connection refused" auf Port 27017:** Chisel-Tunnel läuft nicht oder lokaler Mongo blockiert den Port. Prüfen mit `ss -tlnp | grep 27017`.
- **"Authentication failed":** Chisel-Passwort falsch. User erneut fragen.
- **Langsame Queries:** Produktions-DB kann große Collections haben. Immer mit Filtern arbeiten, nie `find({})` ohne Limit.
- **Rate Limiting:** Kein Thema bei direktem DB-Zugang (nur bei API-Calls relevant).
