Für die Arbeit
Sync
Google-Kalender spiegeln, ohne Chaos.
Unser Team arbeitet mit mehreren Google-Kalendern: private Termine, Team-Kalender, Projekte. Ich wollte, dass belegte Zeiten überall sichtbar sind, ohne Details offenzulegen — und ohne die Fehler, die Kalender-Sync sonst kaputtmachen: Duplikate, Endlos-Schleifen, versehentlich verschickte Einladungen.
Mit Sync meldest du dich mit Google an und legst gerichtete Sync-Paare an: Quelle → Ziel, wahlweise als anonymer „Belegt“-Block oder mit vollen Details. Mehrbenutzer-fähig und auf Wunsch auf deine Workspace-Domain beschränkt.
Was es kann
- Gerichtete Sync-Paare mit Detailgrad pro Paar — Gegenrichtung legst du per Klick mit an
- Loop-Schutz: Spiegel-Events sind markiert und werden nie erneut gespiegelt, auch wenn ein Kalender Quelle und Ziel zugleich ist
- Idempotente Updates: Änderungen treffen dasselbe Ziel-Event, Duplikate entstehen nicht
- Lösch-Propagation: abgesagte oder gelöschte Termine räumen ihren Spiegel-Block ab
- Als „frei“ markierte und abgelehnte Termine blockieren im Ziel keine Zeit
- Serientermine inklusive Ausnahmen und Einzelabsagen
- Keine Einladungs-Mails: jeder Schreibvorgang läuft mit sendUpdates=none
- Pro Paar einstellbar: Titel-Präfix, Event-Farbe, Vertraulich-Schalter
- Google-Tokens liegen Fernet-verschlüsselt in der Datenbank
- Rate-Limit-Backoff, manueller Sofort-Sync, Sync-Historie und Admin-Übersicht
Wie der Sync arbeitet
Ein Scheduler pollt alle drei Minuten (konfigurierbar) und holt über Googles syncToken nur die Änderungen seit dem letzten Lauf — kein Voll-Abgleich bei jedem Durchgang. Läuft ein Token ab, fällt die Engine automatisch auf einen Full-Sync mit 30 Tagen Backfill zurück.
Jedes Spiegel-Event trägt seine Herkunft in den extendedProperties: Paar, Quell-Kalender, Quell-Event. Das ist der Loop-Schutz — und zusammen mit der Mapping-Tabelle der Grund, warum Updates idempotent sind. Niemand bekommt je eine Einladung zu einem Spiegel-Termin.
Selbst hosten
Dein Server, deine Daten.
Das brauchst du
- Server mit Docker und Docker Compose, eine Domain mit A-Record, Ports 80/443 — das mitgelieferte Caddy holt sich das TLS-Zertifikat selbst
- Ein Google-Cloud-Projekt: Calendar API aktivieren, OAuth-Client (Typ „Web application“) mit zwei Redirect-URIs anlegen — /api/auth/google/callback und /calendar/callback
- Scopes: openid email profile plus calendar.events und calendar.readonly. Wenn du auf eine Workspace-Domain beschränkst, reicht Publishing-Status „Internal“
So läuft es an
- 1
Klonen und konfigurieren
git clone https://github.com/laarsv/sync.git && cd sync cp .env.example .env
- 2
Secrets erzeugen
openssl rand -hex 32 # APP_SECRET python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'
- 3
.env füllen
DOMAIN, APP_SECRET, die Google-Credentials und der Fernet-Key sind Pflicht. Optional: ALLOWED_EMAIL_DOMAIN beschränkt den Login auf deine Workspace-Domain, INITIAL_ADMIN_EMAIL bestimmt den Admin.
- 4
Starten
Danach läuft alles unter https://deine-domain. Wer schon einen Reverse-Proxy hat, nimmt stattdessen docker-compose.prod.yml am externen proxy-Netz.
docker compose up -d --build
Steckbrief
- Stack
- FastAPI · SQLite (WAL) · React + Vite · APScheduler
- Google-API
- Calendar REST direkt über httpx — kein SDK
- Lizenz
- MIT