All apps · 0 apps
Unraid Rsync
Plugin from sasa-fajkovic
Overview
Readme
View on GitHubUnraid Rsync
A native Unraid webGui plugin for scheduling and monitoring rsync backup
jobs — over SSH to/from a remote host, straight to an rsync daemon
(rsyncd, the "Rsync Server" a NAS exposes), or locally between two paths on
the server — a multi-job scheduler rather than the usual single-schedule rsync
plugins.
Validate with dry-runs first. rsync moves (and can delete) real data, so exercise a new job with a Dry-run and inspect the per-run log before you trust it for unattended backups. That is ordinary rsync hygiene, not a disclaimer of missing features — everything described below ships today.
What it does
Run multiple independent rsync jobs, each with:
- a transport: SSH (push to or pull from a remote host), rsync
daemon (an
rsyncdmodule on a NAS or another server), or Local (both sides are paths on this server, confined under/mnt); - its own cron schedule (per-job, not one global schedule), with a live Next run column;
- a curated, whitelisted set of rsync flags exposed as checkboxes and value
inputs (no free-form flag string — destructive flags are gated with
guardrails), each with native inline help (
?-on-hover → blue box); - explicit source -> destination pairs (one rsync per pair, not a cartesian product);
- pre/post hooks and a per-job log level;
- live state badges, a per-run log viewer, and last-run reporting;
- optional notifications through Unraid's native notification system.
Transports
A job picks one of three transports.
- SSH — rsync tunnelled over an
sshcommand line. The job references a connection from the reusable Connections tab (shown by name in the UI), which supplies the host, port, remote user and one of three auth methods: existing key file, managed key, or password. A pair's right-hand box is an absolute filesystem path on the remote host. - rsync daemon (
rsyncd) — rsync's own wire protocol, spoken directly to a TCP port (873 unless the daemon was configured otherwise). This is the "Rsync Server" that Synology, QNAP, TrueNAS and friends expose. The job references a connection whose Transport is rsync daemon (rsyncd); the username and secret on it are that daemon's module credentials (itsauth users/ secrets-file entry), not an SSH account. A module with noauth usersis anonymous — leave the secret blank. A pair's right-hand box is a module reference: relative, no host, no leading slash —rsync_bkp, orrsync_bkp/photosfor a folder inside the module. The plugin builds the operanduser@host::moduleand always passes an explicit--port. - Local — both sides are paths on this server, confined under
/mnt. No connection and no credentials.
The rsync daemon protocol is not encrypted. Only a challenge/response (the digest is negotiated — MD4 with an old peer) protects the module secret, and file names and file contents travel in clear over the network. Use it only on a network you trust — SSH remains the recommended transport everywhere else.
Test connection on a daemon connection lists the daemon's public modules. A module listing is answered before authentication, so a green result proves the daemon is reachable and nothing more — it does not verify the module user or the secret. Use a Dry-run to test those.
The connect timeout rsync option (--contimeout) applies to this transport
only: rsync refuses it outright on SSH and Local transfers, so the plugin does
not send it there and warns when one is set.
Managed keys live in their own Credentials keychain tab.
What ships today
- An installable
.plgpackaged in the standard Unraid way (a Slackware.txzbuilt bypkg_build.sh, released via GitHub Actions; CalVer auto-releases on every merge tomain). - A tabbed Unraid Rsync page under Settings → User Utilities with Jobs, Connections, Credentials, Global Settings, Status and History tabs.
- Jobs CRUD + Global Settings (config persisted to
config.json). - A Connections tab (see Credentials) in two flavours: SSH connections with three auth methods — existing key file (default), a managed key (from the Credentials tab), and password (no extra packages needed) — plus Discover host key and selectable strict-host-key modes; and rsync daemon connections with a port, a module user and an optional module secret. Both have a per-connection Test connection probe (an SSH login probe, or a module listing for a daemon — note a listing is answered before authentication, so it does not verify the secret).
- A Credentials tab: a managed SSH key keychain you can generate or import, referenced by connections that use managed-key auth.
- A safe rsync execution engine (whitelisted flags built as an argv array, path guardrails) with manual Run / Dry-run / Abort per job, and native inline help on every rsync flag and option.
- Per-job cron scheduling: each enabled job runs on its own 5-field cron schedule, plus a Next run column on the Jobs list.
- Live status badges in clear status colors — success (green), warning (orange), failed (red), aborted (grey), pending (grey), running (blue, pulsing).
- A per-run log viewer: pick any past run from a selector and watch the log tail update live (1-second poll while a run is in progress).
- A Status tab showing the rolling cross-job plugin log and an
rsync-binary presence indicator (detected path + the first line of
rsync --version, or a clear warning if rsync is somehow absent). - Notifications through Unraid's native
notify, with a per-job notify mode —off,success-only,failure-only, oralways— mapped to the correct webGui importance (success → normal, warning/partial/ timeout → warning, failure → alert).notify initis run on install so notifications work out of the box. - Clean uninstall (removes both the runtime
emhttptree and the persistent/bootconfig dir, and clears the plugin's cron lines from the live crontab).
Scheduling (how it works)
Each enabled job contributes one line to a single cron file that the plugin
regenerates from config.json on every relevant change:
/boot/config/plugins/unraid.rsync/unraid.rsync.cron
The file lives directly in the plugin's flash config dir (not a cron/
subdirectory) because Unraid's /usr/local/sbin/update_cron concatenates each
plugin's cron files with a non-recursive, top-level *.cron glob — a
subdirectory would never be scanned. A single regenerated file (rather than
one file per job) means deleting or disabling a job can never leave an orphaned
schedule behind. Each line invokes the runner directly:
<schedule> php /usr/local/emhttp/plugins/unraid.rsync/scripts/runner.php --job=<id> >/dev/null 2>&1
After rewriting the file (atomically: temp + rename) the plugin runs
update_cron via its absolute path to rebuild the live crontab. Schedules are
re-applied automatically:
- on every config change that affects a job's schedule or enabled state;
- on plugin install/upgrade (the
.plgrunsscripts/apply-cron.php), so a configured schedule is live immediately without waiting for a reboot; - on array start (the
event/startedhook re-applies), which works around a known Unraid 7.x bug where the boot-timeupdate_cronmay not run.
Credentials
SSH and rsync daemon jobs reference a connection by name, so an endpoint's details are defined once and shared. (Local transport jobs use no connection or credentials.) Two tabs cover this:
- Connections — an endpoint plus its Transport. An SSH connection is
host, port and remote user plus an auth method, a Discover host key
action and a selectable strict host-key checking mode (
accept-new— the default —,yes, orno). An rsync daemon connection is host, port (873), the module user and an optional module secret; the SSH-only controls are hidden on it. Both have a per-connection Test connection probe. - Credentials — a managed SSH key keychain you can generate or import, referenced by connections that use managed-key auth.
An SSH connection picks one of three auth methods:
- Existing key file (the default) — point the connection at a key already on
the server, e.g.
/root/.ssh/id_ed25519. Nothing is uploaded or copied into the plugin's store; it uses the file in place. - Managed key — use a key from the plugin's Keys keychain (generated or imported through the UI).
- Password — authenticate with a stored password (see below). Works on a stock Unraid box; nothing to install.
An rsync daemon connection has no auth method. It either sends a module
secret — the daemon's secrets-file entry for its auth users name — or, for a
module with no auth users, nothing at all.
Credential security (read this)
Credentials are stored in /boot/config/plugins/unraid.rsync/credentials.json
on the USB flash, which is FAT32 and world-readable — Unix file permissions
do not apply there. Consequences:
- Existing-key-file auth keeps the private key entirely outside the plugin's store — only the path is recorded — so it never lands on the world-readable flash. This is the default and recommended method.
- Managed private keys are copied to RAM (
tmpfs) at mode600only at run time (OpenSSH refuses a world-readable key), and are never shown again in the UI after they are saved — only the fingerprint and public key are displayed. - Passwords are stored obfuscated (reversible), not encrypted. Anyone with access to the flash drive can recover them. Prefer key authentication and, when password auth is unavoidable, use a dedicated low-privilege remote account.
- rsync daemon module secrets are the fourth case, and they are stored
exactly like passwords: obfuscated (reversible), not encrypted, on the same
world-readable flash. At run time the secret is written to a RAM file at mode
600and handed to rsync as--password-file(rsync refuses a password file any other user can read), so the secret itself never reaches a command line or an environment variable — only that file's path does. Use a dedicated, least-privileged module user, and remember the daemon protocol is unencrypted on the wire as well. - Host key pinning: on
accept-new, the first successful connection pins the host key it saw to the connection; a later, changed key then fails closed instead of being silently re-accepted. Run Discover host key ahead of time to pin it explicitly rather than trusting whatever the first scheduled run sees.
Storing credentials on the array instead of the flash
By default credentials.json lives on /boot for the reasons above. If you want
real at-rest protection, set a Secrets directory on the Global Settings
tab to an absolute path under /mnt (an array share or pool — ideally one that
is encrypted and not exported over SMB/NFS), e.g.
/mnt/user/system/unraid.rsync. The plugin then stores credentials.json there
with real chmod 600 permissions (ext4/xfs/btrfs/zfs honour Unix perms; FAT32
does not). Changing the setting moves the existing file to the new location.
This does not remove the run-time copy-to-tmpfs step — ssh -i still needs
a discrete key file extracted from the JSON at mode 600, and the materialised
copy isolates concurrent runs and is path-redacted from logs. It changes the
at-rest threat surface (root-only array file vs. world-readable flash).
Caveats: the array must be started before any job can read its credentials;
the standard USB flash backup will no longer include them; and uninstalling
the plugin does not delete credentials stored under /mnt — remove them
manually. Leave the field empty to keep the backward-compatible /boot
behaviour.
Password auth needs nothing installed. It uses OpenSSH's own
SSH_ASKPASS mechanism: ssh runs the plugin's scripts/askpass.sh, which reads
the password from a per-run RAM file created at mode 600 and deleted when the
run ends. The password never appears in a command line, in an environment
variable, or in ps — only the path of that file does.
Earlier versions shelved this out to
sshpassand told you to install the NerdTools plugin. NerdTools was archived by its authors in March 2024 and is unavailable on Unraid 7, which left password auth impossible to use on a stock box. That dependency is gone.
Key auth is still the recommended method.
- Pre/post hooks run as
root(viabash -c) before/after the transfer, and their stdout/stderr is captured into the per-run log, which is rendered in the browser. Do not echo secrets in a hook — they would land in a root-written, browser-visible log.
rsync binary
rsync ships in Unraid's base OS at /usr/bin/rsync, so it is always
present on a healthy system. The plugin therefore does not install rsync —
there is no clean Slackware artifact to pin, and a bundled copy would shadow the
base binary. Instead it performs a defensive presence check: before a job
runs, it verifies the binary is executable, and the Status tab shows the
detected rsync path plus the first line of rsync --version (or a clear warning
if it is somehow absent — a sign your system is misconfigured).
Install
Requires Unraid 7.0.0 or newer.
In the Unraid webGui go to Plugins -> Install Plugin.
Paste the
.plgURL:https://github.com/sasa-fajkovic/unraid-rsync/releases/latest/download/unraid.rsync.plgThis is the latest release's manifest. It always carries the correct version + md5 for the newest published
.txz, and it is also the URL the installed plugin checks for updates.Click Install. When it finishes, open Settings → User Utilities → Unraid Rsync.
To remove it: Plugins -> Installed Plugins -> Unraid Rsync -> Remove.
Support
- Bugs / feature requests: open an issue at https://github.com/sasa-fajkovic/unraid-rsync/issues.
- Unraid forum thread: https://forums.unraid.net/topic/199541-plugin-unraid-rsync-multi-job-rsync-backup-scheduler/
(the Community Applications support thread; this is also the
support=URL CA links to).
Updating
Updates are automatic: Plugins -> Check for Updates compares your installed
version against the manifest at the releases/latest URL above and offers an
Update when a newer release has been published. Releases use CalVer
(YYYY.MM.DD, with a same-day lowercase suffix) and are published
automatically on every merge to main, so the update check always sees the
newest build.
Migration (one-time): if you installed an older build whose update URL pointed at the raw
.plgonmain, re-install once from thereleases/latestURL above to switch to the new auto-update source. After that single re-install, updates are picked up automatically as before.
Roadmap
The plugin is feature-complete. The full build landed across these areas, all of which now ship:
- ✅ Skeleton + packaging + CI (installable
.plg, build script, release workflow, tabbed Settings page). - ✅ Config core + Jobs CRUD + Global Settings.
- ✅ Credentials keychain (SSH connections + managed keys) + secure storage.
- ✅ Rsync execution engine (safe argv, path guardrails) + inline help.
- ✅ Per-job cron scheduling + next-run display.
- ✅ Status/state UI + per-run log viewer + last-run reporting.
- ✅ Notifications via Unraid's native
notify.
Genuinely still ahead:
- Community Applications submission — the repo is kept CA-ready (stable
releases/latest.plgURL, valid plugin attributes, versioned.txzassets); listing it in the CA feed is a later, mechanical step.
Building / releasing
See RELEASING.md for the full pipeline. In short:
CI runs on every PR (and is required by branch protection on
main):lint—xmllinton the.plg,bash -n+shellcheckonpkg_build.sh, andphp -lon every PHP file and.pagebody;PHPUnit— the unit-test suite.
A PR cannot merge until both checks are green.
Releasing is automatic. Merging to
mainbuilds the.txzinsideaclemons/slackware:15.0viapkg_build.sh(which rewrites the.plg's version + md5 to match the package), then publishes a versioned GitHub Release with both the.txzand the regenerated.plgattached and marks itlatest. The version is auto-computed (YYYY.MM.DD, with a same-day lowercase suffix for additional releases on the same day).Updates are served from
releases/latest: the installed plugin'spluginURLpoints athttps://github.com/sasa-fajkovic/unraid-rsync/releases/latest/download/unraid.rsync.plg, so Plugins -> Check for Updates -> Update always sees the newest release. The repo's.plgis the source template and is not synced back on release — the GitHub Release asset is the authoritative manifest.
License
See LICENSE.
Install Unraid Rsync on Unraid in a few clicks.
Find Unraid Rsync in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Categories
Download Statistics
Downloads by Month
Related apps
Explore more like this
Explore allDetails
https://github.com/sasa-fajkovic/unraid-rsync/releases/latest/download/unraid.rsync.plg