| backend | ||
| frontend | ||
| nginx | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| README.md | ||
CardSync 🔄
Synology CardDAV → Microsoft 365 Kontakte — Self-hosted, Docker-basiert.
Synchronisiert Kontakte von einem Synology CardDAV-Server automatisch in die Microsoft 365 Kontakte deiner Benutzer. Benutzer melden sich einmalig per Microsoft OAuth an, ein Admin konfiguriert den Synology-Server zentral.
Voraussetzungen
- Docker & Docker Compose
- Synology NAS mit aktiviertem CardDAV-Server (Paket: „CardDAV Server" oder „Contacts")
- Microsoft Azure App-Registrierung
Schnellstart
Azure App-Registrierung erstellen
CardSync unterstützt zwei Betriebsmodi — du kannst sie kombinieren oder nur einen nutzen:
Modus A: OAuth-Login (Delegated Permissions) User melden sich einmalig per Microsoft-Login an. Empfohlen für kleine Setups oder zum Testen.
Modus B: Azure AD Gruppen-Import (Application Permissions) — empfohlen für Firmen Admin trägt eine Azure AD Gruppen-ID ein, alle Mitglieder werden automatisch importiert. Kein User-Login nötig.
Setup-Schritte:
- Gehe zu portal.azure.com → Azure Active Directory → App-Registrierungen
- Neue Registrierung → Name:
CardSync - Kontotypen: nur eigene Organisation
- Redirect-URI (Web):
https://deine-ip-oder-domain/auth/callback - Unter Zertifikate & Geheimnisse ein neues Client-Secret erstellen → notieren
Berechtigungen unter API-Berechtigungen → Microsoft Graph:
Für Modus A (Delegated):
Contacts.ReadWrite(Delegiert)offline_access,openid,profile,email
Für Modus B (Application — Goldstandard):
Contacts.ReadWrite(Anwendung — wichtig, nicht delegiert!)User.Read.All(Anwendung)GroupMember.Read.All(Anwendung)- Danach „Administratorzustimmung erteilen" klicken
Beide Modi können parallel laufen — User können sich entweder selbst anmelden (Modus A), oder werden per Gruppen-Import angelegt (Modus B).
2. Repository vorbereiten
git clone <dieses-repo>
cd cardsync
cp .env.example .env
3. .env konfigurieren
# Datenbank
POSTGRES_PASSWORD=sicher_aendern_123
# Sicherheit (langen zufälligen String generieren: openssl rand -hex 32)
SECRET_KEY=dein_langer_zufaelliger_key
# Microsoft Azure
MS_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
MS_CLIENT_SECRET=dein-client-secret
MS_TENANT_ID=common # oder deine Tenant-ID für Single-Tenant
# URL unter der die App erreichbar ist (KEIN trailing slash)
APP_BASE_URL=http://192.168.1.100
# Admin-E-Mails (kommagetrennt) — diese Benutzer bekommen Admin-Zugang
ADMIN_EMAILS=admin@firma.de,it@firma.de
4. Starten
docker compose up -d
Die App ist jetzt unter https://localhost erreichbar (HTTP wird automatisch auf HTTPS umgeleitet).
⚠️ Beim ersten Start wird automatisch ein selbstsigniertes Zertifikat erzeugt — der Browser zeigt eine Sicherheitswarnung. Einmal akzeptieren und weitermachen.
5. (Optional) Eigenes Zertifikat hinterlegen
Wenn du ein Wildcard- oder CA-signiertes Zertifikat hast:
# Lege deine Dateien EXAKT mit diesen Namen ab:
cp dein-wildcard.crt ./nginx/certs/cert.pem
cp dein-wildcard.key ./nginx/certs/key.pem
# Frontend neu starten — das war's
docker compose restart frontend
Details und PFX-Konvertierung: siehe nginx/certs/README.md
Verwendung
Admin-Einrichtung
- Gehe zu
http://deine-ip/auth/login?mode=admin - Melde dich mit einem der Admin-Microsoft-Accounts an
- Gehe im Admin-Dashboard zu Synology Config
- Trage Server-URL, Benutzername und Passwort ein
- Teste die Verbindung mit Verbindung testen
Benutzer-Onboarding (Modus A — OAuth)
- Benutzer rufen
http://deine-ipauf - Klick auf Mit Microsoft anmelden
- Microsoft OAuth-Zustimmung (Kontakte-Zugriff)
- Adressbuch auswählen und Sync-Intervall einstellen
- Optional: Jetzt synchronisieren für den ersten sofortigen Sync
Benutzer-Import via Azure AD Gruppe (Modus B — empfohlen für Firmen)
- Admin-Dashboard → Azure AD Gruppe
- Object-ID der Azure AD Gruppe eintragen (aus Azure Portal → AD → Gruppen → deine Gruppe → Object ID)
- Default-Adressbuch und Default-Sync-Intervall für neue User wählen
- Gruppe testen klicken → sollte die Mitgliederzahl anzeigen
- Speichern, dann Mitglieder jetzt importieren
- Alle Gruppenmitglieder sind nun in CardSync angelegt, Sync läuft automatisch
- Mitgliedschaft wird im konfigurierten Intervall (Default: 6h) automatisch aktualisiert
Admin: Benutzer verwalten
- Im Admin-Dashboard unter Benutzer alle angemeldeten Benutzer sehen
- Pro Benutzer: Adressbuch zuweisen, Intervall konfigurieren, Sync aktivieren/deaktivieren
- Manuellen Sync für jeden Benutzer triggern
- Sync-Logs einsehen
Synology CardDAV-Server einrichten
- Im Synology Package Center „CardDAV Server" installieren
- Oder im Paket „Contacts": CardDAV ist automatisch aktiv
- Standard-Port: 5006 (HTTP) oder 5007 (HTTPS)
- Server-URL-Format:
http://192.168.1.10:5006oderhttps://nas.firma.de:5007
Architektur
┌─────────────────────────────────────────────┐
│ Docker Compose │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Nginx │──▶│ FastAPI │──▶│PostgreSQL│ │
│ │ :80 │ │ :8000 │ │ :5432 │ │
│ └──────────┘ └────┬─────┘ └──────────┘ │
└───────────────────────┼─────────────────────┘
│
┌────────────┴────────────┐
│ │
┌──────▼──────┐ ┌────────▼──────┐
│ Synology │ │ Microsoft │
│ CardDAV │ │ Graph API │
│ (CardDAV │ │ (REST/OAuth) │
│ Protokoll)│ └───────────────┘
└─────────────┘
Sync-Richtung: Nur Synology → MS365 (einseitig)
Matching-Strategie:
- Kontakte werden per UID (vCard UID-Feld) gematcht
- Die UID wird beim ersten Sync in den MS365-Notizen hinterlegt
- Gelöschte Synology-Kontakte werden aus MS365 entfernt
Sicherheitshinweise
- In Produktion: HTTPS-Reverse-Proxy (z.B. Traefik, Caddy, nginx mit Let's Encrypt) vorschalten
SECRET_KEYundPOSTGRES_PASSWORDimmer ändern- Das Synology-Passwort wird aktuell im Klartext in der DB gespeichert (für Produktion: Verschlüsselung ergänzen)
- Microsoft Tokens werden per JWT-Session verwaltet und automatisch refresht
Logs
docker compose logs -f backend # Backend-Logs mit Sync-Aktivitäten
docker compose logs -f frontend # Nginx-Logs
Entwicklung / Updates
docker compose down
docker compose up -d --build