8.4 KiB
name, description
| name | description |
|---|---|
| synology | Control a Synology NAS end-to-end via two surfaces: the DSM Web API (auth + full API discovery + any API method — system, storage, shares, users/groups, packages, services, FileStation, connections) and an SSH backend for the syno* CLI the Web API doesn't expose (filesystem ACLs, low-level share/user/group internals). Reads run freely; mutating calls (set/create/delete/start/stop/reboot/shutdown/...) are gated behind --confirm. Default device is the Cascades NAS (cascadesDS, 192.168.0.120, admin); point at another client's NAS with --vault. Triggers: synology, diskstation, DSM, cascadesDS, NAS, control the synology, synology drive, hyper backup, active backup, synology package/service/share/user, reboot the nas, synology acl. |
synology — Synology DSM control (Web API + SSH)
Full control of a Synology NAS. Two complementary backends:
- DSM Web API (
scripts/syno_client.py) — the structured surface. Auth → discover the device's own API map → call any API method. This is how you "control all functions":apisshows everything the device exposes,call <API> <method>reaches any of it. - SSH
syno*CLI (scripts/syno-ssh.sh) — the gaps the Web API doesn't cover: filesystem ACLs (synoacltool), share/user/group CLI internals, package CLI. We already use this for the Cascades share-permission inventory (docs/migration/synology-permission-inventory.md).
Default target = Cascades cascadesDS (192.168.0.120, DSM on :5000, admin) — credential
vaulted at clients/cascades-tucson/synology-cascadesds.sops.yaml (host/port/
credentials.username/credentials.password). ext4 filesystem (NOT Btrfs → no Active Backup
for Business). Shares: homes, Public, SalesDept, Server, Management. On a private LAN — every
command needs the Cascades site VPN up (a connect failure almost always = VPN down). Point at
any other NAS with --vault clients/<x>/synology-...sops.yaml (same field layout).
Web API commands
PY="$CLAUDETOOLS_ROOT/.claude/scripts/py.sh"; S=".claude/skills/synology/scripts/syno_client.py"
# verify + discover
bash "$PY" "$S" test # login, print model/serial/firmware/RAM/uptime
bash "$PY" "$S" apis [filter] # the device's full API map (e.g. `apis backup`, `apis drive`)
# reads
bash "$PY" "$S" sysinfo # SYNO.Core.System — model/serial/RAM/temp/uptime
bash "$PY" "$S" util # live CPU/mem/disk/net
bash "$PY" "$S" storage # volumes/disks/RAID/usage (SYNO.Storage.CGI.Storage)
bash "$PY" "$S" shares | users | groups | packages | services | connections
bash "$PY" "$S" ls [folder_path] # FileStation: no path = shares; else list a folder
# generic power tool — ANY API method the device exposes
bash "$PY" "$S" call <API> <method> [k=v ...] [k:=json] [--version N] [--post]
bash "$PY" "$S" call SYNO.Core.System.Status get
bash "$PY" "$S" call SYNO.Backup.Task list # Hyper Backup tasks (if installed)
# writes — ALL gated --confirm
bash "$PY" "$S" pkg-start <id> --confirm | pkg-stop <id> --confirm
bash "$PY" "$S" reboot --confirm | shutdown --confirm
bash "$PY" "$S" call <API> <set-method> k=v --confirm # any mutating method needs --confirm
call params: k=v for strings, k:=json for typed/array values (e.g. additional:='["size","owner"]').
A method whose name starts with a mutating verb (set/create/delete/start/stop/reboot/…) is auto-detected
and refuses to run without --confirm.
SSH commands (the syno* CLI surface)
X=".claude/skills/synology/scripts/syno-ssh.sh"
bash "$X" info | df | shares | users | groups | packages | services # reads
bash "$X" acl <share> # synoacltool -get /volume1/<share> (e.g. acl Server)
bash "$X" reboot --confirm # synoshutdown -r (use when the Web-API reboot 103s)
bash "$X" shutdown --confirm # synoshutdown -s
bash "$X" run "<command>" --confirm # arbitrary command (gated); privileged auto-sudo -S
Requires SSH enabled on the NAS (DSM → Terminal & SNMP). Privileged recipes feed the vaulted
admin password to sudo -S. Auth: sshpass if present, else OpenSSH SSH_ASKPASS (on Windows the
fallback needs MSYS/Git-bash ssh on PATH — system OpenSSH can't exec a shell askpass).
Auth model (DSM Web API)
SYNO.API.Auth login (session=DSM, enable_syno_token=yes) → _sid (session cookie) + a
synotoken (CSRF). Both are attached to every subsequent call (the synotoken as X-SYNO-TOKEN
header + SynoToken param) so writes pass CSRF. 2FA: pass --otp <code> or SYNO_OTP. The client
always logs out at the end. Env overrides for ad-hoc use: SYNO_HOST/SYNO_PORT/SYNO_USER/SYNO_PASS,
SYNO_HTTPS=1 (→ :5001, cert verify off).
Full API reference
references/dsm-api.md is the consolidated, sourced map (auth, system/power, storage/shares,
users/groups/security, packages, Log Center, Drive, backup, network/services + the SSH syno*
surface) with per-row confidence and the 5 "golden rules". Read it before any write — the key
ones: discover versions via apis (don't hardcode), CSRF is mandatory for writes (handled),
setters are read-modify-write (get → mutate → push back; never construct from scratch), and
when a setter's param keys are uncertain run it on-box via synowebapi --exec (validates params).
Why both surfaces (don't reach for SSH first)
The Web API is the default and covers system/storage/shares/users/packages/services/FileStation/
backup/connections. Use SSH only for what the API genuinely lacks — chiefly filesystem ACLs
(synoacltool): the Web API tells you a share is in Windows-ACL mode but NOT the per-file ACE list.
That ACE data is exactly what the Cascades cutover needs (docs/migration/ synology-permission-analysis-2026-04-22.md).
Open Cascades work this skill serves (verified call recipes)
- Confirm model/RAM/DSM version (wiki TODO) —
testanswers it in one call. - Log Center syslog collector (
docs/network/network-logging-plan.md) — the NAS-as-syslog-SERVER isSYNO.LogCenter.*(needs the Log Center package):apis logcenterto confirm it's installed, thencall SYNO.LogCenter.RecvRule list(receive rules),call SYNO.LogCenter.Log list(received logs). NOTESYNO.Core.SyslogClient.*is the forward-own-logs-out side, not the collector. Schedule the snapshotter as a root task viaSYNO.Core.TaskScheduler.Root create. - Synology Drive Team Folder migration (
PROJECT_STATEpending) —apis synologydrive, thencall SYNO.SynologyDrive.TeamFolders list/... Tasks list/... Connection listto inspect before the CS-SERVER cutover. (SYNO.C2FS.*is C2 cloud — not this.) - Hyper Backup offsite (phase4 §6.4) —
call SYNO.Backup.Task list/... Repository listonce configured. (NOTE: Active Backup is installed + running on this ext4 box — the Btrfs requirement is only for ABB dedup/self-healing features, not the package.call SYNO.ActiveBackup.Task list.)
Error logging (mandatory)
On a GENUINE functional failure (DSM login fail, API error, SSH connect/auth rc=255) both scripts
log via .claude/scripts/log-skill-error.sh before surfacing. Handled conditions (missing cred,
VPN-down connect error surfaced to the user, a method refused for lack of --confirm) are NOT logged.
Status / verification
- [PLUMBED] Built from a 5-agent scan of the DSM 7 help tree + the authoritative API sources
(kwent device-extracted
_full.json, N4S4/synology-api, Synology's Web API guides) — seereferences/dsm-api.md. Auth (sid + synotoken CSRF), API discovery, version-by-maxVersion routing, session-expiry re-login (codes 106/119), the mutating-verb gate, and the generic-error map are all coded to spec but not yet live-exercised against the device (needs the Cascades VPN up). First livetestconfirms endpoint shapes + fills the model/DSM-version wiki TODO. Mark verified then. - DSM 7.2.x reboot/shutdown 103: the Web-API
reboot/shutdowncan return error 103 on some builds. Fallback is the SSHreboot|shutdown --confirmrecipe (synoshutdown -r|-s). - Param-schema caveat: method names + versions in the reference are device-authoritative, but many
setter param keys are community/inferred. For a production write where keys are uncertain, capture
the matching
getand round-trip it, or run on-box viasynowebapi --exec.