Installing OpenWrt on Proxmox: Virtual Router in a VM in 30 Minutes

Installing OpenWrt on Proxmox: Virtual Router in a VM in 30 Minutes

Installing OpenWrt on Proxmox comes down to four steps: the right image, two bridges, a VM with Secure Boot disabled, and carefully moving the host IP behind the new router. Here’s the full recipe, with checks and rollback.

Quick answer
  1. Download the OpenWrt x86-64 generic-ext4-combined-efi image to the Proxmox host and unpack it.
  2. Set up two bridges: vmbr0 faces the ISP and has no host IP, vmbr1 becomes the local network.
  3. Create a q35 VM with OVMF, disable pre-enrolled Secure Boot keys, import the image as a disk, connect the first network adapter to LAN and the second to WAN.
  4. Start the VM, set the root password and LAN address, install qemu-ga, enable autostart with order 1, and only then move the host address to vmbr1.

If you’re short on time, here’s the whole path in commands. Run these on the Proxmox host, in a root shell. Below, each step is broken down separately, with explanations of why and what can break.


# Where to run: Proxmox host, root shell
VER=25.12.5
BASE=https://downloads.openwrt.org/releases/${VER}/targets/x86/64
IMG=openwrt-${VER}-x86-64-generic-ext4-combined-efi.img
mkdir -p /root/openwrt && cd /root/openwrt
wget ${BASE}/${IMG}.gz ${BASE}/sha256sums
sha256sum -c --ignore-missing sha256sums
gunzip -k ${IMG}.gz
qm create 100 --name openwrt --ostype l26 --machine q35 --bios ovmf \
  --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0 \
  --cpu host --cores 2 --memory 512 --balloon 0 \
  --scsihw virtio-scsi-single \
  --scsi0 local-lvm:0,import-from=/root/openwrt/${IMG},discard=on,ssd=1 \
  --boot order=scsi0 \
  --net0 virtio,bridge=vmbr1 --net1 virtio,bridge=vmbr0 \
  --serial0 socket --vga serial0 --agent enabled=1 \
  --onboot 1 --startup order=1,up=30
qm start 100 && qm terminal 100

Diagnosis: OpenWrt on Proxmox is up, but there’s no internet

You’re setting up OpenWrt on Proxmox so your home server doubles as a router. The VM is created, the lights are green, but there’s no internet. Or there is internet, but you’ve lost access to the Proxmox web interface. Sound familiar?

Installing OpenWrt on Proxmox takes 15 minutes. Figuring out where your access to Proxmox itself went takes another two hours.

The problem is almost never OpenWrt itself. It does exactly what’s written in its config. What breaks is the junction: which virtual adapter became eth0, which bridge holds the host IP, who hands out DHCP to whom, and who starts first after a reboot. That’s the junction we’ll sort out here.

What you’ll end up with

  • A VM running OpenWrt 25.12 that routes traffic from the local network to the internet through a dedicated WAN bridge.
  • A Proxmox host sitting in the LAN behind OpenWrt, with its web interface not exposed externally.
  • The router autostarting first after a host reboot, with other VMs starting after it.
  • Daily backups of the OpenWrt config, weekly vzdump of the whole VM, and a snapshot before every update.
  • A monitoring script, fail2ban on the Proxmox web interface, and a rollback plan for every risky step.

Time-wise: 30-40 minutes if this is your first time and you’re reading the explanations. About five minutes of that is downloading, the rest is checks. Don’t skip the checks. They’re exactly what saves you a sleepless night.

What you’ll need

A physical server or mini PC running Proxmox VE with hardware virtualization support. Two network cards are preferable: one facing the ISP, one facing the local network. One card also works, that’s covered under alternatives using VLANs.

You need access to the host console beyond the network: a monitor with keyboard, IPMI, iDRAC, or iLO. At some point you’ll be moving the host address from one bridge to another. If you get it wrong without console access, you’ll be walking to the server.

Component Version at time of writing Minimum Comment
Proxmox VE 9.2, based on Debian 13 8.x Commands work on both 8.x and 9.x
OpenWrt 25.12.5, 25.12 branch 24.10 Starting with 25.12, apk replaces opkg as the package manager
OpenWrt image x86/64 generic-ext4-combined-efi – For SeaBIOS use the non-efi variant
Host CPU Intel VT-x or AMD-V 2 cores KVM won’t start without virtualization support
RAM for VM 512 MB 256 MB More is only needed for adblock and VPN
Disk for VM 1 GB ~120 MB Default root partition is about 104 MB
Network cards 2 ports 1 port With one port you need a managed switch and VLANs
QEMU Guest Agent qemu-ga package in OpenWrt – Needed for correct backups and monitoring

At the time of writing, Proxmox VE 9.2 and OpenWrt 25.12.5 are current. Before installing, check for newer releases: OpenWrt ships service updates every couple of months, and you’ll need to update the VER variable accordingly.

The 24.10 branch stopped receiving security fixes in September 2026. If you have it running somewhere, that’s a reason to upgrade, not a reason to install it fresh.

What’s in this article

  • Why OpenWrt in Proxmox doesn’t work the first time.
  • A step-by-step recipe: bridges, image, VM, first boot, moving the host behind the router.
  • Verification: commands and expected output.
  • Troubleshooting: eleven common errors with causes and fixes.
  • Alternatives: single network card, PCI passthrough, LXC, OPNsense, RouterOS CHR.
  • Prevention: monitoring, security, backups, updates, and rollback.
  • FAQ covering what people actually search for.

Why OpenWrt in Proxmox doesn’t work after setup

Good news: almost all the problems here come from one short list. Bad news: during your first setup, you’ll hit at least two items on it.

Cause Why it breaks Symptom
Secure Boot enabled in OVMF The OpenWrt bootloader isn’t signed with Microsoft keys, the VM firmware rejects it Access Denied, VM drops to UEFI Shell
Network adapters swapped OpenWrt on x86 treats the first adapter eth0 as the local network, the second eth1 as the ISP WAN has no address, DHCP gets handed out toward the ISP
Identical LAN and WAN subnets The ISP’s home router also hands out 192.168.1.0/24, routing gets confused Pings work intermittently, no internet
Host IP left on the WAN bridge A host with a public IP on vmbr0 exposes port 8006 and SSH to the internet It works, but it’s not safe. Scanners will find it within a day
No autostart or boot order After a host reboot, other VMs start before the router and don’t get addresses Half your services have no network in the morning
Wrong image rootfs.tar.gz is meant for containers, a non-efi image won’t boot on OVMF No bootable device, empty disk
e1000 emulation instead of virtio The emulated card loads the host CPU on every packet Throughput caps at 300-500 Mbit/s, host kernel pegged

