Files
admin/.wiki/concepts/ocis-on-vds-deploy-recipe.md
vitya 74cf219533 wiki(concepts): ingest ocis-on-vds-deploy-recipe + entity refresh
New concept page documents the oCIS-on-VDS deploy pattern with the 4
non-obvious gotchas surfaced during owncloud-vds-deploy:

  1. UID mismatch — image ocis-user is 1000, host vitya is 1001 →
     compose `user: "1001:1001"` override (alt chown rejected as orphan-UID)
  2. PROXY_TLS=false — explicit per docs when reverse proxy terminates HTTPS
  3. PROXY_ENABLE_BASIC_AUTH=true — required for WebDAV/LibreGraph API
  4. LibreGraph POST /graph/v1.0/users — only way to create users (no CLI)

Plus decomposedfs storage layout, atomic-revert recipe, backup integration
note. Source: .tasks/owncloud-vds-deploy.md.

entities/vds-kzntsv.md updated: stack table + hostnames + file layout
include owncloud row.

index.md catalog + log.md ingest entry refreshed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:29:43 +03:00

181 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: oCIS на VDS — deploy recipe + non-obvious gotchas
type: concept
tags: [recipe, owncloud, ocis, docker, traefik, webdav, libregraph, decomposedfs]
sources: [../../.tasks/owncloud-vds-deploy.md]
updated: 2026-05-21
---
# oCIS на VDS — deploy recipe + non-obvious gotchas
Recipe для разворачивания **ownCloud Infinite Scale** (oCIS) — Go-based замены classic ownCloud Server 10 — в Docker за traefik с LetsEncrypt. Применимо на [[vds-kzntsv]] и других хостах с тем же pattern'ом (`/opt/stacks/<name>/`, traefik network `proxy`, LE certresolver `letsEncrypt`).
Validated 2026-05-21 на image `owncloud/ocis:7.1.0`. Container запустился, traefik routes 200 OK, LibreGraph API + WebDAV работают, init создаёт admin + idm.json в `data/idm/`.
## Когда применять
- Личный personal-cloud для одного пользователя (single binary, no external DB)
- Replace мёртвого / legacy ownCloud Server 10 (oCIS = main line от ownCloud GmbH, OC10 deprecating)
- Files-only use-case (calendar/contacts не нужны — для тех нужен Nextcloud)
- На хосте с уже работающим traefik + LE certresolver (recipe рассчитан на termination upstream)
## Когда **не** применять
- Multi-tenant корпоративная инсталляция → нужны external IDP, OIDC chain, не личный setup
- Нужны calendar / contacts / mail / collabora → Nextcloud, не oCIS
- Block-level dedup критичен → Seafile (oCIS использует file-level decomposedfs)
- Host UID = 1000 (image uid 1000 matches → `user:` override **не** нужен)
## Compose recipe
`/opt/stacks/owncloud/docker-compose.yml`:
```yaml
services:
ocis:
image: owncloud/ocis:7.1.0
container_name: owncloud
restart: unless-stopped
user: "1001:1001" # ← gotcha 1, см. ниже
entrypoint: /bin/sh
command: ["-c", "ocis init || true; exec ocis server"]
environment:
OCIS_URL: https://owncloud.kzntsv.site
OCIS_LOG_LEVEL: info
OCIS_LOG_COLOR: "false"
PROXY_TLS: "false" # ← gotcha 2
PROXY_ENABLE_BASIC_AUTH: "true" # ← gotcha 3
OCIS_INSECURE: "false"
IDM_CREATE_DEMO_USERS: "false"
IDM_ADMIN_PASSWORD: ${OCIS_ADMIN_PASSWORD}
volumes:
- ./data:/var/lib/ocis
- ./config:/etc/ocis
networks: [proxy]
labels:
- traefik.enable=true
- "traefik.http.routers.owncloud.rule=Host(`owncloud.kzntsv.site`)"
- traefik.http.routers.owncloud.entrypoints=websecure
- traefik.http.routers.owncloud.tls.certresolver=letsEncrypt
- traefik.http.services.owncloud.loadbalancer.server.port=9200
networks:
proxy: { external: true }
```
`/opt/stacks/owncloud/.env` (chmod 600):
```
OCIS_ADMIN_PASSWORD=<32+ random chars, store в pass owncloud/admin-password>
```
## Gotcha 1: UID mismatch image vs host
Image `owncloud/ocis` runs as **UID 1000** (`ocis-user` внутри контейнера). Если host-side user-owner mounted dirs ≠ 1000 — контейнер падает в restart-loop с:
```
Could not create config: open /etc/ocis/ocis.yaml: permission denied
The jwt_secret has not been set properly in your config for ocis.
```
«jwt_secret has not been set» — **обманка**, симптом сидит на ровном месте perm-deny при попытке записать ocis.yaml на первом `ocis init` пробеге.
**Fix:** `user: "<host-uid>:<host-gid>"` override в compose. На vds-kzntsv host user `vitya` = UID 1001 → `user: "1001:1001"`. Альтернатива (`chown 1000` host-dirs) **отвергнута**: создаёт orphan UID на хосте, путает auditing + backup tools.
**Diagnose UID:** `stat -c "%u:%g %U:%G" /opt/stacks/owncloud/config`.
## Gotcha 2: `PROXY_TLS=false` за reverse proxy
Дефолт oCIS — `PROXY_TLS=true` (HTTPS на proxy port 9200 self-signed). За traefik, который сам терминирует HTTPS, это даёт двойную TLS-обёртку — traefik пытается сделать backend TLS, не получается.
Per ownCloud docs: «If a reverse proxy is used to terminate HTTPS, `PROXY_TLS` can be set to false, though this means communication between the proxy and Infinite Scale will be unencrypted.» На том же хосте, в bridge network — acceptable.
## Gotcha 3: `PROXY_ENABLE_BASIC_AUTH=true` для WebDAV + admin API
Дефолтно oCIS — OIDC-only (browser-based login). Для **rclone / ownCloud-desktop / curl LibreGraph API** нужен basic auth — иначе 401 везде, включая `GET /graph/v1.0/me`.
**Trade-off:** basic auth не имеет MFA/refresh-tokens. Для personal use acceptable. Для shared deployment — обернуть LDAP / OIDC отдельно.
## Gotcha 4: User-create via LibreGraph API (нет CLI)
oCIS **не** имеет `ocis idm user add` или подобной CLI команды. Создание users — только через:
1. Web UI как admin → Settings → Users
2. LibreGraph API: `POST /graph/v1.0/users` с basic auth admin'а
API recipe:
```bash
curl -u "admin:$ADMIN_PWD" -X POST \
"https://owncloud.kzntsv.site/graph/v1.0/users" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Vitya",
"onPremisesSamAccountName": "vitya",
"mail": "vitya@kzntsv.site",
"passwordProfile": {"password": "<random-32>"},
"accountEnabled": true
}'
```
→ HTTP 201 с user JSON (с `id` UUID).
List users: `GET /graph/v1.0/users`.
## Storage layout (decomposedfs)
После `ocis init` data dir выглядит так:
```
/opt/stacks/owncloud/data/
├── idm/ — internal IDM (LDAP-style) state
├── idp/ — OIDC IdP private keys (private-key.pem etc)
├── nats/ — internal pub-sub messaging
├── search/ — indexer state (bleve)
└── storage/
├── metadata/spaces/<2>/<rest>/ — space metadata
└── users/spaces/<2>/<rest>/ — actual user files (decomposedfs nodes)
```
Каждый user space = `<2-char-prefix>/<26-char-rest-of-uuid>/` (split UUID для FS spread). Files внутри хранятся как **plain bytes** + sidecar metadata (xattrs / .meta.json). Backup-friendly: tar+rsync захватит всё корректно, восстановление = просто разархивировать обратно.
Internal KV-store (`storage/users/spaces/.../metadata/`, `idm/idm.json`, etc.) — **JSON files**, не БД. Это и есть «no external DB needed» — oCIS использует filesystem + NATS вместо Postgres/Redis.
## Backup integration
`/opt/stacks/owncloud` (whole dir) добавлен в rsync source list [[vds-backup-rsync-kreknin]]:
```diff
/opt/stacks/backup \
+ /opt/stacks/owncloud \
/etc/ssh \
```
Live container во время rsync — acceptable trade-off (decomposedfs использует atomic rename, отдельные node-files не corrupt'ятся). Если требуется strictly consistent snapshot — `docker stop owncloud` → rsync → `docker start` (downtime ~30s).
Первый full backup snapshot после import → +~25 GB на kreknin. Далее hardlink-incremental ≈ 1 GB/day.
## Connection chain
```
DNS owncloud.kzntsv.site → 89.253.255.94 (VDS_IP)
→ ufw 443
→ traefik websecure (LE cert via letsEncrypt resolver)
→ docker network proxy (172.18.0.0/16)
→ container owncloud:9200 (oCIS proxy service)
→ internal services: idp / idm / users / groups / proxy / storage-system / sharing / search ...
```
## Atomic revert
```bash
ssh vitya@89.253.255.94 'cd /opt/stacks/owncloud && docker compose down -v && cd .. && rm -rf owncloud'
# rsync source list cleanup (revert):
ssh vitya@89.253.255.94 "sed -i '\\|/opt/stacks/owncloud|d' /opt/stacks/backup/scripts/run.sh"
# secrets cleanup:
pass rm owncloud/admin-password owncloud/user-vitya && pass git push
```
## Related
- [[admin-infra-project]] — общий context для admin-infra repo
- [[vds-kzntsv]] — host entity (owncloud стек добавлен в его software stack)
- [[future-resilient-architecture-goals]] — RTO/RPO targets (oCIS — single-user, RTO/RPO defer)