rusticlone AlphaJack
Install rusticlone with WinGet
winget install --id=AlphaJack.Rusticlone -e Scheduled 3-2-1-1-0 backups for computers and servers built on rustic profiles, with UI and notifications
winget install --id=AlphaJack.Rusticlone -e Scheduled 3-2-1-1-0 backups for computers and servers built on rustic profiles, with UI and notifications
Rusticlone backs up your computers and servers on a schedule, keeps copies in more than one place and warns you when something needs your attention.
One-line installer for Windows PowerShell:
irm https://github.com/AlphaJack/rusticlone/releases/latest/download/rusticlone-installer.ps1 | iex; & "$HOME\.cargo\bin\rusticlone.exe" install --auto-update
One-line installer for Linux and macOS:
curl -LsSf https://github.com/AlphaJack/rusticlone/releases/latest/download/rusticlone-installer.sh | sh && $HOME/.cargo/bin/rusticlone install --auto-update
Homebrew:
brew install AlphaJack/tap/rusticlone
Arch Linux (AUR):
yay -S rusticlone-bin
WinGet:
winget install AlphaJack.Rusticlone
Scoop:
scoop bucket add alphajack https://github.com/AlphaJack/scoop-bucket
scoop install alphajack/rusticlone
Chocolatey:
choco install rusticlone
Cargo:
cargo binstall rusticlone
Manual installation: GitHub release binaries
Docker and Podman: see Container image
NixOS and Home Manager: see Nix
Run rusticlone serve --open to create your first rustic profiles from the web UI.
Rusticlone will offer to download rustic from GitHub if it's not already installed on your system.
Profiles are simple .toml files that contain the information about what folders you back up, where you back them up, and with which password.
Keep a copy of them away from the computer (e.g. password manager, cloud drive, private git repo), as you'll need them to restore your files in case of a disaster.
If you already use rustic, just add these environment variables to your profiles and launch the server with the same command:
[global.env]
# when to take snapshots, copy them to other repositories, and mark old ones for deletion
RUSTICLONE_BACKUP_CRON="@daily"
# when to check data consistency and how much
RUSTICLONE_CHECK_CRON="@weekly"
RUSTICLONE_CHECK_SUBSETS="10"
# when to remove old snapshots
RUSTICLONE_PRUNE_CRON="@monthly"
# where to notify about issues (Apprise format, space separated)
RUSTICLONE_NOTIFY_URLS="dbus:// ntfy://ntfy.sh/mybackups"
For scheduled backups, you need to start Rusticlone on boot or user login. You can do so by running rusticlone install as a admin or regular user.
This will also make the app visible in the start menu or app library, and add a tray icon when it's running as regular user.
It will also create a configuration file based on your system:
| OS | regular user | root / SYSTEM |
|---|---|---|
| Linux | $HOME/.config/rusticlone/rusticlone.env | /etc/rusticlone/rusticlone.env |
| macOS | $HOME/Library/Application Support/rusticlone/rusticlone.env | /etc/rusticlone/rusticlone.env |
| Windows | %APPDATA%\rusticlone\config\rusticlone.env | %PROGRAMDATA%\rusticlone\config\rusticlone.env |
rusticlone --help lists all commands and possible options.
Under the hood, rusticlone launches rustic subcommands directly. From the web app, you can see which rustic command and arguments were used for each operation.
Each step that rusticlone performs needs one or more resources: CPU, disk, upload or download bandwidth, or exclusive repository access.
The internal scheduler ensures that each resource is used by one step at a time and released as soon as a step finishes.
Rusticlone can be configured through environment variables (reference list). They are read at start: restart Rusticlone after editing its configuration file.
Settings for individual collections or repositories are variables in the [global.env] section of rustic profiles.
They can be shared across profiles by using the [global] use-profiles feature.
Rusticlone looks for profiles in the same folders as rustic:
| OS | regular user | root / SYSTEM |
|---|---|---|
| Linux | $HOME/.config/rustic | /root/.config/rustic``/etc/rustic |
| macOS | $HOME/Library/Application Support/rustic | /var/root/Library/Application Support/rustic``/etc/rustic |
| Windows | %APPDATA%\rustic\config | %WINDIR%\System32\config\systemprofile\AppData\Roaming\rustic\config``%PROGRAMDATA%\rustic\config |
Profiles in the working directory are also considered, so it's easy to run one-off commands without moving files.
Rusticlone groups rustic profiles in collections.
A collection is made of a backup profile (the one with [[backup.snapshots]]) plus all the profiles it lists in [copy] targets.
The repository of the backup profile (often located in a separate disk or LAN mount) is considered the primary: snapshots go there first, then they are copied to each target repository. This means that your source files are only read once, and that each repository contains a copy of them. Each repository is independent of the others and can autonomously restore your files to their original location.
As an example, these two profiles make the collection Documents:
Documents-hdd.toml
# files to back up
[[backup.snapshots]]
sources = ["/home/jack/Documents"]
# primary backup destination
[repository]
repository = "/mnt/hdd/backups/Documents"
password = "XXXXXX"
# secondary backup destination(s)
[copy]
targets = ["Documents-b2"]
# snapshots retention policy
[forget]
keep-last = 10
keep-daily = 7
keep-monthly = 12
# schedules and notifications
[global.env]
RUSTICLONE_BACKUP_CRON="@daily"
RUSTICLONE_CHECK_CRON="@weekly"
RUSTICLONE_CHECK_SUBSETS="4"
RUSTICLONE_PRUNE_CRON="@monthly"
RUSTICLONE_NOTIFY_URLS="ntfy://my-secret-backup-topic"
Documents-b2.toml
# secondary backup destination
[repository]
repository = "opendal:b2"
password = "XXXXXX"
[repository.options]
bucket = "my-backups"
bucket_id = "XXXXXX"
application_key_id = "XXXXXX"
application_key = "XXXXXX"
root = "/Documents"
# limited check operations to reduce download costs
[global.env]
RUSTICLONE_CHECK_CRON="@weekly"
RUSTICLONE_CHECK_SUBSETS="50"
rusticlone backup --collection Documents snapshots the sources to the primary repository, copies the new snapshot to Documents-b2, then marks old snapshots for deletion in each repository according to its [forget] policy.
For safety, the primary forgets only after every target has received the copy.
For extra safety, one of your copy targets can be, like Documents-b2, a repository on an air-gapped device (unmounted HDD) or an immutable endpoint (blob storage with Object Lock, or an append-only REST server).
This will give you the second 1 in the 3-2-1-1-0 backup strategy.
On Windows, Microsoft Defender scans every file that rustic reads and writes. In our tests, this made backups 1.5 times slower and restores almost 3 times slower. To avoid this, run this once in a PowerShell opened as administrator:
Add-MpPreference -ExclusionProcess rustic.exe
A snapshot is not a full copy of your files, but a record of what has changed since the last backup:
That's why only the first snapshot is large, and backups are much faster from the second one onwards.
rusticlone check --collection Documents runs a data consistency check on each repository of the collection.
By default, 1/10th of each repo is checked every time and Rusticlone remembers which subset is due next, so with 10 runs it covers the entire repo.
If a subset is failing, it will not advance to the next subset, and will notify you of the issue.
The RUSTICLONE_CHECK_SUBSETS variable also accepts 0 for fast metadata-only checks, and values like "10MiB" or "10%" for random subsets.
Repositories in the same collection can have separate check schedules.
rusticlone prune --collection Documents deletes files of snapshots marked for deletion.
As this can be a slow operation, its schedule is independent of the backup and check ones. Like checks, repositories in the same collection can have separate prune schedules.
A repository without keep-* options in [forget] won't be pruned by Rusticlone (ideal for Object Lock or append-only repositories).
rusticlone due --collection Documents runs whatever is past due for the collection according to its repo schedules.
This means you can run overdue backups, checks and prunes without spinning up the server or running each command individually.
Notifications are only sent when a collection's status changes (like Uptime Kuma up/down), not at every run.
If you'd rather receive a notification at every backup operation, you can use rustic hooks in your profiles.
The RUSTICLONE_NOTIFY_URLS variable accepts space-delimited Apprise URLs.
rusticlone notify --all sends the current status, so you can use it to test URLs.
Don't panic! On a reinstalled computer:
rusticlone restore --all. Rusticlone offers to download rustic if it's missing. If you don't feel sure yet, append --dry-run to see what would happen, or restore one --collection at a time
This will restore each collection from the latest snapshot of available repositories, giving preference to the primary. Rusticlone then offers to copy the profiles where it usually looks for them, so the backup server can use them too.
For more granular control over file restore you can use flags:
# check how many files would be created or replaced in a real restore
rusticlone restore --collection Documents --dry-run
# extract one folder of a snapshot to /tmp/restored/Taxes
rusticlone restore --collection Documents --snapshot 1a2b3c4d --snapshot-path /home/jack/Documents/Taxes --to /tmp/restored
# restore documents as they were on the 1st of October, from the repository with the most recent snapshots before that date
rusticlone restore --collection Documents --at-time 2026-10-01
More flags are available with rusticlone restore --help
The web UI offers the same options:
After a disaster recovery, re-create the primary backup repository from an existing copy repository, never with a backup operation.
If the primary repository is lost too, a plain rusticlone restore --all or rusticlone restore --collection NAME does this for you: it re-creates the primary from an available copy target (e.g. Documents-b2), then extracts the files to their original location, so you only download once.
The reason is the chunker: a fresh repository created by a backup gets a random chunker polynomial, incompatible with the existing copy targets. Snapshots would succeed, but copies to the targets would fail with a chunker polynomial mismatch. At the moment a rustic profile cannot set the chunker polynomial.
To re-create a compatible primary repository from an existing copy target (or vice-versa) by hand, run:
rusticlone recreate --repo Documents-hdd
rusticlone serve shows the status of your collections, live progress and logs.
From there you can start and stop runs, browse and download snapshots, compare them, and restore files or folders.
If RUSTICLONE_LISTEN is not set, the server will listen on localhost on port 32110.
If RUSTICLONE_ADMIN_TOKEN is not set, the server generates a random token in the state folder (see location below).
To access the web UI, open the desktop app, use the tray icon or run rusticlone serve --open.
This way, the token will be automatically passed to the login page and you won't need to enter it manually.
If you want to expose Rusticlone behind a reverse proxy, you have two options:
See packaging/nginx.conf for an example nginx configuration.
Without a public IP address or open ports on your router you can use a VPN like Tailscale or a reverse tunneling service like Cloudflare Tunnel:
cloudflared tunnel run --url http://localhost:32110 my-backups
Most endpoints are meant to be used internally by the built-in htmx-based UI, and require an admin token.
Some can be accessed via a separate RUSTICLONE_METRICS_TOKEN:
/metrics exposes Prometheus metrics/status exposes the same output as rusticlone collections --json/health can be used for the container health check, and doesn't need a token at allRusticlone doesn't have a mobile app, but it can back up their files once they reach a computer or server:
Then back up the folder where they land, creating a new profile:
Mobile-hdd.toml
[[backup.snapshots]]
sources = ["/home/jack/Sync/Mobile"]
[repository]
repository = "/mnt/hdd/backups/Mobile"
password = "XXXXXX"
[global.env]
RUSTICLONE_BACKUP_CRON="@daily"
To check on your backups from your smartphone on the same network:
RUSTICLONE_LISTEN=0.0.0.0:32110 in the configuration file, then restart Rusticlonehttp://:32110 on the phone and log in with the admin token (see Web UI)To see backups from another network, see remote server for a reverse proxy or Cloudflare Tunnel setup.
Rusticlone state is meant to be disposable, as the source of truth for your backups remains your repositories. CLI and server both write to the same shared folder, by default:
| OS | regular user | root / SYSTEM |
|---|---|---|
| Linux | $HOME/.local/state/rusticlone | /var/lib/rusticlone |
| macOS | $HOME/Library/Application Support/rusticlone | /Library/Application Support/rusticlone |
| Windows | %LOCALAPPDATA%\rusticlone | %PROGRAMDATA%\rusticlone\state |
There you can find rustic logs, process locks and a redb database with historical run details and repository statistics.
Commands, the server and its schedule can run at the same time: each run waits for the disk, network link or CPU that another holds.
To use the container image, mount your rustic profiles, Rusticlone's state, the files you want to back up and their backup destination.
Set TZ to your time zone, so that schedules such as @daily follow your clock rather than UTC.
For the Documents collection above:
mkdir -p rustic/{profiles,state}
docker run \
-e RUSTICLONE_ADMIN_TOKEN=XXXXXX \
-e TZ=Europe/Berlin \
-p 32110:32110 \
-v $PWD/rustic/profiles:/etc/rustic \
-v $PWD/rustic/state:/var/lib/rusticlone \
-v /home/jack/Documents:/home/jack/Documents \
-v /mnt/hdd/backups:/mnt/hdd/backups \
ghcr.io/alphajack/rusticlone:latest
You can then access the web UI from port 32110.
The flake's modules take your rustic profiles as Nix, keep them read-only, and start the server with rustic and rclone:
# flake.nix
inputs.rusticlone.url = "github:AlphaJack/rusticlone";
The NixOS module writes the profiles to /etc/rustic and runs the server as root.
On macOS, nix-darwin's inputs.rusticlone.darwinModules.default does the same.
imports = [ inputs.rusticlone.nixosModules.default ];
# profile 1: secret passed via file
programs.rustic.profiles.Documents-hdd = {
backup.snapshots = [ { sources = [ "/home/jack/Documents" ]; } ];
repository = {
repository = "/mnt/hdd/backups/Documents";
password-file = config.sops.secrets.documents.path;
};
copy.targets = [ "Documents-b2" ];
forget = { keep-last = 10; keep-daily = 7; keep-monthly = 12; };
global.env = {
RUSTICLONE_BACKUP_CRON = "@daily";
RUSTICLONE_CHECK_CRON = "@weekly";
RUSTICLONE_CHECK_SUBSETS = "4";
RUSTICLONE_PRUNE_CRON = "@monthly";
};
};
# profile 2: secrets in toml
programs.rustic.profileFiles.Documents-b2 = config.sops.templates."Documents-b2.toml".path;
services.rusticlone = {
enable = true;
# RUSTICLONE_ADMIN_TOKEN and RUSTICLONE_METRICS_TOKEN
environmentFile = config.sops.secrets.rusticlone.path;
};
To restore, run sudo rusticlone restore with the flags you need or use the web UI.
After a disaster, reistall NixOS and run sudo rusticlone restore --all to bring back the files.
The Home Manager module writes the profiles to the unprivileged folder and runs the server as your user at login with its tray icon.
It takes the same programs.rustic and services.rusticlone options:
imports = [ inputs.rusticlone.homeModules.default ];
Restore with rusticlone restore without sudo.
macOS grants Full Disk Access to an executable by its path, so you need to grant it again to the new rusticlone afterwards.