> Article

Proxmox VE Hardening Guide

By Bearloggs
#proxmox #hardening #linux #devsecops

Proxmox VE Hardening Guide#

Exposing a hypervisor directly to the internet is a major security risk. This guide walks you through securing Proxmox VE using a defense-in-depth strategy: OS-level hardening, a dedicated firewall, a WireGuard VPN, and strict access controls.

Critical Warning

  • Risk of Lockout: Changing SSH ports and firewall rules can easily lock you out of your server.
  • Recovery: Ensure you have IPMI/iDRAC/KVM console access or a physical monitor and keyboard attached before applying these changes.
  • Testing: Always test new configurations in a separate terminal window before closing your current session.

1. Correct Repositories & Updates#

By default, Proxmox tries to use the Enterprise repository, which fails for non-subscribers. To ensure you actually receive security patches, you must switch to the “No-Subscription” repository.

Edit your sources list:

# Disable Enterprise Repo (prevents 401 errors)
sudo sed -i "s/^deb/#deb/" /etc/apt/sources.list.d/pve-enterprise.list

# Add No-Subscription Repo
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" | sudo tee /etc/apt/sources.list.d/pve-no-subscription.list

Update the System:

sudo apt update && sudo apt full-upgrade -y
sudo apt autoremove -y

2. Create a Non-Root Admin User#

Never use root for remote SSH access. Create a dedicated user with sudo privileges.

sudo adduser adminuser
sudo usermod -aG sudo adminuser

Generate strong keys on your local machine: We recommend Ed25519 keys for better security and performance.

ssh-keygen -t ed25519 -C "proxmox-admin"
ssh-copy-id -i ~/.ssh/id_ed25519.pub adminuser@your.server.ip

Test the login explicitly:

ssh adminuser@your.server.ip

3. Harden SSH Configuration#

We will move SSH to a high, random port and disable password authentication entirely.

1. Pick a port (e.g., 54321): Ensure the port is not in use:

sudo ss -tuln | grep 54321

2. Edit /etc/ssh/sshd_config:

Port 54321
AddressFamily inet                # Listen on IPv4 only (optional, simplifies rules)
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers adminuser
MaxAuthTries 3

3. Reload and Validate:

sudo sshd -t                  # specific check for config syntax errors
sudo systemctl reload ssh

Do not verify functionality yet—keep your current terminal open and open a NEW terminal to test the connection on port 54321.

4. Setup WireGuard VPN#

We will treat the VPN as the only door into the management interface.

Install WireGuard:

sudo apt install wireguard -y

Generate Server Keys:

umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub

Configure Server (/etc/wireguard/wg0.conf):

[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = <Contents of /etc/wireguard/server.key>
# Enable IP forwarding logic here if needed for VM access

[Peer]
# Your Client (Laptop/Phone)
PublicKey = <Client Public Key>
AllowedIPs = 10.10.10.2/32

Enable IP Forwarding:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Start the Interface:

sudo systemctl enable --now wg-quick@wg0

5. Configure UFW (The Firewall)#

Note: Proxmox has a built-in firewall, but UFW is often easier for single-node hardening. If you are running a Proxmox Cluster, be very careful with UFW as it can block Corosync (UDP 5404/5405).

Install and Set Defaults:

sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing

Step 1: Allow SSH (Temporary Public Access): Crucial step to prevent immediate lockout.

sudo ufw allow 54321/tcp comment 'Temp SSH Public'

Step 2: Allow WireGuard:

sudo ufw allow 51820/udp comment 'WireGuard VPN'

Step 3: Enable the Firewall:

sudo ufw enable

Step 4: Restrict Admin Access to VPN-Only: Once you have confirmed you can connect to the VPN (10.10.10.1), lock everything else down.

# Allow SSH and GUI *only* from inside the VPN
sudo ufw allow from 10.10.10.0/24 to any port 22 proto tcp
sudo ufw allow from 10.10.10.0/24 to any port 54321 proto tcp
sudo ufw allow from 10.10.10.0/24 to any port 8006 proto tcp

# Remove the public SSH rule created in Step 1
sudo ufw delete allow 54321/tcp

6. Configure Fail2Ban (Brute Force Protection)#

Proxmox does not come with Fail2Ban configured for the Web GUI by default. Let’s fix that.

Install:

sudo apt install fail2ban -y

Create Jail Config (/etc/fail2ban/jail.d/proxmox.conf):

[proxmox]
enabled = true
port = https,http,8006
filter = proxmox
logpath = /var/log/daemon.log
maxretry = 3
findtime = 2d
bantime = 1h

Create Filter Config (/etc/fail2ban/filter.d/proxmox.conf):

[Definition]
failregex = pvedaemon\[.*authentication failure; rhost=<HOST> user=.* msg=.*
ignoreregex =

Restart Fail2Ban:

sudo systemctl restart fail2ban
sudo fail2ban-client status proxmox

7. Enable Two-Factor Authentication (2FA)#

Even with a VPN, you should enable 2FA in case your workstation is compromised.

  1. Log into Proxmox Web UI (via VPN IP https://10.10.10.1:8006).
  2. Go to Datacenter > Permissions > Two-Factor.
  3. Add TOTP for your user.
  4. Scan the QR code with an app like Google Authenticator or Raivo OTP.
  5. Important: In the user login realm settings, require TFA.

Safety Checklist#

Before walking away from the server, verify the following:

  • Updates: apt update runs without 401 Unauthorized errors.
  • SSH: Root login is disabled; password login is disabled.
  • SSH: You can login via port 54321.
  • VPN: You can handshake with WireGuard.
  • Firewall: Port 8006 (GUI) and SSH are TIMEOUT when accessed from the public internet (not the VPN).
  • Backups: You have backed up your SSH keys and WireGuard config off-site.

Further Reading#