From 02ad003e524d1058d97547adb3d1bd673fd38596 Mon Sep 17 00:00:00 2001 From: Claudio on hubris Date: Tue, 12 May 2026 18:45:56 +0200 Subject: [PATCH] seafile: CE -> Pro upgrade, ES, Caddy resumable-upload fix Same-day-as-deploy upgrade: image swapped to seafileltd/seafile-pro-mc:13.0-latest, elasticsearch:8.15.0 added as new compose service for Pro's full-text search. Free Pro tier (<=3 users, no license). Existing data + users survived. Also documented the Caddy patch stripping IETF resumable-upload headers (Upload-Draft-Interop-Version etc.) so the iOS Seafile Pro 4.0.2 app falls back to plain multipart upload; without it large uploads stalled and cancelled after ~60s. --- README.md | 2 +- containers/125-seafile.md | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 520ddfd..6bffc7e 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ See the full table in [`containers/index.md`](containers/index.md). Quick links: | 122 | [arriman](containers/122-arriman.md) | 192.168.8.132 | Docker host (\*arr stack) | | 123 | [claudio-bot](containers/123-claudio-bot.md) | 192.168.8.230 | Matrix control plane | | 124 | [authentik](containers/124-authentik.md) | 192.168.8.180 | SSO + split-horizon DNS | -| 125 | [seafile](containers/125-seafile.md) | 192.168.8.185 | Seafile CE (Nextcloud-replacement evaluation) | +| 125 | [seafile](containers/125-seafile.md) | 192.168.8.185 | Seafile Pro (Nextcloud-replacement evaluation) | ### Cross-cutting infrastructure - [DNS — split-horizon](infrastructure/dns.md) diff --git a/containers/125-seafile.md b/containers/125-seafile.md index 66de09a..49c874c 100644 --- a/containers/125-seafile.md +++ b/containers/125-seafile.md @@ -1,33 +1,36 @@ # 125 — `seafile` -Seafile Community Edition 13.0 — exploratory deployment to evaluate as a possible [nextcloud (114)](114-nextcloud.md) replacement. Stood up empty on 2026-05-12; **no migration**, NC stays untouched. +Seafile **Pro** Edition 13.0 — exploratory deployment to evaluate as a possible [nextcloud (114)](114-nextcloud.md) replacement. Stood up on 2026-05-12, upgraded from CE → Pro the same day (free tier, ≤3 users). **No data migrated from NC**; NC stays untouched. ## At a glance - **Hostname:** `seafile` - **IP:** `192.168.8.185` - **Privilege:** privileged (Debian 12, nesting + keyctl) - **Resources:** 4 cores / 8 GiB RAM / 32 GiB rootfs / 1 GiB swap -- **Mounts:** `/mnt/library` ↔ `/mnt/library` (Seafile storage under `/mnt/library/seafile/data`) +- **Mounts:** `/mnt/library` ↔ `/mnt/library` (Seafile storage under `/mnt/library/seafile/data`, ES indices under `/mnt/library/seafile/elasticsearch`) - **Public hostname:** [`files.hubris.network`](../infrastructure/dns.md) → [caddy (121)](121-caddy.md) → `192.168.8.185:80` - **Reachable from:** LAN + Netbird mesh (no public ingress) +- **Edition:** Pro free tier (no `seafile-license.txt`, ≤3 users limit) — `api2/server-info/` returns `features: [seafile-basic, seafile-pro, client-sso-via-local-browser]` ## Stack -Docker-compose at `/opt/seafile/`, three services on a private `seafile-net` bridge: +Docker-compose at `/opt/seafile/`, four services on a private `seafile-net` bridge: | Service | Image | Role | |---|---|---| -| `seafile` | `seafileltd/seafile-mc:13.0-latest` | Seahub + seaf-server + Apache (the `-mc` flavor; uses Redis for cache) | +| `seafile` | `seafileltd/seafile-pro-mc:13.0-latest` | Seahub + seaf-server + Apache (Pro flavour; uses Redis for cache) | | `db` | `mariadb:10.11` | ccnet / seafile / seahub databases | | `redis` | `redis:7-alpine` | session + cache backend | +| `elasticsearch` | `elasticsearch:8.15.0` | full-text search (Pro-only feature) | Compose layout: | File | Purpose | |---|---| -| `/opt/seafile/seafile-server.yml` | upstream-verbatim from `manual.seafile.com/13.0/repo/docker/ce/` | +| `/opt/seafile/seafile-server.yml` | upstream-verbatim from `manual.seafile.com/13.0/repo/docker/ce/` (image swapped to `pro-mc` via `.env`) | +| `/opt/seafile/elasticsearch.yml` | upstream-derived; local tweaks for LXC — `bootstrap.memory_lock=false`, `mem_limit: 2g`, `ES_JAVA_OPTS=-Xms1g -Xmx1g`, no `ulimits.memlock` (privileged LXC can't reliably hold memlock=unlimited) | | `/opt/seafile/docker-compose.override.yml` | local: publishes `192.168.8.185:80`, `extra_hosts: auth.hubris.network:192.168.8.175`, drops bundled-caddy labels (`labels: !reset []`) | -| `/opt/seafile/.env` | mode 600, **not git-tracked** — DB passwords, `JWT_PRIVATE_KEY`, `INIT_SEAFILE_ADMIN_*`, `SEAFILE_SERVER_HOSTNAME=files.hubris.network`, `SEAFILE_SERVER_PROTOCOL=https`, `ENABLE_SEADOC=false` | +| `/opt/seafile/.env` | mode 600, **not git-tracked** — `SEAFILE_IMAGE=seafileltd/seafile-pro-mc:13.0-latest`, `SEAFILE_ELASTICSEARCH_IMAGE=elasticsearch:8.15.0`, `SEAFILE_ELASTICSEARCH_VOLUME=/mnt/library/seafile/elasticsearch`, `COMPOSE_FILE='seafile-server.yml,elasticsearch.yml,docker-compose.override.yml'`, DB passwords, `JWT_PRIVATE_KEY`, `INIT_SEAFILE_ADMIN_*`, `SEAFILE_SERVER_HOSTNAME=files.hubris.network`, `SEAFILE_SERVER_PROTOCOL=https`, `ENABLE_SEADOC=false` | **Do not rotate `JWT_PRIVATE_KEY`** — it invalidates every active session and library access token. @@ -50,8 +53,10 @@ Seahub side: - `ENABLE_OAUTH = True` - `OAUTH_AUTHORIZATION_URL` / `OAUTH_TOKEN_URL` / `OAUTH_USER_INFO_URL` → `https://auth.hubris.network/application/o/{authorize,token,userinfo}/` - `OAUTH_SCOPE = ['openid', 'profile', 'email']` -- `OAUTH_ATTRIBUTE_MAP = {'email': (True, 'contact_email'), 'name': (False, 'name'), 'id': (False, 'not_used')}` +- `OAUTH_ATTRIBUTE_MAP = {'sub': (True, 'uid'), 'email': (True, 'email'), 'name': (False, 'name')}` — `sub` is the stable identifier; without it the early `if not uid:` check renders the generic "Error, please contact administrator" page. - `OAUTH_CREATE_UNKNOWN_USER = True`, `OAUTH_ACTIVATE_USER_AFTER_CREATION = True` — JIT provisioning enabled. +- `CLIENT_SSO_VIA_LOCAL_BROWSER = True` — required so the **iOS Seafile Pro app** bounces OAuth through Safari (system browser) instead of the in-app webview; the webview path cannot complete the round-trip back to the app. +- **Authentik provider scope mappings** — the OAuth2 provider MUST have `openid`, `profile`, `email` scope mappings attached (`property_mappings`), otherwise userinfo returns only `sub` and the OAUTH_ATTRIBUTE_MAP required-claim check fails. The Seahub login page renders a "Single Sign-On" button that 302s through `/sso/` → `/oauth/login/` → Authentik flow. @@ -82,6 +87,20 @@ files.hubris.network { header_up X-Forwarded-Proto https header_up X-Forwarded-Host {host} header_up Host {host} + # Strip IETF resumable-upload negotiation headers. The iOS Seafile Pro app + # (>=4.0) sends Upload-Draft-Interop-Version: 6 + Upload-Complete, but the + # bundled seafile-fileserver doesn't speak that draft. Without stripping, + # uploads hang ~60s waiting for an interim response and then cancel. + header_up -Upload-Draft-Interop-Version + header_up -Upload-Complete + header_up -Upload-Offset + header_up -Upload-Length + transport http { + dial_timeout 30s + read_timeout 1h + write_timeout 1h + } + flush_interval -1 } } ``` @@ -105,5 +124,11 @@ For now: stand up Seafile, kick the tires, decide later whether to: ## Changelog +### 2026-05-12 — CE → Pro upgrade +Image swapped to `seafileltd/seafile-pro-mc:13.0-latest`; added `elasticsearch:8.15.0` as a new service for Pro's full-text search. Free Pro tier (≤3 users, no license). MariaDB dump saved at `/mnt/library/seafile/backups/seafile-all-20260512-183001.sql.gz` (1.1 MB compressed) before the swap; recovery path is `gunzip … | mariadb -uroot` against a fresh CE container if needed. ES tuned for the LXC: `bootstrap.memory_lock=false`, no `ulimits.memlock`, 1 GiB JVM heap, 2 GiB container `mem_limit`. Host `vm.max_map_count` already at 1,048,576 (well above the 262,144 ES minimum). Existing data + JIT users (admin, dtoro) survived the migration; libraries intact (Iphone with 20 files / 53.1 MB carried through). + +### 2026-05-12 — Caddy: strip IETF resumable-upload headers +Patched `files.hubris.network` block to drop `Upload-Draft-Interop-Version`, `Upload-Complete`, `Upload-Offset`, `Upload-Length` from the upstream-bound request, and bumped reverse_proxy timeouts (`read_timeout 1h`, `write_timeout 1h`). Reason: iOS Seafile Pro 4.0.2 negotiates resumable uploads via these headers; bundled fileserver doesn't speak the draft → uploads stalled ~60s and got cancelled. Stripping forces the client to fall back to plain multipart, which works. + ### 2026-05-12 — initial deployment LXC 125 created (privileged Debian 12, 4 c / 8 GiB / 32 GiB, IP `192.168.8.185`). Seafile CE 13.0 docker-compose stack at `/opt/seafile/`, storage on `/mnt/library/seafile/data`. Authentik OAuth provider + Application provisioned via `ak shell` (slug `seafile`, redirect URI `https://files.hubris.network/oauth/callback/`). Caddy site block added on LXC 121, dnsmasq entry on LXC 124. End-to-end OAuth handshake verified to the Authentik flow page. **No data migration** — exploratory deployment alongside Nextcloud.