Kopia is an open source backup tool that takes encrypted, deduplicated and compressed snapshots of directories and stores them in a repository on local disk, SFTP or object storage. Retention, compression and exclusions are defined as policies, and repository cleanup runs automatically. In this tutorial you will install Kopia on Ubuntu 24.04, create a repository in an S3-compatible bucket, set policies, back up /etc and /var/www, restore files, and schedule daily snapshots with a systemd timer.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS with at least 1 GB of RAM, for example a CubePath VPS.
- A non-root user with
sudoprivileges. Snapshots run asrootso they can read every file. - An S3-compatible bucket (AWS S3, Wasabi, Backblaze B2 S3 API, MinIO and similar) with its endpoint, region, access key and secret key. The last part of Step 2 shows how to use a local disk instead.
Step 1 - Installing Kopia from the official repository
Kopia publishes signed packages for Debian and Ubuntu. Download the signing key into the standard keyring directory:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://kopia.io/signing-key | sudo gpg --dearmor -o /etc/apt/keyrings/kopia-keyring.gpg
Add the repository:
echo "deb [signed-by=/etc/apt/keyrings/kopia-keyring.gpg] http://packages.kopia.io/apt/ stable main" | sudo tee /etc/apt/sources.list.d/kopia.list
The repository uses plain HTTP, but packages are verified against the signing key, so tampering would be detected. Install Kopia:
sudo apt update
sudo apt install kopia
Verify the installation:
kopia --version
0.21.1 build: 5a7b3c0e from: kopia/kopia
Step 2 - Creating a repository in S3-compatible storage
A repository is where Kopia stores encrypted content, and all snapshots from all machines connected to it are deduplicated together. Create one in your bucket. The --prefix lets several servers or repositories share one bucket:
sudo kopia repository create s3 \
--bucket=your_bucket \
--prefix=kopia/web01/ \
--endpoint=s3.your_provider.com \
--region=your_region \
--access-key=your_access_key \
--secret-access-key=your_secret_key
Kopia asks for a new repository password twice. That password encrypts everything in the repository.
WarningSave the repository password in a password manager. If you lose it, the backups cannot be decrypted by anyone.
When creation finishes, Kopia connects to the repository and saves the connection settings (including the password) under /root/.config/kopia/, readable only by root. Later kopia commands run as root reuse that connection without asking. Check it:
sudo kopia repository status
Config file: /root/.config/kopia/repository.config
Description: Repository in S3: s3.your_provider.com your_bucket
Hostname: web01
Username: root
Read-only: false
Format blob cache: 15m0s
Storage type: s3
...
Encryption: AES256-GCM-HMAC-SHA256
Splitter: DYNAMIC-4M-BUZHASH
Kopia records snapshots as username@hostname:/path, so each server's snapshots stay separate even in a shared repository.
If you only want to try Kopia, or want a first copy on a second disk, a filesystem repository works the same way:
sudo mkdir -p /mnt/backup/kopia
sudo kopia repository create filesystem --path=/mnt/backup/kopia
You can be connected to one repository at a time per configuration file. Continue the guide with the S3 repository.
Step 3 - Setting retention, compression and exclusions
Policies decide how many snapshots to keep, whether to compress, and what to skip. The global policy applies to every path unless a more specific policy overrides it. Kopia does not compress by default, so turn on zstd, and define a retention schedule:
sudo kopia policy set --global \
--compression=zstd \
--keep-latest=10 \
--keep-hourly=0 \
--keep-daily=14 \
--keep-weekly=8 \
--keep-monthly=12 \
--keep-annual=2
This keeps the 10 most recent snapshots, plus the latest snapshot of each of the last 14 days, 8 weeks, 12 months and 2 years. A snapshot is kept if any rule selects it.
Exclusions use .gitignore syntax and can be set per directory. Skip caches and dependencies inside the web root:
sudo kopia policy set /var/www \
--add-ignore=node_modules \
--add-ignore=cache \
--add-ignore="*.log"
Review the effective policy for a path. The output shows where each value comes from (global or path-specific):
sudo kopia policy show /var/www
Step 4 - Creating your first snapshots
Estimate how much data a path contains before uploading it:
sudo kopia snapshot estimate /var/www
Create snapshots of both directories:
sudo kopia snapshot create /etc /var/www
Snapshotting root@web01:/etc ...
* 0 hashing, 1204 hashed (2.1 MB), 0 cached (0 B), uploaded 812 KB, estimated 2.1 MB (100.0%) 0s left
Created snapshot with root k3f1c0a9e5b7d2a41c8e6f0b9d3a7c521 and ID 6d0f9a1c3e5b7f2a in 1s
Snapshotting root@web01:/var/www ...
Created snapshot with root k9b2e4d6f8a0c1e3b5d7f9a1c3e5b7d90 and ID 1a3c5e7f9b0d2f4a in 42s
Run the same command again. Only changed files are read and only new content is uploaded, so it finishes much faster. List the snapshots of a path:
sudo kopia snapshot list /var/www
root@web01:/var/www
2026-09-25 10:21:07 UTC k9b2e4d6f8a0c1e3b5d7f9a1c3e5b7d90 1.2 GB drwxr-xr-x files:18342 dirs:2210 (latest-2)
2026-09-25 10:24:31 UTC k9b2e4d6f8a0c1e3b5d7f9a1c3e5b7d90 1.2 GB drwxr-xr-x files:18342 dirs:2210 (latest-1,daily-1,weekly-1,monthly-1,annual-1)
The labels in parentheses show which retention rules keep each snapshot. Snapshots that no rule selects any more are removed automatically at the end of the next snapshot of that path.
Step 5 - Restoring files
Browse the contents of a snapshot with kopia ls, using the root ID (the value that starts with k) from the list:
sudo kopia ls -l k3f1c0a9e5b7d2a41c8e6f0b9d3a7c521/nginx
Restore a single file by appending its path to the root ID:
sudo kopia restore k3f1c0a9e5b7d2a41c8e6f0b9d3a7c521/nginx/nginx.conf /tmp/nginx.conf
Restore a whole snapshot to a new directory, which is the safest way to test backups:
sudo kopia restore k9b2e4d6f8a0c1e3b5d7f9a1c3e5b7d90 /srv/restore-www
sudo diff -rq /var/www /srv/restore-www
Files that diff reports only in /var/www should match your ignore rules. Remove /srv/restore-www when you are done.
Step 6 - Scheduling daily snapshots with systemd
kopia snapshot create --all snapshots every path that already has snapshots from this user and host, so new directories only need one manual snapshot to join the schedule. Create a service:
sudo nano /etc/systemd/system/kopia-snapshot.service
[Unit]
Description=Kopia snapshot of all configured paths
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=root
Nice=10
IOSchedulingClass=idle
ExecStart=/usr/bin/kopia snapshot create --all
User=root makes systemd set HOME=/root, which Kopia needs to find its configuration. Create the timer:
sudo nano /etc/systemd/system/kopia-snapshot.timer
[Unit]
Description=Daily Kopia snapshots
[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true
[Install]
WantedBy=timers.target
Enable the timer, then run the service once to test it:
sudo systemctl daemon-reload
sudo systemctl enable --now kopia-snapshot.timer
sudo systemctl start kopia-snapshot.service
sudo journalctl -u kopia-snapshot.service -n 20 --no-pager
Confirm the next run time:
systemctl list-timers kopia-snapshot.timer
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2026-09-26 03:41:12 UTC 17h left Thu 2026-09-25 10:30:44 UTC 1min ago kopia-snapshot.timer kopia-snapshot.service
Step 7 - Checking maintenance and repository health
Kopia deletes unreferenced data and compacts indexes through maintenance. It runs automatically after snapshots, as long as the user and host that created the repository (root@web01 here) keep using it. Check its status:
sudo kopia maintenance info
Owner: root@web01
Quick Cycle:
scheduled: true
interval: 1h0m0s
next run: now
Full Cycle:
scheduled: true
interval: 24h0m0s
next run: 2026-09-26 10:21:07 UTC (in 23h50m)
If you connect other servers to the same repository, only the owner runs maintenance. That is fine as long as the owner keeps taking snapshots.
Once a month, verify that the stored data is readable. This command checks that all referenced content exists and downloads and decrypts a sample of 10% of the files:
sudo kopia snapshot verify --verify-files-percent=10
Troubleshooting
The systemd job fails with "repository not connected" or a config file error. The service is not running as the user that connected to the repository. Keep User=root in the unit and run sudo kopia repository status to confirm the connection exists for root.
kopia repository create fails with an access error. Check the endpoint, region and bucket name, and that the key can list, read, write and delete objects under the prefix.
Snapshots take a lot of disk space in /root/.cache/kopia. Kopia caches metadata and content locally to avoid downloads. Check the cache and its limits with sudo kopia cache info.
An old snapshot is still present after the retention period. Retention is applied at the end of each snapshot of the same path. If a path is no longer backed up, remove its old snapshots with sudo kopia snapshot delete <snapshot-id> --delete.
Conclusion
You installed Kopia from the official repository, created an encrypted repository in S3-compatible storage, defined retention, compression and exclusion policies, tested restores and scheduled daily snapshots with systemd. Next, back up your database dumps by snapshotting the directory where you write them, add a second repository with kopia repository sync-to for an offsite copy, or run kopia server to manage snapshots from several machines through a web interface.
