forget
and
prune
commands let you define exactly how long to keep daily, weekly, and monthly snapshots. We cover the B2-specific flags, realistic output from each command, and the retention automation most tutorials skip.
Backblaze B2 Bucket and Application Key Setup
Sign up at backblaze.com and navigate to B2 Cloud Storage. Create a new bucket with a globally unique name like mycompany-restic-prod-2024. Bucket names must be 6-50 characters, lowercase, numbers, and hyphens only. Set the bucket to Private: public buckets expose your data to anyone with the URL. Choose a region close to your backup source to reduce latency. US West for West Coast servers, EU Central for European hosts.
Under App Keys, generate a new application key restricted to this specific bucket. Do not use the master application key; if your backup script leaks or a server is compromised, an attacker gains full account access. Name the key restic-prod-backup, select your bucket from the dropdown, and set permissions to Read and Write (restic does not need delete for normal operations, but prune requires it). Backblaze shows the keyID (a 25-character string starting with 004) and the applicationKey (a 31-character alphanumeric string) once; save both immediately.
Avoid configuring lifecycle rules in the B2 bucket settings. Restic manages retention through its own forget and prune workflow; bucket lifecycle rules can delete data restic expects to exist, corrupting the repository. Export your credentials as environment variables:
export B2_ACCOUNT_ID="004a1b2c3d4e5f6789abcdef"
export B2_ACCOUNT_KEY="K004xYz9AbCdEfGhIjKlMnOpQrStUv"
Add these to your ~/.bashrc or a dedicated credentials file sourced before backup jobs run.
Installing Restic and Initializing the Repository
Install restic from your distribution's package manager or download the official binary. Debian and Ubuntu ship restic in the main repository, but versions lag behind upstream. For the latest features and bug fixes, download from restic's official documentation or GitHub releases:
apt install restic # Debian/Ubuntu (may be 0.14.x)
dnf install restic # Fedora/RHEL
wget https://github.com/restic/restic/releases/download/v0.16.3/restic_0.16.3_linux_amd64.bz2
bunzip2 restic_0.16.3_linux_amd64.bz2
chmod +x restic_0.16.3_linux_amd64
sudo mv restic_0.16.3_linux_amd64 /usr/local/bin/restic
Verify the version with restic version. Version 0.16.x adds improved B2 upload performance and better snapshot filtering; avoid anything older than 0.14.0.
Initialize the repository with a strong passphrase. Restic encrypts all data with this passphrase; lose it and your backups are unrecoverable. The repository path follows the pattern b2:bucket-name:/optional-subdir. Use / for the bucket root or /hostname to separate multiple backup sources in one bucket:
restic -r b2:mycompany-restic-prod-2024:/ init
enter password for new repository:
enter password again:
created restic repository 3f5a8b2c at b2:mycompany-restic-prod-2024:/
Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
Restic creates four directories in the bucket: config (repository metadata), data (encrypted content blobs), snapshots (snapshot metadata), and keys (encrypted master keys). Store the passphrase in RESTIC_PASSWORD for automation or use --password-file /root/.restic-password with mode 0600.
Running Your First Backup and Understanding Snapshots
Back up directories with the backup command, specifying the repository, paths, and optional tags. Tags let you filter snapshots later; use them for hostname, environment, or backup type:
restic -r b2:mycompany-restic-prod-2024:/ backup /srv /etc --tag production --tag web01
Restic scans all files, splits them into content-defined chunks, and uploads only new chunks. The first backup uploads everything; subsequent backups deduplicate at the block level. Add --exclude for patterns like --exclude '*.log' or --exclude-file /root/restic-exclude.txt for a list of paths. Use --one-file-system to skip mountpoints; without it, restic follows into /proc or /sys.
Backup Command Syntax and Common Flags
The backup command accepts multiple paths, glob patterns in exclude files, and environment-specific flags. For databases, exclude the data directory and back up dumps instead. For logs, exclude rotated archives or set a short retention policy. A production web server might use:
restic -r b2:mycompany-restic-prod-2024:/web01 backup \
/srv/www /etc/nginx /etc/letsencrypt \
--exclude '/srv/www/*/cache' \
--exclude '*.tmp' \
--one-file-system \
--tag web01 --tag production
The --one-file-system flag stops restic from crossing filesystem boundaries; if /srv is a separate partition, restic will not descend into /srv/nfs-mount.
Reading Backup Output and Upload Progress
Restic prints progress every few seconds during backup. The first run shows full file counts and upload sizes:
repository 3f5a8b2c opened successfully, password is correct
created new cache in /root/.cache/restic
Files: 8472 new, 0 changed, 0 unmodified
Dirs: 421 new, 0 changed, 0 unmodified
Added to the repo: 2.147 GiB
processed 8472 files, 2.186 GiB in 3:42
snapshot a3f8b21e saved
The second backup of the same data shows deduplication savings. If you changed 50 MB of logs and config files:
Files: 12 new, 38 changed, 8422 unmodified
Dirs: 2 new, 5 changed, 414 unmodified
Added to the repo: 52.3 MiB
processed 8472 files, 2.186 GiB in 0:18
snapshot b7c4d92f saved
Only 52 MB uploaded despite 2.1 GB total. Restic deduplicated unchanged files and reused existing chunks for the 38 modified files.
Listing and Inspecting Snapshots
List all snapshots with restic snapshots. Each snapshot has a short ID (first 8 hex digits), timestamp, hostname, and paths:
restic -r b2:mycompany-restic-prod-2024:/ snapshots
repository 3f5a8b2c opened successfully, password is correct
ID Time Host Tags Paths
------------------------------------------------------------------------------------
a3f8b21e 2024-01-15 03:00:01 web01 production /srv /etc
b7c4d92f 2024-01-16 03:00:02 web01 production /srv /etc
Inspect a snapshot's contents with ls and storage usage with stats:
restic -r b2:mycompany-restic-prod-2024:/ ls b7c4d92f
/srv/www/index.html
/srv/www/assets/logo.png
/etc/nginx/nginx.conf
...
restic -r b2:mycompany-restic-prod-2024:/ stats b7c4d92f
Total File Count: 8472
Total Size: 2.186 GiB
Run restic check monthly to verify repository integrity. It reads all pack files and confirms checksums match; a corrupted repository will show specific pack file errors. For a broader comparison of restic with other tools, see Restic vs Borg vs Kopia 2026.
Encryption, Keys, and Repository Security
Restic encrypts all data with AES-256 in counter mode and authenticates it with Poly1305-AES before uploading to B2. The repository password you set during init derives a master key that encrypts every file, directory tree, and metadata blob. Your B2 application key grants upload and download permissions, but without the restic passphrase an attacker who compromises your B2 account sees only encrypted blobs. List the current repository keys with:
restic -r b2:mycompany-restic-prod-2024:/ key list
repository 3f5a8b2c opened successfully, password is correct
ID User Host Created
----------------------------------------------------------------------
*3f5a8b2c root backup01 2024-01-15 02:58:42
The asterisk marks the key you used to unlock the repository. Add a second key for team access or disaster recovery with restic key add. Enter the existing password, then set a new password for the additional key. Each key can decrypt the same repository data. Use separate keys for different administrators or automation contexts. Remove an old key when someone leaves the team:
restic -r b2:mycompany-restic-prod-2024:/ key remove 7d8e9f12
Change the passphrase for an existing key with restic key passwd. Enter the old password, then the new one twice. Restic re-encrypts the master key with the new passphrase; repository data stays unchanged.
Warning: Losing all key passphrases makes your backups permanently unrecoverable. Restic has no password reset mechanism and no backdoor. Store at least one passphrase in a password manager or hardware security module separate from the backup server.
Retention Policies with forget and prune
Restic's forget command removes snapshots from the repository index based on age and count, while prune deletes the underlying data blobs no longer referenced by any snapshot. Running forget alone updates metadata but does not reclaim storage; you must follow it with prune to actually delete unreferenced packs. Most production workflows combine both in a single command with the --prune flag. A typical retention policy keeps recent backups granular and older backups sparse: seven daily snapshots, four weekly, and twelve monthly.
Designing a Retention Policy
Choose retention based on recovery time objectives and storage budget. Keep daily backups for a week to recover from recent mistakes, weekly backups for a month to roll back after a bad deployment, and monthly backups for a year to meet compliance requirements. For a 200 GB dataset with 5% daily change, seven dailies and four weeklies add about 50 GB of unique data; twelve monthlies add another 60 GB. Total storage stays under 300 GB even with a year of history.
Use --keep-within for time-based retention when you need all snapshots from a specific window, such as --keep-within 30d to preserve everything from the last month. This ignores daily/weekly/monthly buckets and keeps every snapshot newer than 30 days. Combine it with longer-term policies: --keep-within 7d --keep-weekly 4 --keep-monthly 12 keeps all snapshots from the last week, then switches to weekly and monthly after that.
Running forget with --keep-* Flags
The forget command groups snapshots by host, paths, and tags, then applies retention rules to each group. Restic keeps the newest snapshot in each time bucket and marks the rest for removal. Run forget with --dry-run first to preview which snapshots will be deleted:
restic -r b2:mycompany-restic-prod-2024:/ forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--dry-run
Output shows snapshots grouped by host and paths, with decisions for each:
Applying Policy: keep 7 daily, 4 weekly, 12 monthly snapshots
snapshots for (host web01, paths [/srv /etc]):
keep 7 snapshots:
ID Time Host Tags Reasons
----------------------------------------------------------------------------------
a3f8b21e 2024-01-15 03:00:01 web01 production daily snapshot
b7c4d92f 2024-01-16 03:00:02 web01 production daily snapshot
c8e5a03d 2024-01-17 03:00:01 web01 production daily snapshot
...
remove 3 snapshots:
ID Time Host Tags
----------------------------------------------------------------------------------
d9f6b14e 2024-01-08 03:00:02 web01 production
e0g7c25f 2024-01-09 03:00:01 web01 production
f1h8d36g 2024-01-10 03:00:02 web01 production
Remove --dry-run and add --prune to execute the policy and reclaim storage in one pass. Without --prune, restic only updates the snapshot index; deleted snapshot metadata disappears, but data blobs remain in the repository:
restic -r b2:mycompany-restic-prod-2024:/ forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune
By default, restic groups snapshots by hostname and backup paths. Override this with --group-by to manage retention differently. Use --group-by tags to apply policies per tag, or --group-by host,tags to separate production and staging backups on the same host. For a single-host repository backing up multiple services, --group-by paths applies retention independently to /srv/database and /srv/web.
Reclaiming Storage with prune
The prune operation recalculates which data blobs are still needed by remaining snapshots, then deletes unreferenced packs from B2. Restic reads repository metadata, builds a reference graph, and issues delete requests for orphaned blobs. This can take 10-30 minutes for a 500 GB repository and downloads several megabytes of index data. Run prune during off-peak hours to avoid interfering with backups:
restic -r b2:mycompany-restic-prod-2024:/ prune
repository 3f5a8b2c opened successfully, password is correct
loading indexes...
loading all snapshots...
finding data that is still in use for 14 snapshots
[0:12] 100.00% 14 / 14 snapshots
searching used packs...
collecting packs for deletion and repacking
[0:03] 100.00% 1234 / 1234 packs processed
to repack: 45 blobs / 1.234 GiB
this removes 89 blobs / 2.456 GiB
to delete: 123 blobs / 3.678 GiB
total prune: 212 blobs / 6.134 GiB
remaining: 5678 blobs / 187.2 GiB
unused size after prune: 0 B (0.00% of remaining size)
deleting unreferenced packs
[0:08] 100.00% 123 / 123 files deleted
Restic may repack partially-used packs to reclaim space from deleted snapshots that shared chunks with kept snapshots. This creates temporary upload and download traffic; budget for 10-20% of repository size in bandwidth during prune. For more on building comprehensive retention strategies, see Linux Backup Strategies.
Warning: Do not configure B2 lifecycle rules to auto-delete files older than a certain age. Restic manages its own pack files and indexes; bucket lifecycle rules can delete data restic expects, corrupting the repository. Let restic control all deletion through
forgetandprune.
Restoring Files and Snapshots
Restore an entire snapshot to a target directory with restic restore, specifying the snapshot ID and destination path. Restic downloads only the packs needed for the requested files, validates checksums, and reconstructs the directory tree:
restic -r b2:mycompany-restic-prod-2024:/ restore b7c4d92f --target /restore
repository 3f5a8b2c opened successfully, password is correct
restoring <Snapshot b7c4d92f of [/srv /etc] at 2024-01-16 03:00:02> to /restore
[0:42] 100.00% 8472 / 8472 files 2.186 GiB / 2.186 GiB
The /restore directory now contains srv/ and etc/ with all files from snapshot b7c4d92f. Restore specific paths with --include or --exclude. To recover only /etc/nginx from the snapshot:
restic -r b2:mycompany-restic-prod-2024:/ restore b7c4d92f \
--target /tmp/restore \
--include /etc/nginx
Find files across all snapshots when you know the filename but not which backup contains the version you need. The find command searches snapshot metadata without downloading data blobs:
restic -r b2:mycompany-restic-prod-2024:/ find nginx.conf
repository 3f5a8b2c opened successfully, password is correct
Found matching entries in snapshot a3f8b21e from 2024-01-15 03:00:01
/etc/nginx/nginx.conf
Found matching entries in snapshot b7c4d92f from 2024-01-16 03:00:02
/etc/nginx/nginx.conf
Mount the repository as a read-only filesystem with FUSE to browse snapshots interactively. Install fuse (Debian/Ubuntu) or fuse3 (Fedora/RHEL), then mount the repository to a directory:
mkdir /mnt/restic
restic -r b2:mycompany-restic-prod-2024:/ mount /mnt/restic
repository 3f5a8b2c opened successfully, password is correct
Now serving the repository at /mnt/restic
Use another terminal or tool to browse the contents of this folder.
When finished, quit with Ctrl-C here or umount the mountpoint.
Each snapshot appears under /mnt/restic/snapshots/<date>/. Browse with ls, copy files with cp, or search with find. Restic fetches data on demand; reading a file downloads its packs from B2. Unmount with fusermount -u /mnt/restic or Ctrl-C in the mount terminal.
Add --verify to restore to compare restored file checksums against the repository after extraction. Restic reads each restored file and confirms it matches the snapshot metadata. This catches disk corruption or partial downloads but doubles restore time for large datasets.
Automating Backups with systemd Timers
Manual backups fail the moment you forget to run them. Automate restic with a systemd timer that runs daily, applies retention policies, and logs output for monitoring. Store credentials and repository paths in a shared environment file, write a backup script that handles errors, and configure systemd to run it on a schedule.
Creating the Backup Script
Write the backup script at /usr/local/bin/restic-backup.sh with logic to source credentials, run backup, apply retention with forget --prune, and exit with a status code systemd can track:
#!/bin/bash
set -euo pipefail
source /etc/restic/env
restic -r "${RESTIC_REPOSITORY}" backup \
/srv /etc \
--exclude '/srv/*/cache' \
--one-file-system \
--tag "$(hostname)" --tag production
restic -r "${RESTIC_REPOSITORY}" forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune
restic -r "${RESTIC_REPOSITORY}" check --read-data-subset=5%
Create /etc/restic/env with mode 0600 to protect credentials:
RESTIC_REPOSITORY=b2:mycompany-restic-prod-2024:/web01
RESTIC_PASSWORD=your-repository-passphrase
B2_ACCOUNT_ID=004a1b2c3d4e5f6789abcdef
B2_ACCOUNT_KEY=K004xYz9AbCdEfGhIjKlMnOpQrStUv
Make the script executable with chmod +x /usr/local/bin/restic-backup.sh. The check --read-data-subset verifies 5% of repository packs each run; over 20 days you validate the entire repository without downloading terabytes on every backup.
systemd Service and Timer Units
Create the service unit at /etc/systemd/system/restic-backup.service to run the script with credentials from the environment file:
[Unit]
Description=Restic backup to B2
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
ExecStart=/usr/local/bin/restic-backup.sh
User=root
IOSchedulingClass=idle
CPUSchedulingPolicy=idle
The idle scheduling reduces backup impact on production workloads. Create the timer unit at /etc/systemd/system/restic-backup.timer to run daily at 3 AM:
[Unit]
Description=Restic backup timer
[Timer]
OnCalendar=daily
OnCalendar=03:00
Persistent=true
[Install]
WantedBy=timers.target
Set Persistent=true so systemd runs missed backups after a reboot. Enable and start the timer:
systemctl daemon-reload
systemctl enable --now restic-backup.timer
Add OnFailure=status-email@%n.service to the service unit to send alerts when backups fail, assuming you have configured a notification service. For more on systemd timer patterns, see Linux Automation with Cron, Systemd Timers & Scripts.
Monitoring Backup Status and Logs
Check the timer schedule and last run with systemctl status restic-backup.timer:
โ restic-backup.timer - Restic backup timer
Loaded: loaded (/etc/systemd/system/restic-backup.timer; enabled)
Active: active (waiting) since Mon 2024-01-15 03:00:01 UTC; 1 day 2h ago
Trigger: Tue 2024-01-16 03:00:00 UTC; 20h left
Triggers: โ restic-backup.service
Read backup logs with journalctl -u restic-backup.service. Add --since today or --since "2 days ago" to filter recent runs. Failed backups exit non-zero and show in systemctl status restic-backup.service with failed state. Monitor the timer with standard tools like Prometheus node_exporter's systemd collector or parse journal output for external alerting.
Cost Management and Performance Tuning
Backblaze B2 charges $6 per TB per month for storage, $0.01 per GB for downloads beyond the first gigabyte per day, and transaction fees for API calls. Restic uses Class C transactions (list operations) heavily during backup, forget, and prune; you get 2,500 free per day, then pay $0.004 per 1,000. A daily backup of 100 GB with 10,000 files consumes roughly 1,200 Class C transactions for metadata scanning. Monitor usage in the B2 dashboard under Buckets โ your-bucket โ Usage to track storage growth and transaction patterns.
Reduce costs by running forget --prune regularly to remove old snapshots before they accumulate. A year of daily backups without pruning can triple storage costs; weekly pruning with a 7-daily, 4-weekly, 12-monthly policy keeps growth under 30% for typical workloads. Avoid restoring full snapshots frequently; each restore downloads gigabytes and counts against your free download quota. Use restic mount to browse snapshots and copy only needed files, or restore with --include to fetch specific directories.
Increase upload performance with --read-concurrency to read more files in parallel during backup. The default is 2; raise it to 8-16 on fast storage or high-bandwidth links. Restic caches repository metadata in RESTIC_CACHE_DIR (default ~/.cache/restic); place this on fast local storage or tmpfs to speed up snapshot operations. Set a larger cache with export RESTIC_CACHE_DIR=/mnt/ssd/restic-cache before running backups.
For repositories with large files, adjust --pack-size to control how restic groups blobs into packs. The default 16 MiB works well for mixed workloads; increase to 64 MiB or 128 MiB for video or database files to reduce pack count and metadata overhead. Conversely, lower it to 4 MiB for many small files to improve deduplication granularity. Run restic rebuild-index if repository metadata becomes slow; this regenerates index files and can cut snapshot listing time by 50% in repositories with thousands of snapshots.
Throttle upload bandwidth with --limit-upload to avoid saturating your connection during backups. Set it in kilobytes per second: --limit-upload 10240 limits uploads to 10 MB/s. This prevents backup jobs from interfering with production traffic on shared links. For detailed cost comparisons and strategies, see the Backblaze B2 documentation.
Checklist: Production-Ready Restic B2 Backups
- Repository security: Store passphrase in
/etc/restic/envmode 0600, add second key for disaster recovery, verify keys withrestic key list. - Retention policy: Define
--keep-daily,--keep-weekly,--keep-monthlybased on RTO and budget, test with--dry-runbefore first prune. - Automation: Write backup script with forget/prune, create systemd service with
EnvironmentFile, enable timer withOnCalendar=daily. - Monitoring: Check
systemctl status restic-backup.timerweekly, reviewjournalctl -u restic-backup.servicefor failures, addOnFailure=alerting. - Verification: Run
restic check --read-data-subset=5%in backup script, perform fullrestic checkmonthly, test restore from random snapshot quarterly. - Cost control: Monitor B2 dashboard for storage and transaction growth, prune weekly, avoid unnecessary full restores.
- Documentation: Record repository URL, passphrase location, retention policy, and restore procedure in runbook.
Test your restore process before you need it. Pick a random snapshot, restore to a temporary directory, verify file integrity. For a broader view of backup strategies and tool selection, see Linux Backup & Recovery Strategies: Complete Guide (2026).
Frequently Asked Questions
How much does Backblaze B2 cost for restic backups?
B2 charges $6 per TB per month for storage and $0.01 per GB for downloads beyond 1 GB per day. Class C transactions (list operations) are 2,500 free per day, then $0.004 per 1,000. A 500 GB repository with daily backups, weekly pruning, and rare restores typically costs $3-4 per month: $3 storage, $0.50 transactions, minimal download fees. Costs scale linearly with data size; retention policies control growth.
Can I restore restic backups without downloading the entire repository?
Yes. Restic downloads only the packs needed for requested files. Use restic restore <snapshot-id> --target /restore --include /specific/path to fetch a single directory, or restic mount to browse snapshots as a filesystem and copy individual files. The repository metadata (indexes and snapshots) downloads first, typically a few megabytes, then restic fetches data blobs on demand. A 1 TB repository with 10,000 files can restore a single 5 MB config file in under 10 seconds.
What happens if I lose my restic repository password?
Your backups become permanently unrecoverable. Restic encrypts all data with AES-256 derived from your passphrase; there is no password reset, no backdoor, no recovery mechanism. If you lose all key passphrases, the repository is cryptographically locked forever. Store at least one passphrase in a password manager, hardware security module, or printed paper in a safe. Add a second key with restic key add for disaster recovery, kept separate from production credentials.
How do I automate restic forget and prune without deleting recent backups?
Run restic forget with --keep-daily, --keep-weekly, and --keep-monthly flags in your backup script, followed by --prune to reclaim storage. Restic keeps the newest snapshot in each time bucket and only removes older ones. Test with --dry-run first to preview deletions. A script with restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune preserves all snapshots from the last week, then switches to weekly and monthly retention for older backups.
Does restic encryption protect my data from Backblaze employees?
Yes. Restic encrypts all data client-side with AES-256 before uploading to B2. Your repository passphrase never leaves your backup server; Backblaze stores only encrypted blobs and has no access to your encryption keys. Even with full B2 account access, Backblaze employees see only ciphertext. The B2 application key grants upload and download permissions, but without your restic passphrase the data is cryptographically unreadable. This is true end-to-end encryption; only you control the keys.