Update README.md
This commit is contained in:
1 parent
8d7bc82fef
commit
0b52c0cde4
1 file changed
+578
@@ -0,0 +1,578 @@
|
||||
# 🌐 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.
|
||||
Reference in new issue
Block a user