Backups in 2026: revisit restic, BorgBackup and Kopia before you trust another backup job
Picture a GST and accounting services firm in Surat with fourteen branches (an invented example, not a real client). Each branch has a small Linux file server for scanned invoices and client folders, the head office runs a PostgreSQL database for its billing and compliance tracker, and about forty staff laptops hold working copies of return files. The current “backup” is a nightly rsync from every branch to a NAS at head office, plus a weekly tar to a USB disk. In the March filing rush a laptop picked up ransomware, encrypted the NAS share it had mounted read-write, and the next rsync copied the encrypted files over the good ones at three branches. The USB disk was eleven days old. Three engineers now propose a proper design. One wants restic writing to the S3-compatible bucket they already run. A second wants BorgBackup over SSH to a hardened backup VM. A third wants Kopia, because KopiaUI looks friendly enough for staff laptops.
All three are open-source, deduplicating, client-side encrypted backup programs that store snapshots in a repository you own. They are not sync tools, not filesystem snapshot tools and not database backup tools, though each one sits next to those. This post compares restic, BorgBackup (Borg) and Kopia for servers and developer machines: repository format, encryption and key handling, compression, storage backends, append-only and ransomware resistance, pruning, verification, licences and security. Facts come from release notes, official documentation, source repositories, licence files and CVE records, checked on 13 October 2026. The drill near the end is my own run on this Linux box.
The short version
- A backup the infected machine can delete is only a copy. Decide first who can delete or overwrite backup data, then pick a tool. Sync copies damage forward; a versioned, deduplicated repository keeps yesterday’s good files.
- restic 0.19.1 (5 July 2026, 1:43 PM IST) is the current release. It is a single Go binary (BSD 2-Clause) with zstd compression in repository format v2 and many native backends. Append-only comes from
rest-server --append-onlyorrclone serve restic --append-only, not from restic itself. - BorgBackup 1.4.5 (19 July 2026, 4:06 AM IST) is the current stable release; the 1.2 line has ended. Borg 1.x (BSD 3-Clause) talks to local paths or to
borg serveover SSH, where append-only is a server-side setting. Borg 2.0.0b25 (28 September 2026, 4:29 AM IST) is still a beta that its README says not to use for production. - Kopia 0.23.1 (16 June 2026, 6:57 AM IST) is the current release. It is Go (Apache 2.0) with a CLI, a desktop UI, a repository server and S3 object lock support. Compression is off by default, and space from deleted snapshots returns only over full maintenance cycles.
- Security in 2026: Kopia 0.23.0 fixed a critical unauthenticated remote code execution (CVE-2026-45695) for servers started without a password. Borg 1.4.5 fixed a low-severity extract issue (GHSA-gfp8-w835-v44j). I found no CVE for restic itself; two 2026 rclone CVEs affect
rclone serve restic. - In my drill on one VM, all three tools backed up a 402.7 MiB dataset, restored 2,996 of 2,996 files with matching hashes and timestamps, and caught a flipped byte in a full data check. restic
checkand a Kopia snapshot verify without file reads both missed it.
Where things stand on 13 October 2026
Dates are from each project’s GitHub release page; times are converted from UTC to IST. Licences are from the LICENSE files at the tagged release.
Project
Release
Date (IST)
Notes
Licence
restic
0.19.1
5 July 2026, 1:43 PM
Current release; bug fixes on top of 0.19.0 (mount, SFTP on Windows servers, excludes)
BSD 2-Clause
restic
0.19.0
9 June 2026, 10:36 PM
zstd fastest/better levels, check by snapshot filter, prune repacks small packs by default, faster index loading, restore ownership by name
BSD 2-Clause
restic
0.18.1
21 September 2025, 11:54 PM
Bug fixes on 0.18
BSD 2-Clause
restic
0.18.0
28 March 2025, 1:04 AM
Mitigation for an attack on the content-defined chunker; experimental S3 cold storage
BSD 2-Clause
restic rest-server
0.14.0
1 June 2025, 2:02 AM
Companion REST backend with --append-only and --private-repos
BSD 2-Clause
BorgBackup
1.4.5
19 July 2026, 4:06 AM
Current stable; CVE-2026-62268 fix; “related repositories”; --quick-stats
BSD 3-Clause
BorgBackup
1.4.4
19 March 2026, 1:48 PM
Fixes on 1.4; Linux binaries built with FUSE support
BSD 3-Clause
BorgBackup
1.2.9
5 August 2025, 6:52 AM
Release notes: “likely the final 1.2.x release”; migrate to 1.4
BSD 3-Clause
BorgBackup
2.0.0b25
28 September 2026, 4:29 AM
Beta; breaking changes again (new repos needed for b25)
BSD 3-Clause
BorgBackup
2.0.0b22
22 July 2026, 6:13 PM
Beta carrying the CVE-2026-62268 fix
BSD 3-Clause
Kopia
0.23.1
16 June 2026, 6:57 AM
Current release; fixes a rare race that “might lead to a data loss”, upgrade recommended
Apache 2.0
Kopia
0.23.0
12 May 2026, 5:38 AM
Breaking: insecure unauthenticated server only on loopback (CVE-2026-45695 fix); LZ4 removed
Apache 2.0
Kopia
0.22.3
2 December 2025, 12:07 PM
Last release affected by CVE-2026-45695
Apache 2.0
Kopia
0.22.0
18 November 2025, 5:58 AM
Quick maintenance enabled by default on repository creation; maintenance statistics
Apache 2.0
rclone
v1.75.2
9 October 2026, 4:33 PM
Optional backend bridge for restic and Kopia; serve restic CVE fixes in 1.74.4 and 1.75.0
MIT
Packaging note: restic signs SHA256SUMS with a GPG key whose fingerprint is in its install docs. Borg signs the borg-linux-glibc231-x86_64 binary with Thomas Waldmann’s GPG key, while the -gh binaries built on GitHub carry build attestations instead. Kopia signs checksums.txt with its “Kopia Builder” key. All three verified cleanly in my drill. Borg’s 1.4.5 .asc was made on 31 July 2026, twelve days after the release, so do not assume a signature exists the hour a release appears.
Timeline
Date (IST)
Event
9 July 2013
jborg/attic repository created; Attic by Jonas Borgström is the code Borg later forks
27 April 2014
restic/restic repository created (BSD 2-Clause, Alexander Neumann)
13 May 2015
borgbackup/borg repository created as a fork of Attic
14 September 2015
restic 0.1.0
20 December 2015
kopia/kopia repository created
5 March 2016
Borg 1.0.0
10 May 2019
First Kopia release on GitHub (v0.3.0-pre2)
22 February 2022
Borg 1.2.0; space is freed only by an explicit borg compact from 1.2 onwards
8 August 2022
Borg 2.0.0b1 (first Borg 2 beta, date from the changelog)
25 August 2022
restic 0.14.0: repository format v2 with compression
30 August 2023
CVE-2023-36811 (Borg archive spoofing) published; fixed in Borg 1.2.5 and 1.2.6 with an upgrade procedure
3 July 2024
Borg 1.4.0, “a refreshed 1.2”
28 March 2025
restic 0.18.0 with a chunker attack mitigation
6 May and 23 May 2025
Borg 2.0.0b16 removes append-only remnants; 2.0.0b17 adds BORG_REPO_PERMISSIONS (no-delete, write-only, read-only)
5 August 2025
Borg 1.2.9, likely the final 1.2.x
13 May 2026
Kopia advisory GHSA-2q4c-3mrw-63c3 (later CVE-2026-45695) published, one day after 0.23.0
9 June / 5 July 2026
restic 0.19.0 and 0.19.1
16 June / 19 July 2026
Kopia 0.23.1; Borg 1.4.5
27 August 2026
Borg advisory GHSA-gfp8-w835-v44j published
28 September 2026
Borg 2.0.0b25
Borg users today choose between a mature 1.4 line and a much-changed Borg 2 that is still beta after four years of betas. restic and Kopia are both still on 0.x version numbers, which says more about versioning habits than maturity; both have stable repository formats.
First question: who can delete your backups?
The Surat failure was not about which program copied the files; the machine being protected could destroy the protection. Before comparing tools, write down retention, RPO, RTO, and which credentials can delete or overwrite backup data.
Need
Sync or snapshot alone
Needs a backup repository
Mirror a folder to another disk
rsync, rclone sync
Undo yesterday’s accidental delete
Filesystem snapshots may do
Versioned snapshots with retention
Survive ransomware on a client
Repository the client cannot delete: append-only server, object lock or a pull model
Keep 7 daily, 4 weekly, 12 monthly versions cheaply
Deduplication plus a retention policy
Keep data private on a third-party bucket
Client-side encryption
Prove a restore works
Regular check plus a real restore test
The 3-2-1 habit still holds: three copies, two kinds of storage, one off-site. The off-site copy is only safe if its credentials are not sitting on every branch server.
What these three tools actually are
restic 0.19.1
restic is a single Go binary. A repository is a directory of encrypted files: a config file, keys, snapshots, index and data packs. Files are split with content-defined chunking based on Rabin fingerprints with a per-repository secret polynomial. Files smaller than 512 KiB are not split, and blobs range from 512 KiB to 8 MiB, aiming at about 1 MiB on average, before they are packed into pack files.
Encryption is AES-256 in counter mode with a Poly1305-AES MAC. The repository master key is stored in one or more key files, each encrypted with a key derived from a password using scrypt. restic key add, key list, key remove and key passwd manage several passwords for one repository, which helps when an operations team and a break-glass account both need access. Repository format v2, the default since 0.14.0, adds zstd compression; --compression auto is the default, and 0.19.0 added the fastest and better levels next to max and off.
Native backends listed in the 0.19.1 docs: local, SFTP, REST server, Amazon S3 and S3-compatible stores (MinIO, Wasabi, Alibaba OSS and others), OpenStack Swift, Backblaze B2, Azure Blob Storage and Google Cloud Storage, plus anything rclone supports through rclone: URLs. Retention is restic forget with --keep-last, --keep-daily, --keep-within and similar options, followed by prune (or forget --prune). restic check checks structure; check --read-data reads and verifies every pack, and --read-data-subset=n/t spreads that cost over several runs. restic copy copies snapshots between repositories, which is the simple way to keep a second off-site repository.
Recent changes: 0.19.0 made prune repack small packs by default, let check select snapshots by filter, sped up index loading, and fixed a rare loss of split index entries in old format v1 repositories (repair packs fixes it). 0.18.0 randomised how chunks are assembled into packs, to blunt a published attack on the chunker; the changelog rates the practical risk as low.
BorgBackup 1.4.5 (and the Borg 2 beta)
Borg 1.x is Python with performance-critical parts in C and Cython, and ships standalone binaries so servers need no Python install. A repository is a directory of append-only segment files (500 MiB maximum by default), an index, hints and a config file. The default chunker is buzhash with parameters 19,23,21,4095: 512 KiB minimum, 8 MiB maximum, about 2 MiB target.
Encryption is chosen at borg init and cannot be changed later. The 1.4 docs give a rule of thumb: use repokey with a strong passphrase. repokey and keyfile use AES-CTR-256 with HMAC-SHA256; the -blake2 variants use BLAKE2b-256 for authentication and the chunk ID hash, which can be faster on CPUs without SHA acceleration. authenticated modes detect tampering without encrypting, and none does neither. With repokey the encrypted key lives in the repository; with keyfile it lives on the client, so stealing the repository is not enough. Either way, run borg key export (there is a --paper format) and keep that export away from the repository. Passphrases are stretched with PBKDF2-HMAC-SHA256 according to the security internals page. Compression defaults to lz4; zstd, zlib, lzma, auto (only compress what looks compressible) and obfuscate (pad stored sizes against fingerprinting) are available.
Borg 1.4 reaches remote repositories only through ssh:// URLs with borg serve running on the remote host, so the server needs a compatible Borg too. There is no native S3 backend in 1.4; people who want object storage either sync a Borg repository with rclone (the docs suggest smaller segments for that) or wait for Borg 2. Retention is borg prune with --keep-daily, --keep-weekly and similar, and since 1.2 the space is actually freed only when borg compact runs. borg check verifies repository segments and archive metadata; borg check --verify-data also decrypts and verifies every chunk. 1.4.5 adds “related repositories”, which share deduplication secrets while keeping separate encryption keys.
Borg 2 is a different animal. The b25 changelog lists new commands (repo-create instead of init, repo-list, repo-info), new encryption modes (aes256-ocb, chacha20-poly1305, authenticated-sha256, authenticated-blake3), and storage through borgstore with file, SSH, SFTP, HTTP(S) REST server, rclone and S3/B2 URLs. Archives from 1.x come across with borg transfer, which requires the source to be on 1.2.6 or later with the CVE-2023-36811 upgrade steps done. The master README says Borg 2 is in beta, may break between betas, and should not be used for production backups. Plan on 1.4 and test Borg 2 on the side.
Kopia 0.23.1
Kopia is Go, like restic, and ships a CLI, KopiaUI (a desktop app) and a repository server that clients can talk to instead of holding storage credentials themselves. Files are split by a content-defined splitter (DYNAMIC-4M-BUZHASH by default) and packed into p blobs, with indexes managed by an epoch manager.
Encryption defaults to AES256-GCM-HMAC-SHA256, with CHACHA20-POLY1305-HMAC-SHA256 as the alternative. The password is stretched with scrypt (N=65536, r=8, p=1) according to the encryption docs, and the default content hash is BLAKE2B-256-128. Compression is a per-path or global policy and is off by default: kopia policy show --global on a fresh 0.23.1 repository printed “Compression disabled”, with only metadata compressed using zstd-fastest. Supported compressors include zstd, s2, pgzip, gzip and deflate; LZ4 was removed in 0.23.0. The compression docs include a benchmark table, which is Kopia’s own run on its own sample file. Error correction (--ecc) is marked experimental.
Storage locations in the docs: local or network filesystem, Amazon S3 and S3-compatible stores (with object lock and storage classes), Azure Blob, Backblaze B2, Google Cloud Storage, Google Drive (native support is experimental), WebDAV, SFTP, rclone (experimental, tested with Dropbox, OneDrive and Google Drive) and a Kopia repository server. Retention lives in policies; the global defaults I saw were 10 latest, 48 hourly, 7 daily, 4 weekly, 24 monthly and 3 annual snapshots. kopia snapshot verify checks that snapshot contents exist; add --verify-files-percent=100 to read files back, or use kopia content verify --download-percent=100.
Maintenance is Kopia’s distinctive operational piece. Quick maintenance runs roughly every hour and full maintenance every 24 hours, driven by one designated maintenance owner (user@host). Full maintenance marks unreachable contents, rewrites and deletes packs, and the docs warn that its effects are not immediate: removing unused blobs may take several hours or multiple cycles because of safety rules for concurrent clients. --safety=none speeds this up but is only safe when nothing else is writing.
Feature comparison
Area
restic 0.19.1
Borg 1.4.5
Kopia 0.23.1
Language and packaging
Go, single binary
Python + C, standalone PyInstaller binaries or pip
Go, single binary, KopiaUI, repository server
Chunking
Rabin CDC, 512 KiB to 8 MiB, ~1 MiB average
buzhash, 512 KiB to 8 MiB, ~2 MiB target
buzhash splitter, DYNAMIC-4M-BUZHASH default
Encryption
AES-256-CTR + Poly1305-AES, always on
Chosen at init: AES-CTR-256 + HMAC-SHA256 or BLAKE2b, authenticated-only, or none
AES256-GCM-HMAC-SHA256 (default) or ChaCha20-Poly1305, always on
Password stretching
scrypt
PBKDF2-HMAC-SHA256
scrypt
Several passwords per repo
Yes (restic key add)
No; one passphrase per key, export the key
One repository password; per-user passwords via repository server
Compression default
zstd auto (repo v2)
lz4
Off; enable via policy
Parallelism
Multi-threaded
Single-threaded per borg create
Multi-threaded
Remote access
Many native backends + rclone
borg serve over SSH only
Many native backends + rclone + repository server
Copy to second repo
restic copy
Separate repo, or sync the repo files
kopia repository sync-to
Mount snapshots
restic mount (FUSE)
borg mount (FUSE)
kopia mount
Key handling in practice
Lose the password (and for Borg, the key) and the data is gone. That is the point of client-side encryption, and a common way small teams lose backups. For the Surat firm:
- Keep repository passwords in a secrets manager, not in a script on the branch server; the Vault and OpenBao post covers the options. restic and Borg can fetch a password by command (
RESTIC_PASSWORD_COMMAND,BORG_PASSCOMMAND); Kopia readsKOPIA_PASSWORDor a keyring. - For Borg, export the repository key once with
borg key exportand store it with the passphrase in two places, at least one offline. - For restic, add a second key for a break-glass account with
restic key add, and test it. - For Kopia staff laptops, prefer a repository server so laptops hold a per-user server password, not the bucket’s access key.
Backends, S3 targets and where the bytes live
Backend
restic
Borg 1.4
Kopia
Local disk or NAS mount
Yes
Yes
Yes
SFTP
Yes
No (uses borg serve over SSH instead)
Yes
SSH with server-side process
No
borg serve (needs Borg on server)
No (repository server is HTTPS)
Own REST server
rest-server
Borg 2 only (borgstore REST)
Kopia repository server
S3 and S3-compatible
Native
Borg 2 only
Native, with object lock
B2, Azure, GCS
Native
Borg 2: S3/B2 only
Native
rclone
Yes
Borg 2 only
Yes (experimental)
restic and Kopia can write straight to the Surat firm’s S3-compatible store. The MinIO alternatives post compares self-hosted S3 options; check that yours implements object lock and versioning before you rely on them. A target on the same storage cluster as production is not off-site.
Ransomware resistance: append-only, object lock and pull
A client that can delete its own backups will, sooner or later, delete them. Each tool solves this in a different layer.
Approach
restic
Borg 1.4
Kopia
Append-only server
rest-server --append-only; rclone serve restic --append-only
borg serve --append-only in authorized_keys, or append_only 1 in repo config
No separate append-only mode in the docs; use object lock, or a repository server so clients never hold storage keys
Object lock (WORM) on S3
Not a documented restic feature; any bucket-side lock sits outside restic
No (1.4)
--retention-mode COMPLIANCE --retention-period 30d, extension by full maintenance
Restrict server paths
rest-server --private-repos
--restrict-to-path, --restrict-to-repository
Per-user ACLs on repository server
Admin client for pruning
Separate trusted client runs forget/prune
Temporarily normal mode from a trusted client; review before compact
Maintenance owner runs full maintenance
Three cautions from the docs. restic warns that an attacker who adds junk snapshots to an append-only repository can make a careless forget --keep-last delete the real ones, so use --keep-within there. Borg’s append-only never deletes committed segments, but delete and prune still appear to work; you roll back with the transaction log, and plain rm on the server ignores append-only. Kopia warns that ransomware could abuse object lock by uploading large data with a long lock, so set bucket quotas. Borg 2 betas removed append-only and use a permissions setting (no-delete, write-only, read-only) through BORG_REPO_PERMISSIONS or borg serve --permissions.
A pull model, where the backup server reads clients with read-only access, is another answer; Borg documents pull backups over sshfs.
Retention, pruning and getting space back
Step
restic
Borg 1.4
Kopia
Choose what to keep
forget --keep-daily 7 --keep-weekly 4 ...
prune --keep-daily 7 --keep-weekly 4 ...
Policy: latest, hourly, daily, weekly, monthly, annual
Dry run
forget --dry-run
prune --dry-run --list
snapshot expire without --delete
Free space
prune (or forget --prune)
compact
Full maintenance, over one or more cycles
Default schedule
Whatever you schedule
Whatever you schedule
Quick about hourly, full every 24 h
In my drill, after deleting 80 MiB of files and keeping only the newest snapshot, restic released 83.4 MiB in one forget --prune and Borg 95.0 MiB after prune and compact. Kopia’s first full maintenance with --safety=none found 102.5 MB of unused contents but did not shrink the repository; the second cycle released 38.2 MiB and the third nothing more. That matches the docs, but size a Kopia bucket with headroom.
Check, verify and restore testing
Every tool has a cheap check and an expensive check. The cheap one confirms that the index and metadata are consistent. Only the expensive one reads the data and proves the bytes still decrypt and authenticate.
Level
restic
Borg 1.4
Kopia
Structure
check
check (also reads segment CRCs)
snapshot verify
All data
check --read-data
check --verify-data
content verify --download-percent=100 or snapshot verify --verify-files-percent=100
Partial data over time
--read-data-subset=1/5
--max-duration for repository part
--verify-files-percent=10
Real restore
restore latest --target
extract
snapshot restore
My tamper test (one flipped byte, details in the drill) showed the gap: restic check and a plain Kopia snapshot verify passed a damaged repository, while every full data check failed it. Borg’s plain check also failed it, because its repository part reads all segments. Schedule the expensive check, or a rolling subset, and do a real restore into a scratch directory at least monthly. Compare hashes, not just file counts.
Databases need consistent dumps first
File-level backup of a running PostgreSQL data directory gives you a copy that may not start. Take a consistent dump or a storage snapshot first, then back that up.
- PostgreSQL:
pg_dumpfor logical backups, or a base backup plus WAL archiving for point-in-time recovery. For clusters, the PostgreSQL high availability post covers Patroni and CloudNativePG, which bring their own backup integrations; a replica is not a backup. - restic can read a dump directly:
restic backup --stdin-from-command -- pg_dump -Fc billing. If the command fails, restic does not record a snapshot from its output. - Borg 1.4 has
borg create --content-from-commandfor the same purpose. - Kopia can snapshot stdin with
--stdin-file, and policy actions can run a dump script before a snapshot. - Restore the dump into a test database in your monthly drill. A dump that
pg_restorerejects gives false comfort.
Performance considerations
A few structural points hold regardless of anyone’s benchmark:
- Borg 1.x runs one
borg createon one core for chunking, compression and encryption. restic and Kopia use several cores, which matters most for first backups of large file servers. - Memory grows with repository size because each tool keeps or caches a chunk index. restic 0.19.0 reduced memory for
check,copy,diffandstats; Borg’s FAQ covers scalability; Kopia’s content cache size is configurable. - Later backups are cheap when the tool skips unchanged files by size, mtime and inode; a no-change rerun took under a second for all three in my drill.
- Larger average chunks (Borg, Kopia) cost more new data for small edits inside large files than restic’s 1 MiB average.
- Compression settings change the picture more than the tool does: Kopia stored 355.2 MiB without compression and 223.7 MiB with a zstd policy, against restic’s 223.4 MiB.
- The rest-server README says restic’s REST protocol is faster than SFTP, which moves data in small acknowledged packets.
Licences, history and governance
Item
restic
BorgBackup
Kopia
Licence at current tag
BSD 2-Clause (copyright Alexander Neumann, 2014)
BSD 3-Clause (The Borg Collective 2015 to 2026; Jonas Borgström 2010 to 2014)
Apache 2.0
Origins
Started 2014; 0.1.0 in September 2015
Fork of Attic in May 2015; 1.0 in March 2016
Repository from December 2015; first GitHub release May 2019
Governance
Community project on GitHub with a forum; release signing key of the founder
“The Borg Collective”; releases built and signed by maintainer Thomas Waldmann
Community project on GitHub; 2025 to 2026 release notes credit most changes to a small set of maintainers
Stable vs next
0.19.x only
1.4.x stable, 2.0 beta
0.23.x only
All three are permissively licensed, with none of the relicensing stories earlier Revisit.Tech posts had to cover. The real governance risk is the usual one for volunteer projects: a few people sign releases and review security fixes. That argues for pinning versions, verifying signatures and following advisories.
Security and CVEs
restic
In NVD keyword search and the repository’s GitHub security advisories on 13 October 2026, I found no CVE assigned to restic itself. The closest items are in a companion tool: rclone’s serve restic had CVE-2026-59733 (CVSS 8.8; --private-repos authorisation bypass with .. in the path, fixed in rclone 1.74.4, published 15 July 2026, 3:08 AM IST) and CVE-2026-71309 (CVSS 4.0 score 8.6; backend root escape with a leading ../, fixed in 1.75.0, published 6 August 2026, 1:43 AM IST). If you use rclone as the append-only endpoint for restic, run rclone 1.75.0 or later. restic 0.18.0’s chunker mitigation is a hardening change without a CVE.
BorgBackup
ID
Severity (source)
What
Fixed
GHSA-gfp8-w835-v44j (lists CVE-2026-62268)
Low (GitHub advisory)
A crafted archive could make borg extract follow a symlink, .. or hard link outside the target directory
1.4.5; 2.0.0b22; 1.2.x fix commits only
CVE-2023-36811
4.7 (CNA record)
Archive spoofing via a flaw in the authentication scheme
1.2.5 / 1.2.6 plus documented upgrade steps
CVE-2017-15914
(no CNA score)
Access control override in Borg servers 1.1.x before 1.1.3
1.1.3
CVE-2016-10099, CVE-2016-10100
(no CNA score)
Manifest spoofing and archive overwrite during recovery
1.0.9
The 2026 advisory needs repository write access and, for encrypted repositories, the key and passphrase, hence the low rating. On 13 October 2026 the CVE Program API returned “record does not exist” for CVE-2026-62268, so I cite the GitHub advisory, which also confirms no new 1.2 releases.
Kopia
ID
Severity
What
Fixed
CVE-2026-45695 (GHSA-2q4c-3mrw-63c3)
9.8 critical (GitHub CNA)
Server started with --insecure --without-password accepted unauthenticated requests; an SFTP storage config with external SSH arguments allowed -oProxyCommand command execution
0.23.0 (refuses insecure unauthenticated server on non-loopback addresses)
GHSA-j5vm-7qcc-2wwg
2.0 low
kopia repository status --json printed storage credentials
0.16.0
The CVE is serious but narrow: it needs a server started without a password and reachable over the network, exactly the shortcut people take on a “temporary” office server.
Practical controls
- Run restic 0.19.1, Borg 1.4.5 and Kopia 0.23.1 or newer, and rclone 1.75.0 or newer if it is in the path.
- Verify downloads with the published GPG keys or attestations before you install a backup binary on every server.
- Never start a Kopia server without a password or TLS, and do not expose it beyond the network that needs it.
- Give backup clients write-without-delete access (append-only server, object lock,
--restrict-to-repository), and run pruning from a separate trusted host. - Keep repository passwords and Borg key exports in a secrets manager and in one offline place.
- Do not extract untrusted archives with old Borg versions; treat archives from shared repositories as untrusted input.
- Alert on backup jobs that did not run, not only on jobs that failed.
Decision guide for the Surat scenario
The Surat firm needs: fourteen branch file servers, one PostgreSQL database, forty laptops, an existing S3-compatible bucket at head office, an off-site copy, and protection against a client that gets ransomware.
Option
Fit
Cost of the choice
Keep rsync + USB
Familiar
Copies damage forward; no versions; the March incident will repeat
restic to S3-compatible bucket
Good for branch servers and laptops; one binary; copy for off-site
Append-only needs rest-server or rclone in front; plan pruning from head office
Borg 1.4 over SSH to a backup VM
Good for Linux servers; mature; strong append-only story with borg serve
No native S3 in 1.4; single-threaded; Windows laptops are not its home ground
Kopia with repository server
Good for laptops (KopiaUI) and object lock on S3
Must set compression and watch maintenance; secure the server carefully after CVE-2026-45695
Recommendation for this invented Surat case:
- Make the repository not deletable by any branch server or laptop. That rules out the current design, whatever the tool.
- For the fourteen Linux branch servers, use restic to a rest-server in append-only mode at head office, or Borg 1.4 with
borg serve --append-only --restrict-to-repositoryinauthorized_keys. Both work; pick the one your team will read the docs for. - For the forty laptops, use Kopia with a repository server and per-user accounts, so laptops never hold bucket keys. Set a compression policy on day one.
- Dump PostgreSQL with
pg_dump -Fcto a file, back up that file, and restore it into a scratch database monthly. - Run pruning and full checks only from one hardened admin host.
- Keep an off-site copy (
restic copyor Kopiarepository sync-to) in another city with different credentials. - Keep passwords and key exports in the secrets manager, plus a sealed offline copy with the partner.
- Leave Borg 2 until it leaves beta.
Checklist before you trust a backup job
- Write down RPO, RTO and retention per data class (client files, database, laptops).
- Confirm which credential can delete backup data, and that no client holds it.
- Pin exact versions and verify signatures for every binary you roll out.
- Set compression explicitly (especially on Kopia) and record chunker and encryption choices.
- Store passwords and Borg keys in a secrets manager plus one offline copy.
- Use consistent database dumps or snapshots, never a live data directory.
- Schedule a full data check, or a rolling subset, at least monthly.
- Run a real restore to a scratch location monthly and compare hashes.
- Alert on missing runs, not just on errors.
- Test the full disaster path once a year: new machine, fresh install, only the documented password, restore.
Common mistakes
- Treating
rsyncor a cloud sync folder as backup. - Letting every client hold credentials that can delete or overwrite the repository.
- Running only the cheap
checkand calling the repository verified. - Losing the Borg key because
repokey“keeps it in the repository” and the repository is the thing that died. - Leaving Kopia compression off by accident and buying storage for it.
- Expecting Kopia to return space immediately after snapshot deletion.
- Running
restic forget --keep-lastagainst an append-only repository that an attacker may have filled with junk snapshots. - Backing up a live PostgreSQL data directory and assuming it will start.
- Running Borg 2 betas in production because the features look finished.
- Starting
kopia serverwith--insecure --without-passwordon a LAN “just for setup”.
A drill I ran on 13 October 2026
Environment: shared Linux VM (Debian 13, kernel 6.12), 8 vCPU, about 15.6 GiB RAM with about 6 GiB available, local overlay filesystem, no root, no Docker. Between about 10:19 and 10:28 AM IST I downloaded and verified the three tools and ran the scripted pass quoted here (10:26 to 10:27 AM IST). Load average rose from 1.01 to 2.80 because other work shares this VM.
What ran:
- restic 0.19.1 official
linux_amd64binary;SHA256SUMSGPG signature good (fingerprint matches the restic docs) and SHA-256 matched. - BorgBackup 1.4.5 standalone
borg-linux-glibc231-x86_64; GPG signature good against the fingerprint in Borg’s support docs.borg init -e repokey, default lz4 compression. - Kopia 0.23.1
linux-x64tarball;checksums.txt.siggood against the Kopia Builder key and SHA-256 matched. Default settings, plus one variant repository with a global zstd compression policy for the first backup. - GNU time 1.10 (extracted from the Debian package) recorded wall time, CPU time and peak resident memory per command.
Dataset, all synthetic: 3,000 invoice-like text files, an 80 MiB SQL-like dump, ten 16 MiB random binaries and one 24 MiB random file stored in three places (402.7 MiB, 3,014 files). The change set appended to 30 text files, inserted 4 KiB into one binary, overwrote 64 KiB in another, added 10 MiB of new files, deleted 20 files, renamed a directory and grew the dump. Repositories were on the same local disk; numbers are from one run.
Repository size on disk (MiB) restic Borg Kopia (no compression)
after backup v1 223.4 249.3 355.2 (Kopia + zstd policy: 223.7)
added by backup v2 17.8 24.1 28.3
after keep-last-1 + reclaim 157.8 178.5 383.5 -> 345.3 after 2nd full maintenance
Wall time / peak RSS
backup v1 restic 1.55 s / 323 MiB Borg 2.90 s / 80 MiB Kopia 0.77 s / 296 MiB
no-change rerun restic 0.79 s / 61 MiB Borg 0.82 s / 81 MiB Kopia 0.18 s / 119 MiB
backup v2 restic 1.01 s / 199 MiB Borg 1.11 s / 81 MiB Kopia 0.42 s / 155 MiB
full data check restic 1.17 s / 95 MiB Borg 1.55 s / 80 MiB Kopia 1.02 s / 238 MiB
full restore restic 1.34 s / 144 MiB Borg 1.69 s / 83 MiB Kopia 0.47 s / 376 MiB
init restic 3.29 s (scrypt) Borg 0.62 s Kopia 0.49 s
peak CPU use restic 285 % Borg <= 100 % Kopia 386 % (zstd variant)
Restore vs source: 2,996 / 2,996 files, 0 hash, mtime or mode mismatches, diff -r clean (all three)
Wrong password: refused by all three (exit codes 12, 2, 1)
Tamper (one byte flipped inside live data, copy of each repo):
restic check: pass (missed) check --read-data: FAIL, named the pack
Borg check: FAIL check --verify-data: FAIL
Kopia snapshot verify: pass (missed) content verify 100 %: FAIL verify-files 100 %: FAIL restore: FAIL
What this shows:
- All three deduplicated the triple-stored file and restored identical content, timestamps and permissions.
- Defaults decide sizes: Kopia without a compression policy stored about 60 % more than restic; with zstd it matched.
- Borg stayed on one core at about 80 MiB; restic and Kopia used several cores and more memory.
- Space came back at once for restic and for Borg after
compact, and only partly, over cycles, for Kopia. - My first Kopia tamper attempt hit dead bytes left in a pack after retention, so Kopia correctly reported nothing; the quoted result is a repeat with a byte inside live content.
Limits of the drill: one VM, one run, data in page cache, local repositories only (no SFTP, S3, rest-server or borg serve), no append-only or object lock test, no Windows or macOS, small repository sizes where index memory does not matter, and timings that include process start-up. This is a smoke test, not a benchmark. Artefacts (README, scripts, logs, results) are under /workspace/revisit/drill33/. No servers were started; binaries, repositories and the dataset were deleted afterwards.
Unlearn / re-learn
Unlearn
- A nightly sync to a NAS is a backup.
- “Encrypted” means safe from ransomware.
checkpassing means the data is readable.- Deleting snapshots frees space straight away.
- A replica database or a copied data directory replaces a dump.
- A beta that has been around for years is production-ready.
Re-learn
- Ask who can delete backup data before you ask which tool to use.
- Separate the cheap structural check from the expensive data check, and schedule both.
- Set compression, retention and maintenance explicitly; defaults differ by tool.
- Keep passwords and keys in a secrets manager plus one offline copy.
- Practise a full restore, including the database, before you need it.
Closing
Self-hosted backups in 2026 come down to three solid, permissively licensed tools with different centres of gravity. Learn their repository models: restic’s packs and many backends, Borg’s segments and borg serve, Kopia’s policies, maintenance and repository server. Unlearn the habit of treating sync, snapshots or replicas as backups, and of trusting a green check. Re-learn the current versions and lines: restic 0.19.1, Borg 1.4.5 stable with Borg 2 still in beta, Kopia 0.23.1 with compression off until you turn it on. Practise with a small drill like the one above: one dataset, one change set, one full check, one restore, one flipped byte. Apply one design where no client can delete its own backups, the passwords live somewhere you can reach on a bad day, and the monthly restore test is on someone’s calendar.
Sources
restic
- restic 0.19.1 GitHub release
- restic 0.19.0 GitHub release
- restic 0.18.1 GitHub release
- restic 0.18.0 GitHub release
- restic 0.14.0 GitHub release
- restic 0.1.0 GitHub release
- restic LICENSE at v0.19.1
- restic design document
- restic design.rst at v0.19.1
- restic: Installation and signature verification
- restic: Preparing a new repository (backends)
- restic: Backing up (stdin from command)
- restic: Working with repositories (check, copy)
- restic: Removing backup snapshots (forget, prune, append-only)
- restic: Encryption and keys
- restic rest-server README
- restic rest-server 0.14.0 release
- restic issue 5291: chunker attack mitigation
- Chunking Attacks on File Backup Services using Content-Defined Chunking (IACR ePrint 2025/532)
BorgBackup
- Borg 1.4.5 GitHub release
- Borg 1.4.4 GitHub release
- Borg 1.2.9 GitHub release
- Borg 2.0.0b25 GitHub release
- Borg 2.0.0b22 GitHub release
- Borg changelog at 1.4.5
- Borg 2 changelog at 2.0.0b25
- Borg README on master (Borg 2 beta warning)
- Borg LICENSE at 1.4.5
- Borg 1.4 overview
- BorgBackup home page
- Borg 1.4.5 docs: borg init (encryption modes)
- Borg 1.4.5 docs: borg serve
- Borg 1.4.5 docs: additional notes (append-only, segment size)
- Borg 1.4.5 docs: borg compact
- Borg 1.4.5 docs: borg check
- Borg 1.4.5 docs: security internals
- Borg 1.4.5 docs: support and release signing
- Borg 1.4.5 docs: quick start
- Borg 1.4.5 docs: FAQ
- Attic repository (Borg’s origin)
Kopia
- Kopia 0.23.1 GitHub release
- Kopia 0.23.0 GitHub release
- Kopia 0.22.3 GitHub release
- Kopia 0.22.0 GitHub release
- Kopia LICENSE at v0.23.1
- Kopia issue 5371 (race condition fixed in 0.23.1)
- Kopia pull request 5354 (loopback-only insecure server)
- Kopia docs: installation and signature verification
- Kopia docs: supported storage locations
- Kopia docs: encryption
- Kopia docs: compression
- Kopia docs: maintenance
- Kopia docs: ransomware protection
- Kopia docs: repository server
- Kopia docs: synchronization
- Kopia docs: features
Related tools
- rclone v1.75.2 release
- rclone serve restic
- PostgreSQL docs: backup and restore
- PostgreSQL docs: pg_dump
Security (CVE Program records and GitHub advisories)
- CVE-2026-45695 (Kopia)
- GHSA-2q4c-3mrw-63c3 (Kopia)
- GHSA-j5vm-7qcc-2wwg (Kopia)
- GHSA-gfp8-w835-v44j (Borg, lists CVE-2026-62268)
- GHSA-8fjr-hghr-4m99 (Borg CVE-2023-36811)
- CVE-2023-36811 (Borg)
- CVE-2017-15914 (Borg)
- CVE-2016-10099 (Borg)
- CVE-2016-10100 (Borg)
- CVE-2026-59733 (rclone serve restic)
- CVE-2026-71309 (rclone serve restic)
Internal Revisit.Tech links used in the body
Releted Posts
Distributed tracing in 2026: revisit Jaeger, Grafana Tempo and SigNoz before you store another span
Picture a bus, train and hotel booking platform in Kochi (an invented example, not a real client). Customers book from an Android app, an iOS app and a web app.
Read moreFeature flags in 2026: revisit Unleash, Flagsmith and GrowthBook before you hard-code another release toggle
Picture a test-preparation and online classes platform in Jaipur (an invented example, not a real client). Students use an Android app, an iOS app and a React web app.
Read moreLakehouse table formats in 2026: revisit Apache Iceberg, Delta Lake and Apache Hudi before you pick another format
Picture a payments and lending analytics platform in Hyderabad (an invented example, not a real client). Card authorisations and EMI schedules still land in PostgreSQL 16.
Read more