Simple server backups: folders and databases to S3, SFTP or any rclone remote β incremental, encrypted, scheduled, with an interactive setup TUI.
nest is a single static Go binary. Point it at your data, pick a destination, and a systemd timer keeps your backups running. Restores are one command away.
- πͺΊ Interactive TUI β
sudo nest setupwalks you through remotes, jobs and schedules; no hand-written YAML required (but supported). - Multiple destinations β any S3-compatible storage, SFTP (SSH key auth), or any remote configured in
rclone config. - Two backends per job β restic (incremental, deduplicated, encrypted) or plain
.tar.gzarchives. - Ready-made job presets β Pterodactyl Volumes, Pterodactyl Backups, Folder, MySQL/MariaDB, PostgreSQL.
- Flexible scheduling β daily "HH:MM" or full 5-field cron expressions, driven by a systemd timer.
- Retention policies β keep last/daily/weekly/monthly snapshots per job.
- Telegram notifications β success/failure reports straight to your chat.
- Self-updating β
sudo nest self-updatepulls the latest binary from the mirror. - Wide distro support β deb and rpm packages plus apt/dnf/zypper repositories; x86_64, aarch64 and armhf.
| Distribution | Versions | Architectures |
|---|---|---|
| AlmaLinux | 8β10 | x86_64, aarch64 |
| Amazon Linux | 2 & 2023 | x86_64, aarch64 |
| CentOS | 7β10 | x86_64, aarch64 |
| Debian | 10β13 | x86_64, aarch64, armhf |
| openSUSE Leap | 15β16 | x86_64, aarch64 |
| Oracle Linux | 7β10 | x86_64, aarch64 |
| Raspberry Pi OS | 10β13 | armhf, aarch64 |
| RHEL | 7β10 | x86_64, aarch64 |
| Rocky Linux | 8β10 | x86_64, aarch64 |
| SLES | 12 SP4+ / 15 SP4+ / 16 | x86_64, aarch64 |
| Ubuntu | 16.04 / 18.04 / 20.04 / 22.04 / 24.04 / 26.04 | x86_64, aarch64, armhf |
Other distributions can use the standalone binaries from the mirror (see Manual installation below).
curl --proto '=https' --proto-redir '=https' -fsSL https://mirror.trust-me.host/nest/install.sh | sudo bash
sudo nest setupThe installer detects your distribution, adds the nest package repository (apt, dnf/yum or zypper) and installs the package. nest setup then opens the interactive TUI to configure remotes and backup jobs.
The packages and repositories are signed with the Trusted Technologies Repo OpenPGP key:
53D1 58C2 C57D 928D F0F5 990C 1AF8 5015 7FCE 9AD2
install.sh verifies this fingerprint before trusting the key β you can cross-check it against the copy of this README on GitHub (an independent channel from the mirror).
To enable scheduled backups after setup:
sudo systemctl enable --now nest.timercurl -fsSL https://mirror.trust-me.host/keys/trusted-technologies.asc -o /tmp/nest-key.asc
# verify the fingerprint before trusting the key (see above)
gpg --batch --with-colons --with-fingerprint /tmp/nest-key.asc | awk -F: '/^fpr:/ {print $10; exit}'
sudo gpg --dearmor -o /usr/share/keyrings/nest-archive-keyring.gpg /tmp/nest-key.asc
echo "deb [signed-by=/usr/share/keyrings/nest-archive-keyring.gpg] https://mirror.trust-me.host/nest/apt stable main" \
| sudo tee /etc/apt/sources.list.d/nest.list
sudo apt-get update
sudo apt-get install nestsudo tee /etc/yum.repos.d/nest.repo <<'EOF'
[nest]
name=nest repository
baseurl=https://mirror.trust-me.host/nest/yum
enabled=1
gpgcheck=1
gpgkey=https://mirror.trust-me.host/keys/trusted-technologies.asc
EOF
curl -fsSL https://mirror.trust-me.host/keys/trusted-technologies.asc -o /tmp/nest-key.asc
# verify the fingerprint (see above), then:
sudo rpm --import /tmp/nest-key.asc
sudo dnf install nest # or: yum install nestsudo zypper ar -f -g https://mirror.trust-me.host/nest/yum nest
sudo zypper --gpg-auto-import-keys refresh
sudo zypper install nest# amd64 β use arm64 or armhf on ARM machines
curl -fsSLO https://mirror.trust-me.host/nest/bin/nest-linux-amd64
curl -fsSLO https://mirror.trust-me.host/nest/bin/sha256sums.txt
grep ' nest-linux-amd64$' sha256sums.txt | sha256sum -c -
sudo install -m 0755 nest-linux-amd64 /usr/bin/nest
sudo nest setupChecksums in sha256sums.txt are additionally detached-signed with the repository key (sha256sums.txt.asc); nest verifies that signature automatically whenever it downloads or updates a binary itself.
sudo nest setup (or just sudo nest) opens the TUI:
- Remotes β add a destination:
- s3: endpoint, region, bucket, access/secret key (works with AWS S3, Wasabi, MinIO, Cloudflare R2, ...). Optional
path_prefixseparates multiple servers inside one bucket. - sftp: host, port, user. Key auth only β nest generates
/etc/nest/ssh/id_ed25519if needed; authorize the public key on the backup server. - rclone: pick any remote from your
rclone config(e.g.gdrive:backups).
- s3: endpoint, region, bucket, access/secret key (works with AWS S3, Wasabi, MinIO, Cloudflare R2, ...). Optional
- Jobs β start from a preset (Pterodactyl Volumes
/var/lib/pterodactyl/volumes, Pterodactyl Backups/var/lib/pterodactyl/backups, Folder, MySQL/MariaDB, PostgreSQL) and adjust:- source directory or database credentials,
- target remote,
- backend: incremental (restic) or plain
.tar.gzarchives, - schedule, retention (last/daily/weekly/monthly), exclude patterns.
- Notifications β optionally enable Telegram.
The configuration is stored in /etc/nest/config.yml (mode 0600).
| Command | Description |
|---|---|
nest, nest setup |
Open the interactive setup TUI |
nest backup [--job N] [--scheduled] [--window-minutes 5] |
Run backups: one job, everything, or only jobs due now (--scheduled) |
nest restore --job N [--snapshot latest] [--target DIR] [--path P] |
Restore a snapshot or archive |
nest jobs |
List configured jobs |
nest remotes |
List configured remotes |
nest snapshots --job N |
List snapshots of a job |
nest repair --job N [--full] |
Check/repair a restic repository |
nest version |
Print the version |
nest self-update |
Update the nest binary from the mirror |
Global flags: -c/--config (alternate config path), -v/--verbose. See nest <command> --help for details.
The systemd timer runs nest backup --scheduled every 5 minutes; a job runs when its schedule falls inside the 5-minute window. Schedule formats:
"04:00"β daily at 04:00,"*/30 * * * *"β any 5-field cron expression,- empty β run on every timer tick (every 5 minutes).
Run an ad-hoc backup any time with nest backup (all enabled jobs) or nest backup --job mysql.
# list snapshots of a job
nest snapshots --job pterodactyl-volumes
# restore the latest snapshot to a directory
nest restore --job pterodactyl-volumes --snapshot latest --target /srv/restore
# restore a single path out of a snapshot
nest restore --job mysql --snapshot latest --path dumps/mydb.sql --target /var/lib/nest/restoreThe default --target is /var/lib/nest/restore (created with mode 0700 β restored database dumps must not be world-readable).
- Create a bot with @BotFather and copy the token.
- Get your chat id (e.g. message the bot, then open
https://api.telegram.org/bot<token>/getUpdates). - Enter both in
nest setupβ Notifications, or setnotifications.telegramin the config.
sudo nest self-updateDownloads the latest binary for your architecture from the mirror and replaces /usr/bin/nest.
Backups run through systemd, so logs live in the journal:
journalctl -u nest.service # backup runs
journalctl -u nest.timer # timer triggers
systemctl list-timers nest.timer # next scheduled run/etc/nest/config.yml (mode 0600) is plain YAML, normally managed by nest setup. A fully annotated example showing every field ships as /etc/nest/config.yml.example (and as packaging/config.yml.example in this repo). Minimal sketch:
encryption_password: "change-me-long-random-string" # or NEST_RESTIC_PASSWORD
remotes:
- name: my-s3 # referenced by jobs[].remote
type: s3 # s3 | sftp | rclone
endpoint: s3.eu-central-1.amazonaws.com
bucket: my-backup-bucket
access_key: AKIAEXAMPLE
secret_key: "super-secret"
jobs:
- name: pterodactyl-volumes
type: folder # folder | mysql | postgresql
source: /var/lib/pterodactyl/volumes
remote: my-s3
incremental: true # true = restic, false = .tar.gz archives
schedule: "04:00" # "HH:MM" or 5-field cron; empty = every tick
retention: {daily: 3, weekly: 1}
enabled: truePaths used by nest:
| Path | Purpose |
|---|---|
/usr/bin/nest |
the binary |
/etc/nest/config.yml |
configuration (mode 0600) |
/etc/nest/ssh/ |
SSH keypair for SFTP remotes (mode 0700) |
/var/lib/nest/ |
state: restic/rclone helper binaries downloaded on demand |
/var/cache/nest/ |
restic cache |
- restic backend (
incremental: true) β snapshots are deduplicated, compressed and encrypted inside a restic repository on the remote. Supports per-snapshot restore, partial (--path) restore, retention policies andnest repair. - archive backend (
incremental: false) β every run uploads a full.tar.gzarchive. Simple and portable, but no deduplication or partial restore. - Helper binaries β nest does not bundle restic/rclone. On first use it downloads the right build for your architecture from the mirror (
https://mirror.trust-me.host/nest/bin/) into/var/lib/nest/. Every downloaded binary is verified againstsha256sums.txtdetached-signed with the repository OpenPGP key (the public key is embedded in the nest binary); verification is fail-closed. No internet access to the mirror? Install therestic/rclonedistro packages instead (recommended by the deb package). - Scheduling β
nest.timertriggersnest.serviceevery 5 minutes, which runsnest backup --scheduled; each job whose schedule matches the current 5-minute window is executed.
Requirements: Go 1.25+ (a repo-local toolchain under .tools/go is used automatically when go is not in PATH).
make build # static binaries for amd64/arm64/armhf -> dist/bin/
make test # go test ./...
make vet # go vet ./...
make package # .deb/.rpm via nfpm -> dist/packages/
make tools # download restic/rclone -> dist/tools/bin/
make repo # signed apt + yum repositories -> dist/repo/ (needs NEST_GPG_KEY)
make publish # sync everything to the mirror (needs R2 credentials)
make cleanThe version is injected via -ldflags -X github.com/trusted-technologies/nest/internal/buildinfo.Version=... and resolved as follows: an exact git tag on HEAD wins (semver releases); in CI every other run gets an auto-incrementing 1.0.<run-number> (each push to main publishes a newer package); local untagged builds fall back to dev.
Releases are fully automated: pushing a v* tag runs .github/workflows/release.yml, which builds, signs and publishes everything, then attaches the packages to a GitHub release.
The public mirror (Cloudflare R2, https://mirror.trust-me.host) is shared between projects; nest lives under the /nest prefix and one GPG key signs all projects under /keys:
/nest/install.sh one-liner installer
/nest/VERSION latest released version
/nest/bin/ nest/restic/rclone binaries + signed sha256sums.txt(.asc)
/nest/apt/ Debian/Ubuntu repository (signed: InRelease)
/nest/yum/ RPM repository (signed: repomd.xml.asc)
/keys/trusted-technologies.asc repository GPG public key (ascii-armored)
/keys/trusted-technologies.gpg same key, pre-dearmored for minimal systems
/keys is shared by all projects on the mirror, so project pipelines never
write to it β the key is uploaded there once by a separate, manual process.
To publish by hand:
# one-time: generate the repo signing key
./scripts/gen-repo-key.sh
export NEST_GPG_KEY=<fingerprint> # key used to sign the repos
export R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
export R2_BUCKET=<bucket>
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
make build package tools repo publishCI secrets: GPG_PRIVATE_KEY (armored private key), R2_ENDPOINT, R2_BUCKET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY.
/etc/nest/config.ymlcontains credentials and the restic encryption password; nest always writes it with mode 0600 and tightens the mode on load if it was loosened by hand. Back it up securely β withoutencryption_passwordyour restic snapshots are unrecoverable.- SFTP remotes use SSH key authentication only; nest generates a dedicated keypair in
/etc/nest/ssh/(mode 0700). - The apt and yum repositories are GPG-signed and clients verify signatures (
signed-by/gpgcheck=1); all traffic to the mirror is over HTTPS (redirect downgrades and cross-host redirects are refused). install.shpins the repository key by fingerprint (53D158C2C57D928DF0F5990C1AF850157FCE9AD2, also shown above) β a mirror alone cannot swap in a different key.- Every binary nest downloads (helpers, self-update) is verified against the GPG-signed
sha256sums.txt, fail-closed; self-update also refuses downgrades. - Database passwords travel via environment variables (
MYSQL_PWD/PGPASSWORD), never via command-line arguments; error messages and notifications redact command lines. - The systemd service runs backups with low priority (
Nice=10, idle-IO class) and sandboxing (ProtectSystem=full,NoNewPrivileges=true, β¦) to avoid interfering with production workloads.
Issues and pull requests are welcome at github.com/trusted-technologies/nest. Please run make test and make vet before submitting.
MIT β see LICENSE.