jdx/mise · critical

refusing firewall default incoming {} over SSH: no incoming

Error message

refusing firewall default incoming {} over SSH: no incoming TCP allow rule covers peer {} on server port {} with an unrestricted interface; add a covering rule or set allow_lockout = true

What it means

Final lockout check: after scanning every rule, none provides an incoming TCP allow that covers the current SSH peer and server port with an unrestricted interface. Interface-bound allows deliberately do not count (`covered` is only set for rules without an `interface` key), because mise cannot prove which interface the session uses. Switching `default_incoming` to deny would therefore cut the session, so the apply aborts.

Source

Thrown at src/system/firewall.rs:536

                    _ => {}
                }
                continue;
            }
            // SSH_CONNECTION does not identify the ingress interface. An
            // interface-constrained allow cannot prove that it preserves this
            // session, so keep looking for an unrestricted covering allow.
            if rule.interface.is_none() {
                covered = true;
                if matches!(
                    backend,
                    Some(FirewallBackend::Nftables | FirewallBackend::Ufw)
                ) {
                    break;
                }
            }
        }
        if !covered {
            bail!(
                "refusing firewall default incoming {} over SSH: no incoming TCP allow rule covers peer {} on server port {} with an unrestricted interface; add a covering rule or set allow_lockout = true",
                self.default_incoming.ufw(),
                connection.peer,
                connection.server_port
            );
        }
        Ok(())
    }

    pub fn plans(&self) -> Vec<ResourcePlan> {
        let inspection = self.inspection.as_ref();
        let backend = inspection
            .and_then(|inspection| inspection.backend)
            .unwrap_or(self.backend);
        let desired = format!(
            "{} via {}; incoming {}; outgoing {}; {}",
            match self.state {
                FirewallState::Enabled => "enabled",

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Add an incoming allow that matches the session and has no `interface` key: `direction = "incoming"`, `action = "allow"`, `port = 22`, `protocol = "tcp"`, with source equal to your IP or 0.0.0.0/0.
  2. Remove or fix the `interface` restriction on the intended allow rule.
  3. If connecting via VPN, allow the tunnel peer subnet (or the whole tunnel interface's traffic) without the interface key.
  4. With out-of-band console access, set `allow_lockout = true` to proceed anyway.

Example fix

# before — only an interface-bound allow exists
[[bootstrap.linux.firewall.rules]]
name = "ssh"
interface = "eth0"          # session actually arrives on wg0
port = 22
protocol = "tcp"
action = "allow"

# after — unrestricted interface, peer-scoped
[[bootstrap.linux.firewall.rules]]
name = "ssh"
source = "203.0.113.5/32"   # your peer
port = 22
protocol = "tcp"
action = "allow"
Defensive patterns

Strategy: try-catch

Validate before calling

# pre-flight: confirm a current allow covers your session
# compare `echo $SSH_CONNECTION` (peer, server port) against your rules;
# the allow must have NO interface key and match peer + port

Try / catch

if ! mise bootstrap firewall apply 2>fw.err; then
  if grep -q "no incoming TCP allow rule covers" fw.err; then
    echo "add: allow incoming tcp port <SSHport> from <your-ip> without interface"; exit 1
  fi
  cat fw.err; exit 1
fi

Prevention

When it happens

Trigger: `mise bootstrap firewall apply` with deny-ish `default_incoming` where the only candidate allow rules are interface-restricted (e.g. `interface = "eth0"` while SSH arrives on wg0/ens18), target the wrong port (allowing 22 while connecting on 2222), or the wrong peer CIDR — or no incoming allow exists at all.

Common situations: Interface-name assumptions (ens18 vs eth0, VPN tunnels wg0/tun0 not covered); moving management SSH to a nonstandard port while the allow still lists 22; allows scoped to an office CIDR while connecting from home/VPN; first-time enablement of deny-by-default with no management rule yet.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/2f51095e9f8d8aa4. Report an issue: GitHub.