Files
joplin-web/README.md
T
2026-08-08 21:17:57 +02:00

579 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🌐 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
```text
┌──────────────────────┐
│ Browser │
│ Firefox / Chrome ... │
└──────────┬───────────┘
│
HTTPS
│
▼
┌──────────────────────┐
│ Reverse Proxy │
│ nginx / NPM / etc. │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Joplin Web │
│ nginx + Web App │
│ Port 3000 │
└──────────┬───────────┘
│
HTTPS / API
│
▼
┌──────────────────────┐
│ Joplin Server │
│ Sync + Benutzer │
└──────────────────────┘
```
---
# 📁 Projektstruktur
```text
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:
```yaml
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:
```bash
docker compose pull
docker compose up -d
```
Status prüfen:
```bash
docker compose ps
```
Logs anzeigen:
```bash
docker logs -f joplin-web
```
Die Web-App ist anschließend lokal unter folgendem Port erreichbar:
```text
http://SERVER-IP:3000
```
> Für den produktiven Betrieb sollte Joplin Web über **HTTPS** bereitgestellt werden.
---
# 🔨 Variante 2 – Image selbst bauen
Repository klonen:
```bash
git clone https://gitea.example.com/username/joplin-web.git
cd joplin-web
```
Image bauen:
```bash
docker compose build --no-cache --progress=plain
```
Anschließend starten:
```bash
docker compose up -d
```
Status prüfen:
```bash
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:
```text
packages/app-mobile/web/dist
```
## Runtime
Der eigentliche produktive Container benötigt die Build-Umgebung nicht mehr.
Das fertige Web-Frontend wird über:
```text
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:
```text
https://joplin-web.example.com
```
Der Reverse Proxy kann intern weiterhin auf:
```text
http://JOPLIN-WEB-IP:3000
```
weiterleiten.
---
# 🧠 Cross-Origin Isolation
Für bestimmte Browser-Funktionen werden folgende HTTP-Header ausgeliefert:
```text
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
```
Überprüfen:
```bash
curl -I http://127.0.0.1:3000
```
Beispiel:
```text
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:
```javascript
window.isSecureContext
```
und:
```javascript
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:
```text
https://joplin.example.com
```
Nicht:
```text
https://joplin.example.com/api
```
und nicht:
```text
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:
```text
Joplin Web:
https://joplin-web.example.com
Joplin Server:
https://joplin.example.com
```
Ohne entsprechende Konfiguration können Fehler auftreten wie:
```text
Blocked by CORS policy
```
oder:
```text
Cross-Origin Request Blocked
```
## Beispiel für nginx / Nginx Proxy Manager
Auf dem Reverse Proxy des **Joplin Servers**:
```nginx
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:
```bash
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:
```text
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:
```text
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
```bash
docker compose pull
docker compose up -d
```
Nicht mehr verwendete Images können anschließend entfernt werden:
```bash
docker image prune
```
---
## Bei lokalem Build
Repository aktualisieren:
```bash
git pull
```
Danach neu bauen:
```bash
docker compose build --no-cache
docker compose up -d
```
---
# 📦 Image in eine Gitea Container Registry pushen
Zunächst anmelden:
```bash
docker login gitea.example.com
```
Image taggen:
```bash
docker tag joplin-web-joplin-web:latest \
gitea.example.com/username/joplin-web:latest
```
Danach:
```bash
docker push gitea.example.com/username/joplin-web:latest
```
Auf einem anderen Docker-Server genügt anschließend:
```bash
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:
```bash
docker compose ps
```
Logs:
```bash
docker logs -f joplin-web
```
Container neu starten:
```bash
docker compose restart
```
Container stoppen:
```bash
docker compose down
```
Container starten:
```bash
docker compose up -d
```
Image neu bauen:
```bash
docker compose build --no-cache
```
---
# 🛠️ Fehlerbehebung
## Web-App lädt nicht
Container prüfen:
```bash
docker compose ps
```
Logs:
```bash
docker logs joplin-web --tail 100
```
Webserver lokal testen:
```bash
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
- 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](https://joplinapp.org/) 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.