# 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 ` | | 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 `` 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 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`.