# Running the hardened DeerFlow

Quick reference for starting, stopping, and inspecting the hardened
DeerFlow stack on **data-nuc**. For the full security rationale see
[HARDENING.md](HARDENING.md).

## Prerequisites (one-time, already done on data-nuc)

- `docker` + `docker compose` available
- `/etc/nixos/configuration.nix` imports `scripts/deerflow-firewall.nix`
  (verify: `grep deerflow-firewall /etc/nixos/configuration.nix`)
- After config change: `sudo nixos-rebuild switch`
- `systemctl status deerflow-firewall` shows `active (exited)`
- `.env` exists in the repo root with a real `OLLAMA_CLOUD_API_KEY`
  (template: `.env.example`)

## Start

```bash
cd /home/data/deerflow-factory
docker compose \
    -f deer-flow/docker/docker-compose.yaml \
    -f docker/docker-compose.override.yaml \
    up -d
```

The override file pins the upstream `deer-flow` Docker network to a
stable Linux bridge name `br-deerflow` so the host firewall can
reference it. The firewall rules already in `DOCKER-USER` will activate
the moment the bridge appears — no manual action needed.

## Stop

```bash
cd /home/data/deerflow-factory
docker compose \
    -f deer-flow/docker/docker-compose.yaml \
    -f docker/docker-compose.override.yaml \
    down
```

The firewall rules **stay in place** but become inert (no traffic
matches `-i br-deerflow` once the bridge is gone). They re-activate the
next time you bring the stack up.

## Inspect

| What | Command |
|---|---|
| Compose status | `docker compose -f deer-flow/docker/docker-compose.yaml -f docker/docker-compose.override.yaml ps` |
| Container logs | `docker compose -f deer-flow/docker/docker-compose.yaml -f docker/docker-compose.override.yaml logs -f <service>` |
| Firewall service | `systemctl status deerflow-firewall` |
| Firewall rules | `sudo scripts/deerflow-firewall.sh status` |
| Bridge present? | `ip link show br-deerflow` |

## Smoke-test the egress firewall

After the first `up`, verify the container's egress is correctly
constrained. Replace `<svc>` with the name of any DeerFlow container
that has `curl` available (try `frontend`, `langgraph`, or `provisioner`):

```bash
docker compose -f deer-flow/docker/docker-compose.yaml \
               -f docker/docker-compose.override.yaml \
               exec <svc> sh -c '
    set -e
    echo "[+] Searx (allow):"
    curl -s -o /dev/null -w "  %{http_code}\n" --max-time 5 http://10.67.67.1:8888/ || echo "  fail"
    echo "[+] Internet (allow):"
    curl -s -o /dev/null -w "  %{http_code}\n" --max-time 5 https://api.cloudflare.com/ || echo "  fail"
    echo "[-] Home LAN gateway (block):"
    curl -s -o /dev/null -w "  %{http_code}\n" --max-time 5 http://192.168.3.1/ || echo "  blocked"
    echo "[-] Other Wireguard host (block):"
    curl -s -o /dev/null -w "  %{http_code}\n" --max-time 5 http://10.67.67.16/ || echo "  blocked"
'
```

Expected:

```
[+] Searx (allow):
  200
[+] Internet (allow):
  200       (or 4xx — anything that is not "fail" means egress worked)
[-] Home LAN gateway (block):
  blocked   (curl exits non-zero with "host prohibited")
[-] Other Wireguard host (block):
  blocked
```

If a "block" line returns an HTTP code instead of "blocked", the
firewall is not constraining that destination — stop the container and
check `sudo scripts/deerflow-firewall.sh status`.

## Reset firewall after changes to the script

If you edit `scripts/deerflow-firewall.sh`:

```bash
sudo systemctl restart deerflow-firewall
sudo scripts/deerflow-firewall.sh status
```

## Disable the egress firewall (not recommended)

```bash
sudo systemctl stop deerflow-firewall      # rules removed
sudo systemctl disable deerflow-firewall   # no auto-start at boot
```

To remove permanently: delete the `imports` entry from
`/etc/nixos/configuration.nix` and `sudo nixos-rebuild switch`.
