inmitial commit
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,411 @@
|
|||||||
|
# Installationsanleitung: Euro-Office DocumentServer mit Nextcloud-Anbindung
|
||||||
|
|
||||||
|
Diese Anleitung beschreibt die Installation des Euro-Office DocumentServers (Docker-Variante)
|
||||||
|
auf einem Debian-13-Server und die Anbindung an eine bestehende Nextcloud-Instanz über Apache2
|
||||||
|
als Reverse-Proxy.
|
||||||
|
|
||||||
|
Projekt: https://github.com/Euro-Office/DocumentServer
|
||||||
|
Dokumentation: https://euro-office.github.io/documentation/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Parameter dieser Installation
|
||||||
|
|
||||||
|
Alle im Dokument verwendeten Platzhalter sind hier zentral aufgeführt. Für eine abweichende
|
||||||
|
Installation genügt es, diese Tabelle anzupassen und die Werte in den Befehlen entsprechend
|
||||||
|
zu übernehmen.
|
||||||
|
|
||||||
|
| Platzhalter | Beschreibung | Beispielwert (diese Installation) |
|
||||||
|
|-----------------------------|------------------------------------------------------------|------------------------------------------------------|
|
||||||
|
| `<DS_HOSTNAME>` | Hostname des Euro-Office DocumentServers | `eo-ds.ndnaht.de` |
|
||||||
|
| `<NC_HOSTNAME>` | Hostname der bestehenden Nextcloud-Instanz | `cloud.ndnaht.de` |
|
||||||
|
| `<IPV4_ADDRESS>` | Öffentliche IPv4-Adresse des Servers | `135.181.90.132` |
|
||||||
|
| `<IPV6_ADDRESS>` | Öffentliche IPv6-Adresse des Servers | `2a01:4f9:c014:1ba8::1` |
|
||||||
|
| `<INSTALL_DIR>` | Arbeitsverzeichnis für Docker-Compose-Stack | `/opt/euro-office` |
|
||||||
|
| `<VHOST_DIR>` | Verzeichnis der Apache-vHost-Konfigurationsdateien | `/usr/local/apache2/conf/vhosts` |
|
||||||
|
| `<INTERNAL_PORT>` | Lokaler Port, auf den der Container gemappt wird | `8080` |
|
||||||
|
| `<DOCKER_BRIDGE_NAME>` | Fester Name der Docker-Netzwerk-Bridge | `br-euroffice` |
|
||||||
|
| `<CERT_DIR>` | Verzeichnis mit TLS-Zertifikat (hier: dehydrated) | `/var/lib/dehydrated/certs/<DS_HOSTNAME>` |
|
||||||
|
| `<NC_DOCROOT>` | Docroot-Verzeichnis der Nextcloud-Installation | `/var/www/cloud.ndnaht.de/htdocs` |
|
||||||
|
| `<NC_LOGFILE>` | Pfad der Nextcloud-Logdatei | `/var/www/cloud.ndnaht.de/logs/cloud.log` |
|
||||||
|
| `<PHP_BINARY>` | Pfad zum PHP-CLI-Binary | `/usr/local/php/bin/php` |
|
||||||
|
| `<JWT_SECRET>` | Gemeinsames Secret zwischen DocumentServer und Nextcloud | wird generiert (siehe Schritt 3) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Voraussetzungen
|
||||||
|
|
||||||
|
- **Betriebssystem:** Debian 13 (getestet), amd64 oder arm64
|
||||||
|
- **Docker Engine** (Community Edition) inkl. **Compose-Plugin v2**, installiert über das offizielle Docker-Repository:
|
||||||
|
```
|
||||||
|
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable
|
||||||
|
```
|
||||||
|
- **Mindestens 4 GB RAM** (8 GB empfohlen für Mehrbenutzerbetrieb), 10 GB freier Plattenplatz
|
||||||
|
- **Bestehende Nextcloud-Instanz** (getestet mit Nextcloud 34), erreichbar über Apache2, mit SSH-/`occ`-Zugriff
|
||||||
|
- **DNS-Eintrag** für `<DS_HOSTNAME>`, zeigt auf `<IPV4_ADDRESS>` (bzw. `<IPV6_ADDRESS>`)
|
||||||
|
- **Gültiges TLS-Zertifikat** für `<DS_HOSTNAME>` (hier über [dehydrated](https://github.com/dehydrated-io/dehydrated) verwaltet)
|
||||||
|
- **Apache2** bereits installiert und aktiv, mit folgenden Modulen aktiviert:
|
||||||
|
`proxy`, `proxy_http`, `proxy_wstunnel`, `ssl`, `headers`, `rewrite`
|
||||||
|
- **Firewall-Hinweis:** Falls der Server eine eigene iptables/nftables-Firewall betreibt
|
||||||
|
(Eigenbau-Skript, CSF, ufw o. ä.), die *nicht* automatisch mit Docker zusammenarbeitet,
|
||||||
|
siehe Abschnitt 8 ("Firewall-Anpassung für Docker-Bridge-Netzwerke"). Ohne diesen Schritt
|
||||||
|
ist der Container u. U. nicht einmal vom Host selbst erreichbar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Arbeitsverzeichnis und Secrets anlegen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p <INSTALL_DIR>
|
||||||
|
cd <INSTALL_DIR>
|
||||||
|
```
|
||||||
|
|
||||||
|
JWT-Secret generieren und in `.env` ablegen (wird von Docker Compose automatisch eingelesen):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "EO_JWT_SECRET=$(openssl rand -hex 32)" | sudo tee .env
|
||||||
|
sudo chmod 600 .env
|
||||||
|
```
|
||||||
|
|
||||||
|
> Diesen Wert später 1:1 in die Nextcloud-Konfiguration übernehmen (Schritt 10).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. docker-compose.yaml
|
||||||
|
|
||||||
|
Der Container wird **nicht** direkt öffentlich exponiert, sondern nur auf `127.0.0.1`
|
||||||
|
gebunden — Apache übernimmt als Reverse-Proxy die öffentliche Erreichbarkeit inkl. TLS.
|
||||||
|
Das Docker-Netzwerk bekommt einen **festen Bridge-Namen**, damit Firewall-Regeln, die
|
||||||
|
auf den Interface-Namen verweisen, auch nach einem Neuaufbau des Netzwerks gültig bleiben.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
euro-office:
|
||||||
|
image: ghcr.io/euro-office/documentserver:latest
|
||||||
|
container_name: euro-office-ds
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- JWT_ENABLED=true
|
||||||
|
- JWT_SECRET=${EO_JWT_SECRET}
|
||||||
|
# EXAMPLE_ENABLED bewusst NICHT gesetzt (=false) -> kein offenes Beispiel-App in Produktion
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:<INTERNAL_PORT>:80"
|
||||||
|
volumes:
|
||||||
|
- eo_data:/var/lib/euro-office/documentserver
|
||||||
|
- eo_logs:/var/log/euro-office/documentserver
|
||||||
|
- eo_config:/etc/euro-office/documentserver
|
||||||
|
networks:
|
||||||
|
- euroffice
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -sf http://localhost/healthcheck || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
eo_data:
|
||||||
|
eo_logs:
|
||||||
|
eo_config:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
euroffice:
|
||||||
|
driver: bridge
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.bridge.name: <DOCKER_BRIDGE_NAME>
|
||||||
|
```
|
||||||
|
|
||||||
|
Datei anlegen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <INSTALL_DIR>
|
||||||
|
sudo tee docker-compose.yaml > /dev/null << 'EOF'
|
||||||
|
# --- Inhalt wie oben, Platzhalter durch tatsächliche Werte ersetzt ---
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Konfiguration prüfen, bevor gestartet wird (zeigt das aufgelöste `JWT_SECRET`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo docker compose config
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Container starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <INSTALL_DIR>
|
||||||
|
sudo docker compose up -d
|
||||||
|
sudo docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Erwartet: Status `Up ... (healthy)` nach ca. 60–90 Sekunden (erste Fontgenerierung dauert etwas).
|
||||||
|
|
||||||
|
Lokalen Health-Check testen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -i --max-time 5 http://127.0.0.1:<INTERNAL_PORT>/healthcheck
|
||||||
|
```
|
||||||
|
|
||||||
|
Erwartet: `HTTP/1.1 200 OK`
|
||||||
|
|
||||||
|
> **Falls dieser Test hängt/fehlschlägt (Timeout oder Connection Reset), obwohl
|
||||||
|
> `docker compose ps` bereits `healthy` zeigt:** Das deutet auf ein Firewall-Problem hin —
|
||||||
|
> siehe Abschnitt 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Apache-Module prüfen/aktivieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo a2enmod proxy proxy_http proxy_wstunnel ssl headers rewrite
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
sudo systemctl status apache2 --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Apache-vHost anlegen
|
||||||
|
|
||||||
|
Datei `<VHOST_DIR>/<DS_HOSTNAME>.conf`:
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost <IPV4_ADDRESS>:80 [<IPV6_ADDRESS>]:80>
|
||||||
|
ServerName <DS_HOSTNAME>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteCond %{HTTPS} !=on
|
||||||
|
RewriteRule (.*) https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
|
||||||
|
CustomLog /var/log/apache2/<DS_HOSTNAME>-access.log combined
|
||||||
|
ErrorLog /var/log/apache2/<DS_HOSTNAME>-error.log
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
<VirtualHost <IPV4_ADDRESS>:443 [<IPV6_ADDRESS>]:443>
|
||||||
|
ServerName <DS_HOSTNAME>
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateFile <CERT_DIR>/fullchain.pem
|
||||||
|
SSLCertificateKeyFile <CERT_DIR>/privkey.pem
|
||||||
|
|
||||||
|
ProxyPreserveHost On
|
||||||
|
ProxyRequests Off
|
||||||
|
|
||||||
|
# WebSocket-Verbindungen (Co-Editing) an proxy_wstunnel weiterreichen
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
||||||
|
RewriteRule ^/(.*) ws://127.0.0.1:<INTERNAL_PORT>/$1 [P,L]
|
||||||
|
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
|
||||||
|
RewriteRule ^/(.*) http://127.0.0.1:<INTERNAL_PORT>/$1 [P,L]
|
||||||
|
|
||||||
|
# Wichtig: DocumentServer muss wissen, dass er hinter TLS läuft,
|
||||||
|
# sonst generiert er interne Editor-/Cache-URLs mit http:// statt https://
|
||||||
|
# ("Mixed Content", Editor kann Dokumente nicht laden/herunterladen).
|
||||||
|
RequestHeader set X-Forwarded-Proto "https"
|
||||||
|
RequestHeader set X-Forwarded-Host "<DS_HOSTNAME>"
|
||||||
|
RequestHeader set X-Forwarded-Port "443"
|
||||||
|
|
||||||
|
ProxyPass / http://127.0.0.1:<INTERNAL_PORT>/ retry=0
|
||||||
|
ProxyPassReverse / http://127.0.0.1:<INTERNAL_PORT>/
|
||||||
|
|
||||||
|
# Große Uploads (Dokumente) erlauben
|
||||||
|
LimitRequestBody 0
|
||||||
|
|
||||||
|
CustomLog /var/log/apache2/<DS_HOSTNAME>-access.log combined
|
||||||
|
ErrorLog /var/log/apache2/<DS_HOSTNAME>-error.log
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktivieren und testen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apachectl configtest
|
||||||
|
sudo systemctl reload apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
Erreichbarkeit von außen prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -i https://<DS_HOSTNAME>/healthcheck
|
||||||
|
```
|
||||||
|
|
||||||
|
Erwartet: `HTTP/1.1 200 OK`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Firewall-Anpassung für Docker-Bridge-Netzwerke
|
||||||
|
|
||||||
|
**Nur relevant, wenn eine eigene Firewall-Lösung eingesetzt wird, die den Datenverkehr über
|
||||||
|
Docker-Bridge-Interfaces nicht automatisch zulässt** (z. B. eigene iptables/nftables-Skripte
|
||||||
|
mit einer restriktiven `OUTPUT`/`FORWARD`-Policy).
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
|
||||||
|
- `docker compose ps` zeigt den Container als `healthy` (interner Check funktioniert)
|
||||||
|
- Ein `curl` **von außerhalb des Containers** auf `127.0.0.1:<INTERNAL_PORT>` oder die
|
||||||
|
Container-IP hängt oder liefert `Connection reset by peer` / `Operation timed out`
|
||||||
|
- `ping` auf die Container-IP funktioniert (ICMP ist oft separat erlaubt), TCP jedoch nicht
|
||||||
|
|
||||||
|
### Ursache
|
||||||
|
|
||||||
|
Docker bindet Container-Ports über einen `docker-proxy`-Prozess bzw. NAT-Regeln, die
|
||||||
|
Datenverkehr über das jeweilige Docker-Bridge-Interface (`br-...`) leiten. Eine restriktive
|
||||||
|
Firewall mit interface-spezifischen `ACCEPT`-Regeln (z. B. nur für `eth0`) und einer
|
||||||
|
abschließenden `DROP`-Regel lässt diesen Bridge-Verkehr nicht automatisch durch.
|
||||||
|
|
||||||
|
### Lösung
|
||||||
|
|
||||||
|
1. Docker-Netzwerk mit **festem Bridge-Namen** betreiben (siehe Abschnitt 4,
|
||||||
|
`com.docker.network.bridge.name: <DOCKER_BRIDGE_NAME>`) — verhindert, dass sich der
|
||||||
|
Interface-Name bei jedem Neuaufbau des Netzwerks ändert.
|
||||||
|
2. In der Firewall-Konfiguration eine **explizite Ausnahme für dieses eine Interface**
|
||||||
|
eintragen (kein Wildcard wie `br+`, das würde auch fremde/zukünftige Bridges ungefiltert
|
||||||
|
durchlassen). Je nach Firewall-Lösung z. B.:
|
||||||
|
- Eigenbau-Skript mit `unprotected_ifs`-Variable: `unprotected_ifs="<DOCKER_BRIDGE_NAME>"`
|
||||||
|
- iptables direkt: gezielte `ACCEPT`-Regeln für `-i <DOCKER_BRIDGE_NAME>` / `-o <DOCKER_BRIDGE_NAME>`
|
||||||
|
in den Chains `INPUT`, `OUTPUT` und `FORWARD`
|
||||||
|
3. Firewall neu laden und Docker-Daemon **danach** neu starten, damit Docker seine eigenen
|
||||||
|
iptables-Chains (`DOCKER`, `DOCKER-FORWARD`, `DOCKER-USER`, …) neu aufbaut:
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart <firewall-service>
|
||||||
|
sudo systemctl restart docker
|
||||||
|
cd <INSTALL_DIR> && sudo docker compose up -d
|
||||||
|
```
|
||||||
|
4. **Startreihenfolge dauerhaft absichern**, damit das Problem nach einem Server-Reboot nicht
|
||||||
|
erneut auftritt — Docker soll immer *nach* der Firewall starten:
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /etc/systemd/system/docker.service.d/
|
||||||
|
sudo tee /etc/systemd/system/docker.service.d/after-firewall.conf > /dev/null << 'EOF'
|
||||||
|
[Unit]
|
||||||
|
After=<firewall-service>.service
|
||||||
|
Wants=<firewall-service>.service
|
||||||
|
EOF
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restrisiko
|
||||||
|
|
||||||
|
Ein manueller Neustart der Firewall **während Docker bereits läuft** stört bestehende,
|
||||||
|
schon aktive Container-Verbindungen in der Regel nicht. Wird jedoch **danach** ein neues
|
||||||
|
Docker-Netzwerk angelegt (z. B. `docker compose down && up`, oder ein neuer Compose-Stack),
|
||||||
|
kann die Regel-Einfügung fehlschlagen (`Failed to Setup IP tables: ... No chain/target/match
|
||||||
|
by that name`), weil Dockers eigene Chains beim Firewall-Neuaufbau entfernt wurden. In diesem
|
||||||
|
Fall genügt es, den Docker-Daemon einmal neu zu starten und den Stack erneut zu starten:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart docker
|
||||||
|
cd <INSTALL_DIR> && sudo docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verifikation nach einem vollständigen Server-Reboot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo reboot
|
||||||
|
# nach dem Reboot, neu verbinden:
|
||||||
|
systemctl status <firewall-service> --no-pager
|
||||||
|
systemctl status docker.service --no-pager
|
||||||
|
sudo docker compose -f <INSTALL_DIR>/docker-compose.yaml ps
|
||||||
|
curl -i --max-time 5 https://<DS_HOSTNAME>/healthcheck
|
||||||
|
ip a | grep -A2 <DOCKER_BRIDGE_NAME>
|
||||||
|
sudo docker network ls
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Nextcloud-Connector-App installieren
|
||||||
|
|
||||||
|
Die Euro-Office-Integration ist im offiziellen Nextcloud App Store gelistet.
|
||||||
|
|
||||||
|
**Über die Weboberfläche:**
|
||||||
|
|
||||||
|
1. Als Administrator einloggen
|
||||||
|
2. Profilbild (oben rechts) → **Apps**
|
||||||
|
3. Kategorie **„Büro & Text"** auswählen
|
||||||
|
4. **„Euro-Office"** suchen → **„Download and enable"**
|
||||||
|
|
||||||
|
**Alternativ über die Konsole (`occ`):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <NC_DOCROOT>
|
||||||
|
sudo -u www-data <PHP_BINARY> occ app:install eurooffice
|
||||||
|
```
|
||||||
|
|
||||||
|
`app:install` lädt die App aus dem Nextcloud App Store herunter **und** aktiviert sie in
|
||||||
|
einem Schritt. Falls die App bereits heruntergeladen, aber nur deaktiviert ist, genügt
|
||||||
|
stattdessen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u www-data <PHP_BINARY> occ app:enable eurooffice
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kontrolle per SSH:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u www-data <PHP_BINARY> <NC_DOCROOT>/occ app:list | grep -i eurooffice
|
||||||
|
```
|
||||||
|
|
||||||
|
Erwartet: Eintrag unter *Enabled*, z. B. `eurooffice: 11.0.1`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Nextcloud konfigurieren (DocumentServer-URL + JWT-Secret)
|
||||||
|
|
||||||
|
Zuerst prüfen, welche Config-Keys die App verwendet:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <NC_DOCROOT>
|
||||||
|
sudo -u www-data <PHP_BINARY> occ config:list eurooffice
|
||||||
|
```
|
||||||
|
|
||||||
|
DocumentServer-URL setzen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u www-data <PHP_BINARY> occ config:app:set eurooffice DocumentServerUrl --value="https://<DS_HOSTNAME>/"
|
||||||
|
```
|
||||||
|
|
||||||
|
JWT-Secret setzen (identischer Wert wie in `<INSTALL_DIR>/.env`, Variable `EO_JWT_SECRET`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo grep EO_JWT_SECRET <INSTALL_DIR>/.env
|
||||||
|
sudo -u www-data <PHP_BINARY> occ config:app:set eurooffice jwt_secret --value="<JWT_SECRET>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Kontrolle:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u www-data <PHP_BINARY> occ config:list eurooffice
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Funktionstest
|
||||||
|
|
||||||
|
1. In Nextcloud ein Office-Dokument (`.docx`, `.xlsx`, `.pptx`) öffnen
|
||||||
|
2. Der Euro-Office-Editor sollte sich im Browser öffnen und das Dokument anzeigen
|
||||||
|
|
||||||
|
**Falls die Meldung „Herunterladen ist fehlgeschlagen" erscheint:**
|
||||||
|
|
||||||
|
Browser-Entwicklerkonsole (F12) prüfen. Eine Meldung wie
|
||||||
|
*„Laden von gemischten aktiven Inhalten … wurde blockiert"* (Mixed Content) weist darauf hin,
|
||||||
|
dass der DocumentServer interne URLs mit `http://` statt `https://` erzeugt. Prüfen, ob die
|
||||||
|
`X-Forwarded-*`-Header im vHost (Abschnitt 7) korrekt gesetzt sind, danach:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apachectl configtest
|
||||||
|
sudo systemctl reload apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
Browser-Hard-Reload (`Strg+Shift+R`) und Dokument erneut öffnen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Wartung / Hinweise
|
||||||
|
|
||||||
|
- **Volumes:** `eo_data`, `eo_logs`, `eo_config` (benannte Docker-Volumes) enthalten
|
||||||
|
Konfiguration, Cache und Logs. Für Backups: `docker run --rm -v <volume>:/data -v $(pwd):/backup alpine tar czf /backup/<volume>.tar.gz -C /data .`
|
||||||
|
- **Updates:** `docker compose pull && docker compose up -d`
|
||||||
|
- **Logs im Container:**
|
||||||
|
```bash
|
||||||
|
sudo docker compose exec euro-office find /var/log/euro-office -iname "*.log"
|
||||||
|
```
|
||||||
|
- **EXAMPLE_ENABLED:** bewusst nicht gesetzt/aktiviert — die Beispiel-App hat keine
|
||||||
|
Zugriffskontrolle und darf nicht öffentlich erreichbar sein.
|
||||||
Reference in New Issue
Block a user