---
name: docmaster-access
description: Direkter Zugriff auf DocMaster-Dokumente auf ZimaOS — API-Endpunkte, Container-Management, Auth-Steuerung und Migration.
version: 1.1.0
tags: [docmaster, zimaos, docker, nextjs, dokumente]
---

# DocMaster Access

Zugriff auf die DocMaster-Dokumentenverwaltung (Next.js 16 App) im Docker-Container auf ZimaOS.

## Infrastruktur

| Property | Wert |
|---|---|
| **Projektordner** | `/media/HDD_1TB/DocMaster` (Source, Dev-Compose) |
| **Aktives Compose** | `/DATA/.casaos/apps/DocMaster/docker-compose.yml` (CasaOS-Managed) |
| **Container** | `DocMaster` (Image: `docmaster-docmaster`) |
| **Port** | `3000` |
| **Daten** | `/DATA/.media/HDD_1TB/Dokumente` → Container: `/app/uploads` |
| **ZimaOS Docker** | `DOCKER_CONFIG=/tmp/docker-config` (root/.docker read-only) |

## API-Endpunkte

| Endpoint | Methode | Beschreibung |
|---|---|---|
| `/api/files` | GET | Gibt `{files: {}, categories: [...]}` zurück |
| `/api/files` | PATCH | Datei-Metadaten aktualisieren (name, categoryId, tags, starred, note, documentDate, frist) |
| `/api/files?id=X` | DELETE | Soft-Delete (in Papierkorb) |
| `/api/files?id=X&permanent=1` | DELETE | Endgültig löschen |
| `/api/categories` | GET | Kategorien |
| `/api/preview/[id]` | GET | Datei-Vorschau |
| `/api/preview/[id]?thumb=1` | GET | Thumbnail |
| `/api/upload` | POST | Neue Datei hochladen (multipart) |

## Auth-Steuerung

Auth wird via Env-Var `DOCMASTER_AUTH_DISABLED=1` deaktiviert.  
**Immer nur die CasaOS-Compose-Datei ändern** (`/DATA/.casaos/apps/DocMaster/docker-compose.yml`), nicht die Dev-Datei.

### Auth deaktivieren

1. In `/DATA/.casaos/apps/DocMaster/docker-compose.yml` unter `environment:` hinzufügen:
   ```yaml
   - DOCMASTER_AUTH_DISABLED=1
   ```
2. Container neu erstellen:
   ```bash
   cd /DATA/.casaos/apps/DocMaster
   DOCKER_CONFIG=/tmp/docker-config docker compose up -d --force-recreate
   ```
3. Verifizieren:
   ```bash
   docker exec DocMaster env | grep DOCMASTER_AUTH
   # → DOCMASTER_AUTH_DISABLED=1
   curl -sI http://localhost:3000/
   # → HTTP/1.1 200 OK (nicht 401)
   ```

## Migration: Dateien in .metadata.json registrieren

DocMaster scannt das Upload-Verzeichnis **nicht automatisch**. Wenn der Container neu erstellt wurde oder Dateien manuell hinzugefügt wurden, müssen sie in `.metadata.json` eingetragen werden.

Das Migrations-Skript läuft im Container (node verfügbar):

```bash
cat << 'SCRIPT_END' | docker exec -i DocMaster node
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");

const UPLOADS_DIR = "/app/uploads";
const DATA_FILE = path.join(UPLOADS_DIR, ".metadata.json");

const DEFAULT_CATEGORIES = [
  { id: "personal",  name: "Persönlich", color: "#ff8091", icon: "user" },
  { id: "invoices",  name: "Rechnungen", color: "#FF9F0A", icon: "banknote" },
  { id: "health",    name: "Gesundheit", color: "#BF5AF2", icon: "heart" },
  { id: "finance",   name: "Finanzen",   color: "#30D158", icon: "banknote" },
  { id: "work",      name: "Arbeit",     color: "#0A84FF", icon: "briefcase" },
  { id: "sources",   name: "Quellen",    color: "#5AC8FA", icon: "book-open" },
  { id: "other",     name: "Sonstiges",  color: "#8E8E93", icon: "folder" },
];

const MIME_BY_EXT = {
  ".pdf": "application/pdf", ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
  ".png": "image/png", ".webp": "image/webp", ".gif": "image/gif",
  ".txt": "text/plain", ".md": "text/markdown", ".csv": "text/csv",
  ".doc": "application/msword",
  ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  ".xls": "application/vnd.ms-excel",
  ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ".ppt": "application/vnd.ms-powerpoint",
  ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  ".zip": "application/zip",
};

// Backup
if (fs.existsSync(DATA_FILE)) {
  const ts = Math.floor(Date.now() / 1000);
  fs.copyFileSync(DATA_FILE, DATA_FILE + ".bak." + ts);
  console.log("Backup: " + DATA_FILE + ".bak." + ts);
}

let metadata = { files: {}, categories: DEFAULT_CATEGORIES };
if (fs.existsSync(DATA_FILE)) {
  try { metadata = JSON.parse(fs.readFileSync(DATA_FILE, "utf-8")); }
  catch (e) { console.error("Parse error:", e.message); process.exit(1); }
  metadata.categories = DEFAULT_CATEGORIES;
  if (!metadata.files) metadata.files = {};
}

const alreadyKnown = new Set(
  Object.values(metadata.files).map(f => f.storedName || f.name)
);

const entries = fs.readdirSync(UPLOADS_DIR, { withFileTypes: true });
let added = 0, skipped = 0;

for (const entry of entries) {
  if (!entry.isFile()) continue;
  if (entry.name.startsWith(".")) continue;
  if (alreadyKnown.has(entry.name)) { skipped++; continue; }
  const filePath = path.join(UPLOADS_DIR, entry.name);
  const stat = fs.statSync(filePath);
  const ext = path.extname(entry.name).toLowerCase();
  const mime = MIME_BY_EXT[ext] || "application/octet-stream";
  const id = "doc_" + crypto.randomBytes(8).toString("hex");
  metadata.files[id] = {
    id, name: entry.name, originalName: entry.name, storedName: entry.name,
    size: stat.size, type: mime, uploadedAt: stat.mtime.toISOString(),
    categoryId: null, tags: [], starred: false,
  };
  added++;
  console.log("+ " + entry.name);
}

const tmp = DATA_FILE + ".tmp";
fs.writeFileSync(tmp, JSON.stringify(metadata, null, 2));
fs.renameSync(tmp, DATA_FILE);
console.log("\nAdded: " + added + ", skipped: " + skipped + ", total: " + Object.keys(metadata.files).length);
SCRIPT_END
```

Nach Migration: DocMaster im Browser mit Hard-Refresh (Strg+Shift+R) neu laden.

## Troubleshooting

- **Dokumente nicht sichtbar nach Force-Recreate:** Volume-Mount prüfen. Der Container muss `/DATA/.media/HDD_1TB/Dokumente:/app/uploads` gemountet haben. CasaOS-Compose um `volumes:`-Sektion ergänzen.
- **401 nach Auth-Änderung:** Env-Var im Container prüfen: `docker exec DocMaster env | grep DOCMASTER_AUTH`. Falls nicht gesetzt, Container `--force-recreate`.
- **Permission denied bei Host-Dateizugriff:** Host-Pfade sind root-owned. Schreibzugriffe über `docker exec` ausführen.
- **CasaOS-Compose hat kein volumes-Mapping:** Standardmäßig setzt CasaOS kein Volume. `volumes: - /DATA/.media/HDD_1TB/Dokumente:/app/uploads` manuell hinzufügen, dann `--force-recreate`.
