---
name: synology-dsm
description: >
  · Administer Synology DSM over SSH: volumes, btrfs, packages, snapshots, crash recovery. Triggers: 'synology', 'dsm', 'diskstation', '/volume1', 'synopkg', 'volume crashed'. Not for desktop Linux distros or their btrfs setups.
license: MIT
compatibility: "Requires SSH access to a Synology NAS running DSM 7, with an admin account for sudo. DSM 6 differences are noted but not covered in depth"
metadata:
  source: iuliandita/skills
  date_added: "2026-07-27"
  effort: high
  argument_hint: "[task-or-host-or-volume]"
---

# Synology DSM: Administration and btrfs Recovery

Operate Synology NAS appliances over SSH: package and service control, storage stack
inspection, snapshots and backups, and recovery of btrfs volumes that will not mount.

DSM is a Linux appliance with a heavily modified btrfs and a userspace that regenerates its own
config. Two facts drive most of this skill: **DSM's btrfs on-disk format is newer than the
btrfs-progs DSM ships and diverges from mainline**, so stock tools report healthy volumes as
corrupt; and **DSM regenerates `/etc/fstab` and package state at boot**, so hand edits do not
survive.

**Target versions** (July 2026):
- DSM 7.4.1-90080 - current release (7.4 GA was 90075, 2026-06-16)
- DSM 7.3 (released 2025-10-08) - Long-Term Support line, maintained to October 2027. Patch
  floor is **7.3.2-86009-3 or above**: `-2` carries the SA-26:06 fixes but not SA-26:03
  (CVE-2026-32746). Later `-4` builds exist
- DSM 7.2 - end of maintenance December 2025, yet it still received fixes in SA-26:06 (April
  2026). Treat continued patching as unreliable rather than as policy, and plan an upgrade
- Advisories: Synology-SA-26:03 (CVE-2026-32746, telnetd buffer overflow, CVSS 9.8, unauthenticated
  RCE - keep Telnet off), Synology-SA-26:06 (nine DSM CVEs, 2026-04-15), Synology-SA-26:11 (MailPlus Server)
- Userspace `btrfs` on the appliance is old (v4.0 on DSM 7.1 avoton). Check with `btrfs --version`
  before assuming a subcommand exists

DSM 7.1.x and earlier do not appear in current advisories' fixed-version lists; treat them as
unpatched. That is a reason to plan an upgrade, not to run one on a unit with a broken volume.

Verify the actual build before quoting any of this: `cat /etc.defaults/VERSION`.

## When to use

- Any task on a Synology NAS over SSH: shares, packages, services, users, storage pools
- A volume that will not mount, shows "Volume Crashed", or has gone read-only
- btrfs work on a Synology volume, including snapshots, subvolume flags, and offline recovery
- Deciding whether a DSM warning is real damage or a stock-tool false positive
- Planning disk replacement, RAID repair, or a migration between Synology units
- Hardening DSM: SSH, admin accounts, firewall, package exposure

## When NOT to use

- Generic Linux administration on a normal distro - use **debian-ubuntu**, **arch-btw**,
  **rhel-fedora**, **nixos-btw**
- Mainline btrfs on a normal Linux host - Synology's format divergences do not apply there
- Docker Compose authoring, image builds, registry work (Container Manager runs stock Docker) -
  use **docker** for the container content, this skill only for DSM-side paths and permissions
- Router, VLAN, DNS, or reverse proxy design around the NAS - use **networking**
- OPNsense/pfSense appliances - use **firewall-appliance**
- Kubernetes storage that happens to point at a Synology CSI target - use **kubernetes**
- Application security review or dependency scanning - use **security-audit**
- Localizing a live outage across an unknown stack - use **debug-triage** first, then come back here
- Proxmox, libvirt, or generic hypervisor work - use **virtualization**

## AI Self-Check

Before returning any DSM command, verify. When no SSH session exists yet - the common case when
answering a question - the appliance-state items convert into the first commands the user runs,
in this order, rather than being skipped:

- [ ] DSM major version confirmed (`cat /etc.defaults/VERSION`) - DSM 6 and DSM 7 differ in
  service control, root login, and available tools
