From 19bab852dec9c7663f78ef1fa9d70fb78df13abd Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Fri, 22 May 2026 16:34:29 +0200 Subject: [PATCH] KI-AGENT: Seafile in Selfhost-Stack integrieren --- .env.example | 28 ++++++++++ README.md | 29 ++++++++++- docker-compose.selfhost.yml | 100 ++++++++++++++++++++++++++++++++++++ scripts/selfhost-setup.sh | 40 ++++++++++++++- 4 files changed, 195 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 0c5ef1c..1931ba0 100644 --- a/.env.example +++ b/.env.example @@ -37,6 +37,34 @@ S3_ACCESS_KEY=fedeo-minio S3_SECRET_KEY=change-this-minio-password S3_BUCKET=fedeo +# Datei-Backend. S3 bleibt aktuell der Standard; Seafile ist im Stack +# vorbereitet und kann nach dem Backend-Umbau als vollständiges File-Backend +# genutzt werden. +FEDEO_FILE_BACKEND=s3 + +# Seafile CE läuft bewusst auf einer eigenen Subdomain, damit Desktop-Clients, +# SeaDrive und WebDAV ohne Pfad-Sonderfälle funktionieren. +SEAFILE_SERVER_HOSTNAME=files.app.example.com +SEAFILE_SERVER_PROTOCOL=https +SEAFILE_BASE_URL=https://files.app.example.com +SEAFILE_INTERNAL_URL=http://seafile:80 +SEAFILE_IMAGE=seafileltd/seafile-mc:13.0-latest +SEAFILE_DB_IMAGE=mariadb:10.11 +SEAFILE_REDIS_IMAGE=redis:7-alpine +INIT_SEAFILE_MYSQL_ROOT_PASSWORD=change-this-seafile-root-password +SEAFILE_MYSQL_DB_USER=seafile +SEAFILE_MYSQL_DB_PASSWORD=change-this-seafile-db-password +SEAFILE_REDIS_PASSWORD=change-this-seafile-redis-password +SEAFILE_JWT_PRIVATE_KEY=change-this-seafile-jwt-private-key-at-least-32-chars +INIT_SEAFILE_ADMIN_EMAIL=admin@example.com +INIT_SEAFILE_ADMIN_PASSWORD=change-this-seafile-admin-password +SEAFILE_ENABLE_GO_FILESERVER=true +SEAFILE_ENABLE_SEADOC=false +SEAFILE_ENABLE_NOTIFICATION_SERVER=false +SEAFILE_ENABLE_AI=false +SEAFILE_ENABLE_FACE_RECOGNITION=false +SEAFILE_MD_FILE_COUNT_LIMIT=100000 + M2M_API_KEY=change-this-m2m-key API_BASE_URL=https://app.example.com/backend GOCARDLESS_BASE_URL=https://api.gocardless.com diff --git a/README.md b/README.md index 6c14246..065b36e 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,8 @@ mkdir -p /opt/fedeo/traefik/letsencrypt mkdir -p /opt/fedeo/traefik/logs mkdir -p /opt/fedeo/postgres mkdir -p /opt/fedeo/minio +mkdir -p /opt/fedeo/seafile/mysql +mkdir -p /opt/fedeo/seafile/data touch /opt/fedeo/traefik/letsencrypt/acme.json chmod 600 /opt/fedeo/traefik/letsencrypt/acme.json ``` @@ -133,6 +135,7 @@ cp .env.example .env ``` Ersetze anschließend alle Platzhalter und passe mindestens `DOMAIN`, `CONTACT_EMAIL`, Datenbank-, Secret-, SMTP- und S3-Werte an. +Wenn Seafile genutzt werden soll, muss zusätzlich `SEAFILE_SERVER_HOSTNAME` als eigene Subdomain auf den Server zeigen, zum Beispiel `files.app.example.com`. Alternativ kannst du die Konfiguration geführt erzeugen lassen: @@ -204,6 +207,28 @@ S3_ACCESS_KEY=fedeo-minio S3_SECRET_KEY=change-this-minio-password S3_BUCKET=fedeo +FEDEO_FILE_BACKEND=s3 +SEAFILE_SERVER_HOSTNAME=files.app.example.com +SEAFILE_SERVER_PROTOCOL=https +SEAFILE_BASE_URL=https://files.app.example.com +SEAFILE_INTERNAL_URL=http://seafile:80 +SEAFILE_IMAGE=seafileltd/seafile-mc:13.0-latest +SEAFILE_DB_IMAGE=mariadb:10.11 +SEAFILE_REDIS_IMAGE=redis:7-alpine +INIT_SEAFILE_MYSQL_ROOT_PASSWORD=change-this-seafile-root-password +SEAFILE_MYSQL_DB_USER=seafile +SEAFILE_MYSQL_DB_PASSWORD=change-this-seafile-db-password +SEAFILE_REDIS_PASSWORD=change-this-seafile-redis-password +SEAFILE_JWT_PRIVATE_KEY=change-this-seafile-jwt-private-key-at-least-32-chars +INIT_SEAFILE_ADMIN_EMAIL=admin@example.com +INIT_SEAFILE_ADMIN_PASSWORD=change-this-seafile-admin-password +SEAFILE_ENABLE_GO_FILESERVER=true +SEAFILE_ENABLE_SEADOC=false +SEAFILE_ENABLE_NOTIFICATION_SERVER=false +SEAFILE_ENABLE_AI=false +SEAFILE_ENABLE_FACE_RECOGNITION=false +SEAFILE_MD_FILE_COUNT_LIMIT=100000 + M2M_API_KEY=change-this-m2m-key API_BASE_URL=https://app.example.com/backend GOCARDLESS_BASE_URL=https://api.gocardless.com @@ -246,10 +271,12 @@ NUXT_PUBLIC_MATRIX_ELEMENT_URL=https://app.example.com/element Die `FEDEO_BOOTSTRAP_*`-Werte sind für den ersten Start gedacht. Wenn `FEDEO_BOOTSTRAP_ADMIN_EMAIL` und `FEDEO_BOOTSTRAP_ADMIN_PASSWORD` gesetzt sind, legt das Backend idempotent einen Admin-Benutzer, einen ersten Mandanten, eine Administrator-Rolle und grundlegende Stammdaten an. Nach erfolgreichem Erstzugriff solltest du das Bootstrap-Passwort aus der `.env` entfernen oder ändern. -## Docker Compose mit optionalem S3 und Matrix +## Docker Compose mit optionalem S3, Seafile und Matrix Die Selfhost-Konfiguration wird im Betriebsverzeichnis als `docker-compose.yml` abgelegt. Sie startet MinIO standardmäßig mit. Wenn du stattdessen AWS S3, Hetzner Object Storage, Backblaze B2 S3 oder einen anderen externen S3-Dienst nutzen willst, kannst du die Services `minio` und `createbuckets` entfernen und nur die entsprechenden S3-Umgebungsvariablen auf den externen Anbieter zeigen lassen. +Der Stack enthält zusätzlich Seafile CE als vorbereitetes File-Backend. Seafile läuft unter `SEAFILE_SERVER_HOSTNAME`, nutzt MariaDB und Redis intern und ist für Desktop-Sync, SeaDrive und WebDAV bewusst auf eine eigene Subdomain ausgelegt. FEDEO nutzt aktuell weiter S3 als Standard; `FEDEO_FILE_BACKEND=s3` bleibt deshalb gesetzt, bis das Backend die Seafile-Integration vollständig unterstützt. + Der Matrix-Stack ist im Selfhost-Compose direkt enthalten. Er umfasst Synapse, eine eigene PostgreSQL-Datenbank für Synapse, Redis, `.well-known/matrix`, coturn, LiveKit, den LiveKit-JWT-Service und Element Web. Das einfache Selfhost-Setup nutzt nur `DOMAIN`: Synapse läuft unter `https://DOMAIN/_matrix`, Matrix-Well-Known unter `https://DOMAIN/.well-known/matrix`, LiveKit unter `https://DOMAIN/livekit/sfu`, der JWT-Service unter `https://DOMAIN/livekit/jwt` und Element Web unter `https://DOMAIN/element`. Das Backend führt beim Containerstart standardmäßig `npm run migrate` aus. Setze `FEDEO_RUN_MIGRATIONS=false`, wenn du Migrationen bewusst manuell ausführen möchtest. diff --git a/docker-compose.selfhost.yml b/docker-compose.selfhost.yml index d4a156c..73cec2b 100644 --- a/docker-compose.selfhost.yml +++ b/docker-compose.selfhost.yml @@ -80,6 +80,101 @@ services: networks: - internal + seafile-db: + image: ${SEAFILE_DB_IMAGE:-mariadb:10.11} + container_name: fedeo-seafile-db + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} + MYSQL_LOG_CONSOLE: "true" + MARIADB_AUTO_UPGRADE: "1" + volumes: + - ./seafile/mysql:/var/lib/mysql + healthcheck: + test: + [ + "CMD", + "/usr/local/bin/healthcheck.sh", + "--connect", + "--mariadbupgrade", + "--innodb_initialized", + ] + interval: 20s + start_period: 30s + timeout: 5s + retries: 10 + networks: + - internal + + seafile-redis: + image: ${SEAFILE_REDIS_IMAGE:-redis:7-alpine} + container_name: fedeo-seafile-redis + restart: unless-stopped + command: + - /bin/sh + - -c + - redis-server --requirepass "$$REDIS_PASSWORD" + environment: + REDIS_PASSWORD: ${SEAFILE_REDIS_PASSWORD} + networks: + - internal + + seafile: + image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:13.0-latest} + container_name: fedeo-seafile + restart: unless-stopped + depends_on: + seafile-db: + condition: service_healthy + seafile-redis: + condition: service_started + volumes: + - ./seafile/data:/shared + environment: + SEAFILE_MYSQL_DB_HOST: seafile-db + SEAFILE_MYSQL_DB_PORT: 3306 + SEAFILE_MYSQL_DB_USER: ${SEAFILE_MYSQL_DB_USER:-seafile} + SEAFILE_MYSQL_DB_PASSWORD: ${SEAFILE_MYSQL_DB_PASSWORD} + INIT_SEAFILE_MYSQL_ROOT_PASSWORD: ${INIT_SEAFILE_MYSQL_ROOT_PASSWORD} + SEAFILE_MYSQL_DB_CCNET_DB_NAME: ${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db} + SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: ${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db} + SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: ${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db} + TIME_ZONE: ${TIME_ZONE:-Europe/Berlin} + INIT_SEAFILE_ADMIN_EMAIL: ${INIT_SEAFILE_ADMIN_EMAIL} + INIT_SEAFILE_ADMIN_PASSWORD: ${INIT_SEAFILE_ADMIN_PASSWORD} + SEAFILE_SERVER_HOSTNAME: ${SEAFILE_SERVER_HOSTNAME} + SEAFILE_SERVER_PROTOCOL: ${SEAFILE_SERVER_PROTOCOL:-https} + SITE_ROOT: ${SEAFILE_SITE_ROOT:-/} + NON_ROOT: ${SEAFILE_NON_ROOT:-false} + JWT_PRIVATE_KEY: ${SEAFILE_JWT_PRIVATE_KEY} + SEAFILE_LOG_TO_STDOUT: ${SEAFILE_LOG_TO_STDOUT:-true} + ENABLE_GO_FILESERVER: ${SEAFILE_ENABLE_GO_FILESERVER:-true} + ENABLE_SEADOC: ${SEAFILE_ENABLE_SEADOC:-false} + CACHE_PROVIDER: redis + REDIS_HOST: seafile-redis + REDIS_PORT: 6379 + REDIS_PASSWORD: ${SEAFILE_REDIS_PASSWORD} + ENABLE_NOTIFICATION_SERVER: ${SEAFILE_ENABLE_NOTIFICATION_SERVER:-false} + ENABLE_SEAFILE_AI: ${SEAFILE_ENABLE_AI:-false} + ENABLE_FACE_RECOGNITION: ${SEAFILE_ENABLE_FACE_RECOGNITION:-false} + MD_FILE_COUNT_LIMIT: ${SEAFILE_MD_FILE_COUNT_LIMIT:-100000} + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + labels: + - traefik.enable=true + - traefik.http.routers.fedeo-seafile.rule=Host(`${SEAFILE_SERVER_HOSTNAME}`) + - traefik.http.routers.fedeo-seafile.entrypoints=websecure + - traefik.http.routers.fedeo-seafile.tls.certresolver=letsencrypt + - traefik.http.services.fedeo-seafile.loadbalancer.server.port=80 + - traefik.docker.network=fedeo_web + networks: + - web + - internal + backend: image: git.federspiel.tech/flfeders/fedeo/backend:dev container_name: fedeo-backend @@ -111,6 +206,11 @@ services: S3_ACCESS_KEY: ${S3_ACCESS_KEY} S3_SECRET_KEY: ${S3_SECRET_KEY} S3_BUCKET: ${S3_BUCKET} + FEDEO_FILE_BACKEND: ${FEDEO_FILE_BACKEND:-s3} + SEAFILE_BASE_URL: ${SEAFILE_BASE_URL} + SEAFILE_INTERNAL_URL: ${SEAFILE_INTERNAL_URL} + SEAFILE_ADMIN_EMAIL: ${INIT_SEAFILE_ADMIN_EMAIL} + SEAFILE_ADMIN_PASSWORD: ${INIT_SEAFILE_ADMIN_PASSWORD} M2M_API_KEY: ${M2M_API_KEY} API_BASE_URL: ${API_BASE_URL} GOCARDLESS_BASE_URL: ${GOCARDLESS_BASE_URL} diff --git a/scripts/selfhost-setup.sh b/scripts/selfhost-setup.sh index 3586ae2..f017e62 100755 --- a/scripts/selfhost-setup.sh +++ b/scripts/selfhost-setup.sh @@ -278,6 +278,11 @@ write_env() { local dokubox_secure="${34}" local dokubox_user="${35}" local dokubox_password="${36}" + local seafile_mysql_root_password="${37}" + local seafile_mysql_password="${38}" + local seafile_redis_password="${39}" + local seafile_jwt_private_key="${40}" + local seafile_admin_password="${41}" cat >"$ENV_FILE" <