Desktop app + command line · snapshot backup
A small, fast backup client in Rust with a native GTK desktop app and a scriptable CLI — same engine, same config. Hard-linked snapshots over SSH make every run look like a complete tree, but only what changed takes new space. Restore anything, from any of them.
Moraine 0.2.2 · desktop app + CLI · or build from source with cargo build --release
How it works
Every run creates a new <timestamp>/ folder. Files that haven't changed since last time become hard links — the same data on disk, but visible in every snapshot. A latest symlink always points to the newest one.
The client runs rsync -aAX --delete over SSH into a new <timestamp>/ folder. Permissions, ACLs and xattrs come along.
--link-dest=../latest lets files that haven't changed point at the previous snapshot. New disk is only used for what actually differs.
latest moves to the new snapshot. Auto-prune keeps the N most recent plus daily/weekly/monthly according to your policy.
Features
A shared engine powers both the CLI and the desktop app. Same config, same snapshots, same log.
Every backup is a complete, browsable tree. Unchanged files share disk via hard links — so history costs almost nothing.
rsync --link-destKeep the N most recent plus the newest per day, week and month. Pruning runs automatically after every successful backup.
keep_last · daily · weekly · monthlyBrowse a snapshot's file tree and pick exactly what you want back — or the whole tree. Nothing in the destination folder is ever deleted.
browse · pick · restoreCreate multiple schedules — hourly, daily or weekly — and install them straight into your crontab with one click.
→ crontabEvery backup, restore and prune is written to history.jsonl and shown in a History tab — with time, target and outcome.
Test the SSH key, the connection, that all sources exist and that the destination is writable — before you trust a backup.
moraine verifySee exactly what would be transferred or deleted before anything happens. Applies to backup, restore and prune.
--dry-runrsync over SSH for your NAS, or rclone for cloud and object storage. Same snapshot model, same flow.
ssh · rcloneThe desktop app (built with GTK 4) has a clean dark design system — cards, a teal accent and soft shadows — with native file pickers and dialogs.
GTK 4The desktop app
The same engine as the CLI, with a graphical interface for editing targets, scheduling, restoring and tracking runs. Click around below.
Edit a target and run it right away — with a live-streamed rsync log at the bottom.
Build up multiple schedules and write them to your crontab — the app shows the cron expression as you set it up.
List snapshots, browse the tree and pick exactly what you want back. Files are copied — nothing is deleted.
Every run becomes a row in the log — so you can see after the fact what happened, and when.
The command line
Prefer the terminal? The moraine binary does exactly the same job — perfect for cron and remote servers.
Writes a commented example config to start from.
Tests the SSH key, the connection, that the sources exist and that the destination is writable.
Runs backup for all targets (or a chosen one). Auto-prune after a successful run.
Lists all snapshots on the target, newest first.
Shows which snapshots the retention policy would prune — before anything is deleted.
Version string with embedded git hash and build date from build.rs.
Download
The desktop app + CLI on Linux; the CLI on macOS and Windows (the desktop app lands there next). Same engine and config everywhere.
Now in official Debian. apt install moraine works on unstable / testing (migrating up from sid; the buildds cover arm64/armhf too), and reaches Ubuntu/Mint as they sync. For stable — or auto-updating everywhere today — add the thern.io APT repo:
The thern.io pacman repo — pacman -S moraine. Or the package / PKGBUILD.
The thern.io DNF repo — dnf install moraine, GPG-signed (Fedora/RHEL/openSUSE).
Build the package from the APKBUILD with abuild, then install it with apk. Both the desktop app and the CLI, on musl.
GTK app · rsync · ssh · rclone · muslThe desktop app on any distro, sandboxed, with rsync, ssh and rclone bundled inside it — nothing to match against your system. Served from our own repo on the thern.io CDN, signed with the same GPG key as the APT and DNF repos.
One file, no install, no package manager — download it, make it executable, run it. GTK is bundled, so the desktop app works the same on any distribution. It needs glibc 2.39 or newer (Ubuntu 24.04+, Debian 13+, Fedora 40+, Arch and the rolling distros). On something older, take the Flatpak or the .deb instead. A native aarch64 build (for arm64 desktops) arrives with the next release.
A perfect always-on backup box. These builds are statically linked, so one file runs on any Raspberry Pi OS — no dependencies to match, nothing to compile. Pick arm64 for a Pi 3/4/5 on a 64-bit system, armv7 for a 32-bit one.
The command-line client — best via Homebrew, which also pulls a modern rsync (macOS ships an old one). Or the Apple-Silicon tarball. A universal .pkg installer (Apple Silicon + Intel, into /usr/local) arrives with the next release. The GTK desktop app is coming to macOS.
The x64 desktop app — a one-click installer with the full GTK app, native window controls and the Moraine icon. Or the command-line client (installer that adds moraine to your PATH, winget / Scoop, or the plain zip). Scheduling via Task Scheduler; for rsync/SSH use WSL, or the rclone backend (SFTP/FTP/SMB/cloud).
Build it yourself with cargo build --release. Pure Rust, MIT license — it's all open on GitHub.
Rust · MITBuilt and in the repo — these light up here once they're live in their stores.
Packages are served from the thern.io CDN (GPG-signed APT/DNF/pacman/Flatpak repos) · every build is also on GitHub Releases, verified in CI. Gentoo ships from its own overlay; the macOS .pkg, FreeBSD, OpenBSD and NetBSD recipes live in packaging/.
Get started
Run moraine init, fill in host, sources and retention — and run a --dry-run before your first real backup.
# One or more [[target]] blocks. [[target]] name = "nas" host = "192.168.1.50" user = "backup" port = 22 key = "~/.ssh/backup_ed25519" dest = "/volume1/backups" sources = [ "/home/jonaz/dokument", "/home/jonaz/bilder", ] exclude = [ "*.tmp", "node_modules" ] # Keep 5 most recent + GFS [target.retention] keep_last = 5 keep_daily = 7 keep_weekly = 4 keep_monthly = 6
Snapshots that cost almost no disk, file-level restore and a log of everything that happened.