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 -bshowed 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 linkandip addrto confirm the interfaces looked right. - I used
ss -ltnpinside 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/firewallcontrol 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 -Sandnft 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 -vvvshows where the connection stalls. - Inside the container,
ss -ltnpconfirms 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.logif 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.



