# Mini-Cloud Selbstgehostete Web-Cloud-Plattform mit Dateiverwaltung, Kalender, Kontakte, E-Mail-Webclient, Office-Editor und Passwort-Manager. ## Features - **Dateiverwaltung** - Upload/Download (Drag & Drop + Ordner-Upload), Berechtigungen, Share-Links (Lesen/Schreiben/Nur-Upload, Passwort, Ablaufdatum), Papierkorb, Ordner als ZIP downloaden - **Kalender** - CalDAV-kompatibel (iOS, DAVx5, Thunderbird, Outlook), iCal-Export, Teilen mit Benutzern - **Kontakte** - CardDAV-kompatibel, vCard-Export, Adressbuecher teilen - **E-Mail-Webclient** - IMAP/SMTP-Proxy (kein eigener Mailserver), Multi-Account, Absender-Logik - **Office-Editor** - DOCX, XLSX, PPTX bearbeiten mit OnlyOffice; PDF, Bilder, Text als Vorschau - **Passwort-Manager** - AES-256-GCM clientseitig verschluesselt, TOTP, Passkeys, KeePass/Firefox/CSV-Import, Ordner teilen - **Benutzerverwaltung** - Rollen (Admin/User), Speicher-Quotas, Einladungslinks, oeffentliche Registrierung an/aus - **Backup** - Lokales ZIP-Backup, SFTP-Backup mit Scheduler + Versionierung, Einzeldatei-Restore - **Benachrichtigungen** - System-Email bei Freigaben, Downloads, neuen Benutzern - **Sync-API** - Delta-Sync fuer Desktop/Mobile-Clients ## Tech-Stack | Bereich | Technologie | |---------|------------| | Backend | Python / Flask | | Frontend | Vue 3 / Vite / PrimeVue | | Datenbank | SQLite (WAL-Modus) | | Auth | JWT (Web-UI) + HTTP Basic Auth (CalDAV/CardDAV) | | Office-Editor | OnlyOffice Document Server (optional) | ## Installation ### Voraussetzungen - Python 3.11+ - Node.js 18+ - npm - Docker (fuer Produktion) ### Entwicklungsumgebung ```bash # Repository klonen git clone cd mini-cloud-datei-email-kalender-kontakte # .env anlegen cp .env.example .env # SECRET_KEY und JWT_SECRET_KEY generieren: python3 -c "import secrets; print(secrets.token_urlsafe(64))" # Generierte Werte in .env eintragen # Backend einrichten cd backend python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # Backend starten python wsgi.py # -> laeuft auf http://localhost:5000 (nur API, nicht im Browser oeffnen) # Frontend einrichten (neues Terminal) cd frontend npm install # Frontend starten npm run dev # -> laeuft auf http://localhost:3100 ``` **Wichtig - Ports in der Entwicklung:** | Port | Dienst | Im Browser oeffnen? | |------|--------|---------------------| | `5000` | Backend (Flask API) | Nein - nur API, kein Frontend | | `3100` | Frontend (Vite Dev Server) | **Ja - hier arbeiten!** | Im Entwicklungsmodus immer `http://localhost:3100` im Browser oeffnen. Der Vite Dev Server leitet API-Aufrufe automatisch an Port 5000 weiter (Proxy in `vite.config.js`). In der **Docker-Produktion** laeuft alles auf einem einzigen Port (`5000`) - Backend liefert das gebaute Frontend direkt mit aus. Beim ersten Registrieren wird der Benutzer automatisch zum Admin. ### Docker (Produktion) ```bash # .env anlegen und Secrets eintragen cp .env.example .env # SECRET_KEY und JWT_SECRET_KEY generieren und eintragen: python3 -c "import secrets; print(secrets.token_urlsafe(64))" # Starten docker-compose up --build -d ``` Die Datenbank und hochgeladene Dateien liegen unter `./data/` (Bind Mount, keine Docker Volumes). ### Docker aufraeumen (Speicher freigeben) Nach vielen Builds sammeln sich alte Images und Cache-Layer an: ```bash # Alles Ungenutzte loeschen (Images, Container, Cache, Netzwerke): docker system prune -a -f # Nur alte/ungenutzte Images loeschen: docker image prune -a -f # Nur Build-Cache loeschen: docker builder prune -a -f # Speicherverbrauch anzeigen: docker system df ``` Bei Problemen nach Updates (alte Frontend-Version etc.): ```bash docker-compose down docker-compose build --no-cache docker-compose up -d ``` ### Nginx Reverse-Proxy (Beispiel) Die Datei `nginx.example.conf` enthaelt eine vollstaendige Beispielkonfiguration: ```nginx # cloud.example.com -> Mini-Cloud (Port 5000) server { listen 443 ssl http2; server_name cloud.example.com; ssl_certificate /etc/letsencrypt/live/cloud.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/cloud.example.com/privkey.pem; client_max_body_size 0; location / { proxy_pass http://127.0.0.1:5000; 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; } } ``` Let's Encrypt Zertifikat erstellen: ```bash certbot --nginx -d cloud.example.com ``` ### OnlyOffice Document Server Fuer die Bearbeitung von Word, Excel und PowerPoint Dateien direkt im Browser. OnlyOffice benoetigt eine eigene Subdomain mit HTTPS. **1. .env - OnlyOffice URL setzen:** ```bash ONLYOFFICE_URL=https://office.example.com ``` Das JWT-Secret wird automatisch vom `JWT_SECRET_KEY` verwendet - kein extra Secret noetig. **2. docker-compose.yml - OnlyOffice-Service aktivieren:** Der OnlyOffice-Service ist in der `docker-compose.yml` bereits vorbereitet. Er nutzt den gleichen `JWT_SECRET_KEY` aus der `.env`. **3. Nginx - Eigene Subdomain fuer OnlyOffice:** ```nginx server { listen 443 ssl http2; server_name office.example.com; ssl_certificate /etc/letsencrypt/live/office.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/office.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` **4. Starten:** ```bash certbot --nginx -d office.example.com docker-compose up --build -d ``` **Ohne OnlyOffice** (`ONLYOFFICE_URL` leer) werden Office-Dateien in einer einfachen Vorschau angezeigt. **Mit OnlyOffice** erhaelt man einen vollwertigen Editor (wie Google Docs). ### Zeitzone & NTP In der `.env` stehen zwei Variablen die die Systemzeit betreffen: ```env TZ=Europe/Berlin NTP_SERVER=ptbtime1.ptb.de ``` **`TZ`** setzt die prozessweite Zeitzone (wirkt auf Log-Zeitstempel, Kalender/Task-Zeiten, `datetime.now()`). IANA-Format `Region/Stadt`. Haeufige Werte: | Region | Beispielwerte | | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Deutschland | `Europe/Berlin` | | DACH/EU | `Europe/Vienna`, `Europe/Zurich`, `Europe/Amsterdam`, `Europe/Paris`, `Europe/London`, `Europe/Madrid`, `Europe/Rome`, `Europe/Warsaw` | | Nord-EU | `Europe/Copenhagen`, `Europe/Stockholm`, `Europe/Helsinki`, `Europe/Oslo` | | Sonstige | `UTC`, `America/New_York`, `America/Los_Angeles`, `Asia/Tokyo`, `Australia/Sydney` | Vollstaendige Liste: **`NTP_SERVER`** wird beim Start abgefragt, um die Abweichung der Systemuhr zu pruefen. Bei Drift > 5 s erscheint eine Warnung im Log. **Hinweis:** Im Container wird die Uhr dadurch nicht gesetzt (benoetigt `CAP_SYS_TIME`) - auf dem Host sollte ein NTP-Daemon laufen. Der Check dient nur zur Sichtbarkeit. Default: `ptbtime1.ptb.de` (offizielle deutsche Zeitreferenz der Physikalisch-Technischen Bundesanstalt, Stratum 1, sehr hohe Verfuegbarkeit). Alternativen: `ptbtime2.ptb.de`, `ptbtime3.ptb.de`, `de.pool.ntp.org`, `time.cloudflare.com`. Leerlassen um den Check zu deaktivieren. Aktuelle Werte sind im Admin-Bereich unter **Einstellungen > System** einsehbar. ## Verwendung ### Dateien - Dateien per Drag-and-Drop oder Upload-Button hochladen - Ganze Ordner mit Unterordnern hochladen (Drag & Drop oder Ordner-Button) - Ordner erstellen, Dateien verschieben/umbenennen - Ordner als ZIP herunterladen - Geloeschte Dateien landen im Papierkorb (wiederherstellen oder endgueltig loeschen) - Share-Links erstellen mit drei Berechtigungsstufen: - **Nur Lesen** - Download, Ordnerinhalt sehen - **Lesen + Schreiben** - Download, Upload, Loeschen - **Nur Upload** - Hochladen ohne Einblick (Briefkasten-Modus) - Optional: Passwort und Ablaufdatum fuer Share-Links - Dateien/Ordner mit anderen Benutzern teilen (Lesen/Schreiben/Admin) - Gruenes Icon zeigt an welche Dateien bereits Freigaben haben ### Kalender - Monats-/Wochen-/Tagesansicht (FullCalendar) - Drag & Drop zwischen Tagen, Termindauer per Rand-Ziehen - Wiederkehrende Termine: taeglich/woechentlich/monatlich/jaehrlich, "jeden 2. Mittwoch", eigene Intervalle, Enddatum oder Anzahl - Serientermine: "Nur diesen" oder "Ganze Serie" bearbeiten - Kalender-Sichtbarkeit pro Kalender per Checkbox - Kalender mit anderen Benutzern teilen (Lesen oder Lesen+Schreiben) - iCal-Abo-Link mit optionalem Passwort (HTTP Basic Auth) - Voller CalDAV-Server (RFC 4791 Subset) - siehe unten #### CalDAV-Zugriff Native Sync mit Handy/Laptop-Kalendern. Server-URL ist immer `https:///dav/` - Benutzername + Passwort wie im Web. | Client | Einrichtung | |-----------------|-------------| | **iOS/macOS** | Einstellungen > Kalender > Accounts > Anderer > CalDAV-Account, Server `cloud.example.com/dav/` | | **Android (DAVx5)** | Konto hinzufuegen > Anmeldung mit URL und Benutzername, URL `https://cloud.example.com/dav/` | | **Thunderbird** | Neuer Kalender > Im Netzwerk > CalDAV, URL `https://cloud.example.com/dav/` (Thunderbird findet die Kalender selbst) | | **Outlook** | Plugin CalDAV-Synchronizer, Server-URL `https://cloud.example.com/dav/` | Unterstuetzte Operationen: PROPFIND (Auto-Discovery via `/.well-known/caldav`), REPORT (calendar-query / calendar-multiget inkl. Zeitraumfilter), GET/PUT/DELETE fuer einzelne Termine, MKCALENDAR, EXDATE fuer Serienausnahmen. ETags werden benutzt damit Clients erkennen, was sich geaendert hat. ### Kontakte - Adressbuecher anlegen, Kontakte erstellen/bearbeiten - Adressbuecher mit anderen Benutzern teilen - vCard-Export fuer Backup - CardDAV-Zugriff analog zum Kalender ### E-Mail - E-Mail-Konten unter Einstellungen hinzufuegen (IMAP/SMTP-Zugangsdaten) - Admin kann E-Mail-Konten fuer andere Benutzer anlegen - Kein eigener Mailserver noetig - verbindet sich mit externen Mailservern - Bei keinem konfigurierten Konto wird der E-Mail-Bereich ausgeblendet - Mehrere Konten: Ordner nach Konten gruppiert, Standard-Absender = aktives Konto ### Office-Dateien - Doppelklick oder Auge-Icon oeffnet die Vorschau - **Mit OnlyOffice**: Vollwertiger Editor fuer DOCX, XLSX, PPTX (wie Google Docs) - **Ohne OnlyOffice**: Einfache Vorschau (HTML/Tabelle/Folien), Text-Dateien bearbeitbar - PDF wird inline angezeigt, Bilder mit Vorschau ### Passwort-Manager - Alle Daten clientseitig mit AES-256-GCM verschluesselt (Zero Knowledge) - TOTP-Codes direkt generieren - Passwort-Generator integriert - Import aus: KeePass (.kdbx), Firefox (CSV), Chrome/Bitwarden/1Password (CSV) - Ordner/Gruppen wie in KeePass - Einzelne Passwoerter oder ganze Ordner mit anderen Benutzern teilen ### Backup & Restore - **Lokales Backup**: ZIP-Download mit Datenbank + allen Dateien - **SFTP-Backup**: Automatisch auf SFTP-Server sichern - Mehrere Backup-Ziele moeglich - Konfigurierbares Intervall (15 Min. bis woechentlich) - Versionierung mit automatischem Aufraumen - Versionen durchsuchen und Einzeldateien wiederherstellen - **Restore**: ZIP hochladen (Chunked Upload fuer grosse Backups) oder direkt von SFTP ### Administration - Benutzer anlegen, bearbeiten, deaktivieren, loeschen - Benutzersuche - E-Mail-Konten pro Benutzer verwalten - Oeffentliche Registrierung an/aus - Einladungslinks (funktionieren auch bei deaktivierter Registrierung) - System-Email (SMTP) fuer Benachrichtigungen und Einladungen ## Projektstruktur ``` backend/ app/ api/ # REST-Endpunkte models/ # SQLAlchemy-Models services/ # Business-Logik (Crypto, SFTP, Email, Scheduler) dav/ # CalDAV/CardDAV (Radicale-Vorbereitung) wsgi.py # Einstiegspunkt frontend/ src/ views/ # Vue-Seiten components/ # Wiederverwendbare Komponenten stores/ # Pinia State Management api/ # Axios API-Client router/ # Vue Router data/ # Laufzeitdaten (gitignored) minicloud.db # SQLite-Datenbank files/ # Hochgeladene Dateien ``` ## Desktop Sync Client Der Desktop-Client (`clients/desktop/`) synchronisiert Dateien zwischen der Cloud und einem lokalen Ordner. Gebaut mit Tauri 2 (Rust + Vue). ### Features - **Multi-Sync-Pfade**: Beliebig viele Server-Ordner auf lokale Ordner mappen (z.B. `/Projekte` -> `~/Projekte`, `/Shared/Team` -> `~/Team`) - **Virtual Files**: `.cloud`-Platzhalter (0 Bytes), Download erst bei Doppelklick. Kein Speicherverbrauch fuer nicht benoetigte Dateien - **Full Sync**: Alternativ alle Dateien komplett lokal spiegeln (pro Pfad waehlbar) - **Offline-Markierung**: Einzelne Dateien als offline verfuegbar markieren (Rechtsklick im Datei-Browser) - **Sofort-Sync**: Filesystem-Watcher erkennt lokale Aenderungen sofort (3s Debounce), kein Polling - **Intelligenter Sync**: Checksum-Tracking erkennt wer sich geaendert hat (Server oder Lokal) - **Konflikt-Erkennung**: Bei gleichzeitiger Aenderung wird eine Konflikt-Kopie erstellt - **File Locking**: Lock beim Oeffnen, Heartbeat alle 60s, manuelles Entsperren per Rechtsklick, auto-unlock nach 15 Min ohne Heartbeat - **System-Tray**: Minimiert in den Tray statt zu beenden, Doppelklick oeffnet Fenster - **Minimiert starten**: Optional direkt im Tray starten (Checkbox in Einstellungen) - **Auto-Login**: Zugangsdaten und Sync-Pfade bleiben nach Neustart/Update erhalten - **Terminalserver**: Pro User eine eigene Instanz, keine Konflikte zwischen Benutzern - **.cloud Datei-Handler**: Doppelklick im Explorer oeffnet ueber den Client ### Terminalserver-Verhalten | Szenario | Verhalten | |----------|-----------| | User A startet Client | Laeuft, eigenes Lock-File in `%APPDATA%\MiniCloud Sync\` | | User B startet Client | Laeuft separat, eigenes Lock-File in seinem `%APPDATA%` | | User A doppelklickt `.cloud` | Laufende Instanz von User A oeffnet die Datei | | User A startet nochmal | "Already running" -> beendet sich sofort | | Client crashed | Naechster Start prueft ob PID noch lebt -> stale Lock -> ueberschreibt | ### Virtual Files vs. Full Sync | | Virtual Files | Full Sync | |---|---|---| | Speicher | Nur .cloud Platzhalter (0 Bytes) | Alle Dateien komplett lokal | | Zugriff | Doppelklick = Download + Oeffnen | Sofort verfuegbar | | Offline | Nur markierte Dateien | Alles offline | | Upload | Neue lokale Dateien werden hochgeladen | Bidirektionaler Sync | | Empfehlung | Grosse Datenmengen, Laptops | Kleine Ordner, immer offline noetig | ### Sync-Logik (Checksum-Tracking) Der Client merkt sich den Checksum jeder Datei beim letzten Sync. Beim naechsten Sync wird verglichen wer sich geaendert hat: | Lokal geaendert | Server geaendert | Aktion | |-----------------|------------------|--------| | Nein | Ja | **Server -> Lokal** (Download) | | Ja | Nein | **Lokal -> Server** (Upload) | | Ja | Ja | **Konflikt**: Lokale Datei wird zu `Datei (Konflikt).txt`, Server-Version wird heruntergeladen | | Nein | Nein | Nichts (identisch) | Beim ersten Sync (kein gespeicherter Checksum) gewinnt immer der Server. ### File Locking Dateien werden beim Oeffnen ueber den Client automatisch auf dem Server gesperrt. Andere Benutzer sehen "Datei gesperrt von X" und koennen sie nicht bearbeiten. | Szenario | Was passiert | |----------|-------------| | .cloud Datei oeffnen | Download + Lock + Heartbeat alle 60s | | Fertig -> Rechtsklick "Entsperren" | Lock sofort aufgehoben | | Rechtsklick "Nicht mehr offline" | Lock aufgehoben + zurueck zu .cloud | | Client beenden ohne Entsperren | Kein Heartbeat -> Lock laeuft nach 15 Min ab | | Laptop zugeklappt / Netzwerk weg | Kein Heartbeat -> Lock laeuft nach 15 Min ab | | Admin im Web-UI | Kann jeden Lock jederzeit manuell loesen | #### Was das Lock wirklich kann (und was nicht) Das Auschecken ist ein **Hinweis-Schloss**, kein physikalisches Dateischloss. Kurz gesagt: es hindert alle **Mini-Cloud-Wege** am Bearbeiten, aber nicht den Windows-Explorer oder andere Programme auf der Festplatte. | Wo greift das Lock? | Beispiel | |---------------------|----------| | ✅ Web-Oberflaeche | Anna kann im Browser die Datei nicht oeffnen/bearbeiten - "wird von Adam bearbeitet" | | ✅ Desktop-Client | Doppelklick in der Client-Ansicht -> Fehlermeldung, Datei oeffnet nicht | | ✅ Automatischer Upload | Hat Anna die Datei trotzdem editiert, hebt der Client sie nicht hoch, solange Adam das Lock haelt | | ❌ Windows-/Mac-Explorer | Anna kann die lokale Datei im Dateimanager oeffnen (ist ja eine ganz normale Datei auf der Platte) | | ❌ Externe Programme | Word, Excel, Notepad usw. sehen das Lock nicht - jedes Programm kann die Datei oeffnen | **Beispiel im Alltag:** 1. Adam checkt `Bericht.xlsx` aus (oeffnet sie im Client) 2. Anna hat den Ordner auch gesynct und die Datei liegt bei ihr lokal 3. Anna versucht, sie im Browser zu oeffnen -> **blockiert** 4. Anna versucht, sie im Client zu oeffnen -> **blockiert** 5. Anna oeffnet sie im Explorer direkt -> **geht auf** (weil die Datei technisch ja nur eine normale Datei ist) 6. Anna bearbeitet und speichert lokal -> Client bemerkt die Aenderung, sieht das Fremd-Lock und **haelt den Upload zurueck** 7. Adam checkt ein: jetzt vergleicht der Client - hat Adam auch geaendert? Wenn ja, wird Annas Version zu `Bericht (Konflikt Anna 2026-04-12 143022).xlsx` und Adams Version gewinnt. Niemand verliert Daten, aber ein Mensch muss die Versionen zusammenfuehren. Das ist derselbe Ansatz wie bei Nextcloud oder Dropbox: **Konflikt-Kopie als Sicherheitsnetz**, keine kernel-tiefe Dateisperre. Der Schutz kommt ueber die Upload-Sperre - damit landet ein versehentliches Bearbeiten nie beim eigentlichen Owner. ### Bauen ```bash # Voraussetzung: Docker # Linux: ./build.sh linux # Windows (Cross-Compile): ./build.sh windows # macOS (nur auf Mac): ./build.sh mac # Alle Desktop-Plattformen: ./build.sh all-desktop ``` ### Auto-Upload auf den Server Nach dem Build wird der Client automatisch auf den Cloud-Server hochgeladen und steht dort zum Download bereit. **Auf der Entwicklungsmaschine** (nicht auf dem Server!) in die `.env` eintragen: ```bash # URL der Cloud-Instanz CLOUD_URL=https://cloud.example.com # SECRET_KEY des Zielservers (identisch mit SECRET_KEY in der Server-.env) BUILD_UPLOAD_TOKEN=der-secret-key-vom-server ``` Danach laedt `./build.sh linux` (etc.) den Build automatisch hoch. Auf der Login-Seite erscheint dann "Desktop & Mobile Clients herunterladen". **Wichtig:** `CLOUD_URL` und `BUILD_UPLOAD_TOKEN` gehoeren NUR in die `.env` der Entwicklungsmaschine, NICHT auf den Produktionsserver! ### Einstellungen Einstellungen werden gespeichert in: - **Windows**: `%APPDATA%\MiniCloud Sync\config.json` - **Linux**: `~/.config/MiniCloud Sync/config.json` - **macOS**: `~/Library/Application Support/MiniCloud Sync/config.json` Gespeichert werden: Server-URL, Benutzername, Passwort (base64), Sync-Pfade. Bleiben bei Updates erhalten. ## Roadmap - Mobile Sync-Client (iOS, Android) mit On-Demand-Download + File Provider - Native Passwort-Manager Clients mit Autofill und Biometrie - Radicale-Integration fuer vollstaendiges CalDAV/CardDAV-Protokoll ## Lizenz Privates Projekt.