Author: HomeSecExplorer
This guide is provided “as is,” without warranty of any kind, whether express or implied. The author(s) and the HomeSecExplorer Proxmox Hardening Guide project make no guarantees regarding completeness, accuracy, or fitness for any particular purpose. By using this guide, you agree that:
- Responsibility
You remain solely responsible for evaluating, testing, and validating every recommendation in your environment. Any security control that introduces operational risk must be reviewed, adjusted, or rejected by you. - No Liability
The author(s) and contributors are not liable for direct, indirect, incidental, or consequential damages arising from the use of this guide, even if advised of the possibility of such damages. - Attribution & Licensing
This guide is released under the CC BY 4.0 License (see ../LICENSE). You may copy, modify, and distribute the content provided you retain attribution to the original author(s) and link back to the project repository. - No Endorsement
References to third-party products or services do not imply an endorsement. All trademarks belong to their respective owners. - Community Contributions
Improvements are welcome! Please open an issue on the Proxmox Hardening Guide repository to discuss changes. After consensus is reached, submit a pull request for review. - Community Techniques
Some procedures in this guide are community best-effort methods and not officially supported by Proxmox GmbH. Evaluate, test, and maintain these at your own risk; do not expect vendor support for issues arising from their use.
By continuing to use this document you acknowledge that you have read, understood, and agreed to these terms.
- Terms of Use
- Overview
- Recommendations
- Exception Handling
- Appendices
- Change Notes
- Scope: All Proxmox Backup Server installations.
- Audience: System administrators, security engineers, and compliance auditors responsible for Proxmox Backup Server deployments.
This guide provides prescriptive hardening guidance for Proxmox Backup Server 4. It does not guarantee absolute security; integrate it into a comprehensive cybersecurity program. Always approach changes with caution and follow a structured test-and-release process.
- Never deploy changes directly to production.
- Include the following gates:
- Inventory & Analysis - Document the current configuration and dependencies.
- Impact Review - Read the Impact subsection of each recommendation to identify side-effects.
- Lab Testing - Apply changes to representative, non-production systems.
- Phased Deployment
- Deploy to a limited pilot group.
- Monitor for at least one full business cycle.
- Resolve issues before a wider rollout.
- Gradual Rollout - Expand in stages while continuously monitoring.
Note
No single guide can cover every environment. If you discover conflicts or unexpected impacts, please open an issue on the project repository and share details.
This guidance was developed and validated on Proxmox Backup Server 4 running on Debian 13 “bookworm” (x86-64).
- Commands are executed as root in the default shell.
- When using
sudoor a different shell, confirm command syntax and environmental differences.
To satisfy several CIS Debian Benchmark controls (for example, partition layout), install Debian 13 first and then add the Proxmox Backup Server repository instead of using the Proxmox ISO installer.
- Update system firmware and BIOS.
- Patch BMC / iDRAC / iLO management interfaces to the latest stable versions.
| Convention | Meaning / Example Usage |
|---|---|
Multiline monospace |
Multi-line shell commands, scripts, or configuration files |
Inline monospace |
Single commands, file paths, or UI menu items |
<<placeholder>> |
Text that must be replaced with an actual value |
| Italic text | Cross-references or external document titles |
| Bold text | Warnings, Notes, or emphasized terms |
- CIS Debian Linux 13 Benchmark - CIS Debian
- Proxmox Backup Server Administration Guide - PBS Admin Guide
- Debian Security Hardening Manual - Debian hardening
| Term | Definition |
|---|---|
| PBS | Proxmox Backup Server |
| CIS | Center for Internet Security |
| ACL | Access Control List |
| 2FA | Two-Factor Authentication |
| ACME | Automated Certificate Management Environment; protocol used by Let’s Encrypt |
Maintain a current inventory of all PBS nodes.
Update the table after every hardware or configuration change.
| Hostname | IP Address | Role | OS Version | CIS Level | Hardened On | Location | Notes |
|---|---|---|---|---|---|---|---|
| pbs01 | 10.0.10.20 | Primary PBS | Debian 13 | Level 1 | Dec 2025 | DC1-R1 | No subscription |
| pbs02 | 10.0.10.21 | Secondary PBS | Debian 13 | Level 2 | Dec 2025 | DC2-R1 | No subscription |
| Level | Summary | When to Use |
|---|---|---|
| 1 - Baseline | Minimal operational impact; mandatory for all PBS nodes. | Always |
| 2 - Enhanced | Additional defense-in-depth controls. Evaluate each control for feasibility. | Regulated or high-security workloads |
| 3 - Advanced | Maximum hardening; may introduce downtime or complexity. | Only when data sensitivity or threat model justifies it |
These principles define the intent behind the checklist items below. They guide the most important design decisions and set boundaries for what this guide assumes.
- PBS is a backup vault, not a general-purpose server. Avoid using PBS as a NAS, Docker host, app server, or anything else. Extra services add risk to your last line of defense.
- Strong separation of duties and access paths. Design so one compromised credential does not equal “delete all backups.” Restrict who can modify datastores, retention, prune policies, and permissions. Limit where PBS is reachable from.
- Retention and destructive actions are security controls. Use retention and pruning intentionally and monitor destructive operations. Incidents often target recovery options first.
- Assume the network is hostile; encrypt and restrict. Encrypt where appropriate, protect encryption keys, and restrict outbound access from PBS. Backups often contain the most sensitive data in the environment.
- Offsite or offline backups are required for real resilience. PBS is excellent for fast restores, but you still need a separate recovery source for worst-case scenarios.
- Restore testing is part of hardening. Regularly test file restores, VM restores, and “whole host rebuild” assumptions. A backup that was never tested is not a reliable control.
Apply these controls during or immediately after installation. Retrofitting them later can be disruptive.
Level 1
Description
Establishes a secure minimum configuration for Debian 13 that balances security with stability. Controls include partitioning,
secure permissions, basic hardening of SSH, and kernel parameter tuning.
Measures
- Apply all remediations in the CIS Debian 13 Benchmark Level 1 - Server profile.
Note
During the CIS Debian 13 Benchmark § 4 (Host-Based Firewall) remediation, remember to allow Proxmox Backup Server traffic. For more details look at 1.2.6
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Adds defense-in-depth measures, such as stricter file-permission policies and advanced kernel hardening, suitable for regulated or high-risk environments.
May impact certain workloads or third-party software.
Measures
- Apply all remediations in the CIS Debian 13 Benchmark Level 2 - Server profile after completing Level 1.
- Validate services such as Ceph, ZFS, and PBS in a lab before rolling out to production.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Ensures critical Debian security patches are applied between maintenance windows to reduce the exposure window for known CVEs.
Measures
apt update && apt install unattended-upgrades apt-listchanges -yMake sure the following lines are configured:
-
/etc/apt/apt.conf.d/20auto-upgradesAPT::Periodic::AutocleanInterval "7"; APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1";
-
/etc/apt/apt.conf.d/50unattended-upgradesUnattended-Upgrade::Origins-Pattern { "origin=Debian,codename=${distro_codename},label=Debian"; "origin=Debian,codename=${distro_codename}-security,label=Debian-Security"; "origin=Debian,codename=${distro_codename},label=Debian-Security"; }; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Automatic-Reboot "false"; -
Enable service
systemctl enable unattended-upgrades -
Monitor
/var/log/unattended-upgrades/unattended-upgrades.logfor failures. -
Optionally set mail notification in
/etc/apt/apt.conf.d/50unattended-upgrades.
Tip
For Ansible automation, check out the HomeSecExplorer role for autoupdate. See Appendix B for examples. autoupdate Role
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Apply the recommended server and client-side hardening settings from the ssh-audit Debian 13 guides.
These settings remove legacy ciphers, MACs, and key-exchange algorithms that baseline CIS controls still permit.
Measures
- Follow the ssh-audit Debian 13 server guide.
- Follow the ssh-audit Debian 13 client guide.
Tip
For Ansible automation, check out the HomeSecExplorer role for ssh-audit. See Appendix B for examples. sshaudit Role
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 3
Description
Protects data at rest, guarding against physical theft or drive RMA.
LUKS2 is used for block-device encryption; keys are required at boot.
Measures
- Install Debian 13 with LUKS-encrypted LVM before adding the Proxmox repository.
- Store recovery keys in an offline password manager or HSM.
- If you deploy ZFS: consider ZFS native encryption at the dataset/zvol level instead of whole-disk LUKS, to allow per-dataset keys and more flexible unlock workflows. Choose based on your operational model and recovery plan.
Warning
Controls have not yet been validated. Test thoroughly.
Note
Performance impact is typically < 5 % on modern CPUs with AES-NI.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Enable Debian non-free-firmware alongside main and contrib to ensure required firmware and microcode are available.
Measures
-
Example
/etc/apt/sources.list:deb http://deb.debian.org/debian bookworm main contrib non-free-firmware deb http://deb.debian.org/debian bookworm-updates main contrib non-free-firmware deb http://security.debian.org/debian-security bookworm-security main contrib non-free-firmware
-
Example deb822 format
/etc/apt/sources.list.d/debian.sources:* Components: main non-free-firmware contrib *
-
apt updatethen install required microcode and firmware packages as needed.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Ensures the latest vendor microcode mitigations and stability fixes are applied at boot. Addresses CPU errata and security vulnerabilities that cannot be fully fixed by system firmware alone.
Measures
- Install CPU microcode updates:
- Intel:
apt install intel-microcode - AMD:
apt install amd64-microcode - Reboot to apply (microcode is loaded at boot).
- Intel:
Execution Status
- YES - Control implemented
- NO - Control not implemented
At this point, PBS is installed.
Level 3
Description
Prevents malicious or unsigned kernel modules from loading by validating the boot chain against keys stored in UEFI NVRAM.
Measures
- Follow the PBS docs
- Stage kernel updates on a non-critical node first.
Warning
Controls have not yet been validated. Test thoroughly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 3
Description
When Secure Boot is enabled, the parameter lockdown=integrity blocks unsigned kernel modules, restricts access
to /dev/mem, and kernel-space tampering, even by a compromised root account.
Measures
-
Confirm Secure Boot:
mokutil --sb-state # should report 'SecureBoot enabled' -
Add GRUB parameter:
GRUB_CMDLINE_LINUX_DEFAULT="quiet lockdown=integrity"
update-grub reboot
-
Verify after reboot:
cat /sys/kernel/security/lockdown # Expected: [integrity] confidentiality none
Warning
Controls have not yet been validated. Test thoroughly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Separates IPMI, management and backup traffic from backend storage traffic.
This reduces the risk of lateral movement and prevents backup traffic from congesting the storage network.
Measures
- Place the host's IPMI interface in a dedicated OoB-management VLAN that is not routed to the Internet.
- Place the PBS management interface in a dedicated management VLAN that is not routed to the Internet.
- Mount NFS, SMB, or other backend storage on a dedicated storage VLAN that is not routed to the Internet.
- Enforce inter-VLAN firewall rules at the router and/or Host Firewall layer.
- Set appropriate MTU sizes.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Guarantees access to the Enterprise update repository, long-term maintenance fixes, and official vendor support.
This is an operational control for maintainability and compliance evidence in regulated environments. It is not a security hardening control on its own.
Measures
- Purchase a PBS subscription that matches the node tier (Community, Basic, Standard, or Premium).
- Upload the key:
Configuration --> Subscription --> Upload Subscription Key - Enable the enterprise repository and disable no-subscription.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Place every PBS datastore on its own mount point or own ZFS dataset.
This isolates backup writes from the OS, helps avoid full-disk conditions, and allows stricter mount/ZFS options.
Measures
- Create a separate block device/LV/mount per datastore (recommended), or a separate ZFS dataset per datastore.
- Use the following mount options and properties:
- ext4 / XFS
- mount options:
defaults,nodev,nosuid,noexec
- mount options:
- ext4 / XFS
- ZFS dataset
-
properties:
# example pool/dataset: tank/pbs/ds1 zfs create -o mountpoint=<</mnt/pbs-ds1>> <<tank/pbs/ds1>> zfs set compression=zstd-3 <<tank/pbs/ds1>> zfs set xattr=sa <<tank/pbs/ds1>> zfs set acltype=posixacl <<tank/pbs/ds1>> zfs set exec=off <<tank/pbs/ds1>> zfs set setuid=off <<tank/pbs/ds1>>
-
Warning
ZFS datasets have not yet been validated. Test thoroughly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Local filesystems (ext4/XFS/ZFS) are preferred for primary PBS datastores. If you must use network shares, limit them to secondary/sync targets or carefully hardened environments.
Configure authentication and transport encryption, and use mount options that reduce attack surface and boot-time risk.
Measures
-
General
- Place shares on an isolated storage VLAN not routed to the Internet.
- Restrict server exports to the PBS host IPs only and firewall both directions.
- Mount with
nodev,nosuid,noexec,_netdevand systemd automount to avoid boot hangs. - Monitor: alert if the datastore path is not mounted during backup windows.
-
NFS (preferred over SMB when available)
- Use NFSv4.1/4.2 over TCP with Kerberos privacy:
- Client mount options:
rw,vers=4.2,sec=krb5p,hard,nodev,nosuid,noexec,_netdev,x-systemd.automount,x-systemd.idle-timeout=600
- Client mount options:
- Server-side export hardening (on the NFS server):
- Prefer
syncexports (with SLOG if using ZFS),root_squash,sec=krb5p, and limitrwto PBS IPs. - Disable insecure legacy protocols/versions; use
v4 onlywhere possible.
- Prefer
- Use NFSv4.1/4.2 over TCP with Kerberos privacy:
If Kerberos is not available, you may temporarily use sec=sys only on an isolated storage VLAN with IP allowlists, root_squash, and strict exports. For confidentiality and integrity, prefer sec=krb5p.
- SMB/CIFS (when NFS is not feasible)
- Use SMB 3.x with encryption and Kerberos where available:
-
Client mount options (example
/etc/fstab)://filesrv.example.com/pbs-ds1 /mnt/pbs-ds1 cifs rw,vers=3.1.1,seal,sec=krb5,credentials=/root/.smbcred-pbs,serverino,cache=none,actimeo=30,nodev,nosuid,noexec,_netdev,x-systemd.automount,x-systemd.idle-timeout=600 0 0 -
Create
/root/.smbcred-pbswithchmod 600:username=<<pbs-service-user>> password=<<strong-password-or-token>> domain=<<AD.DOMAIN>> # optional; required for Kerberos setups
-
If Kerberos is unavailable, use
sec=ntlmsspwith strong passwords and IP allowlists (reduced security).
-
- Server-side share hardening:
- Require SMB 3.0+, enable encryption, disable guest/anonymous access, and restrict by host/IP and group.
- Use SMB 3.x with encryption and Kerberos where available:
Warning
SMB/CIFS mounts have not yet been validated. Test thoroughly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Restrict access to SSH and PBS GUI/API on TCP 8007 to trusted management networks. Do not expose SSH and TCP 8007 directly to the Internet.
Measures
-
Identify your trusted networks:
- Management subnet(s)
- Backup subnet(s) with PVE nodes
-
Allow only those subnets to reach TCP 8007 (GUI/API) and TCP 22 (SSH). Set the default INPUT policy to DROP.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Improves auditing and accountability by assigning each administrator a unique @pam, @pbs or LDAP account.
Measures
proxmox-backup-manager user create <<alice@pbs>> --comment "<<Alice - Admin>>"
proxmox-backup-manager acl update <</datastore>> <<Admin>> --auth-id <<alice@pbs>>Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Limits potential blast radius by assigning the smallest role necessary (e.g., DatastoreAdmin instead of Admin).
Measures
- Map each operational task to the minimal role needed.
proxmox-backup-manager acl update <</datastore>> <<DatastoreAdmin>> --auth-id <<alice@pbs>>
- Review assignments quarterly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Two-factor authentication (2FA) adds an additional factor (TOTP or YubiKey OTP) to mitigate password compromise.
Measures
Configuration --> Access Control --> Two Factor Authentication--> enable and enroll token.
Note
Exception for root, see 2.1.4
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Maintain a sealed, offline “break-glass” root credential for emergencies without 2FA. Use personalized accounts with 2FA for daily operations.
Measures
-
Configure personalized @pam or directory accounts with 2FA for admins.
-
Generate a strong root password and store it offline in a tamper-evident container.
-
Log any use of break-glass. Rotate the password immediately after use.
-
Password policy:
- min length: 20
- min uppercase: 3
- min lowercase: 3
- min numbers: 3
- min special: 3
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Routine administration should be performed through named user accounts with least-privilege access. Keep root@pam for emergencies only and ensure actions are attributable to an individual user.
PBS adds an additional layer through PBS RBAC (roles + paths) and API tokens. This section defines what “normal” administration looks like on a hardened system.
Measures
-
Use the PBS UI/API for day-to-day administration with named accounts and least-privilege RBAC.
-
Treat interactive OS shell access as the exception, not the norm.
-
Treat
root@pamas break-glass only (see 2.1.4). Do not use it for daily operations. -
Define access tiers (lower tier number = higher privilege and higher risk):
- Tier 0:
root@pambreak-glass only - Tier 1: named
@pamusers with shell access, optionally SSH and/or sudo (small, documented group) - Tier 2: named users with PBS RBAC (GUI/API, no shell)
- Tier 0:
-
Root account and SSH handling:
- Disable root SSH password authentication. Prefer key-based access only.
- If you run a cluster, restrict root SSH to required cluster networks (see 1.1.1 CIS deviation).
-
Sudoers design patterns:
- Grant sudo only when needed and only to Tier 1 OS shell admins.
- Document who has sudo rights and review it regularly.
- Optionally define fine-grained sudo roles (for example, read-only diagnostics vs OS maintenance).
-
Decide when OS shell access is allowed:
- If the task can be done via GUI/API, use Tier 2 RBAC and do not use SSH.
- If the task requires host OS changes (packages, kernel, drivers, filesystem repair), use SSH as Tier 1 and elevate via sudo when needed.
- If the task is emergency recovery, use Tier 1/0 break-glass access.
-
Audit and logging:
-
API tokens:
- Use dedicated service users and API tokens for automation (no shared credentials).
- Scope ACLs to the minimum required paths and permissions.
- Set expiration and rotate tokens regularly.
- Never use
root@pamAPI tokens for automation. - See 2.2 API Tokens for details.
- See 2.2 API Tokens for details.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
For automations, this step replaces password-based authentication with revocable API tokens that can be scoped to specific paths.
Measures
proxmox-backup-manager user generate-token <<alice@pbs client1 --expire 2026-12-31>>- Assign ACL on
<</datastore/store1>>if the application should access only that datastore.proxmox-backup-manager acl update <</datastore/store1>> <<DatastoreAdmin>> --auth-id <<alice@pbs>>
- Review assignments quarterly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Minimizes damage if a token leaks.
Measures
- Use roles such as
DatastoreAdminrather thanAdmin.proxmox-backup-manager acl update <</datastore>> <<DatastoreAdmin>> --auth-id <<alice@pbs>>
- Review assignments quarterly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Prevents plaintext exposure of secrets in scripts or CI logs.
Measures
- Store secrets in HashiCorp Vault, CyberArk, Bitwarden, or a similar vault solution.
- Never commit tokens to Git or other version-control systems.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Limits lifetime of compromised tokens.
Measures
- Set
--expirewhen creating tokens. - Rotate every 365 days.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Eliminates man-in-the-middle (MITM) risk and browser warnings by replacing each node’s default self-signed certificate
with a certificate issued by an internal CA or Let’s Encrypt.
Measures
- Navigate to
Configuration --> Certificates --> Certificatesand upload the full-chain PEM certificate with its private key. - Prefer ACME/Let’s Encrypt for automated issuance, see 2.3.2 Automate Certificate Renewal.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Prevents expired-cert outages.
Measures
- Register an ACME account under
Configuration --> Certificates --> ACME Accounts.proxmox-backup-manager acme account register <<default OR account-name>> <<mail@example.com>> <<--directory=http://Your-ACME.com>>
- If you are using the DNS-01 challenge, configure the required plugin.
proxmox-backup-manager acme plugin add <<plugin‑name>> <<OPTIONS>>
- Add the server's FQDN under
Configuration --> Certificates --> Certificates.proxmox-backup-manager node update --acmedomain0 https://<<pbs.example.com>>
- Click Order Certificate in the GUI to request and install the certificate.
proxmox-backup-manager acme cert order
Tip
See the PBS docs: Certificate Management
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Blocks brute-force attempts.
Measures
-
Add to
/etc/fail2ban/jail.local(or another appropriate .local file):[sshd] backend=systemd enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 findtime = 2h bantime = 1h [proxmox] enabled = true port = 8007 filter = proxmox-backup-server logpath = /var/log/proxmox-backup/api/auth.log maxretry = 3 findtime = 2h bantime = 1h
-
Create
/etc/fail2ban/filter.d/proxmox-backup-server.conf(or another appropriate file):[Definition] failregex = authentication failure; rhost=\[<HOST>\]:\d+ user=.* msg=.* ignoreregex =
-
Restart fail2ban
systemctl restart fail2ban -
Check fail2ban status:
fail2ban-client statusfail2ban-client status sshdfail2ban-client status proxmox
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Forces an immediate checksum comparison after every chunk upload.
A snapshot is marked OK only if all blocks match their expected SHA-256 hashes, catching transmission errors or bad sectors before the job completes.
Measures
Datastore --> Options: Verify New Backups = Yesproxmox-backup-manager datastore update <<datastore>> --verify-new true
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Runs a full store scan to detect silent bit-rot or latent disk errors on previously verified snapshots.
Any corrupted chunk is flagged so it can be healed from another replica or a fresh backup.
Measures
Datastore --> Verify JobsAdd:- Schedule:
<<sat 18:15>>(pick a low-traffic window)
- Schedule:
proxmox-backup-manager verify-job create <<ID>> --store <<datastore>> --schedule <<18:15>>
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Removes obsolete snapshots according to your retention objectives, keeping space usage predictable and recovery points relevant.
Measures
Datastore --> Prune & GCPrune Jobs -> Add:- Prune Schedule:
<<22:30>> - keep-last:
3 - keep-daily:
7 - keep-weekly:
4 - keep-monthly:
3
- Prune Schedule:
proxmox-backup-manager prune-job create <<ID>> --schedule <<22:30>> --store <<datastore>> --keep-last <<3>> --keep-daily <<3>> --keep-weekly <<4>> --keep-monthly <<3>>
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Reclaims disk space by deleting unreferenced chunks left behind after pruning. Must run after each prune cycle to be effective.
Measures
Datastore --> Prune & GCGarbage Collect Jobs -> Edit:- GC Schedule:
<<23:00>>(~30 min after prune)
- GC Schedule:
proxmox-backup-manager datastore update <<datastore>> --gc-schedule <<23:00>>
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Sends an email whenever a verify, sync, prune, or GC job exits with errors, ensuring operators can investigate before data loss accumulates.
Measures
- Configure
Datastore --> OptionsNotify Edit:- Verification Jobs:
Errors - Sync Jobs:
Errors - Prune Jobs:
Errors - Garbage Collection Jobs:
Errors
- Verification Jobs:
proxmox-backup-manager datastore update <<datastore>> --notify verify=errorproxmox-backup-manager datastore update <<datastore>> --notify sync=errorproxmox-backup-manager datastore update <<datastore>> --notify prune=errorproxmox-backup-manager datastore update <<datastore>> --notify gc=error
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Set a maximum age after which snapshots must be re-verified, even if they passed verification before.
This provides periodic end-to-end integrity checks to detect latent corruption.
Measures
- GUI:
Datastore --> Verify Jobs --> Editset Re-verify after to<<60d>>for general-purpose stores. Use30dfor high-risk data or90dfor very large stores.proxmox-backup-manager verify-job update <<ID>> --outdated-after <<60>>
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Replicate snapshots to a remote PBS to satisfy 3-2-1 and enable recovery even if the primary PBS is lost.
Measures
- Create a Remote pointing to the destination server:
- GUI:
Configuration --> Remotes --> Add. Provide the destination API host, user or API token, and host certificate fingerprint. Test the connection. proxmox-backup-manager remote create <<remotename>> --auth-id <<string>> --host <<string>> --password <<string>> <<--comment <<remote1>> --fingerprint <<abcd>> --port <<8007>>>>
- GUI:
- Create Sync Jobs per datastore or namespace:
- GUI:
Datastore --> Sync Jobs --> Add. - Choose Remote, Remote Datastore, optional Namespace, and the local Target Datastore.
- Schedule for off-peak hours. Consider a bandwidth limit if WAN constrained.
- Leave remove-vanished: false unless you fully understand the implications of destructive syncs.
proxmox-backup-manager sync-job create <<ID>> --remote-store <<remotename>> --store <<datastore>> --schedule <<3:00>> <<--ns <<namespace>> --remote-ns <<namespace>> --rate-in <<value>> --rate-out <<value>>>>
- GUI:
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Guarantees data resilience by keeping three copies of every critical backup stored on two different media or storage tiers,
with at least one copy stored off-site or offline.
This mitigates single-point failures, ransomware, and site-wide disasters.
Measures
- Maintain three copies:
- 1 × production data
- 2 × independent backups
- Use two distinct storage types (e.g., local ZFS + Proxmox Backup Server, NFS share + LTO tape, or Ceph RBD + S3 object storage).
- Keep one copy off-site or offline (remote datacenter, immutable object-store bucket with versioning, or vaulted storage).
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Backs up the entire Proxmox Backup Server host configuration to a second Backup Server. A fresh install can be restored even if the primary PBS is unavailable.
Measures
-
Verify the client is present:
apt update && apt install proxmox-backup-client -y -
Store credentials in a root read-only file:
# Create an API token with Datastore.Backup privilege only # Token name: hostbackup@pbs echo 'PBS_REPOSITORY="<<hostbackup@pbs@backup.example.com:datastore>>" PBS_PASSWORD=<<API_TOKEN>> PBS_FINGERPRINT=<<PBS_FINGERPRINT>>' > /root/.pbs-cred chmod 600 /root/.pbs-cred
-
Automate with systemd daily
-
/etc/systemd/system/pbc-host-backup.service:[Unit] Description=Host-config backup to PBS Wants=network-online.target After=network-online.target [Service] Type=oneshot EnvironmentFile=/root/.pbs-cred ExecStart=/usr/bin/proxmox-backup-client backup \ root.pxar:/ \ etc.pxar:/etc \ --include-dev /boot Nice=10 IOSchedulingClass=best-effort IOSchedulingPriority=7
-
/etc/systemd/system/pbc-host-backup.timer:[Unit] Description=Daily host-config backups [Timer] # Run every day at 06:00 local OnCalendar=*-*-* 06:00:00 Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.target
-
systemctl daemon-reload && systemctl enable --now pbc-host-backup.timer
-
-
Verify restores quarterly:
proxmox-backup-client restore pbsconf.pxar /tmp/pbs-restore --verify
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Encrypts the host-configuration archives before they leave the PBS Node.
Even if the transport or remote PBS is compromised, backup contents remain confidential.
Warning: losing the encryption key makes the backups unrecoverable.
Measures
-
Create a client encryption key (root-only):
proxmox-backup-client key create /root/.pbs-enc-key.json --kdf scrypt chmod 600 /root/.pbs-enc-key.json
- When prompted, enter a strong passphrase for the key.
- Store an offline copy of the key (Vault/HSM or encrypted offline media).
-
Add key to the
.pbs-credfile:echo 'PBS_ENCRYPTION_KEY_FILE=/root/.pbs-enc-key.json PBS_ENCRYPTION_PASSWORD=<<ENC-KEY-PASSWORD>>' >> /root/.pbs-cred chmod 600 /root/.pbs-cred
-
Enable encryption in the systemd job:
-
Append the following arguments to the existing
ExecStart=line in/etc/systemd/system/pbc-host-backup.service:# config of 4.2.1 --crypt-mode encrypt \ --keyfile ${PBS_ENCRYPTION_KEY_FILE} -
Example:
[Unit] Description=Host-config backup to PBS Wants=network-online.target After=network-online.target [Service] Type=oneshot EnvironmentFile=/root/.pbs-cred ExecStart=/usr/bin/proxmox-backup-client backup \ root.pxar:/ \ etc.pxar:/etc \ --include-dev /boot \ --crypt-mode encrypt \ --keyfile ${PBS_ENCRYPTION_KEY_FILE} Nice=10 IOSchedulingClass=best-effort IOSchedulingPriority=7
-
Then reload units:
systemctl daemon-reload systemctl restart pbc-host-backup.timer
-
-
Verify encryption on the server: In the PBS UI or via CLI, confirm the backup shows as encrypted.
Note
Key management is critical: escrow a copy, document recovery, and restrict file permissions (600, root-owned). Rotate keys on a planned schedule; re-encrypt old backups only if policy requires.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Provides tamper-evident storage and allows for correlation of security events.
Measures
In addition to CIS Debian 13 Benchmark § 6.1, forward:
/var/log/proxmox-backup/api/access.log/var/log/proxmox-backup/api/auth.log
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Tracks configuration changes in the proxmox-backup files.
Measures
-
Create a persistent audit rule file:
/etc/audit/rules.d/90-pbs.rules-w /etc/proxmox-backup -p wa -k pbs-config
-
Load rules and verify:
augenrules --load, rebuild /etc/audit/audit.rules from rules.dsystemctl restart auditd, alternative reload if augenrules is not presentauditctl -l | grep pbs-config, should list the /etc/proxmox-backup watchausearch -k pbs-config, view matching audit events
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Detects capacity issues before they become outages.
Measures
- Example:
- Export to Prometheus with
pve_exporter. - Dashboards in Grafana.
- Export to Prometheus with
Note
Or another appropriate monitoring solution.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Turns raw metrics into actionable alerts.
Measures
Create alerts at least for:
- CPU > 80 %
- Disk > 80 %
- RAM > 80 %
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Objective measurement of compliance drift over time.
Measures
- Run OpenSCAP or other quarterly and after major upgrades.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 2
Description
Detects known rootkits in userland and kernel space.
Measures
apt install rkhunterand add tocron.daily.
Warning
Controls have not yet been validated. Test thoroughly.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Level 1
Description
Maintains institutional knowledge and supports audits.
Measures
- Update network diagrams, inventory, and change logs after *every significant change.
Execution Status
- YES - Control implemented
- NO - Control not implemented
Document deviations from this guide with justifications, risk acceptance, and approval signatures.
All CIS control references - section numbers (e.g., 1.1.1), Level tags (Level 1 / Level 2), and remediations map exclusively to the CIS Debian Linux 12 Benchmark v1.1.0 (2024-09-26).
---
- name: Harden PBS
hosts: pbs
become: true
tasks:- HomeSecExplorer ansible-role-sshaudit role
ansible-galaxy install HomeSecExplorer.sshaudit
- name: Run HomeSecExplorer ansible-role-sshaudit
ansible.builtin.include_role:
name: "HomeSecExplorer.sshaudit"
vars:
hsesa_ssh_audit_package_state: absent
hsesa_ssh_audit_test: false
hsesa_regenerate_ssh_host_keys: false- HomeSecExplorer ansible-role-autoupdate role
ansible-galaxy install HomeSecExplorer.autoupdate
- name: Run HomeSecExplorer ansible-role-autoupdate
ansible.builtin.include_role:
name: "HomeSecExplorer.autoupdate"- Start-of-year cold test: Restore the most recent nightly backup to an isolated lab and boot VMs.
- Quarterly file-level restore test: Restore on a single VM disk.
- Document outcomes, time-to-recover, and update runbooks.
- Firmware, IPMI and BIOS updated
- Prepare Network segmentation
- Install Debian with correct partitioning
- Execute Hardening Guide
- Create/Update documentation
| Version | Date | Author | Key Changes | Reviewed By |
|---|---|---|---|---|
| 0.9.0 | 2025-12-30 | HomeSecExplorer | Initial creation. | -------- |
| 0.9.1 | 2026-01-12 | HomeSecExplorer | added: 2.1.5, Design principles | -------- |
