← All projects

Setting up a DMZ VLAN with UniFi for public-facing services

How I isolated my self-hosted blog from the rest of my home network using a dedicated VLAN and UniFi firewall rules — so a compromised server can't reach anything else.


When you self-host something public-facing, you’re opening a door from the internet into your home. The question isn’t whether to open it — it’s how far that door goes. By default, if your server gets compromised, an attacker has a foothold inside your LAN and can potentially reach everything else on your network. A DMZ VLAN removes that risk entirely.

What is a DMZ VLAN?

A DMZ (Demilitarised Zone) is an isolated network segment that sits between the internet and your internal LAN. Traffic from the internet can reach servers in the DMZ, but the DMZ cannot initiate connections back into your main network. Even if a server in the DMZ is fully compromised, the attacker is contained.

Network design

My setup uses three VLANs managed by a UniFi Dream Machine:

VLAN 10 — Management   10.10.100.0/24   Proxmox host, UniFi AP
VLAN 20 — LAN          192.168.1.0/24   Main trusted devices
VLAN 30 — DMZ          172.20.30.0/24   Public-facing servers

The Proxmox host has two NICs — one on the management VLAN for host administration, and one dedicated to the DMZ bridge for LXC containers.

Proxmox network configuration

In Proxmox, I created two Linux bridges:

vmbr0 — Management bridge
  NIC:     nic1 (enx5847ca7829c8)
  IP:      10.10.100.50/24
  Gateway: 10.10.100.254

vmbr1 — DMZ bridge
  NIC:     nic0 (enx5847ca7829c9)
  IP:      none (no host IP on DMZ)
  Gateway: none

The DMZ bridge has no IP assigned at the host level — only the LXC containers attached to it get IPs. This means the Proxmox host itself has no presence on the DMZ network.

UniFi VLAN configuration

In UniFi Network → Settings → Networks, I created a new network:

Name:    DMZ
VLAN ID: 30
Subnet:  172.20.30.0/24
Gateway: 172.20.30.254
DHCP:    Disabled (static IPs only)

The switch port connected to the PC’s DMZ NIC is configured as an Access port on VLAN 30.

UniFi firewall rules

This is the critical part. In UniFi → Firewall & Security → Rules, I created the following in order:

WAN IN rules (internet → DMZ):

Rule 1: Allow established/related sessions
Rule 2: Allow WAN → 172.20.30.10 port 443 (HTTPS)
Rule 3: Allow WAN → 172.20.30.10 port 80  (HTTP → redirect)
Rule 4: Drop all other WAN → DMZ traffic

LAN IN rules (LAN → DMZ):

Rule 5: Allow LAN → DMZ (for management access from trusted devices)

DMZ IN rules (DMZ → everything else):

Rule 6: Allow DMZ → WAN (for outbound: updates, Let's Encrypt)
Rule 7: Drop DMZ → LAN (critical isolation rule)
Rule 8: Drop DMZ → Management VLAN

Rule 7 is the most important. Even if the web server is fully compromised, this rule prevents lateral movement into the rest of the network.

LXC container configuration

The Layer 8 blog runs in an Ubuntu 24.04 LXC container on Proxmox:

CT ID:    109
Hostname: Layer8
Cores:    2
RAM:      2048MB
Disk:     20GB
Bridge:   vmbr1
IP:       172.20.30.10/24
Gateway:  172.20.30.254
DNS:      1.1.1.1

Verifying isolation

To confirm the DMZ cannot reach the LAN, from inside the LXC:

# This should fail — DMZ cannot reach LAN
ping -c 3 192.168.1.1

# This should succeed — DMZ can reach internet
ping -c 3 1.1.1.1

The first ping times out, confirming isolation is working correctly.

Result

The blog is publicly accessible on ports 80 and 443. All other inbound traffic is dropped at the UniFi firewall before it reaches the LXC. The LXC cannot reach the rest of the home network under any circumstances, so a compromise of the web server stays contained in the DMZ.