🌐 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-AUTHHeader - Reverse-Proxy-Konfiguration
- Zertifikatsprobleme
Browser zeigt alten Stand
Joplin Web verwendet Browser-Speicher und Service Worker.
Bei Problemen:
- Alle Joplin-Web-Tabs schließen.
- Website-Daten der Joplin-Web-Domain löschen.
- Browser vollständig schließen.
- Browser neu starten.
- 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
- Joplin: https://joplinapp.org/
- Joplin GitHub: https://github.com/laurent22/joplin
- Joplin Build Documentation: https://joplinapp.org/help/dev/BUILD/
- Docker: https://www.docker.com/
- Gitea: https://about.gitea.com/
📜 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.