tasks(owncloud-vds-deploy): file 🟡 — oCIS on VDS up + WebDAV verified

Deploy phase done: oCIS 7.1.0 в /opt/stacks/owncloud/ через traefik labels на
owncloud.kzntsv.site (LE cert valid), user 'vitya' создан через LibreGraph
API, WebDAV `/dav/files/vitya/` PROPFIND 200 OK.

Decisions in close-note: oCIS vs Seafile/Nextcloud chosen for drop-in
decomposedfs import + lightweight Go binary. user:1001:1001 override after
mount perms fail (host vitya UID 1001 ≠ image ocis-user UID 1000).
PROXY_ENABLE_BASIC_AUTH=true для WebDAV/LibreGraph admin API.

Backup integration: /opt/stacks/owncloud добавлен в rsync sources в
/opt/stacks/backup/scripts/run.sh (vds-backup-rsync-kreknin scope expanded).

Status 🟡 — pending user-side rclone copy 24.7GB → WebDAV (full copy лежит
на другом PC, не на этом).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 19:07:10 +03:00
parent f957830033
commit c46e569908
3 changed files with 134 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
# Admin Task Board
_Updated: 2026-05-21 (admin-infra-project-review closed 🟢 — no new findings; F1-F3 remain documented in [verify-migration] close-note)_
_Updated: 2026-05-21 (owncloud-vds-deploy 🟡 — oCIS up, user vitya created, WebDAV verified; 24.7GB import pending user-side rclone)_
<!--
Status legend:
@@ -10,6 +10,28 @@ _Updated: 2026-05-21 (admin-infra-project-review closed 🟢 — no new findings
🔵 Blocked — waiting on external input
-->
## 🟡 [owncloud-vds-deploy] — oCIS 7.1.0 на vds-kzntsv replace мёртвый ownCloud с Synology; 24.7GB import pending user-side rclone
oCIS deploy завершён, container up, traefik routes 200 OK через LE-cert, user `vitya` создан, WebDAV verified. Backup integration done — `/opt/stacks/owncloud` в rsync sources [[vds-backup-rsync-kreknin]]. Detail в [owncloud-vds-deploy.md](owncloud-vds-deploy.md).
**Status:** paused
**Where I stopped:** infrastructure complete; waiting on user-side rclone copy 24.7GB → WebDAV endpoint. Full copy лежит на другом PC (local C:\Users\vitya\ownCloud — partial 1.3GB не та копия). Compose в `/opt/stacks/owncloud/` (data+config dirs, `.env` chmod 600 с admin-password). Passwords: `pass show owncloud/admin-password` + `pass show owncloud/user-vitya` (pushed). HTTPS endpoint `https://owncloud.kzntsv.site` live.
**Next action:** user запускает rclone на PC где живёт 24.7GB:
```
rclone copy "<src>" :webdav: \
--webdav-url https://owncloud.kzntsv.site/dav/files/vitya \
--webdav-vendor owncloud --webdav-user vitya \
--webdav-pass $(rclone obscure "$(pass show owncloud/user-vitya)") \
--progress --transfers 4 --tpslimit 8 \
--retries 5 --low-level-retries 10 --stats 30s
```
Progress: `ssh vitya@89.253.255.94 'du -sh /opt/stacks/owncloud/data/spaces/'`. Done — 🟢 после size match + spot-check файлов через web UI.
**Branch:** master
---
## 🟢 [admin-infra-project-pointers] — Bootstrap-pointers для design admin-infra-project. Pre-fills target's `.wiki/CLAUDE.md` Domain conventions ссылками на спецификацию. Дизайн не лежит в этом репо — только pointer-stub. Без этой таски следующий агент попадёт в дыру: where_stopped one-liner + пустой Domain conventions stub = угадывание порогов / pipeline-этапов вместо чтения готовых решений.
**Кто делает:** любой следующий агент в этом проекте. Это первая по приоритету таска промоушена — все остальные импл-таски ссылаются на pointers через .wiki/CLAUDE.md.

View File

@@ -0,0 +1,110 @@
# owncloud-vds-deploy
## Goal
Поднять [[owncloud-infinite-scale]] (oCIS 7.1.0) на vds-kzntsv в качестве замены мёртвого ownCloud сервера на Synology NAS (см. [[nas-recovery]]). После восстановления — импортировать 24.7 GB из off-VDS backup-копии. Сервис на `owncloud.kzntsv.site`, files-only (calendar/contacts не нужны).
## Decisions log
- **2026-05-21 — oCIS vs Seafile vs Nextcloud:** oCIS выбран. Reasons: (1) drop-in миграция — decomposedfs storage по сути plain-files на диске (24.7 GB просто кладутся); (2) lightweight — single Go binary, не PHP-monstr classic ownCloud 10; (3) workflow continuity — user уже знаком с ownCloud UX; (4) тривиальный backup (tar `data/` + конфиг); (5) future-proof — oCIS = main line от ownCloud GmbH, classic OC10 deprecating. Seafile отвергнут: block-storage = нет drop-in import, медленнее migration. Nextcloud отвергнут: только files нужны — calendar/contacts overhead не оправдан.
- **2026-05-21 — `user: "1001:1001"` override:** image owncloud/ocis runs as UID 1000 (ocis-user inside container) by default, но host vitya = UID 1001. Mount-target dirs (./data, ./config) owned by vitya → container не мог писать. Fix: добавил `user: "1001:1001"` в compose — container runs as host UID, owns mounted dirs. Альтернатива (`chown 1000` хост-dirs) отвергнута — создаёт orphan UID на хосте.
- **2026-05-21 — `PROXY_ENABLE_BASIC_AUTH=true`:** дефолтно oCIS basic auth выключен (OIDC-only). Для WebDAV-клиентов (rclone, ownCloud desktop) и LibreGraph API admin-операций basic auth нужен → enabled. Trade-off: чуть слабее security (basic auth не имеет MFA/refresh tokens), но threat model personal use acceptable.
- **2026-05-21 — `PROXY_TLS=false`:** docs прямо разрешают, когда TLS термируется на reverse proxy (traefik certresolver letsEncrypt). Альтернатива — собственный self-signed cert внутри контейнера + traefik passthrough — overhead без выгоды.
- **2026-05-21 — admin/user-vitya passwords в pass-store:** `owncloud/admin-password` (32 chars random) + `owncloud/user-vitya` (32 chars random). Encrypted-at-rest, cross-machine sync через `OpeItcLoc03/password-store-private`. Закрывает риски [[secrets-manager-adopt]].
- **2026-05-21 — DNS surprise:** ожидали, что user будет создавать A-запись `owncloud.kzntsv.site → 89.253.255.94` вручную. Reality: запись уже была (видимо ранее создана при wildcard cleanup / dns prep), сразу резолвилась на VDS_IP. Wildcard `*.kzntsv.site → 94.19.247.14` (NAS recovery host) overlay-ится specific записями.
- **2026-05-21 — backup integration:** добавил `/opt/stacks/owncloud` в rsync source list `/opt/stacks/backup/scripts/run.sh` ([[vds-backup-rsync-kreknin]]). После import 24.7GB первый full backup snapshot будет +24.7GB на kreknin, далее ~hardlink incremental. kreknin 5.6 TB free — comfortably fits.
## Implementation sketch
`/opt/stacks/owncloud/docker-compose.yml`:
```yaml
services:
ocis:
image: owncloud/ocis:7.1.0
container_name: owncloud
restart: unless-stopped
user: "1001:1001"
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"
PROXY_ENABLE_BASIC_AUTH: "true"
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-char-random — стор в pass owncloud/admin-password>
```
User creation via LibreGraph API (`POST /graph/v1.0/users`, basic auth as admin).
## Completed steps
- [x] **Compose** написан, image `owncloud/ocis:7.1.0` pulled (digest `sha256:c75af880...b717b`)
- [x] **Dirs:** `/opt/stacks/owncloud/{data,config}` (vitya:vitya 775)
- [x] **Secrets:** `OCIS_ADMIN_PASSWORD` в `.env` (chmod 600), originals в pass-store: `owncloud/admin-password` + `owncloud/user-vitya` (pushed to OpeItcLoc03/password-store-private)
- [x] **Deploy:** `docker compose up -d` через ssh (limited stack — Portainer auto-detects)
- [x] **UID fix:** `user: "1001:1001"` после первого "permission denied" на `/etc/ocis/ocis.yaml`
- [x] **Basic auth fix:** `PROXY_ENABLE_BASIC_AUTH=true` после 401 на LibreGraph API
- [x] **Traefik integration:** labels подхвачены, cert via letsEncrypt valid, HTTPS 200 OK
- [x] **User `vitya` created** через LibreGraph API (`POST /graph/v1.0/users`, id `58110e99-5e92-43f8-a077-9f2ec7f5562e`)
- [x] **WebDAV verified:** `PROPFIND /dav/files/vitya/` returns 200 multistatus с personal space "Vitya" + system space "Shares"
- [x] **Backup integration:** `/opt/stacks/owncloud` добавлен в rsync source list `/opt/stacks/backup/scripts/run.sh` (между `/opt/stacks/backup` и `/etc/ssh`). `bash -n` syntax OK. Next nightly run 05:00 MSK захватит config + (post-import) data.
## Open
- [ ] **Import 24.7 GB** — pending user-side action. User запускает rclone copy с PC где лежит full копия:
```
rclone copy "<src>" :webdav: \
--webdav-url https://owncloud.kzntsv.site/dav/files/vitya \
--webdav-vendor owncloud \
--webdav-user vitya \
--webdav-pass $(rclone obscure "$(pass show owncloud/user-vitya)") \
--progress --transfers 4 --checkers 4 --tpslimit 8 \
--retries 5 --low-level-retries 10 --stats 30s
```
Resumable. Прогресс мониторится с VDS: `ssh vitya@VDS 'du -sh /opt/stacks/owncloud/data/spaces/'`.
- [ ] **Post-import verify:** size match (≈24.7 GB на data/) + spot-check файлов через web UI.
- [ ] **Pin image version** — сейчас `7.1.0` явно (good). Consider tracking 7.x patch releases — но не auto-update на 8.x без manual verify (breaking config schema changes возможны).
- [ ] **API-key rotate?** Portainer api-key в `vds-kzntsv/full-env` оказался invalid (401 "Invalid JWT token"). Не блокирует — admin user/pass работают. Follow-up: regenerate API key через Portainer UI + update pass-store. Отдельная chore-task если нужно.
## Notes
- **Architecture:** request flow → DNS owncloud.kzntsv.site → 89.253.255.94 → ufw 80/443 → traefik websecure → owncloud (172.18.0.14:9200) → decomposedfs storage в `/var/lib/ocis` mount → host `/opt/stacks/owncloud/data/`.
- **Storage layout:** oCIS использует decomposedfs — каждый файл = node с metadata. Spaces (personal + Shares) живут в `data/spaces/<space-uuid>/`. Backup-friendly: plain files на диске, не block storage.
- **Atomic revert:**
```
ssh vitya@89.253.255.94 'cd /opt/stacks/owncloud && docker compose down -v && cd .. && rm -rf owncloud'
# + remove /opt/stacks/owncloud line из run.sh
# + pass rm owncloud/admin-password owncloud/user-vitya && pass git push
```
- **No external DB** — oCIS использует internal KV-store (`data/storage-users/`, `data/idm/`) для metadata. Postgres/MariaDB на VDS не задействованы. Это снимает зависимость от shared-dbs network — owncloud только в `proxy`.

View File

@@ -8,6 +8,7 @@
- [x] ~~**Что бэкапить:**~~ Resolved 2026-05-20. Sources в `/opt/stacks/backup/scripts/run.sh`:
- `/opt/stacks/{gitea,verdaccio/storage,verdaccio/config,registry,traefik,portainer,ntfy,backup}`
- `/opt/stacks/owncloud` (added 2026-05-21 для [[owncloud-vds-deploy]] — oCIS data + config + .env + compose; post-import будет ~25GB, hardlink-incremental после первой ночи)
- `/etc/{ssh,ufw,hosts,docker}`
- `/home/vitya/.ssh`
- DB dumps в `$DUMP_DIR` (pg/maria/mongo/redis) — добавляются в rsync source list.