Baikal CalDAV/CardDAV Server mit Caddy-TLS-Proxy (100 Jahre Zertifikat)
- docker-compose.yml: baikal (ckulka/baikal:nginx) + caddy Reverse Proxy - Persistente Daten unter ./daten (config, data, caddy_certs) - Caddy-Image mit Entrypoint: erstellt beim Start automatisch ein selbstsigniertes 100-Jahres-Zertifikat, falls noch keins vorhanden ist - README mit Setup-, Backup- und Zertifikats-Anleitung
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
# Hostname/IP fuer das selbstsignierte 100-Jahres-Zertifikat (CN + SAN).
|
||||||
|
# Nach dem ersten Start nur wirksam, wenn daten/caddy_certs vorher geleert wird.
|
||||||
|
CADDY_CERT_CN=baikal.local
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Persistente Laufzeitdaten nicht versionieren
|
||||||
|
daten/config/*
|
||||||
|
daten/data/*
|
||||||
|
daten/caddy_certs/*
|
||||||
|
!daten/**/.gitkeep
|
||||||
|
|
||||||
|
.env
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Caddyfile fuer den Baikal CalDAV/CardDAV Server
|
||||||
|
#
|
||||||
|
# auto_https wird global abgeschaltet, weil wir selbst ein Zertifikat
|
||||||
|
# bereitstellen (siehe caddy/entrypoint.sh) statt Caddy per ACME/Let's
|
||||||
|
# Encrypt bzw. seiner internen CA (kurzlebige Zertifikate) machen zu lassen.
|
||||||
|
{
|
||||||
|
auto_https off
|
||||||
|
}
|
||||||
|
|
||||||
|
:443 {
|
||||||
|
tls /certs/baikal.crt /certs/baikal.key
|
||||||
|
|
||||||
|
reverse_proxy baikal:80
|
||||||
|
|
||||||
|
encode gzip
|
||||||
|
log {
|
||||||
|
output stdout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:80 {
|
||||||
|
# Reiner HTTP->HTTPS Redirect
|
||||||
|
redir https://{host}{uri} permanent
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# Baikal Server (Docker)
|
||||||
|
|
||||||
|
CalDAV/CardDAV-Server ([sabre/baikal](https://sabre.io/baikal/)) per Docker Compose,
|
||||||
|
mit vorgeschaltetem [Caddy](https://caddyserver.com/) als TLS-Reverse-Proxy.
|
||||||
|
|
||||||
|
## Aufbau
|
||||||
|
|
||||||
|
- **baikal** — `ckulka/baikal:nginx`, liefert Baikal auf Port 80 (intern)
|
||||||
|
- **caddy** — eigenes Image (`caddy:2-alpine` + `openssl`), terminiert TLS auf
|
||||||
|
Port 443 und leitet an `baikal` weiter. HTTP (Port 80) wird permanent auf
|
||||||
|
HTTPS umgeleitet.
|
||||||
|
|
||||||
|
Alle persistenten Daten liegen im Projektverzeichnis unter `./daten`:
|
||||||
|
|
||||||
|
```
|
||||||
|
daten/
|
||||||
|
config/ Baikal-Konfiguration (Setup, Admin-Login, DB-Settings)
|
||||||
|
data/ Baikal-Nutzdaten (Kalender, Adressbuecher, SQLite-DB)
|
||||||
|
caddy_certs/ Selbstsigniertes TLS-Zertifikat (baikal.crt / baikal.key)
|
||||||
|
```
|
||||||
|
|
||||||
|
`daten/` ist damit der einzige Ordner, den man fuer Backups sichern bzw. bei
|
||||||
|
einem Umzug/Redeploy 1:1 mitnehmen muss.
|
||||||
|
|
||||||
|
## TLS-Zertifikat (100 Jahre, automatisch)
|
||||||
|
|
||||||
|
Der Caddy-Container hat einen eigenen Entrypoint
|
||||||
|
(`caddy/entrypoint.sh`): Beim Start prueft er, ob unter
|
||||||
|
`daten/caddy_certs/baikal.crt` + `baikal.key` bereits ein Zertifikat liegt.
|
||||||
|
|
||||||
|
- **Nicht vorhanden** -> es wird automatisch ein neues, selbstsigniertes
|
||||||
|
Zertifikat per `openssl` erzeugt, gueltig fuer **36500 Tage (100 Jahre)**.
|
||||||
|
- **Vorhanden** -> wird unveraendert weiterverwendet (kein Ueberschreiben bei
|
||||||
|
jedem Neustart).
|
||||||
|
|
||||||
|
Caddys eingebautes automatisches HTTPS (ACME / interne CA mit kurzlebigen
|
||||||
|
Zertifikaten) ist im `Caddyfile` bewusst per `auto_https off` deaktiviert —
|
||||||
|
stattdessen wird das selbst erzeugte Langzeit-Zertifikat direkt referenziert.
|
||||||
|
|
||||||
|
Da es sich um ein selbstsigniertes Zertifikat handelt, werden CalDAV/CardDAV-
|
||||||
|
Clients (Browser, Thunderbird, DAVx5, iOS/macOS Kalender-App, ...) beim ersten
|
||||||
|
Verbinden eine Zertifikatswarnung anzeigen. Das Zertifikat muss dort einmalig
|
||||||
|
als vertrauenswuerdig akzeptiert bzw. importiert werden.
|
||||||
|
|
||||||
|
### Hostname/CN anpassen
|
||||||
|
|
||||||
|
Der Common Name (CN) und SAN-Eintrag des Zertifikats werden ueber die
|
||||||
|
Umgebungsvariable `CADDY_CERT_CN` gesteuert (Default: `baikal.local`).
|
||||||
|
|
||||||
|
Eigene Domain/IP setzen, bevor der Container zum ersten Mal hochfaehrt (das
|
||||||
|
Zertifikat wird nur EINMAL erzeugt — danach `daten/caddy_certs` loeschen und
|
||||||
|
neu starten, falls sich der Hostname aendert):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# .env bearbeiten: CADDY_CERT_CN=baikal.meine-domain.de
|
||||||
|
```
|
||||||
|
|
||||||
|
## Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Danach ist der Setup-Wizard erreichbar unter:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://<host-oder-ip>/admin/
|
||||||
|
```
|
||||||
|
|
||||||
|
Dort einmalig Admin-Zugang, Zeitzone und Datenbank (Standard: SQLite, kein
|
||||||
|
externer DB-Server noetig) einrichten.
|
||||||
|
|
||||||
|
## CalDAV/CardDAV-URLs (nach Setup)
|
||||||
|
|
||||||
|
- CalDAV: `https://<host>/dav.php/calendars/<username>/`
|
||||||
|
- CardDAV: `https://<host>/dav.php/addressbooks/<username>/`
|
||||||
|
|
||||||
|
## Neustart / Update
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Alle Nutzdaten bleiben in `./daten` erhalten, solange dieser Ordner nicht
|
||||||
|
geloescht wird.
|
||||||
|
|
||||||
|
## Zertifikat erneuern / Hostname aendern
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
rm -rf daten/caddy_certs
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Beim naechsten Start wird automatisch ein neues 100-Jahres-Zertifikat mit dem
|
||||||
|
aktuellen `CADDY_CERT_CN` erzeugt.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
FROM caddy:2-alpine
|
||||||
|
|
||||||
|
# openssl wird fuer die automatische Zertifikatserstellung im Entrypoint gebraucht
|
||||||
|
RUN apk add --no-cache openssl
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CERT_DIR="/certs"
|
||||||
|
CERT_FILE="$CERT_DIR/baikal.crt"
|
||||||
|
KEY_FILE="$CERT_DIR/baikal.key"
|
||||||
|
CN="${CADDY_CERT_CN:-baikal.local}"
|
||||||
|
|
||||||
|
mkdir -p "$CERT_DIR"
|
||||||
|
|
||||||
|
if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then
|
||||||
|
echo "[entrypoint] Kein Zertifikat unter $CERT_DIR gefunden - erstelle neues, 100 Jahre gueltiges Zertifikat fuer CN=$CN ..."
|
||||||
|
|
||||||
|
openssl req -x509 -nodes -newkey rsa:4096 -sha256 \
|
||||||
|
-days 36500 \
|
||||||
|
-keyout "$KEY_FILE" \
|
||||||
|
-out "$CERT_FILE" \
|
||||||
|
-subj "/C=DE/ST=Niedersachsen/L=Oldenburg/O=HackerSoft/CN=${CN}" \
|
||||||
|
-addext "subjectAltName=DNS:${CN},DNS:localhost,IP:127.0.0.1"
|
||||||
|
|
||||||
|
chmod 600 "$KEY_FILE"
|
||||||
|
chmod 644 "$CERT_FILE"
|
||||||
|
|
||||||
|
echo "[entrypoint] Zertifikat erstellt (gueltig fuer 36500 Tage / 100 Jahre)."
|
||||||
|
else
|
||||||
|
echo "[entrypoint] Bestehendes Zertifikat in $CERT_DIR gefunden, wird weiterverwendet."
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
# Baikal CalDAV/CardDAV Server + Caddy Reverse Proxy
|
||||||
|
# Alle persistenten Daten (Baikal-Konfig, Kalender/Kontakte, TLS-Zertifikat)
|
||||||
|
# liegen unter ./daten im Projektverzeichnis.
|
||||||
|
|
||||||
|
services:
|
||||||
|
baikal:
|
||||||
|
image: ckulka/baikal:nginx
|
||||||
|
container_name: baikal
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- TZ=Europe/Berlin
|
||||||
|
volumes:
|
||||||
|
- ./daten/config:/var/www/baikal/config
|
||||||
|
- ./daten/data:/var/www/baikal/Specific
|
||||||
|
networks:
|
||||||
|
- baikal_net
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
build: ./caddy
|
||||||
|
container_name: baikal_caddy
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
# Hostname/CN fuer das selbstsignierte 100-Jahres-Zertifikat.
|
||||||
|
# Bei Bedarf auf die tatsaechliche Domain/IP anpassen.
|
||||||
|
- CADDY_CERT_CN=${CADDY_CERT_CN:-baikal.local}
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- ./daten/caddy_certs:/certs
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- baikal
|
||||||
|
networks:
|
||||||
|
- baikal_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
baikal_net:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
Reference in New Issue
Block a user