Go to file
Stefan Hacker b2567d379c fix: CardDAV-Aenderungen loesen SSE-Refresh im Web-UI aus
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 03:56:52 +02:00
backend fix: CardDAV-Aenderungen loesen SSE-Refresh im Web-UI aus 2026-04-13 03:56:52 +02:00
clients/desktop feat: Lock-Badge + smartes Kontextmenue in lokaler Client-Ansicht 2026-04-12 11:32:01 +02:00
frontend feat: Passwort-Manager Mehrfachauswahl + Bulk-Loeschen 2026-04-12 16:08:18 +02:00
.env.example fix: Client-Upload akzeptiert SECRET_KEY oder JWT_SECRET_KEY + Download in Settings 2026-04-11 23:58:54 +02:00
.gitignore fix: build-output/ in .gitignore + aus Git entfernt 2026-04-11 23:55:09 +02:00
CHANGELOG.md docs: CHANGELOG.md - komplette Projekthistorie 2026-04-12 01:52:43 +02:00
Dockerfile fix: SSE-Broadcaster nur 1 Worker - sonst Events zwischen Prozessen verloren 2026-04-12 10:51:49 +02:00
README.md feat: CalDAV-Server (RFC 4791 Subset) fuer native Client-Sync 2026-04-12 12:51:21 +02:00
build.sh fix: Windows Build laedt Setup-Installer hoch statt nackte .exe 2026-04-12 00:09:32 +02:00
docker-compose.yml feat: OnlyOffice Force-Save bei Ctrl+S + private IP erlauben 2026-04-11 22:54:31 +02:00
nginx.example.conf feat: CalDAV-Server (RFC 4791 Subset) fuer native Client-Sync 2026-04-12 12:51:21 +02:00

README.md

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

# Repository klonen
git clone <repo-url>
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)

# .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:

# 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.):

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:

# 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:

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:

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:

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:

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).

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://<deine-domain>/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

# 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:

# 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.