Files
2026-08-08 21:17:57 +02:00

11 KiB
Raw Permalink Blame History

🌐 Joplin Web – Self-Hosted Docker

Eine selbst gehostete Joplin Web App, die den offiziellen Joplin-Web-Client aus dem Joplin-Quellcode baut und anschließend über einen schlanken nginx-Container bereitstellt.

Die Web-App kann mit einem vorhandenen Joplin Server synchronisiert werden und ermöglicht den Zugriff auf Joplin-Notizen direkt über den Browser.

⚠️ Joplin Web befindet sich noch in Entwicklung/Beta. Vor produktivem Einsatz sollten Backups der Joplin-Daten vorhanden sein.


✨ Features

  • 🌐 Joplin direkt im Webbrowser
  • 🐳 Vollständig über Docker betreibbar
  • 🔄 Synchronisation mit einem eigenen Joplin Server
  • 🔐 Betrieb über HTTPS / Reverse Proxy
  • 🗄️ Browserbasierter lokaler Speicher
  • 📎 Unterstützung der Joplin-Synchronisation
  • 🚀 Fertiges Docker-Image kann über eine Container Registry verteilt werden
  • 🛡️ Zusätzlicher Zugriffsschutz über den Reverse Proxy möglich

🏗️ Aufbau

                        ┌──────────────────────┐
                        │       Browser        │
                        │ Firefox / Chrome ... │
                        └──────────┬───────────┘
                                   │
                                 HTTPS
                                   │
                                   ▼
                        ┌──────────────────────┐
                        │    Reverse Proxy     │
                        │ nginx / NPM / etc.   │
                        └──────────┬───────────┘
                                   │
                                   ▼
                        ┌──────────────────────┐
                        │     Joplin Web       │
                        │   nginx + Web App    │
                        │      Port 3000       │
                        └──────────┬───────────┘
                                   │
                              HTTPS / API
                                   │
                                   ▼
                        ┌──────────────────────┐
                        │    Joplin Server     │
                        │   Sync + Benutzer    │
                        └──────────────────────┘

📁 Projektstruktur

joplin-web/
├── Dockerfile
├── docker-compose.yml
├── nginx.conf
├── README.md
└── .gitignore

🚀 Installation

Variante 1 – Fertiges Container-Image

Wenn das Image bereits in einer Container Registry vorhanden ist, wird auf dem Zielserver kein Joplin-Build benötigt.

Beispiel:

services:
  joplin-web:
    image: gitea.example.com/username/joplin-web:latest
    container_name: joplin-web
    restart: unless-stopped

    ports:
      - "3000:80"

    security_opt:
      - no-new-privileges:true

Container starten:

docker compose pull
docker compose up -d

Status prüfen:

docker compose ps

Logs anzeigen:

docker logs -f joplin-web

Die Web-App ist anschließend lokal unter folgendem Port erreichbar:

http://SERVER-IP:3000

Für den produktiven Betrieb sollte Joplin Web über HTTPS bereitgestellt werden.


🔨 Variante 2 – Image selbst bauen

Repository klonen:

git clone https://gitea.example.com/username/joplin-web.git
cd joplin-web

Image bauen:

docker compose build --no-cache --progress=plain

Anschließend starten:

docker compose up -d

Status prüfen:

docker compose ps

🐳 Docker Image

Das Docker-Image wird in mehreren Stufen gebaut.

Builder

Im ersten Schritt wird der offizielle Joplin-Quellcode geladen und die Web-App gebaut.

Dabei werden unter anderem verwendet:

  • Devbox
  • Nix
  • Node.js
  • Yarn
  • Joplin Source
  • Joplin Mobile Web Build

Der Web-Build wird anschließend aus folgendem Verzeichnis übernommen:

packages/app-mobile/web/dist

Runtime

Der eigentliche produktive Container benötigt die Build-Umgebung nicht mehr.

Das fertige Web-Frontend wird über:

nginx

bereitgestellt.

Dadurch bleibt der laufende Container wesentlich kleiner als die Build-Umgebung.


🔐 HTTPS

Joplin Web sollte nicht dauerhaft über eine unverschlüsselte HTTP-Verbindung verwendet werden.

Bestimmte Browser-APIs, die Joplin Web benötigt, stehen nur in einem Secure Context zur Verfügung.

Empfohlen:

https://joplin-web.example.com

Der Reverse Proxy kann intern weiterhin auf:

http://JOPLIN-WEB-IP:3000

weiterleiten.


🧠 Cross-Origin Isolation

Für bestimmte Browser-Funktionen werden folgende HTTP-Header ausgeliefert:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin

Überprüfen:

curl -I http://127.0.0.1:3000

Beispiel:

HTTP/1.1 200 OK
Server: nginx

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin

Im Browser kann zusätzlich geprüft werden:

window.isSecureContext

und:

crossOriginIsolated

🔄 Verbindung mit Joplin Server

In Joplin Web unter der Synchronisationskonfiguration als Ziel Joplin Server auswählen.

Als Server-URL wird ausschließlich die Basis-URL verwendet:

https://joplin.example.com

Nicht:

https://joplin.example.com/api

und nicht:

https://joplin.example.com/login

Anschließend die Zugangsdaten des Joplin-Benutzers eintragen.


🌍 CORS bei eigenem Joplin Server

