KI-AGENT: Seafile in Selfhost-Stack integrieren

This commit is contained in:
2026-05-22 16:34:29 +02:00
parent 8a2429827c
commit 19bab852de
4 changed files with 195 additions and 2 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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}

View File

@@ -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" <<EOF
# FEDEO Selfhosting
@@ -317,6 +322,28 @@ S3_ACCESS_KEY=$(env_quote "fedeo-minio")
S3_SECRET_KEY=$(env_quote "$minio_password")
S3_BUCKET=$(env_quote "fedeo")
FEDEO_FILE_BACKEND=$(env_quote "s3")
SEAFILE_SERVER_HOSTNAME=$(env_quote "files.$domain")
SEAFILE_SERVER_PROTOCOL=$(env_quote "https")
SEAFILE_BASE_URL=$(env_quote "https://files.$domain")
SEAFILE_INTERNAL_URL=$(env_quote "http://seafile:80")
SEAFILE_IMAGE=$(env_quote "seafileltd/seafile-mc:13.0-latest")
SEAFILE_DB_IMAGE=$(env_quote "mariadb:10.11")
SEAFILE_REDIS_IMAGE=$(env_quote "redis:7-alpine")
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=$(env_quote "$seafile_mysql_root_password")
SEAFILE_MYSQL_DB_USER=$(env_quote "seafile")
SEAFILE_MYSQL_DB_PASSWORD=$(env_quote "$seafile_mysql_password")
SEAFILE_REDIS_PASSWORD=$(env_quote "$seafile_redis_password")
SEAFILE_JWT_PRIVATE_KEY=$(env_quote "$seafile_jwt_private_key")
INIT_SEAFILE_ADMIN_EMAIL=$(env_quote "$admin_email")
INIT_SEAFILE_ADMIN_PASSWORD=$(env_quote "$seafile_admin_password")
SEAFILE_ENABLE_GO_FILESERVER=$(env_quote "true")
SEAFILE_ENABLE_SEADOC=$(env_quote "false")
SEAFILE_ENABLE_NOTIFICATION_SERVER=$(env_quote "false")
SEAFILE_ENABLE_AI=$(env_quote "false")
SEAFILE_ENABLE_FACE_RECOGNITION=$(env_quote "false")
SEAFILE_MD_FILE_COUNT_LIMIT=$(env_quote "100000")
M2M_API_KEY=$(env_quote "$m2m_key")
API_BASE_URL=$(env_quote "https://$domain/backend")
GOCARDLESS_BASE_URL=$(env_quote "https://api.gocardless.com")
@@ -364,6 +391,8 @@ prepare_directories() {
"$ROOT_DIR/traefik/logs" \
"$ROOT_DIR/postgres" \
"$ROOT_DIR/minio" \
"$ROOT_DIR/seafile/mysql" \
"$ROOT_DIR/seafile/data" \
"$ROOT_DIR/matrix/postgres" \
"$ROOT_DIR/matrix/synapse"
@@ -403,6 +432,7 @@ main() {
echo "Secrets werden automatisch erzeugt."
local db_password minio_password cookie_secret jwt_secret encryption_key m2m_key
local matrix_db_password matrix_turn_secret matrix_registration_secret livekit_secret
local seafile_mysql_root_password seafile_mysql_password seafile_redis_password seafile_jwt_private_key seafile_admin_password
db_password="$(random_secret)"
minio_password="$(random_secret)"
cookie_secret="$(random_secret)"
@@ -413,6 +443,11 @@ main() {
matrix_turn_secret="$(random_secret)"
matrix_registration_secret="$(random_secret)"
livekit_secret="$(random_secret)"
seafile_mysql_root_password="$(random_secret)"
seafile_mysql_password="$(random_secret)"
seafile_redis_password="$(random_secret)"
seafile_jwt_private_key="$(random_secret)"
seafile_admin_password="$(random_secret)"
local mailer_host="smtp.example.com"
local mailer_port="587"
@@ -471,7 +506,9 @@ main() {
"$mailer_ssl" "$mailer_user" "$mailer_pass" "$mailer_from" "$web_push_public" \
"$web_push_private" "$pdf_license" "$openai_key" "$stirling_key" \
"$gocardless_secret_id" "$gocardless_secret_key" "$dokubox_host" \
"$dokubox_port" "$dokubox_secure" "$dokubox_user" "$dokubox_password"
"$dokubox_port" "$dokubox_secure" "$dokubox_user" "$dokubox_password" \
"$seafile_mysql_root_password" "$seafile_mysql_password" "$seafile_redis_password" \
"$seafile_jwt_private_key" "$seafile_admin_password"
prepare_directories
@@ -481,6 +518,7 @@ main() {
echo
echo "Vor dem Start prüfen:"
echo " 1. DNS zeigt auf diesen Server: $domain"
echo " Zusätzlich für Seafile: files.$domain"
echo " 2. Ports 80, 443, 3478/tcp, 3478/udp, 5349/tcp, 49160-49200/udp sind offen"
echo " 3. Platzhalter für optionale Dienste in .env bei Bedarf ersetzen"