---
name: seafile
description: "Manage ACG's Seafile Pro server (the SeaCloud / SeaDrive backup backend on Jupiter): read-only inventory (who has an account, per-user storage, libraries, which GuruRMM endpoints run the SeaDrive/Seafile client) plus gated admin writes (create/deactivate/delete user, set quota, create/transfer/delete library, share/unshare). Reads run freely; writes preview by default and require --confirm. Built for GPS backup verification + client provisioning. Triggers: seafile, seacloud, seadrive, sync.azcomputerguru, who backs up to seafile, seafile usage, create seafile user, set seafile quota, seafile library."
---

# Seafile (SeaCloud / SeaDrive) Skill

Admin client for ACG's live **Seafile Pro** server — the backend clients call
"SeaCloud" (the server) and "SeaDrive" (the desktop virtual-drive client). Runs in
Docker on Jupiter (`172.16.3.20:8082`, public `https://sync.azcomputerguru.com`).
Answers the GPS backup-audit question: **which customers back up here and how
much data do they hold** — and, with `--rmm`, which enrolled machines actually run
the client.

This skill is one of the backup-verification siblings alongside `b2` (Backblaze),
`owncloud`, and `datto-workplace`. Inventory is read-only; admin **writes**
(user/quota/library/share) exist but are gated behind `--confirm` (see below) and
preview by default.

## Running

```bash
SEAFILE=".claude/skills/seafile/scripts/seafile.py"
py "$SEAFILE" status                 # server reachable + version
py "$SEAFILE" usage                  # per-user storage + library count (audit view)
py "$SEAFILE" users [--inactive]     # all accounts + used/quota + last login
py "$SEAFILE" libraries              # all libraries (repos) + owner + size
py "$SEAFILE" devices [--user EMAIL] # desktop/sync devices the server has seen
py "$SEAFILE" audit                  # active accounts with data (the GPS slice)
py "$SEAFILE" audit --rmm            # + cross-check GuruRMM endpoints for the client
py "$SEAFILE" audit --client Russo --rmm --json
```

Add `--json` to any command for machine-readable output. `--url` overrides the
server base (default is the internal Docker endpoint; use the public host when
off-LAN).

## Write ops (admin) — preview by default, `--confirm` to apply

Every write is **gated**: run it once to see the `[PLAN]`, add `--confirm` to
execute. Preview is fully offline (no auth, no network), so it is safe to eyeball
first. All writes go out **form-encoded** (the share endpoint reads `share_to` via
`getlist`, which requires form encoding, not JSON) against the Seafile Pro 12.0
admin API (`/api/v2.1/admin/...`).

```bash
# users
py "$SEAFILE" user-create client@acme.com --password 'PW' --name 'Acme' --quota-gb 500 --confirm
py "$SEAFILE" user-set client@acme.com --inactive --confirm     # deactivate
py "$SEAFILE" user-set client@acme.com --quota-gb 1024 --confirm # bump quota
py "$SEAFILE" quota  client@acme.com --gb 1024 --confirm         # quota shortcut
py "$SEAFILE" user-delete client@acme.com --confirm             # IRREVERSIBLE

# libraries
py "$SEAFILE" lib-create "Acme Backup" --owner client@acme.com --confirm
py "$SEAFILE" lib-transfer <repo_id> --to newowner@acme.com --confirm
py "$SEAFILE" lib-delete <repo_id> --confirm                    # IRREVERSIBLE

# sharing
py "$SEAFILE" share   <repo_id> --to a@acme.com b@acme.com --perm rw --confirm
py "$SEAFILE" unshare <repo_id> --to a@acme.com --confirm
py "$SEAFILE" share   <repo_id> --to <group_id> --group --perm r --confirm
```

**Quota unit:** `--quota-gb` / `--gb` are **decimal GB** — deliberately the same
unit the read commands (`users` / `usage` / `audit`) display, so a quota you set
round-trips with the quota you later see here. Internally Seafile stores quota in
MB (1 MB = 1 MiB); the preview shows the exact MB it will send (e.g.
`500 GB (-> 476837 MB stored)`) so you can verify before `--confirm`. Caveat:
Seafile's own web admin UI renders quota in binary GiB, so the same quota reads
~7% smaller there — trust this tool's `users` view for the round-trip.

**Any password you set is a credential** — `user-create`/`user-set` print a
reminder; store it in the SOPS vault via the `vault` skill (house rule). Never
hand out or log a Seafile password without vaulting it.

## Credentials

Loaded at runtime from the SOPS vault (never hardcoded):
`services/seafile-pro.sops.yaml` -> `credentials.username` / `credentials.password`
(the Seafile admin account). Auth is `POST /api2/auth-token/` (form) -> a
long-lived API token used as `Authorization: Token <tok>`. The token is a secret;
it is cached at `.claude/skills/seafile/.cache/token.json` (gitignored, mode 0600)
and re-fetched weekly or on a 401/403.

## What the data means

- **quota_usage** (bytes) is the authoritative per-account storage used. A user
  with `is_active: true` and non-zero usage is actively backing up here.
- **libraries** (repos) are the sync roots; `size` + `file_count` + `last_modified`
  show freshness. `usage` rolls libraries up per owner.
- Accounts are emails, so the customer is usually obvious from the domain
  (e.g. `russo@rrs-law.com` = Russo Law, `greg@gstoltzlaw.com` = Stoltz Law).
- As of the build (2026-07-05) only a **handful** of accounts hold data
  (~5 TB total) — Seafile is used by a few clients, not the whole GPS base.

## The "both" cross-check (`--rmm`)

Server-side tells you who has an account; `--rmm` adds the endpoint half. It logs
in to GuruRMM (`infrastructure/gururmm-server.sops.yaml`), and for each agent
(optionally filtered by `--client`) runs a **read-only** detection PowerShell that
reports installed products / running processes / config folders matching
`Seafile` / `SeaDrive`. An agent is reported only if the client is actually
present. Detection dispatches a command to live endpoints — scope with `--client`
rather than sweeping all 350+ agents unless you mean to.

## Notes / gotchas

- Base defaults to `http://172.16.3.20:8082` (direct, no Cloudflare); set
  `SEAFILE_URL=https://sync.azcomputerguru.com` when off the LAN/Tailscale.
- `devices` depends on the admin devices endpoint, which varies by Seafile
  version; it returns `[]` (with a note) rather than failing if unsupported.
- Shared plumbing (repo-root resolve, vault read, GuruRMM client + endpoint
  detection) lives in `.claude/scripts/backup_common.py`, used by all three
  server-backup skills. Detection patterns must be precise per backend — this
  skill uses `Seafile`/`SeaDrive`.
- Seafile Pro also has a MySQL backend on Jupiter (vault `credentials.database.*`)
  for deeper queries; not used here (the admin API covers the audit needs).
