Migrating from UFW to Proxmox VE Firewall: the key steps

Symptoms

I moved my homelab from per-container UFW to the built-in Proxmox VE firewall. It was not a clean flip. I hit broken services, confusing logs and one Vaultwarden outage that took more time than it should have.

The symptoms were plain enough once they showed up. Services stopped responding. SSH timed out now and then. Vaultwarden would not start after a firewall change.

These are the sort of log lines I saw:

  • container syslog: “UFW BLOCK IN=eth0 OUT= MAC=… SRC=1.2.3.4 DST=5.6.7.8 PROTO=TCP SPT=12345 DPT=80”
  • host journal: “pve-firewall[1234]: ERROR: failed to apply rules: chain ‘ufw-user-input’ not found”
  • Vaultwarden startup: “Error: bind EACCES 0.0.0.0:80”

These are the checks I ran and what I found.

  • On the container:
ufw status verbose
  • Expected: inactive
  • Actual: active, with ufw-user-* chains listed
  • On the Proxmox host:
systemctl status pve-firewall
  • Expected: active (running)
  • Actual: active, but journalctl -u pve-firewall -b showed rule application errors
  • Check kernel firewall state:
iptables -L -n
  • Expected: only Proxmox-created chains and the default policy
  • Actual: extra ufw chains still present, mixed in with the host rules

That was the first sign I had two firewall systems fighting over the same ruleset.

Where it showed up

The mess showed up in a few places.

Container settings

  • UFW ran inside each LXC or VM. If it stayed active, it modified iptables rules inside that namespace.
  • Inside a container I checked:
sudo ufw status verbose
sudo systemctl status ufw

I also looked at /var/log/ufw.log for blocked packets.

Network interfaces

  • Proxmox handled bridging and firewall rules at the host level. If the container firewall touched bridged interfaces, packets could be dropped before they reached the service.
  • I used ip link and ip addr to confirm the interfaces looked right.
  • I used ss -ltnp inside the container to check the service was listening where I expected.

Proxmox VE configuration

  • The Proxmox firewall runs centrally and can push rules to nodes, VMs and containers. The GUI and /etc/pve/firewall control that.
  • I checked:
systemctl status pve-firewall
journalctl -u pve-firewall -b

I was looking for unknown chains, failed iptables commands and syntax errors while the rules loaded.

The pattern was consistent: logs mentioning ufw chains, failures when applying rules to a VM, and services that had worked before the change.

Cause

I worked through it in a loop: reproduce, observe, change one thing, repeat.

Conflicting firewall rules

UFW creates its own chains, such as ufw-user-input and ufw-user-forward. The Proxmox firewall expects to manage chains in a known order. If UFW is still active, Proxmox can end up calling or re-ordering chains that no longer line up. That leads to errors and blocked packets.

Half-configured container firewalls

Some container images do not ship UFW cleanly for namespaced environments. A half-configured UFW can leave dangling rules behind.

Service configuration

Vaultwarden and other apps were bound to 0.0.0.0:80 but were blocked by a global deny rule from UFW. The Proxmox firewall then tried to load its policy and hit the UFW chains, which left the service unreachable.

The useful checks were the same ones as above:

ufw status verbose
systemctl status ufw
iptables -S
journalctl -u pve-firewall -b
ss -ltnp

Comparing expected and actual output made it easier to see whether I was dealing with leftover UFW rules or a bad Proxmox rule.

Fix

I kept this reversible. One change, then a test.

Remove UFW completely

  • Inside each container:
sudo ufw disable
sudo apt purge --auto-remove ufw
  • Check removal:
sudo systemctl status ufw
sudo ufw status
  • If ufw chains still show up, check iptables -S and nft list ruleset. In my case, a container reboot or rebuilding its network namespace cleared the leftovers.

I removed UFW from every container before I enabled the Proxmox firewall. That avoided the cross-system conflict. If you want to be more cautious, disable UFW first and leave it off for a while before purging it.

Apply Proxmox firewall rules

  • Enable the Proxmox VE firewall at node or datacentre level in the GUI, or by CLI if that is how you work.
  • Start with permissive rules, then tighten them.
  • Add explicit allow rules for SSH, the Proxmox GUI, and any container services that should be reachable.
  • Keep the rules short and testable. Allow TCP 80 and 443 to the VM IP, test the service, and only then add a global deny.

Test in steps

  • After each rule change:
curl -I http://<container-ip>:80
curl -I https://<container-ip>:443
  • Check service status inside the container:
systemctl status <service>
  • Watch the host firewall log while you apply the change:
journalctl -u pve-firewall -f

If something broke, I reverted the last rule or disabled the Proxmox firewall while I looked at it. I kept backups of /etc/pve/firewall and exported the GUI rule set before making bigger changes.

Check it is fixed

Verify the service

  • Check it from the network with curl, a browser, or another machine on the LAN.
  • For SSH, ssh -vvv shows where the connection stalls.
  • Inside the container, ss -ltnp confirms the service is listening on the right address and port.

Watch the logs

  • Keep an eye on the Proxmox firewall journal:
journalctl -u pve-firewall -f

I wanted to see rules apply cleanly, with no ERROR lines. Any later mention of ufw or unknown chains meant I had missed something.

  • Check the container logs too: /var/log/syslog, /var/log/ufw.log if it exists, and the service logs.

Check the exposed ports

  • From the LAN, I ran:
nmap -Pn -p 1-65535 <container-ip>
  • The only open ports should be the ones you allowed.
  • I also kept a plain list of the inbound and outbound rules I applied in the Proxmox GUI. That made it easier to spot a bad edit later.

The main lessons were simple: remove UFW from the containers before you turn on the Proxmox VE firewall, change one rule at a time, and keep a rollback path. That saved me from another long night when Vaultwarden fell over.

Related posts

Weekly Tech Digest | 06 Jul 2026

Stay updated with the latest in tech! This digest covers AI ethics, auto industry shifts, and the impact of politics on technology, exploring today's pressing issues.

wolfCOSE zero-allocation parsing in embedded C

wolfCOSE looks sensible only if you care about what your firmware actually has to carry. I like that, because on small targets the wrong crypto feature can cost more than the message itself, and there...

restic | v0.19.1

restic v0 19 1: safer FUSE mounts and mountpoint checks, robust backup source and exclude handling, clearer CLI JSON output, Windows SFTP deletion fixes