A remote repository is the heart of an off-site strategy: backups are sent to another host via SSH with borg serve. This episode teaches remote repo setup, an SSH key pair with a restricted command, running borg serve without a full shell, and security practices: a dedicated user, passwordless, and Borg's built-in seccomp sandboxing.

So far the repository has always been local, on the same server as the data. That protects against human error, but not against a server room fire — the 3-2-1 principle demands one copy off-site. Episode 11 moves the repository to a separate host over SSH. This is where security becomes the focus: you will not be giving full shell access to the backup host.
A remote repository is written as user@host:path:
borg@backup-host:/srv/borg/backupBorg detects the user@host: pattern and automatically uses SSH. On the server side, Borg calls borg serve — a daemon opened over SSH to serve backup requests. Client and server do not copy raw files; they exchange chunks over the Borg protocol.
On the backup host, create a dedicated user and install borg:
sudo useradd -m -s /usr/bin/bash borg
sudo apt install -y borgbackup
sudo mkdir -p /srv/borg
sudo chown borg: /srv/borgNote: the borg user is not a superuser and only controls /srv/borg. The principle: keep backup access separate from administrative access.
From the client side:
ssh-keygen -t ed25519 -f ~/.ssh/id_borg -N "" -C "borg-backup"
ssh-copy-id -i ~/.ssh/id_borg.pub borg@backup-hostHowever, ssh-copy-id adds the key with full access. We replace it with a restricted command.
A restricted command limits SSH to running only a specific command — here borg serve with path restrictions:
command="borg serve --restrict-to-path /srv/borg --restrict-to-repository /srv/borg/backup",restrict,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... borg-backupLet us break down the options:
command="borg serve ..." — SSH will only run borg serve, whatever the client requests. No shell.--restrict-to-path /srv/borg — borg serve can only access /srv/borg; it cannot touch any other files on the system.--restrict-to-repository /srv/borg/backup — only one repository can be served.restrict — disables port forwarding, agent forwarding, and X11 forwarding.no-pty — no pseudo-terminal (irrelevant for borg serve, but a good security principle).Important
Without command= in authorized_keys, the SSH key gives full shell access to the borg user. If that key leaks, the attacker gets a shell on the backup host. The restricted command closes that door: an attacker can only use borg serve within the path limits.
export BORG_REPO='borg@backup-host:/srv/borg/backup'
export BORG_RSH='ssh -i ~/.ssh/id_borg'
export BORG_PASSCOMMAND='cat /root/.borg-passphrase'
borg init --encryption=repokey-blake2Note BORG_RSH: it tells Borg which SSH command to use, including the key file. Without it, Borg uses the default ssh, which may not use id_borg.
borg create --stats "$BORG_REPO"::"{hostname}-{now}" /home /etcSince BORG_REPO is already exported, the command above does not need to write out the full path. Borg will open SSH, the server runs borg serve, and the chunks are sent.
Use a dedicated user (borg) — not root, not an application user. If the backup host is compromised through this path, the impact is limited to the repository.
borg user has no password: sudo passwd -l borg.command= in authorized_keys.When borg serve runs, Borg leverages seccomp (Secure Computing Mode) on Linux to sandbox which syscalls the server process may make. This is a defense layer in case borg serve is attacked through malicious repo data — its capabilities are limited to the syscalls backup actually needs. You do not need to do anything: it is active by default on supported platforms.
Tip
Verify the setup with a quick test from the client: borg list must show the repository, and ssh borg@backup-host id must be rejected (because the restricted command refuses anything other than borg serve). If id runs, your authorized_keys config is wrong.
BORG_RSH: Borg uses the default SSH, which fails because the key is not found or a different key is used.borg serve refuses access.borg list from another host to confirm the restricted command works as expected.user@host:path and served by borg serve.command="borg serve --restrict-to-path ..." in authorized_keys.restrict, no-pty disable unneeded SSH features.borg user limits the impact of a breach.borg list succeeds, ssh ... id is rejected.In episode 12 we maintain long-term health: check & maintenance — borg check for consistency, borg check --verify-data for content verification, a monthly schedule, borg compact, log reviews, and disk health monitoring.