Wenn Joplin Web und Joplin Server unterschiedliche Domains verwenden, muss der Browser Cross-Origin-Anfragen zulassen.

Beispiel:

Joplin Web:
https://joplin-web.example.com

Joplin Server:
https://joplin.example.com

Ohne entsprechende Konfiguration können Fehler auftreten wie:

Blocked by CORS policy

oder:

Cross-Origin Request Blocked

Beispiel für nginx / Nginx Proxy Manager

Auf dem Reverse Proxy des Joplin Servers:

proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;

more_set_headers "Access-Control-Allow-Origin: https://joplin-web.example.com";
more_set_headers "Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS";
more_set_headers "Access-Control-Allow-Headers: Content-Type, Authorization, X-API-MIN-VERSION, X-API-AUTH";
more_set_headers "Vary: Origin";

Die Domain muss an die eigene Joplin-Web-Adresse angepasst werden.


CORS testen

Preflight-Anfrage:

curl -i -X OPTIONS \
  -H "Origin: https://joplin-web.example.com" \
  -H "Access-Control-Request-Method: PUT" \
  -H "Access-Control-Request-Headers: content-type,x-api-min-version,x-api-auth" \
  https://joplin.example.com/api/items/root:/testing.txt:/content

Die Antwort sollte unter anderem enthalten:

Access-Control-Allow-Origin: https://joplin-web.example.com

Access-Control-Allow-Methods:
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS

Access-Control-Allow-Headers:
Content-Type, Authorization, X-API-MIN-VERSION, X-API-AUTH

🔒 Zusätzlicher Zugriffsschutz

Da die Web-App grundsätzlich über ihre URL erreichbar ist, empfiehlt sich ein zusätzlicher Schutz auf Reverse-Proxy-Ebene.

Mögliche Lösungen:

  • HTTP Basic Authentication
  • Nginx Proxy Manager Access Lists
  • Authelia
  • Authentik
  • VPN / WireGuard / NetBird

Die Architektur sieht dann beispielsweise so aus:

Internet
   │
   ▼
Reverse Proxy
   │
   ├── Authentifizierung
   │
   ▼
Joplin Web
   │
   ▼
Joplin Server

Die eigentlichen Joplin-Zugangsdaten werden weiterhin für die Synchronisation mit dem Joplin Server verwendet.


🔄 Update

Bei Verwendung eines fertigen Images

docker compose pull
docker compose up -d

Nicht mehr verwendete Images können anschließend entfernt werden:

docker image prune

Bei lokalem Build

Repository aktualisieren:

git pull

Danach neu bauen:

docker compose build --no-cache
docker compose up -d

📦 Image in eine Gitea Container Registry pushen

Zunächst anmelden:

docker login gitea.example.com

Image taggen:

docker tag joplin-web-joplin-web:latest \
  gitea.example.com/username/joplin-web:latest

Danach:

docker push gitea.example.com/username/joplin-web:latest

Auf einem anderen Docker-Server genügt anschließend:

docker login gitea.example.com
docker compose pull
docker compose up -d

Damit muss Joplin auf dem Zielserver nicht erneut aus dem Quellcode gebaut werden.


🧹 Nützliche Docker-Befehle

Container anzeigen:

docker compose ps

Logs:

docker logs -f joplin-web

Container neu starten:

docker compose restart

Container stoppen:

docker compose down

Container starten:

docker compose up -d

Image neu bauen:

docker compose build --no-cache

🛠️ Fehlerbehebung

Web-App lädt nicht

Container prüfen:

docker compose ps

Logs:

docker logs joplin-web --tail 100

Webserver lokal testen:

curl -I http://127.0.0.1:3000

Synchronisation schlägt fehl

Browser-Entwicklertools öffnen und unter Console bzw. Network nach Fehlern suchen.

Häufige Ursachen:

  • falsche Joplin-Server-URL
  • CORS
  • fehlender X-API-AUTH Header
  • Reverse-Proxy-Konfiguration
  • Zertifikatsprobleme

Browser zeigt alten Stand

Joplin Web verwendet Browser-Speicher und Service Worker.

Bei Problemen:

  1. Alle Joplin-Web-Tabs schließen.
  2. Website-Daten der Joplin-Web-Domain löschen.
  3. Browser vollständig schließen.
  4. Browser neu starten.
  5. Joplin Web erneut öffnen.

⚠️ Hinweise

Joplin Web speichert lokale Client-Daten im Browser.

Daher gilt:

  • Browserdaten nicht unüberlegt löschen.
  • Synchronisation vor größeren Änderungen vollständig durchführen.
  • Regelmäßige Backups des Joplin Servers erstellen.
  • Die Web-App möglichst nur über HTTPS betreiben.
  • Für öffentlich erreichbare Installationen zusätzlichen Zugriffsschutz verwenden.

🔗 Links


📜 Lizenz

Dieses Repository enthält die Docker-/Deployment-Konfiguration für Joplin Web.

Joplin selbst ist ein eigenständiges Open-Source-Projekt. Für Joplin gelten die Lizenzbedingungen des offiziellen Joplin-Projekts.


❤️ Credits

Joplin wird von Laurent Cozic und der Joplin-Community entwickelt.

Dieses Repository stellt lediglich eine Docker-basierte Möglichkeit bereit, den Joplin-Web-Client selbst zu bauen und zu hosten.