VPS Snaps

How to back up a Linux server with Duplicati

Duplicati is free, open-source (MIT-licensed) backup software that splits your files into blocks, stores each block once, compresses and encrypts them on the server, and uploads them to storage such as an S3-compatible bucket or Backblaze B2. On Ubuntu, install the CLI package (it includes the web UI server), start the duplicati service, and reach the UI on port 8200 through an SSH tunnel, never directly. Save the encryption passphrase somewhere off the server before the first backup: without it, nothing can be restored.

9 min readUpdated Checked against official documentation

Install Duplicati on Ubuntu

Duplicati ships Linux packages in three forms: GUI (needs a desktop), CLI and Agent. On a server, use CLI: it contains the web UI server (duplicati-server) and the command-line tools, without the tray icon and its desktop libraries. The current stable release is 2.4.0.0, from 3 September 2026. On ARM servers, replace x64 with arm64.

Terminal
curl -LO https://updates.duplicati.com/stable/duplicati-2.4.0.0_stable_2026-09-03-linux-x64-cli.deb
Terminal
sudo dpkg -i duplicati-2.4.0.0_stable_2026-09-03-linux-x64-cli.deb

The package puts the programs in /usr/lib/duplicati with commands in /usr/bin (duplicati-server, duplicati-cli, duplicati-server-util, duplicati-recovery-tool and more), and installs a systemd unit, duplicati.service, with a settings file at /etc/default/duplicati. It does not start the service:

Terminal
sudo systemctl daemon-reload
Terminal
sudo systemctl enable --now duplicati.service

The service runs as root, so it can read every file, and keeps its settings and job databases in /root/.config/Duplicati (/var/lib/Duplicati on some systems). Since 2.3.1.0 it refuses a data folder whose permissions are looser than it expects.

Keep the web UI on localhost and use an SSH tunnel

The server listens on port 8200 on the loopback interface only. Keep it that way: the UI drives a root process that holds your storage keys and passphrase. Never add --webservice-interface=any to DAEMON_OPTS in /etc/default/duplicati, and never open port 8200 in a firewall. From your own computer, forward a local port to it over SSH:

Terminal
ssh -L 8200:127.0.0.1:8200 user@your-server

While that session is open, browse to http://localhost:8200 on your computer. If 8200 is busy locally, use -L 8201:127.0.0.1:8200 and port 8201. On first start, Duplicati sets a random password and writes a short-lived sign-in link to the journal:

Terminal
sudo journalctl --unit=duplicati | less

Open the link through the tunnel. Duplicati asks you to pick a password the first time; make it long and keep it in your password manager. If the link has expired, restart the service for a new one. If you lose the password later, this sets a new one by reading the server database as root:

Terminal
sudo duplicati-server-util change-password --server-datafolder=/root/.config/Duplicati

The server database (Duplicati-server.sqlite) stores every job's passphrase and storage keys. Anyone who can sign in to the UI can restore, change or delete your backups. Duplicati can encrypt those fields with a key you supply (--settings-encryption-key or the SETTINGS_ENCRYPTION_KEY variable) and logs a warning until you do.

Create a backup job to S3-compatible storage or Backblaze B2

