Introduction
Resticis a deduplicating backup program written in Go that has earned 32,774 stars on GitHub. While most developers think of restic as a command‑line tool, the project also exposes a Go package (github.com/restic/restic) that lets you embed backup logic directly into your applications. This library is valuable because it handles secure, encrypted, incremental backups with minimal boilerplate, letting you focus on business logic rather than low‑level file handling.
Developers care about restic for several reasons:
- Built‑in encryption – all data is encrypted before it leaves the host, using the industry‑standard AES‑256‑GCM.
- Content‑addressed storage – identical files are stored only once, dramatically reducing repository size.
- Cross‑platform repository backends – local disk, NFS, S3, Azure Blob, and more can be used as storage backends. * Programmatic API – you can invoke backup, restore, prune, and check operations from Go code, making it ideal for automated CI/CD pipelines, server‑side agents, or custom backup orchestrators.
Typical use cases include:
- Nightly backups of database dumps or configuration files on a fleet of micro‑services.
- Archival of user‑generated content in SaaS applications, where storage costs are a concern.
- Disaster‑recovery workflows that need to verify integrity and authenticity of restored data. Because restic is written in Go, you can embed it as a library without spawning external processes, gaining performance benefits and easier testing. The following sections walk you through its most useful features, installation, a minimal “Hello World” program, and production‑grade examples that you can drop into your own services.
— ## Key Features
| Feature | Why It Matters | Comparison to “Vanilla” Go |
|---|---|---|
| Deduplication | Stores each unique chunk only once, saving space and bandwidth. | Standard io/ioutil or os.File only copy bytes; you’d need a custom chunking algorithm. |
| Authenticated Encryption | AES‑256‑GCM with a per‑repository key; tampering is detected automatically. | Go’s crypto package can encrypt, but you must manage IVs, authentication tags, and key rotation yourself. |
| Multiple Repository Backends | Local FS, SSH, S3, Azure, GCS, etc., via the same API. | Using net/http or aws-sdk directly would require separate code paths for each provider. |
| Incremental Snapshots | Only new or changed data is uploaded; snapshots are cheap to create. | A naive copy‑every‑night approach repeats large amounts of unchanged data. |
| Pruning & Lifecycle Management | Automatic removal of old snapshots based on retention policies. | You’d need to track snapshot metadata and implement retention logic manually. |
| Context‑aware Operations | Supports context.Context for cancellation, timeouts, and graceful shutdowns. |
Manual signal handling or os/signal is required without the library. |
| Rich Error Types | Detailed, machine‑readable errors (e.g., ErrLockBusy, ErrCheckFailed). |
Errors from raw os calls are often opaque or require extensive parsing. |
| Testable API | Functions accept interfaces, enabling mock repositories in unit tests. | Hard to mock low‑level file system calls without additional abstraction layers. |
These capabilities make restic more than a backup tool – it is a robust, production‑ready storage engine that can be embedded in any Go service that needs reliable, secure data protection.
Installation and Setup
To start using the restic library in your own Go modules, run the following command to fetch the latest stable release:
Version requirement – The library targets Go 1.21 or newer. Earlier versions may compile but could miss recent bug fixes.
No external dependencies are required beyond the standard library; the module pulls in only the Go standard packages it needs.
Verify installation with a tiny program that prints the library version:
1package main
2
3import (
4 "fmt"
5 "github.com/restic/restic"
6)
7
8func main() {
9 fmt.Printf("restic library version: %s\n", restic.Version)
10}
Execute it with go run. You should see something like: ```
restic library version: v0.16.4
1
2If the version prints correctly, the library is ready for use. ---
3
4## Basic Usage
5
6Below is a **complete, runnable example** that demonstrates the simplest possible backup operation:
7
81. **Create (or open) a local repository**.
92. **Add a small file** to the repository as a snapshot.
103. **List existing snapshots** to confirm the operation succeeded.
11
12```go
13package main
14
15import (
16 "fmt"
17 "log"
18 "os"
19
20 "github.com/restic/restic"
21)
22
23func main() {
24 // -----------------------------------------------------------------
25 // 1️⃣ Open (or create) a repository at ./myrepo with password "secret"
26 // -----------------------------------------------------------------
27 repoPassword := "secret"
28 repoPath := "./myrepo"
29
30 // Open will create the repository directory if it does not exist.
31 repo, err := restic.Open(repoPath, repoPassword)
32 if err != nil {
33 log.Fatalf("failed to open repository: %v", err)
34 }
35 defer repo.Close()
36
37 // -----------------------------------------------------------------
38 // 2️⃣ Create a snapshot of the current directory (".")
39 // -----------------------------------------------------------------
40 // The Backup call returns a Snapshot ID (a short SHA‑256 hash).
41 snapID, err := repo.Backup(".", "my-first-backup")
42 if err != nil {
43 log.Fatalf("backup failed: %v", err)
44 }
45 fmt.Printf("Created snapshot %s\n", snapID)
46
47 // -----------------------------------------------------------------
48 // 3️⃣ List all snapshots in the repository
49 // -----------------------------------------------------------------
50 snaps, err := repo.Snapshots()
51 if err != nil {
52 log.Fatalf("listing snapshots failed: %v", err)
53 }
54 fmt.Println("Snapshots in repository:")
55 for _, s := range snaps {
56 fmt.Printf(" - %s ( %s )\n", s.ID, s.Time)
57 }
58}
Explanation of each line
| Line(s) | Purpose |
|---|---|
repo, err := restic.Open(repoPath, repoPassword) |
Opens an existing repository or creates a new one under repoPath. The password protects the repository encryption key. |
snapID, err := repo.Backup(".", "my-first-backup") |
Takes a snapshot of the current working directory (.). The second argument is a human‑readable tag that will appear in the snapshot metadata. |
snaps, err := repo.Snapshots() |
Retrieves a slice of all snapshots stored in the repository, allowing you to verify that the backup succeeded. |
defer repo.Close() |
Ensures the underlying file handles are released when main exits. |
Expected output (assuming the repository is empty before the run):
1Created snapshot 0e9b4c9c
2Snapshots in repository:
3 - 0e9b4c9c ( 2025-09-27 14:32:10 +0000 UTC )
The program demonstrates repository initialization, snapshot creation, and listing – the core workflow for any backup‑oriented application built on restic.
Real‑World Examples
The following three