# Setillo

Synology DS223j NAS running DSM 7.3.2. Secondary Synology used for monitoring exporters and AdGuard secondary DNS.

## Specs

| | |
|---|---|
| Model | DS223j |
| Platform | rtd1619b (aarch64) |
| DSM | 7.3.2 (build 86009) |
| Storage | `/volume1` — 8.8 TB btrfs |
| Tailscale | 1.96.4 (as of 2026-04-11) |

## Running services

Containers under DSM Container Manager:

| Name | Image | Purpose |
|---|---|---|
| `node_exporter` | `quay.io/prometheus/node-exporter` | Prometheus host metrics |
| `snmp_exporter` | `quay.io/prometheus/snmp-exporter` | SNMP metrics for network gear |
| `adguard` | `adguard/adguardhome` | Secondary AdGuard DNS resolver |
| `dozzle-agent` | `amir20/dozzle` | Remote log agent for the main Dozzle instance |

## Sudoers restriction (important)

The `vish` user has passwordless sudo but **cannot invoke shells via sudo**:

```
(ALL) NOPASSWD: "REDACTED_PASSWORD" !/bin/ash, !/bin/sh, !/bin/bash, !/usr/bin/su
```

Practical implications:

- ✅ Works: `sudo mkdir`, `sudo mount`, `sudo wget`, `sudo /opt/bin/opkg install foo`, `sudo tee /etc/file`, `sudo systemctl enable foo`
- ❌ Blocked: `sudo sh script.sh`, `sudo bash -c '...'`, `sudo -i`, `sudo ./script.sh` (even with a `#!/bin/sh` shebang — the kernel exec of `#!/bin/sh script.sh` is blocked)

To run shell scripts as root, translate them into a series of individual `sudo` invocations of non-shell binaries. Use `sudo tee file <<EOF` heredocs to write files (tee is not a shell, so it's allowed).

## Entware (opkg package manager)

Installed 2026-04-11 to work around DSM's minimal busybox toolset.

### Layout

| | |
|---|---|
| Distro | `aarch64-k3.10`, GLIBC 2.27 |
| Home | `/volume1/@entware` |
| Mount point | `/opt` (bind mount) |
| Persistence | `/etc/systemd/system/opt.mount` (enabled, `After=syno-volume.target`, `WantedBy=local-fs.target`) |
| Installed size | ~260 MB (153 packages) |

### Persistence unit

`/etc/systemd/system/opt.mount`:

```ini
[Unit]
Description=Entware bind mount for /opt
DefaultDependencies=no
After=syno-volume.target
Requires=syno-volume.target
Before=local-fs.target
Conflicts=umount.target

[Mount]
What=/volume1/@entware
Where=/opt
Type=none
Options=bind

[Install]
WantedBy=local-fs.target
```

### PATH setup

`/opt` uses three binary directories. `~/.profile` sets:

```sh
export PATH=/opt/bin:/opt/sbin:/opt/usr/bin:$PATH
```

Some binaries live at `/opt/bin`, some at `/opt/sbin` (e.g. `iotop`, `fzf`), some at `/opt/usr/bin` (e.g. `fd`, `eza`). Keep all three in PATH.

### /opt/containerd preservation

DSM pre-creates empty stub dirs `/opt/containerd/{bin,lib}` (cosmetic — real containerd lives at `/var/packages/REDACTED_APP_PASSWORD/`). The Entware install recreated these stubs inside the bind-mounted tree so Synology's view of `/opt/containerd` is preserved whether `/opt` is bind-mounted or not. If you ever rebuild Entware, recreate them:

```sh
sudo mkdir -p /opt/containerd/bin /opt/containerd/lib
sudo chmod 711 /opt/containerd
```

### Installing packages

Entware's `opkg` is not in the default sudo PATH (and sudoers blocks shells, so you can't `sudo bash -c`). Always invoke opkg by full path:

```sh
sudo /opt/bin/opkg update
sudo /opt/bin/opkg install <pkg>
```

For Python packages not in the Entware repo, use `/opt/bin/pip3`:

```sh
sudo /opt/bin/pip3 install --break-system-packages <pkg>
```

### Currently installed (high-value tools)

| Category | Packages |
|---|---|
| Shell | `bash`, `tmux`, `screen`, `htop`, `vim-full`, `nano`, `less`, `fzf` |
| Network | `iperf3`, `mtr-json`, `bind-dig`, `tcpdump`, `nmap`, `socat`, `curl`, `wget-ssl`, `nethogs`, `iftop`, `whois`, `mosh-full`, `openssh-client`, `openssh-sftp-server` |
| Filesystem | `rsync`, `rclone`, `ncdu`, `pv`, `file`, `tree`, `lsof`, `jq`, `yq` (pip) |
| Observability | `sysstat`, `dstat`, `strace`, `procps-ng`, `python3-iotop`, `glances` (pip), `fail2ban` |
| Dev | `git`, `python3`, `python3-pip`, `node`, `gnupg2` |
| Modern unix | `ripgrep`, `fd`, `eza`, `zoxide` |

### Not available in the Entware aarch64-k3.10 repo

- `bat` — install via `cargo install bat` if needed
- `duf` — use `df` / `ncdu` instead
- `bash-completion` — individual tools (git, fzf) provide their own
- `yq`, `glances` — installed via `pip3` instead

### Uninstall (full reversal)

```sh
sudo systemctl disable --now opt.mount
sudo rm /etc/systemd/system/opt.mount
sudo systemctl daemon-reload
sudo rm -rf /volume1/@entware
```

### DSM upgrade caveat

DSM major version bumps (e.g. 7.3 → 8) can clobber `/etc/systemd/system/`. After any DSM upgrade, re-check:

```sh
systemctl is-enabled opt.mount
```

If missing, recreate the unit file (content above), then `sudo systemctl daemon-reload && sudo systemctl enable --now opt.mount`. The Entware tree itself survives on `/volume1/@entware` — only the mount unit needs recreating.

## Tailscale upgrades

Tailscale's Synology package ships a built-in self-updater. Don't hunt for SPK URLs — just:

```sh
sudo tailscale update --yes
```

It downloads the right `.spk` from `pkgs.tailscale.com` and installs it in place. Confirmed working 2026-04-11 (upgraded 1.92.3 → 1.96.4).
