Borg

Backup & Restore~13 min

The Borg destination writes host backups to a Borg repository. Three repository types are supported: local filesystem path, mounted external disk, or remote server via SSH. Chunk-level deduplication across all archives in the repository and optional repokey encryption.

What Borg is

Borg (also spelled BorgBackup) is an open-source deduplicating backup tool maintained by the Borg Backup community. It stores every archive as a set of variable-length chunks inside a repository; chunks are shared across archives so re-backing up unchanged data has near-zero storage cost. Borg is not tied to Proxmox — it is a general-purpose backup tool used across many environments. ProxMenux uses it as one of the three destinations for host backups; every Borg-specific mechanism described on this page (repository types, borg-serve over SSH, repokey encryption, prune) is standard Borg behaviour.

Chunk-based deduplication with local or SSH-served repositories

A Borg repository stores chunks that are shared across every archive it contains, so re-backing up an unchanged file transfers and stores nothing new. ProxMenux invokes borg create against a repository at backup time and borg extract at restore time. The repository can live on the same filesystem as the source, on a mounted external disk, or on a remote host accessed over SSH.

The borg binary

Borg is not a base dependency of the ProxMenux installer. When a backup runs, hb_ensure_borg resolves the binary from four sources in order and returns the first that works:

#SourceDetail
1System borgIf the host already has borg installed via APT (which borg resolves), that binary is used.
2State-dir cache/usr/local/share/proxmenux/borg — kept from a prior GitHub download on this host.
3Monitor AppImage bundle/usr/local/share/proxmenux/monitor-app/usr/bin/borg — the AppImage bundles a signed borg-linux64. This is the offline-safe path: a host with no internet still has a working borg.
4GitHub downloadwget against the pinned borg-linux64 URL under github.com/borgbackup/borg/releases/, verified against a constant SHA-256 in lib_host_backup_common.sh (HB_BORG_LINUX64_SHA256). On checksum mismatch the binary is discarded and the backup aborts. The downloaded file is cached in the state dir so subsequent backups use path 2.

Repository types

The repository type is chosen when a target is added. Each type resolves to a different repository URL that Borg understands.

TypeRepository URLDetail
remotessh://USER@HOST/RPATHRepository lives on a remote server that runs borg serve. Requires an SSH connection to that server.
usb/mnt/MOUNTPOINT/borgbackupRepository lives on a mounted external disk (typically USB). The mount is resolved via hb_prompt_mounted_path, which detects, mounts or formats USB partitions as needed.
local/backup/borgbackup (any absolute path)Repository lives on a local directory. Meaningful only when the target directory is on a separate physical disk — a repository on the same disk as the source protects against operator error but not against disk failure.

Preparing the Borg server (server side)

The remote repository type expects a working Borg server accessible over SSH. ProxMenux does not bootstrap the server itself — it only authorises a key against an existing account on it. This section documents what the server needs before ProxMenux can connect.

Where the server can live

Any Linux host with SSH access qualifies. Common setups:

  • A dedicated NAS or backup box (Debian, Ubuntu, TrueNAS SCALE with a shell).
  • An LXC container inside a Proxmox node. Small footprint, isolated from the host running the backups.
  • Another Proxmox host on the same LAN, or a VM anywhere reachable over SSH.

LXC as Borg server

If the Borg server runs inside an LXC, the container must have a user account with a password.

Requirements on the server

RequirementDetail
borg binary at /usr/bin/borgThe command="/usr/bin/borg serve ..." line ProxMenux writes into authorized_keys hard-codes that path. Installing via APT (apt install borgbackup) puts it there. A standalone binary must be symlinked to /usr/bin/borg.
A dedicated user account (typically borg)Owns the repository directory and receives incoming SSH connections. Does not need sudo or shell access — the authorized_keys line disables interactive shells anyway.
A writable repository directoryThe path the operator gives ProxMenux (for example /backup/borgbackup) must exist on the server and be owned by the borg user.
SSH daemon accepting the borg userPubkeyAuthentication yes (default). Password authentication is only needed for the one-shot generate-auto flow — after the key is installed, the server can disable password auth entirely.

Minimal server setup

On a Debian or Ubuntu Borg server, a working baseline is four commands as root:

apt install borgbackup
useradd -m -d /home/borg -s /bin/bash borg
mkdir -p /backup/borgbackup
chown borg:borg /backup/borgbackup

After this, ProxMenux's generate-auto mode can connect using the borg user's password once, install its own SSH key, and every subsequent backup uses that key. No further server-side configuration is needed — the key restricts itself to borg serve on that path.

SSH authentication (client side)

Remote Borg repositories are accessed over SSH. The connection runs from the ProxMenux host to a user account on the Borg server that runs borg serve. This user is typically named borg, NOT the admin/root user of the server — the borg-serve command line locks the connection to that specific repository path (see the key strategies below).

The four key strategies

When a remote target is added, ProxMenux prompts for the SSH user, host and remote path, then asks how to authenticate. Four modes:

