Skill: pfrederiksen/synology-backup (version 2.0.3)

--- name: synology-backup description: "Backup and restore OpenClaw workspace, configs, and agent data to a Synology NAS via SMB or SSH/rsync. Use when: backing up workspace files, restoring from a snapshot, checking backup status/health, verifying backup integrity, or setting up automated daily backups. Supports Tailscale for secure remote VPS-to-NAS connectivity. Designed for explicit OpenClaw cron/session notifications instead of hidden shell-side delivery." metadata: openclaw: requires: bins: - rsync - jq apt: - rsync - jq - cifs-utils notes: "SSH transport requires SSH key auth to Synology. SMB transport requires cifs-utils and a chmod 600 credentials file. Cron/session layer should own notifications explicitly." --- # Synology Backup Backup OpenClaw data to a Synology NAS over SMB or SSH/rsync. Designed for secure, automated daily snapshots with configurable retention, integrity verification, and failure alerting. ## Setup ### 1. Network Connectivity For VPS-to-NAS backups, use [Tailscale](https://tailscale.com) for secure connectivity without exposing SMB to the internet: 1. Install Tailscale on the Synology (Package Center → search "Tailscale") 2. Install Tailscale on the VPS — see [Tailscale's official install guide](https://tailscale.com/download) for your platform 3. Join both to the same tailnet 4. Use the Synology's Tailscale IP in config For local network setups, use the NAS local IP directly. ### 2. Synology Preparation 1. Create a dedicated user on the Synology (e.g., `openclaw-backup`) with minimal permissions 2. Create or choose a shared folder (e.g., `backups`) 3. Grant the user read/write access to **only** that folder — not admin access ### 3. Credentials File (SMB transport) Create an SMB credentials file with restricted permissions — **never store credentials in config or scripts**: ```bash touch ~/.openclaw/.smb-credentials chmod 600 ~/.openclaw/.smb-credentials # Add two lines: # username=<your-synology-user> # [REDACTED_SECRET] ``` ### 4. Configuration Create `~/.openclaw/synology-backup.json`: ```json { "host": "100.x.x.x", "share": "backups/openclaw", "mountPoint": "/mnt/synology", "credentialsFile": "~/.openclaw/.smb-credentials", "smbVersion": "3.0", "transport": "smb", "notifyOnSuccess": false, "backupPaths": [ "~/.openclaw/workspace", "~/.openclaw/openclaw.json", "~/.openclaw/cron", "~/.openclaw/agents" ], "backupExclude": [], "includeSubAgentWorkspaces": true, "retention": 7, "preRestoreRetention": 3, "schedule": "0 3 * * *" } ``` **SSH transport (recommended):** Set `"transport": "ssh"` and add `"sshUser": "your-user"`. No credentials file needed — uses SSH key auth. Requires rsync + SSH access to the Synology. > ⚠️ **SSH host key warning:** Scripts use `StrictHostKeyChecking=yes`. Add your NAS host key to `~/.ssh/known_hosts` first by connecting manually once (`ssh user@nas-ip`) before automation. **Sensitive files:** The `.env` file (containing API keys) is **excluded by default**. Only add it to `backupPaths` if your NAS share is restricted to a dedicated low-privilege user and encrypted at rest. When in doubt, leave it out — you can always re-enter API keys from scratch. | Field | Description | Default | |-------|-------------|---------| | `host` | Synology IP (Tailscale or local) | required | | `share` | SMB share path | required | | `mountPoint` | Local mount point | `/mnt/synology` | | `credentialsFile` | Path to SMB credentials file | required (SMB) | | `smbVersion` | SMB protocol version | `3.0` | | `transport` | `smb` or `ssh` | `smb` | | `sshUser` | SSH username | required (SSH) | | `backupPaths` | Paths to backup | workspace + config | | `includeSubAgentWorkspaces` | Auto-include `workspace-*` dirs | `true` | | `retention` | Days of daily snapshots to keep | `7` | | `preRestoreRetention` | Days to keep pre-restore safety snapshots | `3` | | `backupExclude` | rsync exclude patterns (`.git/`, `node_modules/` always excluded) | `[]` | | `notifyOnSuccess` | Write success state and allow higher-level success reporting if desired | `false` | | `schedule` | Cron expression (host timezone) | `0 3 * * *` | | `sshUser` | SSH username (required for ssh transport) | — | | `sshHost` | SSH hostname (defaults to `host`) | — | | `sshPort` | SSH port | `22` | | `sshDest` | Remote backup directory path (required for ssh transport) | — | ### 5. Install Dependencies ```bash apt-get install -y cifs-utils rsync jq ``` `jq` is required — all scripts use it to parse the config JSON. ### 6. Register the Backup Cron ```bash openclaw cron add \ --name "Synology Backup" \ --schedule "0 3 * * *" \ --tz "America/Los_Angeles" \ --message "Run the daily Synology backup: bash ~/.openclaw/workspace/skills/synology-backup/scripts/backup.sh && bash ~/.openclaw/workspace/skills/synology-backup/scripts/verify.sh. If either step fails, use the OpenClaw message tool explicitly to alert the target channel with the failing step and key error text. Then reply NO_REPLY." ``` ## Usage ### Backup Now ```bash scripts/backup.sh ``` Runs an incremental backup. Add `--dry-run` to preview what would be backed up without touching anything. ### Check Status ```bash scripts/status.sh ``` Shows mount health, last backup time, snapshot count, total size, and pre-restore safety snapshots. ### Verify Integrity ```bash scripts/verify.sh # verify latest snapshot scripts/verify.sh 2026-03-25 # verify specific date ``` Checksums key files and counts directory contents against the snapshot to confirm data integrity. ### Restore a Snapshot ```bash scripts/restore.sh # list available snapshots scripts/restore.sh 2026-03-25 # restore from specific date ``` Before restoring, automatically saves a **pre-restore safety snapshot** of your current state. If the restore goes wrong, restore the safety snapshot to undo. ## What Gets Backed Up - `~/.openclaw/workspace/` — memory, SOUL, AGENTS, skills, all workspace files - `~/.openclaw/workspace-*/` — all sub-agent workspaces (if enabled) - `~/.openclaw/openclaw.json` — main config - `~/.openclaw/cron/` — cron job definitions - `~/.openclaw/agents/` — agent configurations - `~/.openclaw/.env` — **opt-in only** (contains API keys) ## Snapshot Structure ``` backups/ ├── 2026-03-25/ │ ├── manifest.json # timestamp, host, path counts │ ├── workspace/ │ ├── workspace-news/ │ ├── agents/ │ ├── cron/ │ └── openclaw.json ├── pre-restore-2026-03-25-143022/ # safety snapshot before restore ├── 2026-03-24/ └── ... ``` ## Failure Alerting If a backup fails, the recommended pattern is for the **OpenClaw cron/session layer** to send the alert explicitly via the `message` tool. Recommended alert contents: - which step failed (`backup.sh` or `verify.sh`) - key error text - hostname and snapshot date when available ## Before You Enable Automated Cron Run with `--dry-run` first and review the output: ```bash scripts/backup.sh --dry-run ``` Then make sure your cron prompt owns notification behavior explicitly instead of relying on shell-side delivery. ## Security Notes - **Credentials**: Always use a dedicated SMB credentials file with `chmod 600`. Never inline secrets in config, scripts, or fstab. - **jq required**: Install with `apt-get install -y jq`. All scripts depend on it for config parsing. - **Notifications**: Keep notification ownership in the OpenClaw cron/session layer. Avoid hidden shell-side delivery paths. - **SSH host keys**: Pre-provision `~/.ssh/known_hosts` and keep `StrictHostKeyChecking=yes` in `lib.sh` for hardened setups. - **Network**: Use Tailscale or a VPN for remote backups. Never expose SMB (port 445) to the public internet. - **Sensitive data**: `.env` excluded by default — only include if NAS access is tightly restricted. - **NAS user**: Dedicated user with access to only the backup share — not an admin account. - **Input validation**: All config values validated before use — no shell injection via host, share, mount, or path fields. - **Path allowlist**: Restore uses an explicit allowlist (`workspace`, `cron`, `agents`, `openclaw.json`, `.env`) — no arbitrary path writes. ## System Access **Files read:** `~/.openclaw/synology-backup.json`, `~/.openclaw/.smb-credentials` **Files written:** Synology NAS share (via SMB mount or SSH/rsync), `manifest.json` in each snapshot **Network:** SMB (port 445) or SSH (port 22) to Synology NAS IP only **Commands used:** `mount`, `rsync`, `cp`, `find`, `du`, `df`, `md5sum`, `jq` (required) **Secrets stored:** None — SMB credentials live in a separate `chmod 600` file


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)