Building a Secure Proxmox Virtualization Host with Ubuntu, Windows, OPNsense, and OpenVPN (with VLANs, Automation & Zero-Trust Firewall)

 

Building a Secure Proxmox Virtualization Host with Ubuntu, Windows, OPNsense, and OpenVPN (with VLANs, Automation & Zero-Trust Firewall)

What You Will Learn (At a Glance)

By following this guide, you’ll be able to:

  • Install & secure Proxmox VE on Debian 12

  • Create VLANs to separate Management, Servers, Windows PCs, VPN, and DMZ

  • Deploy Ubuntu and Windows VMs efficiently using automation and templates

  • Set up OPNsense firewall with zero-trust, deny-by-default rules

  • Provide secure remote access via OpenVPN

  • Integrate Authentik + Active Directory for identity and MFA

  • Enforce network segmentation and prevent lateral movement

  • Backup, monitor, and maintain a fully secure virtual environment

Virtualization is the backbone of modern infrastructure, and Proxmox VE is one of the most powerful open-source platforms available today. In this guide, we’ll walk you step-by-step through building a secure Proxmox host using a stable Linux foundation, automating VM creation, enforcing zero-trust firewall rules, and integrating Active Directory + Authentik MFA.

By the end, your environment will host:

  •  1 Ubuntu Server VM

  •  9 Windows VMs

  •  1 OPNsense firewall

  •  1 OpenVPN gateway for remote access

This setup is suitable for homelabs, test environments, or small businesses seeking enterprise-grade capabilities without enterprise licensing costs.


Why Proxmox and Which Linux Is “Best”?

Proxmox VE is built on Debian, which is rock-solid, secure, and actively maintained. For long-term support and stability, Debian 12 (Bookworm) is the recommended base.

Benefits of Debian 12:

  • Long security support window

  • Minimal attack surface

  • Rock-solid KVM + ZFS support

  • Actively maintained by Proxmox

Best practice: Install Proxmox using the official ISO, which already includes a hardened Debian base.


Hardware Recommendations (Baseline)

ComponentRecommendation
CPU8–16 cores (Intel VT-x / AMD-V enabled)
RAM64 GB minimum (Windows VMs consume memory fast)
StorageNVMe SSDs (ZFS mirror preferred)
NICs2 NICs minimum (WAN + LAN separation)

Step 1: Install Proxmox VE

  1. Download the latest ISO: Proxmox VE Downloads

  2. During installation:

    • Filesystem: ZFS (RAID1 if possible)

    • Hostname: pve01.yourdomain.local

    • Management IP: Static

    • Root password: Strong (SSH keys only later)

After installation, you can access the web GUI:

https://<proxmox-ip>:8006

Step 2: Initial Host Hardening

Update the system:

apt update && apt full-upgrade -y

Disable the enterprise repo if unlicensed:

sed -i 's/^deb/#deb/' /etc/apt/sources.list.d/pve-enterprise.list echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-no-subscription.list apt update

Enable Proxmox firewall globally:

pve-firewall start pve-firewall enable

Secure SSH access:

nano /etc/ssh/sshd_config

Ensure:

PermitRootLogin prohibit-password PasswordAuthentication no

Restart SSH:

systemctl restart ssh

🔐 Use SSH keys only for management access.


Step 3: Network Design (Critical for Security)

VLAN Plan

VLANPurposeSubnet
10Management192.168.10.0/24
20Servers (Ubuntu)192.168.20.0/24
30Windows Workstations192.168.30.0/24
40VPN Clients192.168.40.0/24
99DMZ / Services192.168.99.0/24

Proxmox VLAN-Aware Bridge Configuration

Edit /etc/network/interfaces:

auto vmbr1 iface vmbr1 inet manual bridge_ports none bridge_stp off bridge_fd 0 bridge_vlan_aware yes

Reload networking:

ifreload -a

✅ Proxmox is now VLAN-capable
❌ No IPs should be assigned to the host for VLANs (routing is handled by OPNsense).


Step 4: Create OPNsense Firewall VM

