Add RUN.md quick reference; fix status display in firewall script
- RUN.md: start/stop/inspect/smoke-test commands for the hardened DeerFlow stack on data-nuc, including the docker compose -f overlay invocation and a copy-paste smoke test that verifies allow + block destinations from inside the container. - scripts/deerflow-firewall.sh: status now uses iptables -nvL so the input-interface column is included, and the awk filter shows the header plus all rules matching br-deerflow. The previous version used -nL which omits the interface column entirely, so the grep found nothing even when the rules were correctly installed.
This commit is contained in:
112
RUN.md
Normal file
112
RUN.md
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# 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`.
|
||||||
@@ -119,8 +119,9 @@ cmd_down() {
|
|||||||
|
|
||||||
cmd_status() {
|
cmd_status() {
|
||||||
require_chain
|
require_chain
|
||||||
echo "DOCKER-USER chain (relevant rules):"
|
echo "DOCKER-USER chain (rules matching $BRIDGE):"
|
||||||
iptables -w -nL "$CHAIN" --line-numbers | grep -E "$BRIDGE|^Chain|^num" || true
|
# -nvL prints the input interface column so we can grep for our bridge.
|
||||||
|
iptables -w -nvL "$CHAIN" --line-numbers | awk -v b="$BRIDGE" 'NR<=2 || $0 ~ b'
|
||||||
|
|
||||||
if ip link show "$BRIDGE" >/dev/null 2>&1; then
|
if ip link show "$BRIDGE" >/dev/null 2>&1; then
|
||||||
echo
|
echo
|
||||||
|
|||||||
Reference in New Issue
Block a user