Now take a look at the diagram. It shows everything we’re about to build. Remember the main rule: the Proxmox host has no address on the WAN bridge. The host lives in the LAN, like any ordinary client of the router.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    ISP["ISP or ISP router"] --> NIC1["enp1s0 physical WAN port"]
    NIC1 --> VMBR0["vmbr0 WAN bridge, no host IP"]
    VMBR0 --> ETH1["net1 in the VM, eth1 inside"]
    ETH1 --> OWRT["VM 100 OpenWrt"]
    OWRT --> ETH0["net0 in the VM, eth0 inside"]
    ETH0 --> VMBR1["vmbr1 LAN bridge"]
    VMBR1 --> HOST["Proxmox host 192.168.10.2"]
    VMBR1 --> VMS["Other VMs and containers"]
    VMBR1 --> NIC2["enp2s0 physical LAN port"]
    NIC2 --> SW["Switch and clients"]
    style ISP fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style VMBR0 fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style OWRT fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style VMBR1 fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style HOST fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style SW fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af

The address plan used in this article is below. Substitute your own values, but keep the LAN subnet different from whatever the ISP or its router hands out.

Node Interface Address
OpenWrt eth1, WAN DHCP from ISP or static
OpenWrt br-lan, LAN 192.168.10.1/24
Proxmox host vmbr1 192.168.10.2/24, gateway 192.168.10.1
LAN clients – DHCP from OpenWrt, pool 192.168.10.100-250

Recipe: installing OpenWrt on Proxmox step by step

Ports that will be in use

First, figure out what’s listening where. This matters for the firewall step and for troubleshooting, when it’s unclear exactly who’s answering a given request.

Port Protocol Service Where it listens Reachable externally?
8006 TCP Proxmox web interface Host, 192.168.10.2 No, LAN only
22 TCP Proxmox host SSH Host, 192.168.10.2 No, LAN only
3128 TCP Proxmox SPICE proxy Host No
80, 443 TCP LuCI, OpenWrt web interface OpenWrt, 192.168.10.1 No, OpenWrt’s firewall blocks inbound from WAN
22 TCP Dropbear, OpenWrt SSH OpenWrt, LAN only No
53 TCP, UDP DNS, dnsmasq OpenWrt, LAN No
67, 68 UDP DHCP OpenWrt: server on LAN, client on WAN Client on WAN only
51820 UDP WireGuard, if you set it up OpenWrt, WAN Yes, if you open it with a rule

Preparation: check the host

Why: to make sure KVM is available, and to identify your network card and storage names. The names enp1s0 and local-lvm in this article are just examples. Yours are almost certainly different.


# Where to run: Proxmox host, root shell
pveversion
grep -Ec '(vmx|svm)' /proc/cpuinfo
ip -br link
pvesm status
cat /etc/network/interfaces

What you should see: pveversion shows pve-manager 9.x or 8.x. The vmx or svm counter is greater than zero, otherwise enable virtualization in the BIOS. In the ip -br link output, find your physical ports, usually named enp-something or eno-something. In pvesm status, note the storage of type lvmthin or zfspool, that’s where the VM disk will go.

Look closely at /etc/network/interfaces. After a standard install, it already has vmbr0 with the host’s IP and one physical port. We’ll turn that vmbr0 into the WAN bridge. The port it contains should face the ISP or the ISP’s router.

Step 1. Back up the host’s network config

Why: you’ll be editing the host’s network settings twice later on. A copy of the config means a one-command rollback instead of a trip to the server.