Create the bucket and a key limited to it first: see Backblaze B2, Amazon S3 or Cloudflare R2. Then click Add backup, choose Add a new backup, and work through the five steps:

  1. Basic configuration. A name, the encryption method (AES-256 by default) and the passphrase. Use the built-in generator and store the passphrase off the server.
  2. Storage destination. For S3-compatible storage, enter the bucket, a folder path, the server (your provider's S3 endpoint), the access key ID and the secret key. For B2's native API, enter the bucket, a path in the bucket, the application ID (B2's keyID) and the application key. Click Test destination. Give every job its own folder: two jobs in one folder break each other.
  3. Source data. Pick folders such as /etc, /srv/www and /home. Filters can exclude caches; folder filters end with /, and * also matches /.
  4. Schedule. Daily at a quiet hour is a good start.
  5. Retention and miscellaneous. The remote volume size (50 MB by default) and when old versions are deleted (below).

Duplicati encrypts with your passphrase before upload and has no recovery. Its own setup page says: "it is not possible to recover anything if this passphrase is lost". A copy that only lives on the server dies with the server.

  • The S3 connection does not use TLS unless the use-ssl option is on or the server is entered as an https:// URL. Turn it on for any provider that supports TLS.
  • Many providers other than AWS need --s3-client=minio or --s3-disable-chunk-encoding (not both). Try one if uploads fail.
  • A live database's files can change while they are read, so back up a dump instead: run pg_dump or mysqldump before the job and include the dump folder.

How Duplicati stores your data

Duplicati reads each file in fixed-size blocks (1 MB by default in 2.4) and keeps a hash of each one, so a block already stored is never uploaded again. New blocks are packed into remote volumes, compressed, encrypted and uploaded. After each backup it uploads a file list and downloads a few random volumes to check them. A local database per job tracks every block and volume, so backups run without downloading any volumes.

Remote fileHolds
duplicati-b….dblock.zip.aesThe data blocks, up to the remote volume size.
duplicati-i….dindex.zip.aesAn index of the blocks in one dblock file.
duplicati-<time>.dlist.zip.aesOne per backup version: the files in it and the blocks that rebuild them.

Two consequences from the docs: the block size cannot change after the first backup, and restoring even a small file downloads every volume that holds its blocks. The docs suggest volumes of 50–500 MiB for cloud storage.

Choose a retention setting

SettingCommand-line optionKeeps
Delete older than--keep-time=90DEvery version from the last 90 days
Keep versions--keep-versions=30The newest 30 versions, however old
Smart backup retention--retention-policy="1W:1D,4W:1W,12M:1M"One a day for a week, one a week for 4 weeks, one a month for 12 months
Retention policy (custom)--retention-policy="7D:U,1Y:1W"Everything for 7 days, then one a week for a year

Retention runs after each successful backup, and Duplicati never deletes the last version. Deleting a version marks its unused blocks as waste; space comes back when compaction rewrites volumes. For choosing the numbers, see backup retention policies.

Run backups from the command line

duplicati-cli runs every operation without the server, which suits cron or a systemd timer, or a server where you want no web UI at all. Keep secrets out of the command line, where other users can see them, in a root-only parameters file:

/root/duplicati/web1.params
--aws-access-key-id=<access key id>
--aws-secret-access-key=<secret access key>
--passphrase=<your passphrase>
Terminal
sudo chmod 600 /root/duplicati/web1.params
Terminal
sudo duplicati-cli backup "s3://my-backups/web1?s3-server-name=<endpoint>&use-ssl=true" /etc /srv/www --parameters-file=/root/duplicati/web1.params --retention-policy="1W:1D,4W:1W,12M:1M"

s3-server-name is the endpoint without https://. For B2's native API, the URL is b2://<bucket>/<folder> with --b2-accountid and --b2-applicationkey. Without --dbpath, the CLI keeps its own local database per destination URL. A job made in the UI has a separate database: for a UI job's destination, pass that job's database path with --dbpath or stay in the UI. Export → As commandline in the UI prints the equivalent command for a UI job.

Exit codeMeaning
0Success
1Success, but no files changed
2Success with warnings
3Backup finished with errors (for test: errors found in storage)
50Backup uploaded some files but did not finish
100An error occurred
200Invalid command-line arguments

Alert on 3 and above. To start a UI-defined job from cron instead, use sudo duplicati-server-util run "web1", which queues it in the running server.

Restore, including when the database or server is gone

In the UI, open Restore, pick the job, choose a version and the files, and restore to a different folder first. Duplicati does not restore permissions unless you ask, so turn that on for a server restore. From the command line:

Terminal
sudo duplicati-cli restore "s3://my-backups/web1?s3-server-name=<endpoint>&use-ssl=true" "/srv/www/*" --restore-path=/restore/duplicati-test --restore-permissions=true --parameters-file=/root/duplicati/web1.params

Add --version=N for an older version (0 is the newest). Without --overwrite, a file that already exists is restored under a timestamped name.

  • Local database lost or damaged. Run duplicati-cli repair with the same URL and parameters file. It rebuilds the database from storage; only logs and remote volume hashes are lost, but it can take a while.
  • Server lost. Install Duplicati anywhere, open Restore and choose Direct restore from backup files. You need only the destination details and the passphrase; Duplicati builds a temporary database. Since 2.4, encrypted backups also store the job's settings without secrets, which the restore screen can import. An exported job file (Export → To File) works too.
  • Storage damaged. duplicati-recovery-tool downloads and decrypts every remote file into a local folder (download), indexes the blocks (index) and restores what it can (restore). It needs local space for the whole backup.

Test restores and know the limits

After each backup Duplicati checks a sample of volumes. To check more, duplicati-cli test with the URL and a sample count (or all) downloads, decrypts and verifies that many sets of files. That proves the files are intact, not that you can restore. Once a month, restore a folder on another machine with Direct restore from backup files and compare it with the live copy using diff -r; see how to test a backup restore.

  • Duplicati refuses to open files that hold a Linux advisory lock unless you set --ignore-advisory-locking=true.
  • If the local database and the storage disagree, a backup stops with an error until you repair them.
  • FreeBSD is not supported.
  • Duplicati sends usage telemetry by default. Opt out in Settings, or add USAGEREPORTER_Duplicati_LEVEL=none to /etc/default/duplicati so not even the start event is sent.

Duplicati, restic or Borg

All three encrypt on the server before upload and are useless without the passphrase. restic and Borg are command-line tools you schedule yourself; Duplicati adds a web UI with its own scheduler and point-and-click restores, at the cost of a web service to keep private and a local database to keep in step with the storage. restic writes straight to S3-compatible storage, like Duplicati; Borg 1.x needs a second server running Borg over SSH. If you are at home with cron and a shell, restic has fewer moving parts.

Frequently asked questions

What port does Duplicati use?
8200, on the loopback interface only by default. Change it with --webservice-port, and reach it from another machine through an SSH tunnel rather than exposing it.
Can I restore a Duplicati backup without the original server or database?
Yes. On any machine with Duplicati, use Direct restore from backup files (or duplicati-cli restore) with the destination details and the passphrase. Duplicati builds a temporary database from the backup files.
What happens if I lose the Duplicati encryption passphrase?
Nothing can be restored. The backup files are encrypted with it and there is no recovery, so keep a copy off the server.
How do I reset the Duplicati web UI password on Linux?
Run sudo duplicati-server-util change-password --server-datafolder=/root/.config/Duplicati, or start the server once with --webservice-password=<new password> and then restart it without that option.
Is Duplicati free?
Yes. The Duplicati client is open source under the MIT license and, in its own documentation's words, free to use with no limitations.

How this was checked

Commands, limits and prices were checked against these official pages, on October 4, 2026: