Zum Inhalt springen

Docker-Bereitstellung ​

Mindwtr bietet offizielle Docker-Unterstützung für den Betrieb von:

  • mindwtr-app: der Desktop-Web-/PWA-Build, bereitgestellt durch Nginx
  • mindwtr-cloud: der schlanke Synchronisierungsserver und die REST-API zur Aufgabenautomatisierung

Diese sind als Docker-Images verfügbar und lassen sich einfach mit Docker Compose orchestrieren.


Schnellstart (Docker Compose) ​

Sie müssen das Repository nicht klonen. Die offiziellen Images werden auf GHCR veröffentlicht, und die Datei compose.yaml lädt sie für Sie herunter.

  1. Laden Sie die Compose-Datei herunter:

    bash
    curl -LO https://raw.githubusercontent.com/dongdongbh/Mindwtr/main/docker/compose.yaml
  2. Legen Sie daneben eine .env-Datei an (Docker Compose liest sie automatisch):

    dotenv
    MINDWTR_CLOUD_AUTH_TOKENS=your_token_here
    MINDWTR_CLOUD_CORS_ORIGIN=http://localhost:5173

    MINDWTR_CLOUD_CORS_ORIGIN muss exakt der Adresse entsprechen, unter der Sie die PWA im Browser öffnen, einschließlich Schema und Port. http://localhost:5173 funktioniert nur, wenn der Browser auf dem Docker-Host selbst läuft. Von jedem anderen Gerät aus verwenden Sie die Adresse des Hosts, zum Beispiel http://192.168.1.20:5173. Es kann nur eine Origin gesetzt werden.

  3. Laden und starten Sie die Dienste:

    bash
    docker compose pull
    docker compose up -d
  4. Rufen Sie die Dienste auf:

    • PWA (Web-App): Öffnen Sie http://localhost:5173 im Browser.
    • Cloud-Verfügbarkeitsprüfung: Öffnen Sie http://localhost:8787/health.
    • Cloud-Speicherbereitschaft: Öffnen Sie http://localhost:8787/ready.
    • Self-Hosted-URL für lokale Tests: http://localhost:8787
    • Basis-URL der REST-API: http://localhost:8787/v1

/health meldet nur, dass der Cloud-Server HTTP-Anfragen beantwortet. /ready prüft zusätzlich, ob das konfigurierte Datenverzeichnis beschreibbar ist; diese Adresse zeigt also, ob der Server Ihre Daten wirklich speichern kann. Compose verwendet die im Image enthaltene Zustandsprüfung: aktuelle Images prüfen /ready, ältere /health.

Wenn Sie die Images stattdessen aus dem Quellcode bauen möchten, klonen Sie das Repository und führen Sie in dessen Stammverzeichnis docker compose -f docker/compose.yaml up --build -d aus. Siehe Manuell bauen weiter unten.

Diese standardmäßige Compose-Datei verwendet ausschließlich HTTP und ist für lokale/private Tests vorgesehen. Mindwtr-Clients für Desktop- und Mobilgeräte akzeptieren HTTP nur für erkannte lokale/private Ziele wie localhost, 127.0.0.1, 10.x.x.x, 172.16.x.x bis 172.31.x.x, 192.168.x.x, Loopback-/private IPv6-Adressen, *.local und *.home.arpa.

Verwenden Sie HTTPS für öffentliche URLs, benutzerdefinierte DNS-Namen, VPN-Hostnamen, Tailscale, ZeroTier oder jeden Namen, der nicht als lokal/privat erkannt wird, oder aktivieren Sie Unsichere Verbindungen (HTTP) zulassen in den Sync-Einstellungen der App, um diesen Hostnamen über unverschlüsseltes HTTP zu akzeptieren. Die Daten werden dann unverschlüsselt übertragen; nutzen Sie die Option daher nur in einem Netzwerk, dem Sie vertrauen.


HTTPS-Einrichtung mit Caddy ​

Verwenden Sie für die öffentliche Desktop- oder Mobilsynchronisierung die Compose-Datei mit Caddy:

bash
cp docker/.env.https.example docker/.env.https.local

Bearbeiten Sie docker/.env.https.local:

dotenv
MINDWTR_CLOUD_DOMAIN=mindwtr.example.com
MINDWTR_CLOUD_AUTH_TOKENS=your_long_random_token
MINDWTR_CLOUD_CORS_ORIGIN=https://mindwtr.example.com
MINDWTR_CADDYFILE=Caddyfile.https

Starten Sie den Stack:

bash
docker compose --env-file docker/.env.https.local -f docker/compose.https.yaml up -d

Prüfen Sie den Server:

bash
curl https://mindwtr.example.com/health
curl https://mindwtr.example.com/ready

Setzen Sie in Mindwtr unter Einstellungen → Synchronisierung → Self-Hosted die Self-Hosted-URL auf:

text
https://mindwtr.example.com

Mindwtr hängt /v1/data automatisch an.

Öffentliches HTTPS ​

Verwenden Sie Caddyfile.https, wenn MINDWTR_CLOUD_DOMAIN ein öffentlicher DNS-Name ist, der auf diesen Docker-Host verweist. Die Ports 80 und 443 müssen für die automatische Zertifikatsausstellung erreichbar sein. Caddy bezieht und erneuert das Zertifikat und leitet Anfragen per Reverse Proxy an mindwtr-cloud weiter.

HTTPS nur im LAN ​

Verwenden Sie Caddyfile.local-https, wenn der Hostname nur in Ihrem Heimnetz aufgelöst wird:

dotenv
MINDWTR_CLOUD_DOMAIN=mindwtr.home.arpa
MINDWTR_CLOUD_CORS_ORIGIN=https://mindwtr.home.arpa
MINDWTR_CADDYFILE=Caddyfile.local-https

Dies verwendet die interne Zertifizierungsstelle von Caddy. Jedes Clientgerät muss dem lokalen Stammzertifikat von Caddy vertrauen, bevor Mindwtr die HTTPS-Verbindung akzeptiert. Mindwtr 1.2.0 und neuer vertraut unter Android auf benutzerinstallierte Zertifizierungsstellen; auf iPhone und iPad muss das Stammzertifikat zusätzlich installiert und ausdrücklich als vollständig vertrauenswürdig aktiviert werden. Öffentliche Let's-Encrypt-Zertifikate bleiben die einfachste Wahl, wenn der Hostname öffentlich erreichbar ist.

Exportieren Sie nach dem Start des reinen LAN-Stacks das lokale Stammzertifikat von Caddy:

bash
docker compose --env-file docker/.env.https.local -f docker/compose.https.yaml cp caddy:/data/caddy/pki/authorities/local/root.crt ./mindwtr-caddy-root.crt

Installieren Sie dieses Zertifikat auf jedem Gerät, das mit diesem Hostnamen synchronisiert, als vertrauenswürdiges Stammzertifikat.


Konfiguration ​

Synchronisierungstoken ​

Der Cloud-Server benötigt ein Token zur Authentifizierung. Sie müssen es in den Umgebungsvariablen festlegen.

Setzen Sie in docker/compose.yaml (oder über eine Umgebungsvariable):

yaml
MINDWTR_CLOUD_AUTH_TOKENS=your_token_here

MINDWTR_CLOUD_TOKEN wird aus Gründen der Abwärtskompatibilität weiterhin akzeptiert, ist aber veraltet.

Für ein dateibasiertes Docker Secret entfernen Sie MINDWTR_CLOUD_AUTH_TOKENS aus Ihrer .env-Datei, legen das Token in einer Host-Datei ab, die nur ihr Eigentümer lesen kann, und starten Compose mit dem Overlay docker/compose.secrets.yaml. MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST muss ein absoluter Pfad auf dem Host sein:

bash
printf '%s\n' 'replace_with_a_token_at_least_20_characters_long' > /absolute/path/mindwtr-cloud-tokens
chmod 600 /absolute/path/mindwtr-cloud-tokens
MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST=/absolute/path/mindwtr-cloud-tokens \
  docker compose -f docker/compose.yaml -f docker/compose.secrets.yaml up -d

Das Overlay bindet diese Datei schreibgeschützt unter /run/secrets/mindwtr_cloud_tokens ein und setzt MINDWTR_CLOUD_AUTH_TOKENS_FILE für Sie, sodass das Token nie in die gerenderte Compose-Umgebung gelangt. Belassen Sie die Host-Datei im Modus 0600. Der Server startet weiterhin nicht, wenn weder die direkt eingetragene Einstellung noch eine lesbare Token-Datei ein gültiges Token liefert.

Dasselbe Overlay funktioniert auch mit dem Caddy-HTTPS-Stack. Entfernen Sie das direkt eingetragene Token aus docker/.env.https.local und führen Sie dann aus:

bash
MINDWTR_CLOUD_AUTH_TOKENS_FILE_HOST=/absolute/path/mindwtr-cloud-tokens \
  docker compose --env-file docker/.env.https.local \
    -f docker/compose.https.yaml -f docker/compose.secrets.yaml up -d

Token erzeugen: Mit folgendem Befehl können Sie ein starkes zufälliges Token erzeugen:

bash
cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 50 | head -n 1

Clientkonfiguration ​

So verbinden Sie Ihre Mindwtr-Clients (Desktop oder Mobilgerät) mit dieser selbst gehosteten Cloud:

  1. Öffnen Sie Einstellungen → Synchronisierung.
  2. Wählen Sie Self-Hosted (oder Cloud).
  3. Setzen Sie die Self-Hosted-URL auf den Basisendpunkt Ihres Servers:
    http://localhost:8787
    Mindwtr hängt /v1/data automatisch an diese URL an.
  4. Geben Sie dasselbe Token ein, das Sie in MINDWTR_CLOUD_AUTH_TOKENS konfiguriert haben.

Verwenden Sie für privates LAN-HTTP eine lokale/private Adresse wie http://192.168.1.20:8787. Verwenden Sie für öffentliche URLs die oben beschriebene HTTPS-Einrichtung mit Caddy.

Sync-Einstellungen der Web-App vorbelegen ​

Ein neuer Browser, der die PWA öffnet, kann die Cloud-URL bereits ausgefüllt vorfinden, sodass nur noch das Token eingegeben werden muss:

  • Gleiche Domain (empfohlen): Wenn App und Cloud-API eine Domain teilen (wie im Caddy-HTTPS-Setup), erkennt die Web-App die Cloud automatisch auf ihrer eigenen Origin. Nichts zu konfigurieren.
  • Getrennte Domains: Setzen Sie MINDWTR_DEFAULT_CLOUD_URL am mindwtr-app-Container auf die öffentliche Cloud-URL, etwa in Kubernetes oder wenn App und API auf verschiedenen Hosts laufen.

Der Wert füllt nur das Einrichtungsformular vor. Er überschreibt nie eine bereits konfigurierte URL, und die Synchronisierung bleibt aus, bis die Person mit ihrem Token speichert.

Einschränken, wer die gehostete Web-App öffnen darf ​