ModeBest forWhat it does
generate-autoRecommendedProxMenux generates a new ed25519 keypair at ~/.ssh/borg_proxmenux_HOST_ed25519, then uses sshpass to log in ONCE to the server with the admin password and append the public key to ~borg/.ssh/authorized_keys. The admin password is only used for this one call — it is never stored.
generate-manualNo admin password on this hostProxMenux generates the keypair as above but displays the full authorized_keys line for the operator to paste manually into the server. The admin password never leaves the ProxMenux host because it is never asked for.
generate-pctBorg server is a PVE LXCThe Borg server runs inside an LXC on a PVE node. ProxMenux authorises the key via pct exec from the PVE host — root on the PVE host writes into the LXC's ~borg/.ssh/authorized_keys without needing SSH into the LXC itself.
existingUse an existing keyProxMenux scans /root/.ssh/ and $HOME/.ssh/ for parseable ed25519/RSA private keys and lists them. The operator picks one or browses manually to a non-standard path.
noneDefault SSH configNo custom key — Borg relies on the host's default SSH configuration (typically ~/.ssh/id_rsa or an SSH agent).

The authorized_keys line

For every generated key, the authorized_keys line ProxMenux writes on the server locks the key to a single borg-serve invocation against the configured repository path:

command="/usr/bin/borg serve --restrict-to-path RPATH",restrict PUBKEY

The command= forces every SSH session using this key to run only that borg-serve command; restrict disables port forwarding, agent forwarding, X11 forwarding and PTY allocation. The key cannot be used to open an interactive shell on the server or to access any other repository path, even if the account has broader privileges.

Saved targets

A saved target persists the repository configuration under a friendly name so the details do not have to be re-entered. Storage layout in the ProxMenux state directory:

FileContent
borg-targets.txtOne line per target: NAME|REPO|SSH_KEY_PATH|ENCRYPT_MODE. Read by hb_collect_borg_configs to populate the target-selection menu.
borg-pass-NAME.txtPassphrase for the target NAMEd above (chmod 600). Only present when the operator chose repokey encryption.

Saving is optional — the operator can decline the save prompt for a one-shot backup that leaves no credentials on the host.

Encryption

Repositories are initialised with an encryption mode via hb_borg_init_if_needed: the modern borg repo-create -e MODE when available, or the legacy borg init --encryption=MODE. ProxMenux exposes two modes: repokey (default) and none. In repokey mode Borg stores the encryption key inside the repository itself; access requires a passphrase, which ProxMenux prompts for twice with match validation and stores at borg-pass-NAME.txt. A mandatory acknowledgement dialog is shown after the passphrase is saved: the passphrase is the only way to access the encrypted archives, and losing it makes every archive in the repository unrecoverable.

Runtime environment

ProxMenux exports the following environment variables before invoking borg. They configure the connection and unlock the repository without embedding secrets in the command line.

VariableValuePurpose
BORG_RSHssh -i SSH_KEY_PATH -o StrictHostKeyChecking=accept-newThe remote-shell command Borg uses for SSH-served repositories. Set only when a custom key was selected; otherwise unset so Borg uses the default SSH configuration.
BORG_PASSPHRASE(passphrase from borg-pass-NAME.txt)Unlocks the repokey. Set only when the target uses repokey encryption. Never appears in the process argument list.
BORG_ENCRYPT_MODErepokey | noneUsed by hb_borg_init_if_needed when initialising a repository that does not yet exist. Ignored by borg create on existing repositories.
BORG_RELOCATED_REPO_ACCESS_IS_OKyesSuppresses the interactive prompt Borg raises when the repository URL differs from the URL it was originally reached from (common after a mount-point rename or SSH-host reachable via new address).
BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OKyesSuppresses the interactive prompt Borg raises the first time an unencrypted repository is accessed from a new client.

Archive naming and retention

Every backup creates a new archive inside the repository.

hostcfg-HOSTNAME-YYYYMMDD_HHMMSS

For scheduled jobs, run_scheduled_backup.sh runs borg prune against the repository after each successful backup with the retention values configured on the job (--keep-last, --keep-daily, --keep-weekly). Interactive backups do not prune.

Retrieval on the restore side

The restore flow lists archives with borg list REPO and extracts the selected one with borg extract REPO::ARCHIVE-NAME into a staging directory that _rs_check_layout feeds to the standard restore pipeline. For manual retrieval outside ProxMenux the same commands work; the extracted tree is the standard three-payload layout described in How it works.

References

Official Borg documentation for the components ProxMenux relies on.

  • Borg documentation — main entry point covering concepts, deployment, quickstart and every command.
  • borg create — the command ProxMenux invokes on every backup, with all supported flags.
  • Repository encryption — the encryption modes Borg supports, including repokey which ProxMenux uses by default.
  • borg serve and SSH deployment — how to set up a central Borg server accessed over SSH, including the borg-serve command and the restrict-to-path flag ProxMenux writes into authorized_keys.
  • borg prune — the retention model behind --keep-last / --keep-daily / --keep-weekly that ProxMenux applies per scheduled job.