VM Specs:

  • CPU: 2 cores

  • RAM: 4 GB

  • NICs:

    • NIC1 → vmbr2 (WAN)

    • NIC2 → vmbr1 (LAN)

Upload ISO:

scp OPNsense-24.x.iso root@pve01:/var/lib/vz/template/iso/

Create VM (example VMID 100):

qm create 100 --name opnsense --memory 4096 --cores 2 --net0 virtio,bridge=vmbr2 --net1 virtio,bridge=vmbr1

Attach ISO and disk via GUI, then install normally.
🔥 OPNsense becomes your default gateway for all internal traffic.

OPNsense VLAN Configuration

  • Parent Interface: LAN (vtnet1)

  • Add VLANs 10, 20, 30, 40, 99

  • Assign interfaces and configure optional DHCP

  • Firewall rules: default deny, allow only as required

  • 🔥 Do not allow lateral movement by default


Step 5: Hardening OPNsense Firewall Rules (Zero-Trust by Design)

At this stage, OPNsense is more than a router — it enforces trust boundaries. The principle is simple:

Nothing talks unless you explicitly allow it.

Core Security Principles

  •  No lateral movement by default

  •  Explicit allow rules only

  •  Inter-VLAN isolation

  •  Full logging for sensitive paths

  •  Minimal exposed services

VLAN Reference

VLANPurposeInterface
10ManagementVLAN10_MGMT
20Linux ServersVLAN20_SERVERS
30WindowsVLAN30_WINDOWS
40VPN ClientsVLAN40_VPN
99DMZVLAN99_DMZ

Step 5a: Global Firewall Defaults

  • Disable Anti-Lockout (after confirming SSH/GUI access from MGMT VLAN)
    Firewall → Settings → Advanced → Disable Anti-lockout

  • Ensure explicit allow rules exist for admin access

Step 5b: Management VLAN (VLAN 10)

Goal: Admins only. Minimal internet access.

Allow Rules (Top → Bottom):

  1. Admin Access to Firewall

    • Source: VLAN10_MGMT

    • Destination: This Firewall

    • Ports: 443, 22

  2. DNS

    • Port: 53

  3. Updates

    • Ports: 80, 443

  4. Explicit Block (Optional)

    • Source: VLAN10_MGMT

    • Destination: any

    • Log: Enabled

Prevents accidental pivoting from admin machines.

Step 5c: Server VLAN (VLAN 20 – Ubuntu)

  • Allow internet for updates (80, 443)

  • Allow DNS to firewall

  • Allow SSH only from Management VLAN

  • Block connections to Windows VLAN

  • Log blocked traffic

Step 5d: Windows VLAN (VLAN 30)

  • Allow minimal internet (80, 443)

  • DNS to firewall

  • RDP only from Management VLAN

  • Block Windows → Servers

  • Log blocked traffic

Step 5e: VPN VLAN (VLAN 40)

  • VPN → Servers (ports 22, 443)

  • VPN → Windows (optional, 3389)

  • Block VPN → Management

  • Log blocked traffic

Step 5f: DMZ VLAN (VLAN 99)

  • Allow DMZ → Internet (80, 443)

  • Block DMZ → Internal LAN

  • Log blocked traffic

Step 5g: WAN Hardening

  • No “allow any” rules

  • No admin access from WAN

  • Disable ping (optional)

  • Only allow required port forwards (HTTPS to DMZ)

Step 5h: Logging & Optional Packages

  • Enable logging on all block rules, VPN, and DMZ

  • Optional: Zenarmor (Sensei) for Layer 7 visibility, Suricata IDS/IPS (inline)


Step 6: OpenVPN Gateway VM

  • Either integrated into OPNsense (recommended)

  • Or separate Ubuntu VM

qm create 101 --name openvpn --memory 2048 --cores 2 --net0 virtio,bridge=vmbr3 apt install openvpn easy-rsa -y

Route VPN clients → OPNsense → internal networks.
MFA enforced via Authentik later.


Step 7: Ubuntu Server VM

qm create 200 --name ubuntu-server --memory 4096 --cores 4 --net0 virtio,bridge=vmbr1

