Veeam Hardened Repository rev 06
Veeam Hardened Repository provides a secure, immutable backup repository for Veeam Backup & Replication. It runs as an isolated LXC container on the storage server, using ZFS-backed ZVOLs formatted with XFS as the backup storage target.
Note: Veeam Hardened Repository is delivered as an optional Small Update (the xc-veeam-hdrep module). This article describes revision 06. If your system was updated to a newer revision, refer to the matching Extension:Veeam_Hardened_Repository_rev_NN article.
How the hardening works
The "hardened" property is the result of two complementary mechanisms working together:
- Immutable backups — Veeam writes backups to the XFS repository with the Make recent backups immutable for N days setting enabled. While immutability is in effect, backup files cannot be modified or deleted from outside Veeam, protecting them from ransomware and accidental removal. The XFS filesystem is formatted with reflink support, which also enables Veeam's fast-clone (synthetic backup) optimisation.
- Minimal attack surface — the dedicated locveeam account is granted elevated privileges only during the initial Veeam onboarding handshake, then sudo is removed immediately afterwards. SSH access on port 22522 is disabled after onboarding completes, closing the inbound path entirely.
The role of the xc-veeam-hdrep module is to provision the XFS-on-ZVOL repository and orchestrate this temporary-privilege/SSH handshake. Veeam enforces immutability; the module enforces privilege minimisation.
Prerequisites
Before running the setup, ensure the following are in place:
- A ZFS storage pool with sufficient free space.
- One or more ZVOLs with veeam in the name (the setup script discovers ZVOLs by this keyword).
- Network access to the storage server from the Veeam Backup & Replication console.
Note: Setup does not require internet access. All software the repository needs is already included in the container image, and the Veeam Data Mover / transport components used during onboarding are delivered by the Veeam Backup & Replication server itself over the SSH connection on port 22522. An isolated or air-gapped storage server deployment is fully supported.
Accessing the container console
The repository container exposes a web-based console at:
https://<server-ip>:4200/veeam-hdrep
Login: enter admin as the username and your storage server administrator password.
Accept the self-signed certificate warning if prompted. The console gives direct shell access to the container for running the initial setup and any subsequent maintenance commands.
Initial setup
Setup is performed once, using the interactive make_veeam_repo script included in the container. All steps below are run inside the container console.
Running the setup script
- Connect to the container console at
https://<server-ip>:4200/veeam-hdrep. - Navigate to the tools directory and run the setup script:
cd /tools sudo ./make_veeam_repo
- Follow the interactive prompts described in the sections below.
Note: The script needs root privileges to modify system files (SSH configuration, fstab, cron) and automatically elevates itself if it is not already running as root. sudo ./make_veeam_repo, as shown above, remains the recommended way to start it.
User account creation
The script creates the dedicated locveeam account (UID 1000) used exclusively for Veeam access. If the account does not yet exist, you will be prompted to set a password for it.
Log dataset selection
The script prompts you to select a ZFS pool where the _veeam_logs dataset will be created. This dataset stores Veeam service logs. The dataset itself remains in the selected pool — during setup the container moves its mount point to /var/lib/veeam and unmounts /Pools. This is automatic; no user action is required.
Note: If a _veeam_logs dataset already exists in the selected pool, back up its contents before proceeding.
ZVOL selection and formatting
The script lists all ZVOLs whose path contains veeam. Enter the numbers of the ZVOLs you want to use as backup repositories, separated by spaces.
For each selected ZVOL:
- If the ZVOL is already XFS-formatted, it is used as-is.
- If the ZVOL is not XFS-formatted, the script will warn that all data on the ZVOL will be erased. Type
formatto confirm, or anything else to cancel.
Formatting uses optimised XFS parameters for backup workloads:
| Parameter | Value | Purpose |
|---|---|---|
| Block size | 4096 bytes | Standard block size |
| Reflink | enabled | Efficient data deduplication at the XFS level |
| CRC | enabled | Metadata integrity checksums |
Mount point configuration
For each formatted ZVOL, the script:
- Creates a mount point at
/mnt/<zvol_name>. - Adds an entry to
/etc/fstabwith the following XFS options:noatime,nodiratime— disables access-time updates to reduce write overheadnodiscard— disables TRIM for ZFS-backed storage compatibilitylogbufs=8,logbsize=32k— XFS journal tuning for write-heavy workloadsnofail— system boots even if the mount is unavailable
- Sets ownership to
locveeam:locveeamand permissions to700.
Maintenance scheduling
The script configures automated filesystem trimming (fstrim) via cron. You will be prompted to choose a schedule:
- Daily
- Weekly (Mondays)
- Monthly (1st of the month)
A custom start time in 24-hour format can be selected for each option.
SSH configuration
SSH is enabled on port 22522 and configured to allow access for the locveeam user. The non-standard port is intentional — it avoids conflicts with the host SSH service and is required in the Veeam Backup & Replication repository configuration.
Temporary sudo privileges
After the repository volumes are prepared, the script temporarily grants locveeam sudo access. This allows the Veeam agent to perform its initial configuration steps (such as installing transport components) when you connect from the Veeam console.
The script pauses and waits for you to complete the Veeam-side setup (described in the next section). Once you confirm, sudo access is removed and SSH is disabled to harden the repository.
Configuring the Veeam side
With the storage prepared and locveeam temporarily elevated, complete the Veeam Backup & Replication wizard to register the repository. These steps are performed in the Veeam Backup & Replication console on your Windows backup server.
Note: Do not press Enter in the container console until you have completed all steps in this section and Veeam has finished deploying its transport components. The make_veeam_repo script is waiting at that prompt — pressing Enter removes sudo and disables SSH, which will interrupt a Veeam deployment still in progress.
Step 1 — Add Backup Repository
- In the Veeam Backup & Replication console, navigate to Backup Infrastructure → Backup Repositories.
- Right-click Backup Repositories and select Add Backup Repository.
- When prompted for the repository type, select Direct attached storage.
Step 2 — Select Linux (Hardened Repository)
On the next screen, select Linux (Hardened Repository).
Step 3 — Name the repository
Enter a display name for the repository and click Next.
Step 4 — Add the Linux server and credentials
- Click Add New next to the server field and enter the IP address or hostname of the storage server.
- When prompted for credentials, click Add and choose Single-use credentials for hardened repository.
- Enter the following:
- Username:
locveeam - Password: the password set during
make_veeam_repo - SSH port:
22522— this must be entered explicitly. The container's SSH service listens only on port 22522; port 22 is not open at all.
- Leave Elevate account privileges automatically enabled, leave both Add account to the sudoers file and Use "su" if "sudo" fails unchecked, and leave Root password empty.
- The make_veeam_repo script has already granted temporary sudo to locveeam, which is why Elevate account privileges automatically works without a root password. Checking Add account to the sudoers file would create a permanent sudoers entry, and checking Use "su" if "sudo" fails would require setting a root password — either one undermines the hardening this module exists to provide, so both must stay unchecked.
- When prompted, review and trust the server's SSH fingerprint.
Note: When make_veeam_repo pauses and waits for you (see Step 8 — Finalize and harden below), it prints this exact Credentials dialog on screen — username, password hint, SSH port, and the two checkboxes to leave unchecked — so you can copy each value directly from the console instead of this article.
Veeam will connect over SSH and install its Transport and Installer services on the container.
Step 5 — Select the backup directory
- Click Populate to load the available storage.
- Select
/mnt/<zvol_name>— the XFS repository created by the script.
- You may optionally append a subdirectory, for example
/mnt/<zvol_name>/backups.
Step 6 — Repository properties
On the Repository step of the wizard, verify the following settings:
- Use fast cloning on XFS volumes — ensure this is checked. It is supported because the repository uses XFS with reflink enabled, and it reduces storage consumption for synthetic full backups.
- Make recent backups immutable for — set this to the number of days matching your retention requirement. Backups will be protected from modification or deletion for this period.
Click Next.
Step 7 — Mount server and finish
- On the Mount Server step, the Veeam Backup & Replication server is pre-selected as the default mount server — click Next.
- Review the summary and click Apply, then Finish.
Step 8 — Finalize and harden
Return to the container console where make_veeam_repo is still waiting. Confirm that Veeam has finished deploying its transport components (the wizard completed without errors), then press Enter.
The script will:
- Remove sudo from locveeam.
- Disable SSH on port 22522.
The repository is now hardened. The locveeam account remains active for Veeam's internal data-path use, but no interactive login path remains open.
Updating the Veeam Backup Server
When you later update the Veeam Backup Server, Veeam may need to update the Veeam Data Mover service on this repository over SSH. Because the repository is hardened — SSH is disabled and locveeam has no sudo — that connection is blocked. You need to open a temporary maintenance window before running the Veeam Backup Server update.
Open the container console at https://<server-ip>:4200/veeam-hdrep, then run:
cd /tools sudo ./update_veeam_repo
Note: The script elevates itself to root automatically if it is not already running as root, so an admin operator can run it directly without switching to root first. sudo ./update_veeam_repo, as shown above, remains the recommended way to start it.
The update_veeam_repo script re-enables SSH on port 22522 and grants locveeam temporary sudo (the Data Mover update requires the same elevated privileges as the initial onboarding), then waits. With the maintenance window open, run the Veeam Backup Server update from the Veeam console. When the update completes, return to the container console and press Enter — the script re-hardens the repository by removing sudo and disabling SSH.
Note: For security reasons, do not leave SSH enabled after the update is complete. Use update_veeam_repo for this purpose — do not re-run make_veeam_repo, as its SSH-enable step is gated behind ZVOL re-selection.
Expanding the repository
A repository can be enlarged at any time without recreating it and without losing data. Expansion happens in two steps, because the volume and the file system on it are grown separately.
Step 1 — enlarge the volume on the storage server. In the web GUI, set a larger size for the zvol:
- Storage → Pools → <pool> → Volumes → <volume> → Edit zvol
Then enter the new, larger value in the Size field.
Note: Raising a purchased or allocated capacity figure elsewhere does not by itself enlarge an existing volume — the volume itself has to be resized explicitly, or the file system will have nothing new to grow into. This is the most common reason to see every volume reported as already up to date in the next step.
Step 2 — grow the file system in the container. Open the container console at https://<server-ip>:4200/veeam-hdrep, then run:
cd /tools sudo ./grow_veeam_repo
Note: The script elevates itself to root automatically if it is not already running as root, so an admin operator can run it directly and is simply asked for a password. sudo ./grow_veeam_repo, as shown above, remains the recommended way to start it. The locveeam account cannot run it — that account deliberately has no sudo rights once the repository is hardened.
The script lists every repository volume, showing the current file system size, the size of the underlying volume, and whether there is room to grow:
Veeam Hardened Repository - expand an existing repository Repository volumes: 1) /mnt/my_veeam_backup_repo ZVOL Pool-0/my_veeam_backup_repo FS 17.0T dev 40.0T [CAN GROW +23.0T] 2) /mnt/veeam-rep-02 ZVOL Pool-0/veeam-rep-02 FS 8.0T dev 8.0T [up to date] Enter the number(s) to grow, separated by spaces (or press ENTER to cancel):
If every volume shows [up to date], the volume itself has not been enlarged yet — go back to Step 1. A repository that is configured but not currently mounted is not listed, since a file system can only be grown while mounted; check with mount | grep /mnt and mount it first.
Enter the number of the volume to grow, or several numbers separated by spaces to grow multiple volumes in one pass. Pressing Enter without a number cancels and changes nothing:
Growing XFS on /mnt/my_veeam_backup_repo... data blocks changed from 4563402752 to 10737418240 Done: /mnt/my_veeam_backup_repo is now 40.0T (was 17.0T).
The file system is expanded in place while it stays mounted, so backup jobs keep running and no maintenance window is needed — unlike updating the Veeam Backup Server, this operation never touches SSH: it stays disabled and the repository stays hardened throughout.
The tool never shrinks a file system and never resizes the volume itself — it only grows the file system up to the volume's current size. The mount point, mount options, and the scheduled fstrim job are all unchanged by the operation, and Veeam needs no reconfiguration — the repository simply reports more free space.
Storage and access reference
| Path (inside container) | Purpose |
|---|---|
/mnt/<zvol_name> |
Backup data storage (XFS on ZVOL) |
/var/lib/veeam |
Veeam log dataset (ZFS dataset) |
/var/lib/veeam/log/ |
Veeam service log files |
/etc/fstab |
Volume mount configuration |
/etc/ssh/sshd_config |
SSH daemon configuration (port 22522) |
/etc/cron.d/fstrim_* |
Automated trim schedules |
Maintenance
Monitoring disk space
From the container console:
df -h /mnt/<zvol_name>
Manual filesystem trim
sudo fstrim /mnt/<zvol_name>
Checking mount status
mountpoint /mnt/<zvol_name> mount | grep /mnt/<zvol_name>
Viewing logs
journalctl -u ssh journalctl -u veeam-ds-logs tail -f /var/log/auth.log
Updates
Do not run system package updates inside the container. The container has limited disk space, and updates are delivered as new container revisions through the standard small-update mechanism.
Known issues and limitations
- ZVOLs must include "veeam" in the name. The setup script discovers ZVOLs by searching for this keyword in their device path. ZVOLs without it will not appear in the selection list.
- Formatting is destructive. Selecting a non-XFS ZVOL and confirming with
formatirreversibly erases all data on that ZVOL. Verify your selection before confirming. - No in-container package updates. Due to disk space constraints, running
apt upgradeor similar inside the container is not supported. Updates are delivered as new container revisions. - SSH is a transient onboarding channel only. Veeam connects once over SSH on port
22522using the password set forlocveeam(single-use credentials) to deploy its Data Mover. Backup traffic afterwards does not use SSH. The setup script automatically disables SSH at the finalize step (after you press Enter to confirm onboarding is complete), so SSH key authentication is not required for normal operation. If you later need manual shell access, re-enable SSH and add public keys to/home/locveeam/.ssh/authorized_keysinside the container. - Expansion only ever grows.
grow_veeam_reponever shrinks a file system and never resizes the underlying volume — it only grows the file system up to the volume's current size. To reduce space usage, remove old backups from within Veeam instead.
Changelog
rev 06
- Fixed: a start-up race that could leave the Veeam services on the repository unable to start. The container holds those services back until the Veeam log storage has been prepared. Veeam's own components record the account last used for the connection in a settings file that, by coincidence, carried the same name as the one holding that rule, and overwrote it. With the rule gone, the Veeam services could start before the log storage was ready on a later container restart, and when that happened they failed to start. The container now keeps its rule under a name the Veeam components do not use, so it survives onboarding and every subsequent Veeam update. Existing repositories are repaired by the update itself — no reconfiguration is needed, and the setup script does not have to be run again.
rev 05
- New
grow_veeam_repotool to expand an existing repository: it grows the XFS file system onto a volume that has already been enlarged on the storage server. The file system stays mounted while it grows, so backup jobs keep running and no maintenance window is needed. update_veeam_reponow automatically elevates itself to root if it is not already running as root, matching the behaviormake_veeam_repoalready had, so an admin operator can run it directly.make_veeam_reponow displays the Veeam credentials dialog values on screen at the onboarding pause.
rev 04
- The setup script (
make_veeam_repo) now automatically elevates itself to root if it is not already running as root, so it completes reliably even if you forget to prefix it withsudo. Running it assudo ./make_veeam_repo, as shown above, remains correct and is still the recommended way to start it. - Removed a leftover package-installation check that could misfire and, on a storage server without internet access, print a long series of spurious connection errors. The required XFS tools have always shipped inside the container image, so this change only removes noise — it does not add or change any requirement.
rev 03
- SSH is now automatically disabled at the finalize step (Step 8) when onboarding completes, hardening the repository immediately without requiring manual intervention.
- New
update_veeam_repomaintenance script to safely open and close the SSH and sudo window when updating the Veeam Backup Server — re-enables SSH on port 22522 and grantslocveeamtemporary sudo, then re-hardens on confirmation.
rev 02
- Initial release of Veeam Hardened Repository container.
- Interactive setup script (
make_veeam_repo) for user account, ZVOL selection, XFS formatting, and SSH configuration. - Automated
fstrimscheduling via cron. - Temporary sudo workflow for Veeam transport component installation.
- Log dataset support (
_veeam_logsZFS dataset mounted at/var/lib/veeam).
For further customization or troubleshooting, refer to the upstream Veeam documentation or contact Open-E support.