{"record":{"id":"ede978a99f082bc3","repo":"jdx/mise","slug":"firewall-rule-uses-per-source-connection-limi","errorCode":null,"errorMessage":"firewall rule '{}' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"","messagePattern":"firewall rule '(.+?)' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/firewall.rs","lineNumber":1052,"sourceCode":"        }\n        FirewallBackend::Ufw => backend_active(backend),\n        FirewallBackend::Auto => false,\n    }\n}\n\nfn validate_backend_request(request: &FirewallRequest, backend: FirewallBackend) -> Result<()> {\n    for rule in &request.rules {\n        if rule.action == FirewallAction::Limit {\n            if rule.direction != FirewallDirection::Incoming\n                || rule.protocol != Some(FirewallProtocol::Tcp)\n            {\n                bail!(\n                    \"firewall rule '{}' uses action = \\\"limit\\\", which requires direction = \\\"incoming\\\" and protocol = \\\"tcp\\\"\",\n                    rule.name\n                );\n            }\n            if backend == FirewallBackend::Firewalld {\n                bail!(\n                    \"firewall rule '{}' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = \\\"nftables\\\" or \\\"ufw\\\"\",\n                    rule.name\n                );\n            }\n        }\n        if backend == FirewallBackend::Firewalld && rule.interface.is_some() {\n            bail!(\n                \"firewall rule '{}' uses interface matching, which firewalld policies cannot express safely; select backend = \\\"nftables\\\" or \\\"ufw\\\"\",\n                rule.name\n            );\n        }\n        if backend == FirewallBackend::Ufw\n            && matches!(\n                rule.protocol,\n                Some(FirewallProtocol::Sctp | FirewallProtocol::Dccp)\n            )\n        {\n            bail!(","sourceCodeStart":1034,"sourceCodeEnd":1070,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/firewall.rs#L1034-L1070","documentation":"Per-source connection limiting (`action = \"limit\"`) cannot be expressed safely through firewalld policies, so mise rejects any request that pairs the firewalld backend with a limit rule. The user must switch to the nftables or ufw backend, which can represent the limit semantics correctly.","triggerScenarios":"A firewall request where `backend = \"firewalld\"` (explicitly or via auto-detection on a firewalld host) and at least one rule has `action = \"limit\"`, passed through `validate_backend_request()` during inspect/apply.","commonSituations":"Running on RHEL/CentOS/Fedora where firewalld is the detected backend, while the ruleset was written with ufw-style rate-limit rules; sharing one bootstrap config across Debian (ufw) and RHEL (firewalld) hosts.","solutions":["Set `backend = \"nftables\"` or `backend = \"ufw\"` in the firewall request for hosts needing limit rules","Install and enable the chosen backend on the host if missing","Or restructure the rule to `action = \"allow\"`/`deny` under firewalld and implement rate limiting with a separate rich rule/nft set outside mise"],"exampleFix":"// before\nbackend = \"firewalld\"\n[[rule]]\nname = \"ssh-limit\"\naction = \"limit\"\ndirection = \"incoming\"\nprotocol = \"tcp\"\n// after\nbackend = \"nftables\"\n[[rule]]\nname = \"ssh-limit\"\naction = \"limit\"\ndirection = \"incoming\"\nprotocol = \"tcp\"","handlingStrategy":"validation","validationCode":"// config lint\nfunction backendSupportsLimit(backend, rules) {\n  return backend !== \"firewalld\" || !rules.some(r => r.action === \"limit\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on nftables or ufw wherever rate-limit rules are needed","Split per-host configs: firewalld hosts get allow/deny-only rulesets","Check `mise bootstrap firewall status` for the detected backend before authoring rules","Document that action=limit is incompatible with firewalld in your team's firewall README"],"tags":["firewall","firewalld","backend-compatibility","rate-limit"],"backgroundTag":"unsupported-operation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}