Install Ubuntu Server LTS (22.04/24.04).
Post-install hardening:

ufw enable ufw allow ssh apt install unattended-upgrades -y

Automate Ubuntu VMs (Cloud-Init)

  1. Download Cloud-Init image:

cd /var/lib/vz/template/iso wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
  1. Create template VM:

qm create 9000 --name ubuntu-template --memory 2048 --cores 2 --net0 virtio,bridge=vmbr1,tag=20 qm importdisk 9000 jammy-server-cloudimg-amd64.img local-lvm qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0 --ide2 local-lvm:cloudinit --boot c --bootdisk scsi0 --serial0 socket --vga serial0 qm template 9000
  1. Deploy VMs:

qm clone 9000 201 --name ubuntu-app01 qm set 201 --memory 4096 --cores 4 --ipconfig0 ip=192.168.20.10/24,gw=192.168.20.1 --nameserver 192.168.20.1 --ciuser admin --sshkeys ~/.ssh/id_rsa.pub qm start 201

Bulk deployment:

for i in {1..5}; do vmid=$((210+i)) qm clone 9000 $vmid --name ubuntu-srv$i qm set $vmid --ipconfig0 ip=192.168.20.$((20+i))/24,gw=192.168.20.1 qm start $vmid done

Step 8: Windows Virtual Machines (9 Total)

Recommended Specs per VM:

  • CPU: 2 cores

  • RAM: 4–8 GB

  • Disk: 60–100 GB

Create base template:

  1. Fully patch Windows

  2. Install VirtIO drivers

  3. Apply security baseline

  4. Run Sysprep:

sysprep /generalize /oobe /shutdown

Convert to template:

qm template 9100

Clone for multiple VMs:

qm clone 9100 301 --name win01 qm set 301 --memory 8192 --cores 4 qm start 301

Step 9: VLAN-Aware Security Model

All traffic controlled via OPNsense:

RuleAction
Windows → UbuntuDeny
Ubuntu → WindowsAllow (specific ports)
VPN → ServersAllow
DMZ → LANDeny
Management VLANAdmin-only

Step 10: Backup & Security Best Practices

  • Enable Proxmox Backup:

vzdump --compress zstd --mode snapshot
  • Enable 2FA for Proxmox UI (Datacenter → Permissions → TFA)

  • Regular updates:

apt update && apt upgrade -y

Step 11: Active Directory Integration

  1. Deploy Windows Server VM in VLAN 20

  2. Promote to Domain Controller

  3. Domain: corp.local

  4. Create service account: svc-authentik

  5. Create groups: VPN-Users, Proxmox-Admins, BreakGlass-Admins


Step 12: Authentik Setup (Identity + MFA)

Ubuntu VM Specs:

  • CPU: 2 cores

  • RAM: 4 GB

  • Disk: 40 GB

Install Docker & Compose:

curl -fsSL https://get.docker.com | sudo sh sudo apt install docker-compose-plugin -y

Deploy Authentik:

mkdir ~/authentik && cd ~/authentik curl -O https://goauthentik.io/docker-compose.yml docker compose up -d

Create .env file with strong secrets.


Step 13: Connect Authentik to Active Directory

  • LDAP Source → Bind to AD

  • Sync users & groups

  • Authentik mirrors AD automatically


Step 14: Enable MFA in Authentik

  • TOTP & WebAuthn devices

  • Create MFA policy: Require MFA, re-auth every 12 hours

  • Authentication flow: Identification → Password → MFA


Step 15: Create Policies for Services

VPN MFA Policy:

return user.group_memberships.filter(name="VPN-Users").exists()

Break-Glass Policy:

return not user.group_memberships.filter(name="BreakGlass-Admins").exists()

Attach policies to MFA stage.


Step 16: Integrate Authentik with Services

  • OpenVPN / OPNsense: Authentik via OIDC, enforce MFA

  • Proxmox: LDAP via Authentik, MFA before login

  • Windows VMs: Native AD login, MFA enforced