- [ ] No command from the hard-refusal list below
- [ ] Destructive storage operations run against a dm-snapshot overlay, not the live device
- [ ] Any `mount`, `mdadm`, `dmsetup`, or `btrfs` write path stated with its blast radius
- [ ] `cd /` before anything that unmounts `/volume1` (SSH sessions land in the home dir on it)
- [ ] Shell syntax is ash-compatible (`/bin/sh` is ash - no process substitution, no bashisms)
- [ ] Long-running jobs wrapped in `setsid nohup ... < /dev/null &`, not attached to the SSH session
- [ ] Binaries deployed to `/root/` or a package dir, never `/tmp` (`noexec`)
- [ ] Tool presence checked, not assumed - `lsof`, `fuser`, `mountpoint`, `modinfo` are absent
- [ ] Config edits target files DSM does not regenerate, or the regeneration is accounted for
- [ ] Backup or snapshot state verified before any repair, not after
- [ ] **Current source checked**: dated versions, CLI flags, API names, and support windows are verified against primary docs before repeating them
- [ ] **Hidden state identified**: DSM version, model, package dependencies, mounted volumes, and prior repair attempts are made explicit before acting
- [ ] **Verification is real**: checks exercise the actual mount, service, or filesystem rather than reading a DSM banner
- [ ] **Routing overlap checked**: generic Linux, container, and network tasks are routed to the matching skill
- [ ] **Spec claims verified**: claims about DSM behavior are checked against the appliance or Synology's GPL kernel source, not recalled

---

## Hard refusals

These are rules, not suggestions. Each one has destroyed a real volume.

1. **Never run `btrfs check --repair --init-extent-tree` on a Synology volume.** Observed
   behavior: full scan completes, then it writes a zero-entry node into the chunk tree, hits
   `BUG_ON` in `btrfs_try_chunk_alloc`, and leaves the filesystem permanently unmountable
   (`open_ctree failed`). There is no recovery from this short of restore or a data recovery lab.
2. **Never `mount -o clear_cache` on a damaged volume.** Unconditional, because proving the free
   space tree is *not* the damaged structure is exactly what a damaged filesystem prevents.
   Clearing the tree requires freeing its own blocks, which requires the damaged block. The
   transaction aborts during mount and the filesystem then fails `open_ctree` entirely - strictly
   worse than before.
3. **No repair of any kind without a dm-snapshot overlay in place.** One named exception: when
   there is no usable backup, a single read-only mount attempt on the bare origin is permitted
   to reach evacuation, accepting that the mount replays the log tree and is therefore a write.
   Everything after that attempt goes through the overlay. See `references/btrfs-recovery.md`.
4. **Never click "Repair" in DSM on a crashed volume before identifying which layer failed.**
   The banner does not distinguish mdadm degradation from btrfs read-only. Repair at the wrong
   layer writes to every disk in the pool.
5. **Never run `mdadm --assemble --force` or `--create` as a first move on a suspect array.**
   Force-assembly with stale event counts silently picks a wrong parity generation.
6. **Never enable Telnet, including as an SSH workaround.** CVE-2026-32746 is an unauthenticated
   RCE in DSM's telnetd (CVSS 9.8). If SSH is unusable, use the console or DSM's UI.

Confirm with the user before any RAID repair, volume delete, DSM update, disk removal, or
package uninstall. All of these are outward-facing or irreversible. When running unattended with
no one to ask, stop and report what needs approval - never proceed on a default.

---

## Environment facts

Observed on a DS415+ running DSM 7.1.1 (avoton). The mechanisms hold broadly, but re-check any
row that a decision rests on - `scp -O`, in particular, follows from DSM's SFTP service being
off, which is a toggle rather than a fixed property.