Der Browser-Build ist ein statisches Bundle, und die angezeigten Daten liegen nur im Speicher des jeweiligen Browsers; die Aufgabendaten und die API sind durch das Bearer-Token auf /v1/* geschützt. Mindwtr hat daher keinen eigenen Anmeldebildschirm. Wenn die Web-App aus dem Internet erreichbar ist und Fremde sie nicht öffnen sollen, richten Sie HTTP Basic Auth auf dem vorgeschalteten Proxy ein, für jeden Pfad außer /v1/*. Browser melden sich dann einmal an, während die Desktop- und Mobil-Apps weiter ihr Bearer-Token verwenden. Mit dem mitgelieferten Caddy erzeugen Sie einen Hash mit caddy hash-password und verwenden:

example.com {
	@ui not path /v1/*
	basic_auth @ui {
		alice <bcrypt hash>
	}
	handle /v1/* {
		reverse_proxy mindwtr-cloud:8787
	}
	handle {
		reverse_proxy mindwtr-app:5173
	}
}

Bei nginx setzen Sie auth_basic in den Block location / und lassen location /v1/ ohne diese Angabe. Lassen Sie MINDWTR_CLOUD_AUTH_TOKENS und MINDWTR_CLOUD_CORS_ORIGIN wie oben beschrieben gesetzt; sie schützen die Daten, die Proxy-Anmeldung entscheidet nur, wer die Seite laden darf.

Dropbox-Synchronisierung und die Docker-PWA ​

Das Docker-Image mindwtr-app stellt den Browser-/PWA-Build bereit. Die native Dropbox-OAuth-Synchronisierung ist in dieser Laufzeitumgebung nicht verfügbar, da die Dropbox-Verbindung in den nativen Desktop- und Mobil-Apps implementiert ist. Das Hinzufügen von VITE_DROPBOX_APP_KEY oder DROPBOX_APP_KEY über .env, env_file, die Compose-Laufzeitumgebung oder ein Docker-Buildargument aktiviert Dropbox in Docker nicht.

Verwenden Sie für eine mit Docker gehostete Synchronisierung den mitgelieferten Self-Hosted-Cloud-Server oder WebDAV. Wenn der Self-Hosted-Endpunkt hinter Authelia oder einem anderen interaktiven SSO-Proxy liegt, konfigurieren Sie den Proxy so, dass der Synchronisierungs-/API-Pfad von Mindwtr das Bearer-Token von Mindwtr direkt verwenden kann. Die Mobil-App kann keine Authelia-Browseranmeldung vor /v1/data abschließen.

Erinnerungen in der Docker-PWA ​

Erinnerungen für Aufgaben, Start-, Fällig- und Überprüfungstermine erscheinen auch im Browser-Build, als Web-Benachrichtigungen. Erteilen Sie der Seite die Benachrichtigungsberechtigung (Einstellungen → Benachrichtigungen) und lassen Sie einen Mindwtr-Tab offen: Der Browser-Build hat keinen Hintergrunddienst, Erinnerungen werden also nur bei laufendem Tab ausgeliefert. Ein Tab im Hintergrund wird in seinen Timern gebremst, eine Erinnerung kann daher bis zu eine Minute später eintreffen; eine Erinnerung, die bei vollständig geschlossenen Tabs fällig war, wird übersprungen und nicht nachgeliefert. Für Erinnerungen, die einen geschlossenen Browser überdauern, verwenden Sie die Desktop- oder Mobil-App.

API zur Aufgabenautomatisierung ​

Derselbe Container mindwtr-cloud stellt auch die REST-API zur Aufgabenautomatisierung bereit. Sie verwendet dieselbe Basis-URL und dasselbe Bearer-Token wie die Synchronisierung.

Häufig verwendete Endpunkte:

  • GET /v1/data und PUT /v1/data für die Synchronisierung
  • GET /v1/tasks und POST /v1/tasks zum Auflisten und Erstellen von Aufgaben
  • GET /v1/projects für Projekte
  • GET /v1/search?query=... zur Suche nach Aufgaben und Projekten

Beispiel:

bash
curl -X POST http://localhost:8787/v1/tasks \
  -H "Authorization: Bearer your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"input":"Review PR @work /due:tomorrow"}'

CORS-Ursprung (Produktion) ​

Der Cloud-Server verwendet standardmäßig http://localhost:5173 für CORS. Setzen Sie für den Produktivbetrieb:

yaml
MINDWTR_CLOUD_CORS_ORIGIN=https://your-app-domain.example

Datenpersistenz ​

Binden Sie ein Volume für das Datenverzeichnis ein, damit Ihre Cloud-Daten bei Containerneustarts erhalten bleiben.

In Ihrer compose.yaml:

yaml
volumes:
  - ./data:/app/cloud_data

Manuell bauen ​

Wenn Sie die Images ohne Compose selbst bauen möchten:

PWA bauen:

bash
docker build -f docker/app/Dockerfile -t mindwtr-app .

Cloud-Server bauen:

bash
docker build -f docker/cloud/Dockerfile -t mindwtr-cloud .

GitHub Actions und GHCR ​

Das Projekt enthält einen GitHub-Actions-Workflow, der Images automatisch baut und an die GitHub Container Registry (GHCR) überträgt.

Offizielle Images:

  • ghcr.io/dongdongbh/mindwtr-app:latest
  • ghcr.io/dongdongbh/mindwtr-cloud:latest

Vorabversionen sind unter dem beweglichen Tag beta verfügbar, der immer auf die neueste Veröffentlichung (Release Candidate oder stabile Version) verweist, oder über eine feste Version, z. B. ghcr.io/dongdongbh/mindwtr-app:1.2.0-rc.1. latest bleibt stets bei der stabilen Version. Weitere Plattformen finden Sie unter An den Beta-Kanälen teilnehmen.

Die Datei docker/compose.yaml ist standardmäßig für diese Images konfiguriert, sodass Sie die neueste Version einfach abrufen können, ohne lokal zu bauen.


Technische Hinweise ​

  • PWA-Bereitstellung: Die Web-App verwendet clientseitiges Rendering. Der Nginx-Container ist mit try_files so konfiguriert, dass alle Anfragen an index.html umgeleitet werden. Dadurch entstehen beim Neuladen einer Seite keine 404-Fehler.
  • Basis-Image: Der Build verwendet Bun (fest auf v1.3 gesetzt) und enthält die für better-sqlite3 erforderlichen C++20-Flags.

Mindwtr ist kostenlos, quelloffen und lokal orientiert.
Getting Things Done und GTD sind eingetragene Marken der David Allen Company. Mindwtr ist weder mit der David Allen Company verbunden noch wird es von ihr unterstützt oder gesponsert.