Step 17: Testing & Final Lockdown

  1. Authentik login & MFA enrollment

  2. VPN connection

  3. Proxmox login

  4. Windows access

  5. Disable local admin accounts

  6. Enable logging everywhere


Final Architecture Overview

Internet | [OPNsense VM] | (vmbr1 - VLAN Aware) ├── VLAN 10 → Proxmox Mgmt ├── VLAN 20 → Ubuntu Servers ├── VLAN 30 → Windows PCs ├── VLAN 40 → VPN Clients └── VLAN 99 → DMZ | [OpenVPN] → Remote Users [Authentik] → MFA / Policies

Closing Thoughts

With this setup, you now have:

  •  Enterprise-grade virtualization

  •  Rapid VM provisioning

  •  Repeatable builds

  •  Firewall-enforced trust boundaries

  •  Network segmentation and VLAN isolation

  •  Centralized identity with MFA

Your lab or small business environment is now secure, automated, zero-trust, and fully integrated, ready for Windows, Linux, VPN, and OPNsense firewalled services.

Closing Thoughts

With this setup, you now have:

  •  Enterprise-grade virtualization

  •  Rapid VM provisioning

  •  Repeatable builds

  •  Firewall-enforced trust boundaries

  •  Network segmentation and VLAN isolation

  •  Centralized identity with MFA

Your lab or small business environment is now secure, automated, zero-trust, and fully integrated, ready for Windows, Linux, VPN, and OPNsense firewalled services.


Here is a little add-on for you to try:

Step 1: Separate Workstation VLAN

Create a new VLAN specifically for workstations that will only access servers via VPN:

VLANPurposeSubnet
50Remote Workstations192.168.50.0/24
  • Update Proxmox VLAN-aware bridge (vmbr1) to include VLAN 50.

  • Tag workstation NICs with VLAN 50.

Example Proxmox VM NIC for a workstation:

qm set <vmid> --net0 virtio,bridge=vmbr1,tag=50

Step 2: Adjust OPNsense Firewall Rules

Workstation VLAN (VLAN 50)

  • Allow only VPN access to Server VLAN (VLAN 20)

    • Source: VLAN50

    • Destination: VLAN20

    • Ports: 22, 443, or whatever your services need

  • Block all other LAN traffic

    • Destination: VLAN10 (Management), VLAN30 (Windows LAN), VLAN99 (DMZ)

🔐 This ensures that the workstations cannot reach servers directly unless connected via VPN.

VPN VLAN (VLAN 40)

  • Ensure the VPN gateway maps VPN clients into the Server VLAN (VLAN20)

  • Authentik MFA enforcement applies here


Step 3: OpenVPN Configuration

  • Assign VPN clients an IP range separate from VLAN50

    • e.g., 10.10.50.0/24

  • Configure routing so VPN clients can access VLAN20 (Servers) only

  • Block access to Management VLAN and Windows LAN VLAN

Example server-side OpenVPN route:

push "route 192.168.20.0 255.255.255.0" push "route 192.168.10.0 255.255.255.0 vpn-noperm"
  • Authentik integration ensures users must authenticate via MFA before traffic is allowed.


Step 4: Windows Workstation Deployment

  • Assign each VM NIC to VLAN50

  • Configure the OpenVPN client on each workstation to connect automatically on boot

  • Ensure no direct routes to Server VLAN exist outside of VPN


Step 5: Testing the Isolation

  1. Attempt to ping a server directly from a workstation VM → Should fail

  2. Connect via OpenVPN → Access to servers allowed based on policy

  3. Confirm MFA prompt occurs before access

  4. Attempt lateral movement to other VLANs → Should be blocked


Result:

  • Workstations are physically or logically isolated

  • All access to servers goes through VPN + MFA

  • Full zero-trust enforced across the lab environment




Comments

Popular posts from this blog

Building a Secure Virtual OPNsense 26.1 Firewall with VLANs, DMZ, and CARP High Availability

Proxmox VE + full Kubernetes (kubeadm) step-by-step

Monitoring Virtualized Environments with Graylog: A Complete Guide