# đ Oikos
**Selbstgehosteter Familienplaner â privat, offen, ohne Abonnement**
[](https://nodejs.org)
[](https://www.docker.com)
[](https://www.zetetic.net/sqlcipher/)
[](https://web.dev/progressive-web-apps/)
[](./LICENSE)
Alle Daten bleiben auf deinem eigenen Server.
Kein Cloud-Zwang. Keine Datenweitergabe. Kein Tracking.
[Screenshots](#screenshots) · [Module](#module) · [Schnellstart](#schnellstart) · [Konfiguration](#konfiguration) · [Kalender-Sync](#kalender-synchronisation) · [Sicherheit](#sicherheit)
---
## Screenshots
---
## Module
| | Modul | Highlights |
|---|---|---|
| đ | **Dashboard** | Wetter-Widget, anstehende Termine, dringende Aufgaben, Essen heute, Pinnwand-Vorschau |
| â
| **Aufgaben** | Listenansicht + Kanban, Teilaufgaben, Swipe-Gesten, wiederkehrende Aufgaben (RRULE) |
| đ | **Einkauf** | Mehrere Listen, automatische Kategorie-Sortierung, Integration mit Essensplan |
| đœïž | **Essensplan** | Wochenansicht, Zutatenverwaltung, Zutaten â Einkaufsliste mit einem Klick |
| đ
| **Kalender** | Monats-/Wochen-/Tages-/Agenda-Ansicht, Google Calendar & Apple Calendar Sync |
| đ | **Pinnwand** | Farbige Sticky Notes, Markdown-Light (fett, kursiv, Listen) |
| đ„ | **Kontakte** | Wichtige Familien-Kontakte, Direktanruf (`tel:`), Maps-Links |
| đ° | **Budget** | Einnahmen/Ausgaben, Kategorien, Monatsvergleich, CSV-Export |
| âïž | **Einstellungen** | Passwort Ă€ndern, Kalender-Sync verwalten, Familienmitglieder anlegen |
---
## Tech Stack
**Backend:** Node.js · Express · SQLite/SQLCipher · express-session · bcrypt
**Frontend:** Vanilla JavaScript (ES-Module) · Kein Framework · Kein Build-Step
**Deployment:** Docker · Nginx Reverse Proxy · PWA (Service Worker + Manifest)
**Optional:** Google Calendar API v3 (OAuth 2.0) · Apple iCloud CalDAV (tsdav)
---
## Schnellstart
### Voraussetzungen
- **Docker** + **Docker Compose**
- Ein Linux-Server mit Nginx Reverse Proxy und SSL (empfohlen: [Nginx Proxy Manager](https://nginxproxymanager.com))
### 1 â Repository klonen
```bash
git clone https://github.com/ulsklyc/oikos.git
cd oikos
```
### 2 â Umgebungsvariablen setzen
```bash
cp .env.example .env
```
Mindestens diese zwei Pflichtfelder in `.env` ausfĂŒllen:
```env
# Langen zufÀlligen String (℠32 Zeichen)
SESSION_SECRET=...
# AES-256-SchlĂŒssel fĂŒr SQLCipher-DatenbankverschlĂŒsselung
DB_ENCRYPTION_KEY=...
```
> VollstĂ€ndige Variablen-Referenz â [Konfiguration](#konfiguration)
### 3 â Container starten
```bash
docker compose up -d
```
> Der erste Build dauert 2â3 Minuten (SQLCipher wird gegen better-sqlite3 kompiliert).
### 4 â Admin-Account anlegen
```bash
docker compose exec oikos node setup.js
```
Das interaktive Script fragt nach Benutzername, Anzeigename und Passwort. Dieser Account hat Admin-Rechte und kann weitere Familienmitglieder anlegen.
### 5 â App öffnen
`http://localhost:3000` â oder die konfigurierte Domain nach dem Nginx-Setup.
---
## Nginx Reverse Proxy
Die Datei [`nginx.conf.example`](./nginx.conf.example) enthÀlt eine vollstÀndige Konfiguration.
**Mit Nginx Proxy Manager:**
1. Neuen Proxy Host anlegen: `oikos.deine-domain.de` â `localhost:3000`
2. SSL-Zertifikat via Let's Encrypt ausstellen
3. Inhalt aus `nginx.conf.example` im Feld "Advanced" eintragen
**Wichtig:** `X-Forwarded-Proto` muss gesetzt sein (in der Vorlage enthalten), damit Session-Cookies in Produktion korrekt als `Secure` gesetzt werden.
---
## Konfiguration
### Pflicht
| Variable | Beschreibung |
|---|---|
| `SESSION_SECRET` | ZufĂ€lliger String â„ 32 Zeichen fĂŒr Session-Signing |
| `DB_ENCRYPTION_KEY` | SQLCipher AES-256-SchlĂŒssel (leer = keine VerschlĂŒsselung) |
### Wetter-Widget
Kostenlosen API-Key bei [openweathermap.org](https://openweathermap.org/api) registrieren:
```env
OPENWEATHER_API_KEY=...
OPENWEATHER_CITY=Berlin
OPENWEATHER_UNITS=metric # metric = °C, imperial = °F
OPENWEATHER_LANG=de
```
### Weitere Optionen
| Variable | Standard | Beschreibung |
|---|---|---|
| `PORT` | `3000` | Server-Port |
| `NODE_ENV` | `development` | `production` fĂŒr Deployment |
| `DB_PATH` | `./oikos.db` | Pfad zur SQLite-Datei |
| `SYNC_INTERVAL_MINUTES` | `15` | Automatischer Kalender-Sync-Intervall |
| `RATE_LIMIT_MAX_ATTEMPTS` | `5` | Max. Login-Versuche pro Minute |
VollstÀndige Vorlage: [`.env.example`](./.env.example)
---
## Kalender-Synchronisation
### Google Calendar
Einrichtung anzeigen
#### Google Cloud Console vorbereiten
1. Projekt unter [console.cloud.google.com](https://console.cloud.google.com) anlegen
2. **Google Calendar API** aktivieren
3. **OAuth 2.0-Client-ID** erstellen (Typ: âWebanwendung")
4. Autorisierte Redirect-URI eintragen:
```
https://oikos.deine-domain.de/api/v1/calendar/google/callback
```
5. In `.env` eintragen:
```env
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GOOGLE_REDIRECT_URI=https://oikos.deine-domain.de/api/v1/calendar/google/callback
```
6. Container neu starten: `docker compose up -d`
#### Verbindung herstellen
1. Mit einem **Admin**-Konto einloggen
2. **Einstellungen â Kalender-Synchronisation â Mit Google verbinden**
3. Google-Konto autorisieren â automatische Weiterleitung zurĂŒck
**Sync-Verhalten:**
- Erster Sync: Events der letzten 3 Monate + nÀchsten 12 Monate
- Folge-Syncs: nur Ănderungen via Google syncToken (effizient)
- Outbound: neue lokale Termine werden nach Google ĂŒbertragen
- Konflikt: Google gewinnt bei gleichzeitiger Ănderung
### Apple Calendar (iCloud CalDAV)
Einrichtung anzeigen
#### App-spezifisches Passwort erstellen
1. [appleid.apple.com](https://appleid.apple.com) â âAnmeldung und Sicherheit" â âApp-spezifische Passwörter"
2. Neues Passwort fĂŒr âOikos" erstellen
3. In `.env` eintragen:
```env
APPLE_CALDAV_URL=https://caldav.icloud.com
APPLE_USERNAME=deine@apple-id.de
APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx
```
4. Container neu starten: `docker compose up -d`
Der Sync-Button erscheint automatisch in den Einstellungen.
---
## Familienmitglieder
Neue Mitglieder können nur Admins anlegen â es gibt keinen öffentlichen Registrierungs-Endpoint.
**Im Browser:** Einstellungen â Familienmitglieder â Mitglied hinzufĂŒgen
**Per Script** (z.B. fĂŒr weiteren Admin):
```bash
docker compose exec oikos node setup.js
```
---
## Updates
```bash
git pull
docker compose up -d --build
```
Datenbank-Migrationen laufen automatisch beim Start. Daten im Volume `oikos_data` bleiben erhalten.
---
## Entwicklung
```bash
npm install
cp .env.example .env
# SESSION_SECRET setzen â DB_ENCRYPTION_KEY weglassen (kein SQLCipher lokal)
npm run dev # Server mit Auto-Reload
```
```bash
npm test # 146 Tests, 7 Suiten (In-Memory-SQLite, keine laufende App nötig)
```
---
## Datensicherung
```bash
# Backup erstellen
docker run --rm \
-v oikos_oikos_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/oikos-backup-$(date +%Y%m%d).tar.gz /data
# Backup wiederherstellen
docker compose down
docker run --rm \
-v oikos_oikos_data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/oikos-backup-YYYYMMDD.tar.gz -C /
docker compose up -d
```
---
## Sicherheit
- Sessions: `httpOnly`, `SameSite=Strict`, `Secure` in Produktion, 7 Tage TTL
- CSRF-Schutz via Double Submit Cookie auf allen schreibenden Requests
- Passwörter mit bcrypt (Cost Factor 12) gehasht
- Login-Rate-Limit: 5 Versuche/Minute
- API-Rate-Limit: 300 Requests/Minute pro IP
- Content Security Policy via Helmet
- Datenbank optional mit SQLCipher AES-256 verschlĂŒsselt (im Docker-Container)
- Kein API-Endpoint ohne Session-Auth erreichbar (auĂer `/api/v1/auth/login`)
---
## Lizenz
[MIT](./LICENSE) © 2025 ulsklyc