Add 125 (seafile) — Nextcloud-replacement evaluation

LXC 125 stood up as a Seafile CE 13.0 docker-compose deployment, behind
files.hubris.network. Authentik OAuth wired up via ak shell. No data
migration — exploration alongside Nextcloud (114).
This commit is contained in:
Claudio on hubris
2026-05-12 12:45:45 +02:00
parent bb410eea49
commit 40f6c93fd5
4 changed files with 115 additions and 0 deletions

View File

@@ -31,6 +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) | | 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 | | 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 | | 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) |
### Cross-cutting infrastructure ### Cross-cutting infrastructure
- [DNS — split-horizon](infrastructure/dns.md) - [DNS — split-horizon](infrastructure/dns.md)

109
containers/125-seafile.md Normal file
View File

@@ -0,0 +1,109 @@
# 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.
## 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`)
- **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)
## Stack
Docker-compose at `/opt/seafile/`, three 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) |
| `db` | `mariadb:10.11` | ccnet / seafile / seahub databases |
| `redis` | `redis:7-alpine` | session + cache backend |
Compose layout:
| File | Purpose |
|---|---|
| `/opt/seafile/seafile-server.yml` | upstream-verbatim from `manual.seafile.com/13.0/repo/docker/ce/` |
| `/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` |
**Do not rotate `JWT_PRIVATE_KEY`** — it invalidates every active session and library access token.
## Storage layout
- `/mnt/library/seafile/data/` — bind-mounted to `/shared` in the seafile container. Holds config (`seafile/conf/`), logs (`seafile/logs/`), and the heavy block/fs/commit trees (`seafile/seafile-data/storage/`). Group-owned `:media` 2775.
- `/opt/seafile/mysql/` — mariadb data (small, stays on rootfs).
## Auth
Native OAuth2/OIDC against [authentik (124)](124-authentik.md). Configuration in `/mnt/library/seafile/data/seafile/conf/seahub_settings.py` between the `# BEGIN-HUBRIS-OAUTH` / `# END-HUBRIS-OAUTH` markers.
Authentik side:
- **Provider:** `Provider for Seafile` (OAuth2/OIDC, confidential, signing key = self-signed cert)
- **Application slug:** `seafile`
- **Redirect URI:** `https://files.hubris.network/oauth/callback/` (trailing slash mandatory)
- **Launch URL:** `https://files.hubris.network/`
- **Policy binding:** `authentik Admins` group
- Provisioned via `ak shell` script (idempotent — `OAuth2Provider.objects.get_or_create(name="Provider for Seafile")`)
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_CREATE_UNKNOWN_USER = True`, `OAUTH_ACTIVATE_USER_AFTER_CREATION = True` — JIT provisioning enabled.
The Seahub login page renders a "Single Sign-On" button that 302s through `/sso/``/oauth/login/` → Authentik flow.
### Reverse-proxy settings (also in seahub_settings.py)
```python
SERVICE_URL = "https://files.hubris.network"
FILE_SERVER_ROOT = "https://files.hubris.network/seafhttp"
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
CSRF_TRUSTED_ORIGINS = ['https://files.hubris.network']
```
## DNS / mesh
- LAN clients resolve `files.hubris.network``192.168.8.175` via [dnsmasq on LXC 124](../infrastructure/dns.md) (entry: `address=/files.hubris.network/192.168.8.175`).
- Netbird mesh peers reach `192.168.8.185` through the existing `192.168.8.0/24` route advertised by the hubris peer.
- The Seafile container itself needs `auth.hubris.network → 192.168.8.175` mapped at the Docker level (Docker's resolver doesn't follow LXC `/etc/hosts` or the dnsmasq split-horizon), so `docker-compose.override.yml` carries `extra_hosts: auth.hubris.network:192.168.8.175`. See [mesh migration](../infrastructure/mesh.md) for the pattern.
## Caddy block (LXC 121)
```
files.hubris.network {
tls {
dns ionos {env.IONOS_AUTH_API_TOKEN}
}
encode zstd gzip
request_body {
max_size 10GB
}
reverse_proxy 192.168.8.185:80 {
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
header_up Host {host}
}
}
```
No `import authentik` — Seafile handles OAuth natively, forward-auth would block the `/oauth/callback/` round-trip.
## Why exploration-only (and not a Nextcloud cutover)
The [mulita (120)](120-mule-images.md) photo stack is tightly coupled to Nextcloud — it reads storage roots from `/mnt/library/homecloud/{user}/files/`, proxies thumbnails through NC's `/core/preview`, and consumes NC `webhook_listeners` for file events. Migrating off Nextcloud would require re-architecting all three integration points first.
For now: stand up Seafile, kick the tires, decide later whether to:
1. Keep NC for photos and move docs/files to Seafile.
2. Refactor mulita off NC, then full cutover.
3. Roll back (Seafile is rollback-safe — NC is untouched throughout).
## Related
- [authentik (124)](124-authentik.md)
- [caddy (121)](121-caddy.md)
- [nextcloud (114)](114-nextcloud.md)
- [DNS](../infrastructure/dns.md)
- [Mesh](../infrastructure/mesh.md)
- [Media permissions](../infrastructure/media-permissions.md)
## Changelog
### 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.

View File

@@ -18,6 +18,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per
| 122 | [arriman](122-arriman.md) | 192.168.8.132 | priv | 4 | 8 GiB | 24 GiB | `/mnt/library` | `jellyseerr` / `qbit` / `sab` | running | | 122 | [arriman](122-arriman.md) | 192.168.8.132 | priv | 4 | 8 GiB | 24 GiB | `/mnt/library` | `jellyseerr` / `qbit` / `sab` | running |
| 123 | [claudio-bot](123-claudio-bot.md) | 192.168.8.230 | unpriv | 1 | 512 MiB | 8 GiB | — | — | running | | 123 | [claudio-bot](123-claudio-bot.md) | 192.168.8.230 | unpriv | 1 | 512 MiB | 8 GiB | — | — | running |
| 124 | [authentik](124-authentik.md) | 192.168.8.180 | priv | 2 | 4 GiB | 20 GiB | — | `auth.hubris.network` | running | | 124 | [authentik](124-authentik.md) | 192.168.8.180 | priv | 2 | 4 GiB | 20 GiB | — | `auth.hubris.network` | running |
| 125 | [seafile](125-seafile.md) | 192.168.8.185 | priv | 4 | 8 GiB | 32 GiB | `/mnt/library` | `files.hubris.network` | running |
## Recently destroyed (kept for archaeology) ## Recently destroyed (kept for archaeology)

View File

@@ -30,6 +30,7 @@ address=/sab.hubris.network/192.168.8.175
address=/blog.hubris.network/192.168.8.175 address=/blog.hubris.network/192.168.8.175
address=/photos.hubris.network/192.168.8.175 address=/photos.hubris.network/192.168.8.175
address=/artifacto.hubris.network/192.168.8.175 address=/artifacto.hubris.network/192.168.8.175
address=/files.hubris.network/192.168.8.175
``` ```
## Why split-horizon ## Why split-horizon
@@ -73,6 +74,9 @@ Either:
## Changelog ## Changelog
### 2026-05-12 — `files.hubris.network` added
For [seafile (125)](../containers/125-seafile.md) — Nextcloud-replacement evaluation. Entry points at 192.168.8.175 (Caddy reverse-proxies to 192.168.8.185:80).
### 2026-04-28 — wiki entry created ### 2026-04-28 — wiki entry created
Initial documentation. 16 active entries. Initial documentation. 16 active entries.