# UFW + Docker Port Binding Interaction

## The Problem

Binding a Docker container port to `0.0.0.0:<port>` makes it listen on all interfaces, but **UFW still blocks inbound connections** to that port on the host's LAN interface.

```bash
# docker-compose.yml — this change alone is NOT enough:
ports:
  - "0.0.0.0:3081:3081"   # Binds to all interfaces

# ss shows it's listening on all interfaces:
ss -tlnp | grep 3081
# => LISTEN 0  65535  0.0.0.0:3081   0.0.0.0:*

# But curl from another machine or via LAN IP fails:
curl http://192.168.1.50:3081
# => curl: (7) Failed to connect — UFW blocked
```

## The Fix

Both steps are required:

```bash
# Step 1: Docker port binding (docker-compose.yml)
ports:
  - "0.0.0.0:3081:3081"

# Step 2: UFW allow rule (separate, doesn't follow Docker)
sudo ufw allow from 192.168.1.0/24 to any port 3081 comment 'Open WebUI LAN'
# Also for Tailscale if needed:
sudo ufw allow from 100.64.0.0/10 to any port 3081 comment 'Open WebUI Tailscale'
```

## Why This Happens

Docker manipulates iptables/nftables for container networking, but UFW manages its own ruleset independently. Docker's `-p 0.0.0.0:<port>:<port>` only ensures the Docker proxy binds to all interfaces — UFW's `default deny incoming` still drops packets on the host's physical interface before they reach Docker's chains unless an explicit allow exists.

## Verification

```bash
# Confirm port is bound to 0.0.0.0
ss -tlnp | grep :3081
# => LISTEN 0  65535  0.0.0.0:3081

# Confirm UFW rule exists
sudo ufw status | grep 3081
# => 3081                       ALLOW       192.168.1.0/24

# Test from LAN
curl http://192.168.1.50:3081  # Should return HTTP 200
```