| Fact | Consequence |
|---|---|
| `/tmp` is `noexec` | Deploy binaries to `/root/` or a package dir |
| sftp subsystem disabled | `scp` needs `-O` (legacy protocol) or it fails with `subsystem request failed` |
| User homes live on the data volume (`/volume1/homes/<user>`) | If the volume is down, key auth breaks (`authorized_keys` unreadable) and login prints `Could not chdir to home directory` |
| Every SSH session lands in the home dir | `umount /volume1` fails with "target is busy". Always `cd /` first |
| `/bin/sh` is ash | No bashisms, no process substitution `<(...)` |
| Missing tools | `fuser`, `mountpoint`, `modinfo`, `lsof` absent - read `/proc` directly |
| Present tools | `python3`, `mdadm`, `dmsetup`, `losetup`, `truncate`, `blockdev`, `btrfs`, `systemctl`, `smartctl` |
| Root login | DSM 7 disables direct root SSH. Log in as an admin user and `sudo -i` |
| `/etc/fstab` is regenerated at boot | Hand-edited mount options do not persist |
| `syno_poweroff_task` | Exists on DSM 6, **not** on DSM 7.1+. Stop packages and services individually |
| Defaults live in `/etc.defaults/` | Edits there survive DSM updates better than `/etc/`; both can be overwritten by a major upgrade |

Read `references/dsm-cli.md` for the command reference (packages, services, shares, users,
indexing, logs, SMART, notifications).

---

## Workflow

### Step 1: Identify the appliance before anything else

```sh
cat /etc.defaults/VERSION                  # productversion, buildnumber, majorversion
grep unique /etc.defaults/synoinfo.conf    # platform, e.g. synology_avoton_415+
uname -a                                   # kernel (3.10.x or 4.4.x on most models)
synopkg list --name                        # installed packages
```

Model and build determine which GPL kernel source to read, which btrfs features exist, and
whether DSM 6 or DSM 7 semantics apply. Do not skip this step to save a round trip - almost
every later decision depends on it.

### Step 2: Establish the storage picture

```sh
cat /proc/mdstat                           # all md arrays, degraded state, resync progress
sudo vgs; sudo lvs                         # LVM layer
sudo btrfs filesystem show                 # filesystems and devices
sudo btrfs filesystem usage /volume1       # data vs metadata allocation
df -h /volume1
mount | grep volume                        # actual mount options in force
```

The stack is `/dev/sdX3 -> mdN (RAID) -> vgN/volume_N -> cachedev_N (flashcache shim) -> btrfs`.
`md0` (system, ~8 GB) and `md1` (swap, ~2 GB) are RAID1 across **all** disks and are commonly
found degraded and ignored for months. Check them; repair is a plain `mdadm --add` and an 8 GB
RAID1 resync finishes in under a minute.

Read `references/storage-and-backup.md` for SHR, disk replacement, compatibility database,
snapshots, and backup verification.

### Step 3: Route on symptom

| Symptom | Route |
|---|---|
| Volume mounts, DSM is healthy, routine task | `references/dsm-cli.md` |
| Degraded array, disk replaced, pool repair | `references/storage-and-backup.md` |
| Volume read-only, "Volume Crashed", will not mount | `references/gotchas.md`, then `references/storage-and-backup.md` section 4 **first** - the banner does not say which layer failed. Only once the array and LV are confirmed healthy does it become `references/btrfs-recovery.md` |
| Stock `btrfs` reports corruption but the volume mounts and reads fine | Likely a Synology format divergence, not damage. `references/btrfs-recovery.md`, section on private trees |
| Package keeps restarting after being disabled | Dependency resurrection - `references/dsm-cli.md` |

### Step 4: Change with a stated blast radius

Before any write: state what is affected, whether it is reversible, and what the rollback is.
For storage operations, the rollback is the overlay or a verified backup - nothing else counts.

### Step 5: Verify against the runtime, not the UI

DSM's banners lag reality and its health status is derived. Verify the thing itself:

```sh
mount | grep /volume1                          # actually mounted, and rw or ro?
sudo btrfs filesystem usage /volume1           # metadata headroom
sudo dmesg | tail -100                         # kernel truth about the mount
synopkg status <Pkg>                           # package state as JSON
# damage survey: hours on a large share, so detach it and keep stderr
sudo setsid nohup sh -c 'find /volume1/<share> -size +0 > /dev/null' \
  > /root/survey.log 2>&1 < /dev/null &
```

`find <dir>` alone performs readdir only and reads no inodes, so it reports a badly damaged
filesystem as clean. **`-type f` does not fix that**: `find` answers `-type` from the `d_type`
that `readdir` already returned and skips the `stat` entirely. Use a predicate that needs inode
data - `-size +0`, `-printf '%s\n'`, `-newer <ref>` - and let stderr through instead of
discarding it, since the EIO lines are the finding.

