Short answer: this is not the ZimaOS 1.7 network-apps issue. It is a bug in ZFW, and I have a fix.
What is happening
Your CMS is a Docker container, and ZFW filters container ports in Docker’s
DOCKER-USER chain. That works — over IPv4. From your LAN you reach the
CMS over IPv4, so everything looks correct, and it is.
From outside, your domain name is very likely resolving to an AAAA record,
so the client connects over IPv6 — and that takes a completely different
path through the kernel. On a stock ZimaOS, Docker’s IPv6 support is off, so
containers have no IPv6 address of their own. An IPv6 connection to a published
port is instead handled by Docker’s docker-proxy helper on the host, which
means it is filtered by the host’s IPv6 input chain (ZFW-IN6) and never
reaches DOCKER-USER.
ZFW was only putting the host half of your rules into that IPv6 chain. No
Docker container port ever got an allow rule there, so with the default policy
on Deny, every IPv6 connection to your CMS was dropped — while the rule table
showed a green “Allow”, and while IPv4 kept working perfectly from the LAN.
There is a second half to this, and it explains why it only started now. Before
ZFW 1.0.17, the IPv6 chain was being written into the wrong iptables backend
(legacy while ZimaOS 1.6.2+ actually runs nf_tables), so it was inert — it
existed but no packet ever traversed it. You came from 1.0.10. Upgrading to
1.0.21 is the moment IPv6 filtering became real on your machine for the first
time. Nothing about your setup changed; ZFW’s IPv6 filtering simply started
working, and it was working wrongly.
ZeroTier kept working because ZFW always bypasses the ZeroTier and Tailscale
interfaces, and disabling ZFW removed the chain entirely — both consistent with
this.
Please confirm it — one command
Try to reach the CMS from outside, then on the ZimaOS box run:
sudo journalctl -k --since "-5 min" | grep -E "ZFW-IN6-DROP|ZFW-DOCK-DROP"
- Lines with
ZFW-IN6-DROP and an SRC= address containing colons
→ it is the IPv6 problem described above.
- Lines with
ZFW-DOCK-DROP and a normal public IPv4 SRC=
→ it is the second cause below, which is worth checking either way.
Please also check the Source column of your rules
Open the Rules tab and look at the Source column, not just the Action
column. If your rules were re-created on the fresh install (the “Recommended
defaults” set), every one of them has your LAN range as its source, e.g.
192.168.1.0/24 — including the rules for your Docker apps. Those rules read
“Allow”, and they allow only your LAN. Anyone coming from the internet has
a different source address, matches no rule, and is blocked. That alone would
produce exactly the symptom you describe, on IPv4, with no IPv6 involved.
Two rules with an IPv4 source can never apply to IPv6 either — that is a
limitation of ip6tables, not something I can work around: there is no way to
write “192.168.1.0/24” as an IPv6 match.
Fix right now, without waiting for a release
For each service that must be reachable from the internet, add one rule:
- Action: Allow
- Source: Any
- Ports: the published port (443 for your CMS)
- Zone: Docker
Keep your existing LAN rule next to it; leave the default policy on Deny. Then
add a second rule with Zone Host and Source Any for the same port — that
is the one that opens the IPv6 input chain on 1.0.21. Use Safe-Apply so the
120-second timer can rescue you, and test from a phone on mobile data (not from
your LAN, and not over ZeroTier — neither of those goes through the path that is
broken).
For services that should stay private, leave them scoped to your LAN. In that
case the IPv6 drop is doing what you want.
What changes in ZFW 1.0.22
- Rules now cover Docker-published ports on IPv6 as well, so the second rule
above stops being necessary.
- A rule that cannot apply to IPv6 — because its source is an IPv4 address or
range, or a country — is now marked IPv4 only in the rule table, with a
tooltip explaining what to change. This used to be completely silent, which
is the real reason this cost you a day.
- If the default policy is Deny, your host has a public IPv6 address, and not
one rule reaches the IPv6 chain, the Rules tab now says so in a banner
instead of showing a table full of green “Allow” rows.
One thing 1.0.22 deliberately does not do: it does not widen a LAN-scoped
rule to the internet on your behalf. That has to stay your decision — it just
stops being invisible.
The symptom description (“works locally, dead from outside, fine over ZeroTier”) is what pinned it down 