Sr Technical Writer and Team Lead

Restic is an open-source backup client written in Go that supports encrypted, incremental, and deduplicated backups to a variety of storage backends. You can back up data to an object storage service such as DigitalOcean Spaces, Amazon S3, or any S3-compatible endpoint using Restic.
Restic encrypts all data locally using AES-256 in counter mode with Poly1305-AES authentication before sending it to the backend. This means your backup data remains secure even when stored on a remote, untrusted server. Restic also performs content-defined chunking and deduplication, so only new or changed data blocks are transmitted after the initial full backup, which reduces both bandwidth usage and storage costs.
In this tutorial, you will install Restic on a Linux server, configure credentials for an S3-compatible object storage service, initialize an encrypted backup repository, back up files, inspect and restore snapshots, set up retention policies with restic forget and restic prune, verify repository integrity with restic check, and automate recurring backups using cron.
restic forget --prune command lets you define granular retention policies (hourly, daily, weekly, monthly) to automatically remove outdated snapshots.restic check regularly verifies the structural integrity of your repository and confirms that backed-up data can be restored.Before you begin this tutorial, you will need the following:
sudo privileges. You can set this up by following the Initial Server Setup with Ubuntu tutorial. Restic also runs on macOS and other Linux distributions. The commands in this tutorial work on any UNIX-based system.If you are using DigitalOcean Spaces, you can create a Space and generate API keys by following the DigitalOcean Spaces product documentation. Spaces provides S3-compatible object storage with a built-in CDN, starting at $5/month for 250 GiB of storage and 1 TiB of outbound transfer.
Once you have your object storage credentials, proceed to the next step to install Restic.
Restic distributes precompiled binaries for Linux, macOS, and Windows. You can download a single executable and run it without installing additional dependencies or using a package manager.
First, navigate to Restic’s latest release page on GitHub. As of this writing, the latest stable version is 0.18.1, released in September 2025. Under the Assets section, find the file that matches your operating system and architecture:
restic_0.18.1_linux_amd64.bz2restic_0.18.1_darwin_amd64.bz2restic_0.18.1_darwin_arm64.bz2Download the file using curl. Replace the filename if you are on a different platform:
- cd ~
- curl -LO https://github.com/restic/restic/releases/download/v0.18.1/restic_0.18.1_linux_amd64.bz2
Decompress the downloaded file:
- bunzip2 restic_0.18.1_linux_amd64.bz2
Copy the binary to /usr/local/bin and make it executable:
- sudo cp restic_0.18.1_linux_amd64 /usr/local/bin/restic
- sudo chmod a+x /usr/local/bin/restic
Verify the installation by checking the version:
- restic version
Outputrestic 0.18.1 compiled with go1.23.6 on linux/amd64
If you see the version output, Restic is installed and ready to use. You can also install Restic through your system’s package manager (apt install restic on Debian/Ubuntu, brew install restic on macOS), though these repositories may carry an older version.
Note: If you installed Restic version 0.9.4 or later, you can update to the newest release at any time by running sudo restic self-update. This downloads the latest binary directly from GitHub and replaces the existing one.
Restic reads connection details and the repository password from environment variables. Storing these in a dedicated file keeps your credentials out of shell history and makes them available for automated scripts.
Create a configuration file in your home directory:
- nano ~/.restic-env
Add the following lines, replacing the placeholder values with your actual object storage credentials:
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export RESTIC_REPOSITORY="s3:server-url/bucket-name"
export RESTIC_PASSWORD="a-strong-password"
Here is what each variable controls:
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY: The credentials for authenticating with your S3-compatible storage provider. For DigitalOcean Spaces, generate these from the Spaces Access Keys page in the control panel. Consider creating a dedicated key pair for Restic so you can revoke access independently if the keys are compromised.RESTIC_REPOSITORY: The full path to your backup repository. For DigitalOcean Spaces, the format is s3:region.digitaloceanspaces.com/bucket-name. For example: s3:nyc3.digitaloceanspaces.com/my-backups. If you need to connect over plain HTTP or a non-standard port, include that in the URL: s3:http://example-server:3000/bucket-name.RESTIC_PASSWORD: The passphrase Restic uses to derive encryption keys for your repository. All data is encrypted locally before upload using AES-256-CTR with Poly1305-AES authentication. Choose a strong, unique password and store a copy in a secure location such as a password manager. If you lose this password, your backups cannot be decrypted or restored.Generate a strong random password with openssl:
- openssl rand -base64 24
Outputj8CGOSdz8ibUYK137wtdiD0SJiNroGUp
Copy the output into the RESTIC_PASSWORD field. Save and close the file when you are done.
Restrict the file permissions so that only your user can read it:
- chmod 600 ~/.restic-env
Note: For production environments, consider storing credentials in a secrets manager such as HashiCorp Vault or using environment-specific .env file management tools. Avoid committing credential files to version control repositories.
Before you can create backups, you need to initialize a Restic repository in your object storage bucket. This creates the directory structure and encryption metadata that Restic requires.
Load the environment variables into your current shell session:
- source ~/.restic-env
Confirm the repository URL loaded correctly:
- echo $RESTIC_REPOSITORY
You should see your repository URL printed to the terminal. Now initialize the repository:
- restic init
Outputcreated restic repository 57f73c1afc at s3:nyc3.digitaloceanspaces.com/my-backups
Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
The repository is now initialized and ready to receive backup data. Restic has created several directories inside your bucket (config, data, index, keys, locks, snapshots) that manage the repository structure and metadata.
With the repository initialized, you can back up data to an object storage service by running the restic backup command. The first backup sends all selected files to the repository. Subsequent backups are incremental, meaning Restic only uploads data blocks that are new or have changed since the last snapshot.
If you are testing with a new system and need sample data, create a text file:
- echo "Restic backs up data to object storage with encryption and deduplication." >> ~/testfile.txt
Back up your home directory:
- restic backup ~
Outputrepository 57f73c1a opened (version 2, compression level auto)
[0:02] 100.00% 4 / 4 index files loaded
Files: 14 new, 0 changed, 0 unmodified
Dirs: 4 new, 0 changed, 0 unmodified
Data Blobs: 13 new
Tree Blobs: 5 new
Added to the repository: 10.214 MiB (9.875 MiB stored)
processed 14 files, 10.230 MiB in 0:04
snapshot a1b2c3d4 saved
Restic displays a progress summary and prints the snapshot ID when the backup completes. Each snapshot represents a complete point-in-time image of the backed-up directory.
Note: To back up a different directory, replace ~ with the target path. If the directory is owned by another user, prefix the command with sudo. Remember to use sudo again during restore operations if you need to preserve original file ownership and permissions.
You can also use the --tag flag to label snapshots for easier identification and filtering:
- restic backup ~ --tag daily --tag production
To see all backups stored in your repository, use the snapshots subcommand:
- restic snapshots
Outputrepository 57f73c1a opened (version 2, compression level auto)
ID Time Host Tags Paths Size
-----------------------------------------------------------------------------------
a1b2c3d4 2026-03-17 10:15:00 backup-srv /home/sammy 10.230 MiB
-----------------------------------------------------------------------------------
1 snapshots
The output shows each snapshot’s ID, timestamp, hostname, tags, backed-up paths, and size. You can filter snapshots by host, tag, or path:
- restic snapshots --tag daily
To see what changed between two snapshots, use restic diff:
- restic diff snapshot-id-1 snapshot-id-2
The Host column helps distinguish backups when multiple machines send data to the same repository. Each machine needs access to the repository password, and you can set up multiple passwords using restic key add for more fine-grained access control. For more details, see the Restic key management documentation.
Over time, your repository will accumulate many snapshots. The restic forget command removes snapshot metadata based on retention rules you define, and the --prune flag deletes the actual data blobs that are no longer referenced by any remaining snapshot.
Here is an example that keeps the most recent 24 hourly snapshots, 7 daily snapshots, 4 weekly snapshots, and 6 monthly snapshots:
- restic forget --prune --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 6
Outputrepository 57f73c1a opened (version 2, compression level auto)
Applying Policy: keep 24 hourly, 7 daily, 4 weekly, 6 monthly snapshots
keep 1 snapshots:
ID Time Host Tags Reasons Paths
------------------------------------------------------------------------------------
a1b2c3d4 2026-03-17 10:15:00 backup-srv hourly snapshot /home/sammy
------------------------------------------------------------------------------------
1 snapshots
[0:01] 100.00% 1 / 1 packs deleted
Done
The available retention flags are:
| Flag | Description |
|---|---|
--keep-last n |
Keep the last n snapshots |
--keep-hourly n |
Keep the last n hourly snapshots |
--keep-daily n |
Keep the last n daily snapshots |
--keep-weekly n |
Keep the last n weekly snapshots |
--keep-monthly n |
Keep the last n monthly snapshots |
--keep-yearly n |
Keep the last n yearly snapshots |
--keep-tag tag |
Keep all snapshots with the specified tag |
You can combine multiple flags in a single command. Restic evaluates all rules and keeps any snapshot that matches at least one of them.
Note: The restic forget command only removes the snapshot references. Running restic forget without --prune leaves the underlying data packs in the repository. Always include --prune or run restic prune separately afterward to reclaim storage space.
Regular integrity checks confirm that your backup repository is consistent and that the data stored in it can be successfully restored. The restic check command verifies the repository structure, indexes, and optionally the content of data packs.
Run a basic structural check:
- restic check
Outputrepository 57f73c1a opened (version 2, compression level auto)
using temporary cache in /tmp/restic-check-cache-123456789
create exclusive lock for repository
load indexes
check all packs
check snapshots, trees and blobs
[0:00] 100.00% 1 / 1 snapshots
no errors were found
To also verify that the actual data within pack files is intact and readable, add the --read-data flag:
- restic check --read-data
This downloads and verifies every data pack in the repository, which can take a long time and consume significant bandwidth for large repositories. For regular use, the basic restic check is sufficient. Reserve --read-data for periodic deep verification, such as once a month.
If restic check reports errors, you can attempt automatic repairs using:
- restic repair index
- restic repair snapshots
These commands rebuild damaged index files and remove references to missing data blobs. See the Restic troubleshooting documentation for more details.
You can restore an entire snapshot or specific files from your backup repository. Use a snapshot ID from the output of restic snapshots.
Restore a full snapshot to a target directory:
- restic restore a1b2c3d4 --target /tmp/restore
Outputrepository 57f73c1a opened (version 2, compression level auto)
restoring <Snapshot a1b2c3d4 of [/home/sammy] at 2026-03-17 10:15:00 +0000 UTC by sammy@backup-srv> to /tmp/restore
Summary: Restored 18 files/dirs (10.230 MiB) in 0:03
Navigate to the restored directory and verify the contents:
- ls /tmp/restore/home/sammy/
Outputtestfile.txt .restic-env
You can use the --include and --exclude flags to restore only specific files or directories:
- restic restore a1b2c3d4 --target /tmp/restore --include "/home/sammy/testfile.txt"
Restic also supports mounting a snapshot as a read-only FUSE filesystem, which lets you browse and copy individual files without restoring the entire snapshot:
- mkdir /tmp/restic-mount
- restic mount /tmp/restic-mount
This makes all snapshots available under /tmp/restic-mount/snapshots/. You can then navigate through the directory structure and copy the files you need. Press Ctrl+C to unmount when finished.
Note: The restic mount command requires FUSE to be installed on your system. On Ubuntu, install it with sudo apt install fuse. On macOS, install macFUSE.
Running backups manually works for testing, but production systems need automated, scheduled backups. You can use the cron system service to run backup and pruning tasks on a recurring schedule. For more information on cron syntax and configuration, see How To Use Cron to Automate Tasks on Ubuntu.
Open your user’s crontab for editing:
- crontab -e
If prompted, select a text editor (such as nano), then add the following line at the end of the file:
. . .
42 * * * * . /home/sammy/.restic-env; /usr/local/bin/restic backup -q /home/sammy; /usr/local/bin/restic forget -q --prune --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 6 >> /home/sammy/restic-backup.log 2>&1
This cron entry does the following:
42 * * * * runs the task at the 42nd minute of every hour.. /home/sammy/.restic-env loads the environment variables (equivalent to source).restic backup -q /home/sammy runs a quiet backup of the home directory.restic forget -q --prune --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 6 applies the retention policy and prunes unreferenced data.>> /home/sammy/restic-backup.log 2>&1 appends both standard output and errors to a log file for troubleshooting.Save and close the crontab. The cron daemon activates the schedule immediately.
If your system uses systemd, you can create a timer unit instead of a cron job. Systemd timers provide better logging through journalctl, dependency management, and more precise scheduling.
Create a service unit file:
- sudo nano /etc/systemd/system/restic-backup.service
Add the following content:
[Unit]
Description=Restic backup to object storage
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=sammy
EnvironmentFile=/home/sammy/.restic-env
ExecStart=/usr/local/bin/restic backup -q /home/sammy
ExecStartPost=/usr/local/bin/restic forget -q --prune --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 6
Create the corresponding timer unit:
- sudo nano /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run Restic backup hourly
[Timer]
OnCalendar=hourly
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
Enable and start the timer:
- sudo systemctl daemon-reload
- sudo systemctl enable --now restic-backup.timer
Verify the timer is active:
- systemctl list-timers restic-backup.timer
To check the output of the most recent backup run:
- journalctl -u restic-backup.service --no-pager -n 20
For more details on systemd units and timer configuration, see Understanding Systemd Units and Unit Files.
After a few hours, run restic snapshots to confirm that new snapshots are being created automatically.
When choosing a backup tool for object storage, it helps to understand how Restic compares to other popular options. The following table summarizes the key differences:
| Feature | Restic | BorgBackup | Duplicity | rclone |
|---|---|---|---|---|
| Encryption | AES-256-CTR + Poly1305-AES | AES-256-CTR + HMAC-SHA256 | GnuPG (GPG) | Optional (via crypt remote) |
| Deduplication | Content-defined chunking | Content-defined chunking | File-level | None (sync tool) |
| S3 Support | Native | No (requires rclone mount) | Yes (via boto) | Native |
| Compression | Zstd (since 0.14) | LZ4, Zstd, Zlib | GZip | Varies by remote |
| Multiple hosts per repo | Yes | Yes | No | N/A |
| FUSE mount | Yes | Yes | No | Yes |
| Written in | Go | Python/C | Python | Go |
Restic and BorgBackup share many design principles, but Restic’s native S3 support makes it a strong fit for backing up data to an S3-compatible object storage service without extra configuration. If you need a sync tool rather than a versioned backup tool, rclone may be a better choice. You can also use rclone as a backend for Restic with the rclone: repository URL scheme, which gives you access to over 70 cloud storage providers.
To understand the differences between object storage and block storage and determine which is right for your use case, see Object Storage vs. Block Storage Services.
Restic encrypts all backup data using AES-256 in counter mode (CTR) and authenticates it with Poly1305-AES. Encryption and authentication happen locally on your machine before any data leaves for the remote repository. The encryption keys are derived from your repository password using the scrypt key derivation function, which makes brute-force attacks computationally expensive. Each file in the repository carries a 16-byte random initialization vector and a 16-byte message authentication code.
Yes. DigitalOcean Spaces is S3-compatible, so Restic connects to it natively using the s3: repository URL scheme. Set RESTIC_REPOSITORY to s3:region.digitaloceanspaces.com/bucket-name (for example, s3:nyc3.digitaloceanspaces.com/my-backups) and provide your Spaces access key and secret key through the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
Restic splits files into variable-length chunks using a content-defined chunking algorithm (Rabin fingerprinting). Each chunk is identified by its SHA-256 hash. If the same chunk appears in multiple files or across multiple backup snapshots, Restic stores it only once. This deduplication happens before encryption and significantly reduces the total storage required, especially for incremental backups where most data has not changed.
You cannot. Restic derives all encryption keys from the repository password. There is no backdoor, recovery key, or password reset mechanism. If you lose the password, your backup data is permanently inaccessible. Always store your repository password in a password manager and keep a separate offline backup of the password in a physically secure location.
The restic forget command removes snapshot metadata (the pointers that reference specific backup states) based on the retention rules you provide. It does not delete the underlying data packs. The restic prune command scans the repository for data packs that are no longer referenced by any remaining snapshot and removes them. Running restic forget --prune combines both operations in a single step, which is the recommended approach.
In this tutorial, you installed Restic, configured S3-compatible object storage credentials, initialized an encrypted backup repository, created and restored backups, set up retention policies, verified repository integrity, and automated the backup workflow. Restic’s combination of AES-256 encryption, incremental deduplication, and native S3 support makes it a practical tool for protecting data on object storage services like DigitalOcean Spaces.
For more in-depth information about Restic’s features, refer to the official Restic documentation.
If you are looking to build on what you learned in this tutorial, here are some recommended resources:
Ready to get started with S3-compatible object storage? Create a DigitalOcean Spaces bucket and start backing up your data today. New accounts receive $200 in free credit for the first 60 days.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
I help Businesses scale with AI x SEO x (authentic) Content that revives traffic and keeps leads flowing | 3,000,000+ Average monthly readers on Medium | Sr Technical Writer(Team Lead) @ DigitalOcean | Ex-Cloud Consultant @ AMEX | Ex-Site Reliability Engineer(DevOps)@Nutanix
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi,
thanks for this article! We would like to add that there are other features as well, such as mounting the repository via FUSE which allows for browsing the snapshots and their contents.
On behalf of all the restic authors, Fabian
Couldn’t get it to work. All I get is this:
~$ restic init
create backend at https://mybackendurlname.nyc3.digitaloceanspaces.com/foldername failed: invalid backend
If the repo is in a local directory, you need to add a local: prefix
Failed for me too
$ restic init create backend at s3:https://the-space-for-worik.ams3.digitaloceanspaces.com/Bucket01 failed: client.BucketExists: The specified key does not exist.
I am not sure what “bucket” is in this context
Thanks for the tutorial. I got it working with backblaze b2 (your tutorial is better than backblaze’s ;))
Borg and restic are great. Here there’s an article, in Italian, about them. There’s also a useful script to check if on AC (and not battery), snapshot the file system and backup using borg and restic: https://www.dragas.net/posts/alla-ricerca-del-backup-perfetto-borg-e-restic/
This isn’t working for me on Ubuntu 18.10 using Restic 0.9.2. Keys are assigned using the method described above. Keys work for other applications. I even created a new custom API for this application and it still fails.
restic -r s3:sfo2.digitaloceanspaces.com/hbe-backups/ init
Fatal: create repository at s3:sfo2.digitaloceanspaces.com/hbe-backups/ failed: client.BucketExists: The request signature we calculated does not match the signature you provided. Check your key and signing method.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.