---

## Recovery first moves

**Establish the goal before the sequence.** With a verified backup, the goal is repair. Without
one, the goal is **evacuation**: get the data off a read-only mount first, and treat repair as a
later, optional problem. Buying destination disks is cheaper than a recovery lab. Ask which
situation the user is in; do not assume.

When a volume will not mount, do these in order. Details in `references/btrfs-recovery.md`;
read `references/gotchas.md` before the first write of any kind.

**The branch that decides the order:** with a verified backup, build the overlay first and run
every mount attempt against it. Without one, take the named exception in hard refusal 3 - one
read-only mount attempt on the bare origin, accepting the log-replay write, because evacuation
beats purity. After that attempt, everything goes through the overlay.

1. **Stop writing.** Do not repair, do not reboot repeatedly, do not let DSM auto-repair. Do not
   update DSM on a unit with a broken volume.
2. **Identify version and platform** (Step 1 above), and confirm the failure is above the RAID
   layer (`references/storage-and-backup.md` section 4).
3. **Try the cheap read-only mount options**, cheapest first, reading `dmesg` after each failure.
   `-o ro,no_quota_tree` alone recovers a common class of Synology mount failure. Note that a
   read-only mount still replays the log tree, which is a write - the reference explains when
   that forces the overlay first.
4. **If a read-only mount succeeds and there is no backup, evacuate now.** Repair decisions get
   easier once the data is elsewhere.
5. **Build a dm-snapshot overlay and fingerprint the origin** before any write attempt. The
   overlay and a mounted origin are mutually exclusive, so this is a branch point, not a step
   that stacks on top of step 3.
6. **Read the GPL kernel source** for the nearest published release family when the cheap options
   fail (the archive carries families such as `7.3-86009`, `7.2-72806`, `7.1.1-42962`, not every
   build; 7.4 has no drop yet):
   `https://archive.synology.com/download/ToolChain/Synology%20NAS%20GPL%20Source/<VER>-<BUILD>/`
   Extract `fs/btrfs/` and read `ctree.h`, `disk-io.c`, `super.c`, `usrquota.c`. It converts a
   black box into a documented system, and twenty minutes there beats hours of probing.
7. **Only then** consider offline tools, and only a patched btrfs-progs build, against the overlay.

---

## Packages and services

```sh
synopkg list --name                  # installed packages (no --started on 7.1)
synopkg status <Pkg>                 # JSON status
synopkg stop|start <Pkg>
synopkg enable|disable <Pkg>         # autostart marker in /var/packages/<Pkg>/enabled
systemctl stop pkgctl-<Pkg>.service  # the underlying unit
```

**Package dependencies resurrect packages.** `synopkg disable` is not enough if another
installed package declares the target in `install_dep_packages`:

```sh
grep -h install_dep_packages /var/packages/*/INFO
```

Synology Drive declares SynoFinder, so SynoFinder restarts within a minute of being disabled.
When the goal is "stop indexing this share", use the indexer's own control tool rather than
fighting the package manager - see `references/dsm-cli.md`.

---

## Security

- Keep Telnet disabled (CVE-2026-32746, CVSS 9.8, unauthenticated RCE in DSM's telnetd)
- Disable the default `admin` account; use a named admin with 2FA
- Move SSH off 22 only as noise reduction, not as a control; restrict by firewall rule instead
- Do not expose DSM's web UI directly to the internet. QuickConnect and DDNS both widen exposure;
  prefer a VPN into the LAN
- Patch level matters more than version line: 7.3 LTS with current patches is a supported
  posture, 7.2.1 without them is not
- Snapshots are not backups until they are replicated off the unit. Immutable (WORM) snapshots,
  introduced in DSM 7.2, resist an admin-account compromise; ordinary snapshots do not
- Package exposure is the real attack surface: MailPlus, Photos, and Drive carry most advisories.
  Uninstall what is unused

## Performance

- Check `btrfs filesystem usage` metadata headroom before blaming disks. A metadata-full btrfs
  behaves like a failing filesystem while every disk is healthy
- Indexing (`synoindexd`, `synoelasticd`) and Photos face-recognition dominate CPU on small units;
  pause per share rather than disabling packages
- `synoindexd` and snapshot deletion both spike I/O; do not benchmark during either
- SHR/RAID5 resync and btrfs balance are both throughput killers - check `/proc/mdstat` before
  investigating "slow NAS" complaints

---

## Reference Files

- `references/dsm-cli.md` - DSM command surface: packages, services, shares, users, network,
  indexing, logs, notifications, SMART, DSM API. Read for any routine administration task.
- `references/storage-and-backup.md` - SHR and the RAID/LVM/btrfs stack, disk replacement,
  drive compatibility database, snapshots, Hyper Backup, restore verification. Read when the
  task touches disks, pools, snapshots, or backups.
- `references/btrfs-recovery.md` - Synology's btrfs divergences (private root flags, private
  trees, private mount options, the usrquota mount trap), dm-snapshot overlay procedure, mount
  escalation ladder, tool matrix, btrfs-progs bugs, subvolume flag ioctls. Read when a volume
  will not mount or when stock tools report corruption.