# Where to run: Proxmox host
cp /etc/network/interfaces /root/interfaces.bak
cp /etc/hosts /root/hosts.bak
ls -l /root/*.bak

Result: two .bak files in /root. Don’t overwrite them in the following steps, they’re your point of return.

Step 2. Create the LAN bridge vmbr1

Why: OpenWrt needs a bridge to hand out addresses on. We’re not touching the host’s IP yet, it stays on vmbr0, so you don’t lose access. We create the bridge without an address.

Open /etc/network/interfaces and append this block. Replace enp2s0 with your own second physical port. If you don’t have a second port and the LAN is only needed for VMs inside the host, write bridge-ports none.


auto vmbr1
iface vmbr1 inet manual
        bridge-ports enp2s0
        bridge-stp off
        bridge-fd 0
#LAN behind OpenWrt

Apply the config. Proxmox ships ifupdown2, which can reload the network without rebooting and without dropping existing interfaces.


# Where to run: Proxmox host
ifreload -a
ip -br link show vmbr1
bridge link show | grep vmbr1

Result: vmbr1 is UP if a cable is plugged in, or UNKNOWN if not. The second output shows that enp2s0 became a bridge port. Access to Proxmox wasn’t lost, because we never touched vmbr0.

You can do the same thing in the web interface: Node → System → Network → Create → Linux Bridge. Same result, the difference is that commands are easier to repeat on a second server.

Step 3. Download the OpenWrt image and verify the checksum

Why: you need an x86/64 image with UEFI-compatible partitioning. The ext4 variant is easier to extend and repair, squashfs lets you roll back to factory settings. In a VM, Proxmox’s snapshot feature handles rollback, so ext4 is more convenient.

File in targets/x86/64 Purpose Use it?
generic-ext4-combined-efi.img.gz VM with OVMF, UEFI Yes, the main option
generic-ext4-combined.img.gz VM with SeaBIOS If you choose BIOS instead of UEFI
generic-squashfs-combined-efi.img.gz Hardware needing factory reset Possible, but harder to extend the disk
rootfs.tar.gz LXC container No, this is for containers

All images live on the official OpenWrt download server. Download directly to the host, skip an intermediate PC.


# Where to run: Proxmox host
VER=25.12.5
BASE=https://downloads.openwrt.org/releases/${VER}/targets/x86/64
IMG=openwrt-${VER}-x86-64-generic-ext4-combined-efi.img
mkdir -p /root/openwrt && cd /root/openwrt
wget ${BASE}/${IMG}.gz
wget ${BASE}/sha256sums
sha256sum -c --ignore-missing sha256sums

Result: a line with the image name and “OK”. If you see FAILED, the image is corrupted or tampered with, download it again. Don’t set up a router from a file that didn’t pass verification. This is the one device in your network through which all traffic flows.


# Where to run: Proxmox host, /root/openwrt directory
gunzip -k ${IMG}.gz
ls -lh /root/openwrt/

Don’t panic here. gunzip will almost certainly complain about “trailing garbage ignored”. That’s normal: OpenWrt appends a signature at the end of the image, gunzip doesn’t understand it and says so honestly. The .img file is still fully unpacked, around 120 MB in size.

Step 4. Create the VM with one command

Why: the web wizard for creating a VM requires an ISO and offers extra stuff you don’t need. One qm create command creates the VM, imports the image as a disk right away, and sets everything a router needs. The import-from parameter works with Proxmox VE 7.2 and later.


# Where to run: Proxmox host
VER=25.12.5
IMG=openwrt-${VER}-x86-64-generic-ext4-combined-efi.img
qm create 100 \
  --name openwrt \
  --ostype l26 \
  --machine q35 \
  --bios ovmf \
  --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0 \
  --cpu host \
  --cores 2 \
  --memory 512 \
  --balloon 0 \
  --scsihw virtio-scsi-single \
  --scsi0 local-lvm:0,import-from=/root/openwrt/${IMG},discard=on,ssd=1 \
  --boot order=scsi0 \
  --net0 virtio,bridge=vmbr1 \
  --net1 virtio,bridge=vmbr0 \
  --serial0 socket \
  --vga serial0 \
  --agent enabled=1 \
  --onboot 1 \
  --startup order=1,up=30

Let’s go over the parameters that actually matter for the outcome. The rest can be left as is.

Parameter Value Why
pre-enrolled-keys=0 Empty Secure Boot key database Without this, OVMF won’t let the unsigned OpenWrt bootloader run
net0 on vmbr1 First adapter, eth0 inside OpenWrt on x86 makes eth0 the local network
net1 on vmbr0 Second adapter, eth1 inside eth1 becomes WAN with a DHCP client by default
cpu host All of the host CPU’s instructions Faster encryption for VPN. In a cluster with migration, use x86-64-v2-AES instead
balloon 0 No dynamic memory The router shouldn’t have RAM taken away from it under load
serial0 and vga serial0 Serial console Makes qm terminal and copy-paste in the console work
agent enabled=1 Channel for QEMU Guest Agent Clean shutdown, snapshots, monitoring
onboot and startup order=1,up=30 Autostart first, 30-second pause Other VMs start once the router is already handing out DHCP

If 100 is already taken, pick a free ID. Find one with pvesh get /cluster/nextid. Replace local-lvm with your own storage from the pvesm status output. For ZFS it’s usually local-zfs.


# Where to run: Proxmox host
qm config 100

Result: the config has scsi0 at roughly 120 MB, efidisk0, two network adapters on different bridges, and a line reading onboot: 1. Write down the MAC addresses of net0 and net1 from this output. You’ll need them if you ever have to swap the adapters.

Step 5. Grow the disk if you need room for packages

Why: the image’s root partition is about 104 MB. For a router with LuCI and a couple of packages, that’s plenty. If you’re planning adblock lists, a Zabbix agent, and WireGuard logs, give it a gigabyte.

This step is optional. Skip it if you’re not sure you’ll need the space. One caveat: a standard sysupgrade with an image rewrites the partition table and reverts the size back to the original. You’ll have to extend it again after every such upgrade.


# Where to run: Proxmox host, VM powered off
qm disk resize 100 scsi0 1G

The disk grew, but the partition inside it is still the old size. We’ll extend it in step 8, once OpenWrt has internet and we can install parted.

Step 6. First boot and console

Why: on first boot OpenWrt has no password, LAN sits on 192.168.1.1, and the only network access to it is from vmbr1. The most reliable path is the serial console straight from the host.


# Where to run: Proxmox host
qm start 100
qm terminal 100

Press Enter, and you’ll get a root@OpenWrt prompt. Exit the console with Ctrl+O. The same console is available in the web interface via the Console button, xterm.js mode.

First, check that the adapters landed the way we planned. This is the main spot where setting up OpenWrt on Proxmox goes sideways.


# Where to run: OpenWrt console, qm terminal 100
ip -br link
uci show network | grep -E "device|proto"

Result: eth0 belongs to br-lan, and the wan interface uses eth1 with proto dhcp. If it’s the other way around, exit the console and check the troubleshooting section, there’s a command there for swapping adapters on the Proxmox side.

Step 7. Root password and LAN address

Why: without a password, LuCI and SSH let in anyone on the LAN. We’re changing the LAN address because the ISP router almost always sits on 192.168.1.0/24, and identical subnets on WAN and LAN break routing.


# Where to run: OpenWrt console
passwd
uci set network.lan.ipaddr='192.168.10.1'
uci set network.lan.netmask='255.255.255.0'
uci set system.@system[0].hostname='openwrt-pve'
uci commit network
uci commit system
service network restart

Result: ip -br addr show br-lan shows 192.168.10.1/24. OpenWrt’s DHCP pool is offset from the network address, so after changing the subnet it will automatically move to 192.168.10.100-250.

If your ISP uses a static address or PPPoE, configure WAN now. For PPPoE, the commands below apply, use your own login and password.


# Where to run: OpenWrt console, PPPoE only
uci set network.wan.proto='pppoe'
uci set network.wan.username='isp_login'
uci set network.wan.password='isp_password'
uci commit network
service network restart

Step 8. Check WAN and install QEMU Guest Agent

Why: make sure the router sees the internet while the host is still on its old address. If something’s wrong here, you can fix it without risking losing access to Proxmox.


# Where to run: OpenWrt console
ifstatus wan | grep -A3 '"ipv4-address"'
ping -c 3 1.1.1.1
ping -c 3 openwrt.org

Result: WAN has an address, both pings succeed. If the first ping works but the second doesn’t, it’s a DNS issue, see the troubleshooting section.

Now the agent. In 25.12, packages are installed via apk, opkg is gone. This is a common reason why old instructions don’t work verbatim.


# Where to run: OpenWrt console
apk update
apk add qemu-ga
service qemu-ga enable
service qemu-ga start

This part matters: the agent channel only appears in the VM after a full power-off and power-on from the host. A reboot from inside OpenWrt doesn’t count. Do it now.


# Where to run: Proxmox host
qm shutdown 100 && qm start 100
sleep 20
qm agent 100 ping && echo "agent OK"
qm guest cmd 100 network-get-interfaces | grep -E '"name"|"ip-address"'

Result: “agent OK” and a list of interfaces with addresses, including WAN. Now Proxmox sees the VM’s addresses in the summary, can shut it down cleanly, and freeze its filesystem before backups.

If you grew the disk in step 5, extend the partition now. The method comes from the official OpenWrt guide on expanding the root partition. The second partition in the combined-efi image is the root one.


# Where to run: OpenWrt console, only if you did step 5
apk add parted losetup resize2fs e2fsprogs
parted -f -s /dev/sda resizepart 2 100%
reboot

# Where to run: OpenWrt console, after reboot
LOOP="$(losetup -f)"
losetup ${LOOP} /dev/sda2
fsck.ext4 -y ${LOOP}
resize2fs ${LOOP}
reboot

After the second reboot, df -h / will show about a gigabyte. If the partition didn’t grow, check that the disk in Proxmox was actually increased: lsblk inside OpenWrt will show sda’s size.

Step 9. Move the Proxmox host behind OpenWrt

This is the riskiest step. Right now the host sits on vmbr0 next to the router’s WAN. We’re removing the address from vmbr0 and giving the host an address in the LAN, where OpenWrt becomes the gateway.

Critical: you could lose access to the server
Do this step from the host’s local console: monitor with keyboard, IPMI, iDRAC, or iLO. First, set up an auto-rollback timer, it will restore the old config after five minutes unless you cancel it manually. Don’t start until step 8 has fully succeeded: OpenWrt needs internet and a root password in place.

# Where to run: Proxmox host, from local console or IPMI
systemd-run --on-active=300 --unit=net-rollback \
  /bin/sh -c 'cp /root/interfaces.bak /etc/network/interfaces; cp /root/hosts.bak /etc/hosts; ifreload -a'
systemctl list-timers net-rollback.timer

The timer is set. This is a production technique: when making network changes on a remote box, always set up an automatic rollback. If connectivity drops, everything reverts on its own after five minutes.

Now the final /etc/network/interfaces. Replace the file entirely, substituting your own port names. vmbr0 no longer has an address, just the port facing the ISP.


auto lo
iface lo inet loopback

iface enp1s0 inet manual

iface enp2s0 inet manual

auto vmbr0
iface vmbr0 inet manual
        bridge-ports enp1s0
        bridge-stp off
        bridge-fd 0
#WAN, no host address

auto vmbr1
iface vmbr1 inet static
        address 192.168.10.2/24
        gateway 192.168.10.1
        bridge-ports enp2s0
        bridge-stp off
        bridge-fd 0
#LAN behind OpenWrt

source /etc/network/interfaces.d/*

Proxmox requires that the node name resolve to its actual address via /etc/hosts. If you leave the old IP there, the web interface will break and pve-cluster will fail. Fix the node name line and the DNS entry.


# Where to run: Proxmox host
OLDIP=$(hostname -i | awk '{print $1}')
sed -i "s/^${OLDIP}\b/192.168.10.2/" /etc/hosts
grep "$(hostname)" /etc/hosts
echo "nameserver 192.168.10.1" > /etc/resolv.conf
ifreload -a

Check that everything’s alive, then cancel the rollback.


# Where to run: Proxmox host
ip -br addr show vmbr1
ip route | grep default
ping -c 3 192.168.10.1
ping -c 3 1.1.1.1
systemctl stop net-rollback.timer

Result: vmbr1 has address 192.168.10.2/24, the default route goes through 192.168.10.1, both pings succeed. Timer stopped. Plug a laptop into the switch behind enp2s0. It’ll get an address from 192.168.10.100-250, and Proxmox will open at https://192.168.10.2:8006, LuCI at http://192.168.10.1.

If something went wrong and the timer already fired, you’re back on the old address. Figure out what broke and repeat the step with a new timer.

Step 10. Lock down SSH on OpenWrt with keys

Why: a root password for LuCI is needed, but password-based SSH is an unnecessary hole even inside the LAN. The Proxmox host’s key will also be useful for automated config backups.


# Where to run: Proxmox host, then repeat from your own PC
test -f /root/.ssh/id_ed25519 || ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519
cat /root/.ssh/id_ed25519.pub | ssh root@192.168.10.1 "cat >> /etc/dropbear/authorized_keys"
ssh root@192.168.10.1 "uname -a"

The usual ssh-copy-id won’t work here: it puts the key in the home directory, but Dropbear reads /etc/dropbear/authorized_keys. Once key-based login works from every machine you need, disable passwords and restrict SSH to the LAN only.


# Where to run: console or SSH into OpenWrt
uci set dropbear.@dropbear[0].PasswordAuth='off'
uci set dropbear.@dropbear[0].RootPasswordAuth='off'
uci set dropbear.@dropbear[0].Interface='lan'
uci commit dropbear
service dropbear restart

Don’t close your current session. Open a new one and verify key-based login. If it won’t let you in, flip PasswordAuth back to on in the old session and troubleshoot.

Step 11. Startup order for other VMs

Why: the router starts first and waits 30 seconds. Give the rest of your guests order 2 and higher, so they don’t boot before DHCP and DNS are up.


# Where to run: Proxmox host, use your own VM IDs
qm set 101 --onboot 1 --startup order=2,up=10
pct set 200 --onboot 1 --startup order=2
qm config 100 | grep -E 'onboot|startup'

Result: VM 100 has onboot 1 and order=1. Reboot the host during a maintenance window and confirm all guests come up with addresses. That’s the only honest test of autostart.

Here’s what the startup sequence looks like after a host reboot. If any VM ends up without an address after booting, look for the mistake in this chain.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#f8fafc',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'noteBkgColor': '#fefce8',
    'noteTextColor': '#713f12',
    'noteBorderColor': '#fbbf24',
    'actorBkg': '#f8fafc',
    'actorBorder': '#94a3b8',
    'actorTextColor': '#1e293b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'sequence': {
    'mirrorActors': false,
    'messageAlign': 'center',
    'actorMargin': 120,
    'width': 160,
    'noteMargin': 12
  }
}}%%
sequenceDiagram
    participant H as Proxmox host
    participant O as OpenWrt VM 100
    participant P as ISP
    participant V as Other VMs
    H->>O: Start, order 1
    O->>P: DHCP request on WAN
    P->>O: WAN address and gateway
    Note over O: dnsmasq hands out addresses in LAN
    H->>H: Wait 30 seconds
    H->>V: Start, order 2
    V->>O: DHCP request on LAN
    O->>V: Address from 192.168.10.0/24

How to verify OpenWrt in Proxmox is working correctly

Verification happens from three angles: the host sees the VM and its agent, the router sees the internet, and a client on the LAN gets an address and reaches the outside world. If all three are green, you’re done.


# Where to run: Proxmox host
qm status 100 --verbose | grep -E '^status|^uptime|^qmpstatus'
qm agent 100 ping && echo "agent OK"
ip route | grep default
ping -c 3 192.168.10.1
ping -c 3 1.1.1.1
getent hosts proxmox.com

# Where to run: SSH into OpenWrt
ifstatus wan | grep -E '"up"|"address"'
logread | grep -E 'dnsmasq-dhcp|netifd' | tail -20
cat /tmp/dhcp.leases
fw4 print | grep -c chain
df -h /
free -m

# Where to run: Linux client on the LAN, e.g. a laptop
ip -br addr
ip route | grep default
ping -c 3 192.168.10.1
ping -c 3 google.com
Check Expected result If not
qm status 100 status: running, qmpstatus: running Check the startup log: journalctl -u pve-guests
qm agent 100 ping Empty output and “agent OK” Agent isn’t installed or the VM hasn’t been restarted from the host
ifstatus wan “up”: true and an ISP-assigned address Adapters swapped, or the ISP binds to a MAC address
/tmp/dhcp.leases Lines with client MACs and addresses LAN port isn’t in vmbr1, or there’s a second DHCP server on the network
df -h / More than 50% free Extend the disk per steps 5 and 8
ping google.com from client Replies with no loss DNS or NAT issue, see troubleshooting

And one more test almost nobody bothers with. From an external machine, say a phone on mobile data, try to open the public IP on port 8006. You should get a timeout. If it opens, the host still has an address on the WAN bridge.

Troubleshooting: common OpenWrt on Proxmox errors

It’s rarely as bad as you think. Usually it’s much simpler: two swapped lines in a config. Below are the errors in roughly the order I see them most often.

First, a decision tree for diagnosing issues. Go top to bottom, don’t skip steps.

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    A["No internet behind OpenWrt"] --> B{"Did the VM boot?"}
    B -->|No| C["Secure Boot or wrong image"]
    B -->|Yes| D{"Does WAN have an address?"}
    D -->|No| E["net0 and net1 swapped"]
    D -->|Yes| F{"Ping 1.1.1.1 from the router?"}
    F -->|No| G["Subnet conflict or gateway issue"]
    F -->|Yes| H{"Did the client get an address?"}
    H -->|No| I["LAN port not in vmbr1"]
    H -->|Yes| J["Check DNS on the client"]
    style A fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style C fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
    style E fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
    style G fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
    style I fill:#f8fafc,stroke:#ef4444,stroke-width:2px,color:#b91c1c
    style J fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d

Error 1. Access Denied on boot, VM drops to UEFI Shell

Cause: the VM was created via the web interface with the “Pre-Enroll keys” checkbox on. OVMF enables Secure Boot and rejects the unsigned OpenWrt bootloader.

Fix: recreate the EFI disk without pre-enrolled keys. The OpenWrt disk itself stays untouched, no data is lost.


# Where to run: Proxmox host
qm stop 100
qm set 100 --delete efidisk0
qm set 100 --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0
qm start 100

Error 2. No bootable device, or endless reboot loop

Cause: boot order isn’t set, or a non-efi image is attached to a VM running OVMF. The reverse also happens: an efi image on SeaBIOS boots, but not reliably.

Fix: check the boot order. If it’s a non-efi image, switch the VM to SeaBIOS.


# Where to run: Proxmox host
qm config 100 | grep -E 'boot|bios|scsi0'
qm set 100 --boot order=scsi0
# only if the image is non-efi:
qm set 100 --bios seabios

Error 3. WAN has no address, DHCP goes out toward the ISP

Cause: net0 is connected to the WAN bridge, net1 to LAN. OpenWrt is dutifully running a DHCP server on eth0 and handing out addresses into the ISP’s network. Some ISPs block the port over this.

Fix: swap the bridges on the Proxmox side, keeping the MAC addresses intact. No changes needed inside OpenWrt. Grab the MACs from qm config 100.


# Where to run: Proxmox host, substitute MACs from qm config 100
qm config 100 | grep ^net
qm set 100 --net0 virtio=BC:24:11:AA:AA:AA,bridge=vmbr1
qm set 100 --net1 virtio=BC:24:11:BB:BB:BB,bridge=vmbr0
qm reboot 100

Error 4. The ISP won’t assign an address to the new router

Cause: the ISP has bound your service to the old router’s MAC address. The virtual adapter has a random MAC from Proxmox’s own range.

Fix: assign the old router’s MAC to the WAN adapter. Do this on the Proxmox side, so the MAC survives any OpenWrt reinstall. Remove the old router from the network, two identical MACs on the same segment cause chaos.


# Where to run: Proxmox host, substitute your old router's MAC
qm set 100 --net1 virtio=AA:BB:CC:DD:EE:FF,bridge=vmbr0
qm reboot 100

Error 5. Pings work intermittently, internet comes and goes

Cause: a subnet conflict. The ISP router handed out a WAN address from 192.168.1.0/24, while OpenWrt’s LAN is still on 192.168.1.1. The kernel can’t figure out where to send replies.

Fix: change the LAN subnet to something else. After that, remember that the Proxmox host’s address needs to move too.


# Where to run: OpenWrt console, qm terminal 100
ifstatus wan | grep '"address"'
uci get network.lan.ipaddr
uci set network.lan.ipaddr='192.168.10.1'
uci commit network
service network restart

Error 6. Proxmox web interface disappeared after moving the address

Cause: /etc/hosts still has the old address, or vmbr1 doesn’t have the port you’re connecting through, or the laptop is still on the old subnet.

First, get back to a working state
If the rollback timer wasn’t set and connectivity is gone, go to the host’s local console. Restore the saved network and hosts files, reload the network, and only then investigate the cause. Don’t edit the config blindly a third time in a row.

# Where to run: Proxmox host, local console
cp /root/interfaces.bak /etc/network/interfaces
cp /root/hosts.bak /etc/hosts
ifreload -a
systemctl restart pve-cluster pveproxy

Once access is back, check three things: the node name in /etc/hosts points to the new address, vmbr1 has the correct physical port, and the laptop is plugged into that port or into a switch behind it.

Error 7. LAN clients aren’t getting an address

Cause: the physical port isn’t added to vmbr1, a second DHCP server is running on the network, or Proxmox’s firewall is enabled on the VM’s network adapter and blocking broadcast traffic.

Fix: listen for DHCP directly on the host’s bridge. If the client’s requests show up but no replies, the problem is in OpenWrt. If no requests show up at all, it’s in the physical layer or the bridge.


# Where to run: Proxmox host
bridge link show | grep vmbr1
apt install -y tcpdump
tcpdump -ni vmbr1 -c 20 port 67 or port 68
qm config 100 | grep ^net

In the qm config output, net0 and net1 shouldn’t have firewall=1. Filtering is handled by OpenWrt, a double firewall on the same path just adds confusion.

Error 8. Internet works by IP, but sites won’t load

Cause: DNS isn’t working. Either the ISP isn’t handing out DNS via DHCP, dnsmasq has crashed, or the host’s /etc/resolv.conf still has the old server.


# Where to run: SSH into OpenWrt
nslookup google.com 127.0.0.1
cat /tmp/resolv.conf.d/resolv.conf.auto
service dnsmasq restart
logread -e dnsmasq | tail -20

If the ISP isn’t handing out DNS, set servers manually on WAN. Then check resolv.conf on the Proxmox host, it should have 192.168.10.1.


# Where to run: SSH into OpenWrt
uci set network.wan.peerdns='0'
uci add_list network.wan.dns='8.8.8.8'
uci add_list network.wan.dns='1.1.1.1'
uci commit network
service network restart

Error 9. Low throughput and high host CPU load

Cause: the adapter model is e1000 or rtl8139, there’s a single queue on a gigabit-or-faster link, or MTU isn’t tuned for PPPoE.

Fix: switch to virtio with multiple queues, matching the number of VM cores. In OpenWrt, enable packet steering, which spreads packet processing across cores.


# Where to run: Proxmox host, keep the same MACs
qm set 100 --net0 virtio=BC:24:11:AA:AA:AA,bridge=vmbr1,queues=2
qm set 100 --net1 virtio=BC:24:11:BB:BB:BB,bridge=vmbr0,queues=2

# Where to run: SSH into OpenWrt
uci set network.globals.packet_steering='1'
uci commit network
service network restart

Measure before and after. iperf3 between a LAN client and an outside server will give you a real number. Trust the graphs, not your gut feeling.

Error 10. QEMU guest agent is not running

Cause: the agent isn’t installed, isn’t running, or the VM hasn’t been fully powered off since the agent option was enabled. The virtual agent port only gets added on a cold start.


# Where to run: SSH into OpenWrt
apk info -e qemu-ga && service qemu-ga status

# Where to run: Proxmox host
qm set 100 --agent enabled=1
qm shutdown 100 && qm start 100
qm agent 100 ping && echo "agent OK"

Error 11. Packages missing or disk shrunk after an upgrade

Cause: sysupgrade with an image installs a clean system and carries over only the config. Manually installed packages need to be reinstalled. The partition table also comes straight from the image.

Fix: save the package list before upgrading, reinstall it in one command afterward. For minor upgrades within a branch, Attended Sysupgrade is more convenient, it builds an image with your packages already included.


# Where to run: SSH into OpenWrt, before upgrading
apk info > /etc/backup-packages.txt
echo /etc/backup-packages.txt >> /etc/sysupgrade.conf
Error Cause Fix
Access Denied, UEFI Shell Secure Boot with Microsoft keys Recreate efidisk0 with pre-enrolled-keys=0
No bootable device Boot order, or wrong image boot order=scsi0, image matching your BIOS type
WAN has no address net0 and net1 swapped Swap bridges, keeping the MACs
ISP won’t assign an address MAC binding Old router’s MAC on net1
Internet intermittent Identical WAN and LAN subnets LAN on 192.168.10.0/24
Lost access to Proxmox /etc/hosts, bridge port, laptop subnet Rollback and retry with a timer
Clients get no address Port not on bridge, second DHCP, NIC firewall tcpdump on vmbr1, remove firewall=1
Sites won’t load DNS Manual DNS on WAN, host’s resolv.conf
Low throughput e1000, single queue virtio, queues, packet steering
Agent not responding No cold start qm shutdown and qm start
Packages gone after upgrade sysupgrade installs a clean system Backup package list, use ASU

Alternatives: OpenWrt in LXC, NIC passthrough, other routers

A VM with virtio is a compromise between speed, isolation, and simplicity. It covers most home and office setups up to gigabit speeds. But there are other options, and in some cases a different approach makes more sense.

Single network card: VLAN-aware bridge

Mini PCs often have just one port. In that case, WAN and LAN are split across VLANs, handled by a managed switch. The ISP cable goes into an access port on VLAN 20, the server connects via a trunk carrying VLANs 10 and 20.

Without a managed switch, this scheme doesn’t work. Tagged traffic has nothing to untag it. An $8 unmanaged switch won’t help here.


auto lo
iface lo inet loopback

iface enp1s0 inet manual

auto vmbr0
iface vmbr0 inet manual
        bridge-ports enp1s0
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094

auto vmbr0.10
iface vmbr0.10 inet static
        address 192.168.10.2/24
        gateway 192.168.10.1
#Host on LAN, VLAN 10

# Where to run: Proxmox host, keep the same MACs
qm set 100 --net0 virtio=BC:24:11:AA:AA:AA,bridge=vmbr0,tag=10
qm set 100 --net1 virtio=BC:24:11:BB:BB:BB,bridge=vmbr0,tag=20

Nothing changes inside OpenWrt: it still sees eth0 and eth1 without tags. The Proxmox bridge handles the tagging.

Passing a network card through to the VM

If your link runs at 2.5 or 10 Gbit/s and virtio can’t keep up, give the physical card to the VM entirely via PCI passthrough. The host no longer sees that card at all. Packets bypass its network stack, latency and load drop.


# Where to run: Proxmox host
dmesg | grep -e DMAR -e IOMMU | head
lspci -nn | grep -i ethernet
find /sys/kernel/iommu_groups/ -type l | grep 03:00
qm set 100 --hostpci0 0000:03:00.0,pcie=1

Downsides: the VM can’t migrate to another node, the card needs to be in its own IOMMU group, and if the VM crashes, the port is dead until it restarts. On recent Proxmox kernels, IOMMU is enabled by default for Intel, and it usually works out of the box for AMD too. Check the dmesg output, not five-year-old forum posts.

OpenWrt in an LXC container

It works, but it’s a variant for experiments. The container shares a kernel with the host, so OpenWrt’s kernel modules can’t be loaded, and some functionality like certain VPN setups and SQM runs into the Proxmox kernel’s limitations. On the plus side, resource usage is close to zero.


# Where to run: Proxmox host, testing only
VER=25.12.5
cd /var/lib/vz/template/cache
wget https://downloads.openwrt.org/releases/${VER}/targets/x86/64/openwrt-${VER}-x86-64-rootfs.tar.gz
pct create 200 local:vztmpl/openwrt-${VER}-x86-64-rootfs.tar.gz \
  --ostype unmanaged --arch amd64 --hostname openwrt-lxc \
  --cores 1 --memory 256 --swap 0 --rootfs local-lvm:1 \
  --net0 name=eth0,bridge=vmbr1 --net1 name=eth1,bridge=vmbr0

I wouldn’t use LXC for a network’s main router. A host kernel update here can silently change the router’s behavior, and you’ll find out about it from your users.

Comparing the options

Option Speed Complexity Isolation When to pick it
OpenWrt in a VM, virtio Up to 1-2 Gbit/s Low Full Home, small office, home lab
OpenWrt in a VM, PCI passthrough Line-rate at 2.5-10G Medium Full Fast link, dedicated network card
OpenWrt in LXC High Medium Weak Testing, isolated internal subnets
OPNsense in a VM Up to 1-2 Gbit/s Medium Full You need IDS, reporting, and an enterprise-level web UI
MikroTik RouterOS CHR Depends on license Medium Full Your whole network already runs MikroTik and needs consistent config style
Proxmox host itself as router, nftables Maximum High None Minimalism, you understand nftables. The host becomes the edge device
Separate hardware router Depends on hardware Low Physical Internet needs to stay up even while the server is being serviced

Why this article uses a VM with virtio: it survives host updates without surprises, can be snapshotted before every change, and can migrate to another node. The throughput is plenty for a typical connection. When the link gets faster, switching to passthrough is a single command.

Worth noting on that last table row: a virtual router means a host reboot equals an internet outage. If that’s unacceptable, keep a hardware router and use OpenWrt on Proxmox for lab segments only.

Prevention: monitoring, security, backups, updates

A router nobody monitors breaks on a Friday evening. That’s not a law of nature, just a statistic drawn from my own incidents.

Monitoring

The minimum worth setting up right away: a script on the host that checks the agent, the router’s LAN address, and internet access once a minute. It logs errors to the system journal. From there, Zabbix, Prometheus, or any log collector can pick them up.


# Where to run: Proxmox host
cat > /usr/local/bin/openwrt-watch.sh <<'EOF'
#!/bin/sh
VMID=100
GW=192.168.10.1
EXT=1.1.1.1
qm agent "$VMID" ping >/dev/null 2>&1 || logger -t openwrt-watch "VM $VMID: guest agent not responding"
ping -c 2 -W 2 "$GW" >/dev/null 2>&1 || logger -t openwrt-watch "OpenWrt $GW unreachable from LAN"
ping -c 2 -W 2 "$EXT" >/dev/null 2>&1 || logger -t openwrt-watch "No internet access through OpenWrt"
EOF
chmod +x /usr/local/bin/openwrt-watch.sh
echo '* * * * * root /usr/local/bin/openwrt-watch.sh' > /etc/cron.d/openwrt-watch
journalctl -t openwrt-watch --since "10 min ago"

I deliberately don’t add an automatic qm reset based on these checks. A router that restarts itself every five minutes because of a flaky ISP is worse than one that’s simply down. Alert first, let a human decide what to do.

If you run Zabbix, attach an ICMP Ping template to 192.168.10.1 and add a trigger for packet loss to an external address. For metrics from inside OpenWrt, there’s a zabbix-agentd package, install it with apk add. Make sure its port is only open to the Zabbix server’s address.

Security

Firewall. Don’t install UFW on the Proxmox host. Proxmox has its own pve-firewall on nftables or iptables, and two rule managers on one machine will step on each other. On OpenWrt, fw4 runs with a default policy: everything inbound from WAN is rejected, LAN is trusted.

On the host, enable the datacenter-level firewall and restrict management access to the LAN subnet. Proxmox’s “management” IP set is designed specifically for this: access to 8006 and 22 from it is allowed automatically.


# File /etc/pve/firewall/cluster.fw on the Proxmox host
[OPTIONS]
enable: 1
policy_in: DROP
policy_out: ACCEPT

[IPSET management]
192.168.10.0/24
Host firewall: don't lock yourself out
Before enabling this, make sure your laptop’s address falls within the subnet listed in the management set. Compile the rules before they take effect. If access drops, you can stop the firewall from the host’s local console.

# Where to run: Proxmox host
pve-firewall compile | head -40
pve-firewall status
# rollback from local console, if locked out:
# pve-firewall stop

Don’t enable Proxmox’s firewall on the OpenWrt VM’s own network adapters. The router does its own filtering, and an extra layer of conntrack on the bridge breaks asymmetric flows and adds latency.

fail2ban for the web interface. On Debian 13, logs live in journald, so the backend has to be systemd. The filter catches failed logins to pvedaemon.


# Where to run: Proxmox host
apt install -y fail2ban python3-systemd
cat > /etc/fail2ban/filter.d/proxmox.conf <<'EOF'
[Definition]
failregex = pvedaemon\[.*authentication failure; rhost=<HOST> user=.* msg=.*
ignoreregex =
journalmatch = _SYSTEMD_UNIT=pvedaemon.service
EOF
cat > /etc/fail2ban/jail.d/proxmox.local <<'EOF'
[DEFAULT]
backend = systemd
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true

[proxmox]
enabled = true
port = https,http,8006
filter = proxmox
maxretry = 3
findtime = 2d
bantime = 1h
EOF
systemctl enable --now fail2ban
fail2ban-client status proxmox

Check: enter a wrong password in the web interface three times from a test machine. Its address should show up in fail2ban-client status proxmox. Unban it with fail2ban-client set proxmox unbanip and the address.

SSH hardening on the host. Leave root key-based login in place: Proxmox uses it for cluster and migration operations. Disable passwords entirely. First make sure your key is already in /root/.ssh/authorized_keys and that key login works.


# Where to run: Proxmox host
cat > /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 30
EOF
sshd -t && systemctl reload ssh

A separate user. There’s no database in this setup, so the role usually played by a dedicated DB account is filled here by a dedicated Proxmox user for everyday work. Keep root@pam for emergencies, and set up a user with a limited role for yourself, with TOTP enabled in the web interface.


# Where to run: Proxmox host
pveum user add andrey@pve --comment "Daily work"
pveum passwd andrey@pve
pveum acl modify /vms -user andrey@pve -role PVEVMAdmin
pveum user permissions andrey@pve

IP restrictions. The Proxmox web interface and LuCI are already LAN-only by design: the host has no WAN address, and fw4 blocks inbound traffic to the router. If you need remote access, set up WireGuard on OpenWrt and connect through the tunnel. Never expose port 8006 externally.

Backups

A router without a config backup means 43 firewall rules you’re reconstructing from memory at 3 a.m. You’ll remember 41 of them. The other two will surface a month later.

What to back up How often Where to keep it How to restore
OpenWrt config, sysupgrade -b Daily and before changes Host, then NAS or PBS sysupgrade -r with the archive, then reboot
VM 100 entirely, vzdump Weekly Proxmox Backup Server or a separate disk qmrestore over the existing VM or into a new one
VM snapshot Before every update Same storage as the disk qm rollback
/etc/network/interfaces, /etc/hosts, /etc/pve With every network change Off the host Copy the files back and ifreload

A script for daily OpenWrt config backups to the host. We put the host’s key in Dropbear back in step 10. The -O flag on scp is needed because modern OpenSSH defaults to SFTP, and Dropbear doesn’t have an SFTP server.


# Where to run: Proxmox host
cat > /usr/local/bin/openwrt-backup.sh <<'EOF'
#!/bin/sh
set -e
OWRT=root@192.168.10.1
DST=/root/backup/openwrt
F=owrt-$(date +%F).tar.gz
mkdir -p "$DST"
ssh -o BatchMode=yes "$OWRT" "apk info > /etc/backup-packages.txt; sysupgrade -b /tmp/$F"
scp -O -o BatchMode=yes "$OWRT:/tmp/$F" "$DST/"
ssh -o BatchMode=yes "$OWRT" "rm -f /tmp/$F"
find "$DST" -name 'owrt-*.tar.gz' -mtime +30 -delete
EOF
chmod +x /usr/local/bin/openwrt-backup.sh
echo '30 3 * * * root /usr/local/bin/openwrt-backup.sh' > /etc/cron.d/openwrt-backup
/usr/local/bin/openwrt-backup.sh && ls -lh /root/backup/openwrt/

Weekly vzdump through a job in the datacenter. Snapshot mode with a running agent freezes the VM’s filesystem for a fraction of a second, without rebooting the router.


# Where to run: Proxmox host, substitute your own storage
pvesh create /cluster/backup --schedule "sun 03:00" --vmid 100 \
  --storage local --mode snapshot --compress zstd \
  --prune-backups keep-last=4 --comment "OpenWrt weekly"
pvesh get /cluster/backup
vzdump 100 --storage local --mode snapshot --compress zstd

The last command runs an ad-hoc backup immediately. Run it to make sure the job actually works.

Restore. A backup that’s never been restored isn’t a backup, it’s a hope. Once a quarter, deploy a copy into a separate VM numbered 900 with no network and confirm it boots.


# Where to run: Proxmox host
ls /var/lib/vz/dump/ | grep qemu-100
qmrestore /var/lib/vz/dump/vzdump-qemu-100-DATE.vma.zst 900 --unique 1
qm set 900 --net0 virtio,bridge=vmbr1,link_down=1 --net1 virtio,bridge=vmbr0,link_down=1 --onboot 0
qm start 900 && qm terminal 900

# Where to run: SSH into OpenWrt, restoring config only
sysupgrade -r /tmp/owrt-DATE.tar.gz
reboot

Updates

Updating OpenWrt within the 25.12 branch. Take a snapshot before any update. It takes 2 seconds and saves you an evening.


# Where to run: Proxmox host
qm snapshot 100 pre-upgrade --description "Before OpenWrt upgrade"
qm listsnapshot 100

The most convenient path is Attended Sysupgrade. It’s enabled by default in 25.12: LuCI has a System → Attended Sysupgrade entry, and the owut utility is available from the console. The build server assembles an image with your packages already included.


# Where to run: SSH into OpenWrt
apk add owut
owut check
owut upgrade

Manual path, if ASU isn’t available. Download the new combined-efi image straight into /tmp on the router, the filesystem there is RAM-backed, and 512 MB of memory is enough. The -v flag shows which config files get carried over.


# Where to run: SSH into OpenWrt, substitute the new version number
cd /tmp
wget https://downloads.openwrt.org/releases/25.12.6/targets/x86/64/openwrt-25.12.6-x86-64-generic-ext4-combined-efi.img.gz
sysupgrade -v /tmp/openwrt-25.12.6-x86-64-generic-ext4-combined-efi.img.gz

After rebooting, reinstall packages from your saved list, check internet access and the agent. Don’t run apk upgrade for everything at once on a live router. In OpenWrt the system and its packages are built as a single unit, and a bulk upgrade on a production router is a classic way to end up with incompatible libraries.

For major branch upgrades, say from 24.10 to 25.12, I use a blue-green deployment approach. A new VM built from the fresh image, config restored from backup via sysupgrade -r, bridges switched over, old VM kept powered off for a week. Rollback in that case takes 20 seconds.

Rolling back a minor upgrade, if something breaks.


# Where to run: Proxmox host
qm rollback 100 pre-upgrade
qm start 100
# once everything's been stable for a few days:
qm delsnapshot 100 pre-upgrade

Updating Proxmox. Always apt full-upgrade, never apt upgrade: Proxmox changes dependencies, and a plain upgrade leaves the system half-upgraded. Remember that a host reboot means an internet outage for the whole network. Plan a maintenance window.


# Where to run: Proxmox host
vzdump 100 --storage local --mode snapshot --compress zstd
apt update
apt list --upgradable
apt full-upgrade
pveversion -v | head -5
proxmox-boot-tool kernel list

If something breaks in networking or passthrough after an upgrade, roll back to the previous kernel without reinstalling anything. Pin it and reboot.


# Where to run: Proxmox host, take the version from kernel list
proxmox-boot-tool kernel pin 6.17.2-1-pve
reboot
# once a fixed kernel is released:
# proxmox-boot-tool kernel unpin

For major Proxmox version upgrades, there are dedicated check utilities, like pve8to9 for moving from 8 to 9. Run it with the –full flag before upgrading and fix everything it flags. Those warnings aren’t there for show.

FAQ: common questions about OpenWrt on Proxmox

Why isn’t OpenWrt on Proxmox handing out internet after setup?

Nine times out of ten, the network adapters are swapped or the LAN and WAN subnets overlap. Check that net0 is connected to the LAN bridge, net1 to the WAN bridge, and that the router’s LAN isn’t on 192.168.1.0/24 if the ISP router is on the same subnet. The tenth case is usually DNS: ping by IP works, but sites won’t load.

How do I verify OpenWrt in Proxmox is working correctly?

From the host, run qm agent 100 ping and ping an external address, inside OpenWrt check ifstatus wan and /tmp/dhcp.leases. From a LAN client, verify it got an address from the router’s pool and can open sites by name. The last test is trying to open port 8006 on the public IP from outside, it should time out.

What do I do if OpenWrt on Proxmox won’t boot with UEFI?

Secure Boot is almost always the culprit: creating a VM through the web interface defaults to pre-enrolled keys. Delete efidisk0 and recreate it with pre-enrolled-keys=0. If that doesn’t help, confirm the image is actually combined-efi, and that the boot order points to scsi0.

How is OpenWrt in a virtual machine different from OpenWrt in an LXC container?

A VM runs its own OpenWrt kernel with all modules, is isolated from the host, and gets snapshotted along with its full state. A container uses the Proxmox kernel, so some network features aren’t available, and a host kernel update can change the router’s behavior. Use a VM for your main router, keep containers for testing.

Can I install OpenWrt on Proxmox with a single network card?

Yes, with a VLAN-aware bridge and a managed switch. Run the ISP cable into an access port on one VLAN, connect the server via a trunk, and assign different tags to the VM’s adapters. Without a managed switch this setup doesn’t work, and the LAN remains internal to the VMs on the host.

How much memory and how many cores does OpenWrt on Proxmox need?

A typical router needs one or two cores and 256-512 MB of memory. More is needed for adblock with large lists, WireGuard on a gigabit link, or SQM. It’s best to disable dynamic memory ballooning for this VM.

Which OpenWrt image should I use for Proxmox: ext4 or squashfs?

ext4 is more convenient for a VM: the partition is easier to extend and repair, and Proxmox’s snapshot feature handles rollback to a working state. Squashfs is useful on hardware where you need a factory reset without external tools. For OVMF, pick the variant with “efi” in the name, for SeaBIOS pick the one without it.

How do I update OpenWrt in Proxmox without losing my settings?

Take a VM snapshot, back up the config with sysupgrade -b, and upgrade via Attended Sysupgrade, which builds an image including your packages. A manual sysupgrade also preserves configs, but you’ll need to reinstall packages yourself. If anything breaks, qm rollback restores the VM to its pre-upgrade state in seconds.

Outcome: what’s working for you now

We built a router on OpenWrt 25.12 inside Proxmox: two bridges with clear roles, a virtio VM with Secure Boot disabled, an agent for correct backups, and autostart as the first priority. The host moved behind the router with an auto-rollback timer and no longer exposes its web interface to the internet. On top of that: fail2ban, keys instead of passwords, and management access restricted to the LAN subnet.

From here the router runs itself: the config gets backed up every night, the VM once a week, and before every update there’s a snapshot plus a one-command rollback. The logical next step is WireGuard on OpenWrt for remote access to your home network and to Proxmox itself. No port forwarding, no stress. The router is virtual, but its incidents are entirely real. The difference now is that they get resolved in a minute.

Didn't work?
If it didn’t work, leave a comment and we’ll sort it out. Include the output of qm config 100 from the host, ifstatus wan from OpenWrt, and a description of which step went wrong. With that info, finding the cause usually takes just a couple of messages.

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →
Поделитесь:

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top