- `references/gotchas.md` - footguns, diagnostic hygiene, ash shell traps, behavior of a
  damaged volume. Read before any repair attempt.

## Output Contract

See `references/output-contract.md` for the full contract.

- **Skill name:** SYNOLOGY-DSM
- **Deliverable bucket:** `audits`
- **Mode:** conditional. When invoked to **analyze, review, audit, or improve** an existing
  system (health review, recovery post-mortem, hardening audit), emit the full contract and
  write the deliverable to `docs/local/audits/synology-dsm/<YYYY-MM-DD>-<slug>.md`. When invoked
  to answer a question, run a routine command, or explain behavior, respond freely.
- **Severity scale:** `P0 | P1 | P2 | P3 | info` (see shared contract).

## Related Skills

- **docker** - Container Manager on DSM is stock Docker plus a GUI. That skill owns the compose
  file and image; this one owns `/volume1` paths, DSM permissions, and package lifecycle.
- **networking** - DNS, VPN, reverse proxy, and VLAN work around the NAS. This skill stops at
  the appliance's own interfaces.
- **debug-triage** - localizes an unknown failing layer during a live incident. Use it first when
  "the NAS is down" could be network, power, or storage; this skill takes over once it is DSM.
- **debian-ubuntu** - DSM 7 is Debian-derived, so some package intuitions carry over, but DSM's
  own package manager and config regeneration do not behave like apt.
- **security-audit** - reviews application code and dependencies. This skill covers appliance
  hardening and DSM-specific exposure.
- **virtualization** - Virtual Machine Manager on DSM runs QEMU/KVM underneath; that skill covers
  the guest and hypervisor concepts, this one the DSM package around them.

## Rules

1. **Identify the DSM version and platform before advising anything.** Behavior differs across
   DSM 6, 7.1, 7.2, and 7.4.
2. **No repair without an overlay.** Any operation that can write to a damaged volume runs
   against a dm-snapshot overlay first.
3. **Never `--init-extent-tree`, never `clear_cache` on a damaged volume.** Both destroy volumes,
   and the `clear_cache` ban is unconditional.
4. **Read Synology's GPL kernel source for the exact build before deep recovery work.** It is
   authoritative documentation of the on-disk format and nothing else is.
5. **Treat mainline-tool corruption reports as unverified.** Synology's private root flags and
   trees are rejected by mainline's tree-checker. Confirm damage against the DSM kernel's own
   behavior before acting on a stock-tool verdict.
6. **Damage surveys need an inode-reading predicate.** `find` bare or with `-type f` reads no
   inodes and reports a corrupt volume as clean. Use `-size +0` or `-printf '%s\n'`.
7. **Confirm before destructive or outward-facing actions**: RAID repair, volume delete, disk
   removal, package uninstall, DSM update, reboot of a production unit.
8. **Detach long-running jobs.** `setsid nohup ... < /dev/null &`, with the logic in a script
   file so `pkill -f` patterns cannot match your own command line.
9. **Suspect the diagnostic first when it returns nothing.** Empty output on a damaged system is
   usually a broken check, not a clean result.
10. **Snapshots are not backups.** Verify a restore path off the unit before touching storage.
