Teardown and State
DECNET keeps the whole fleet picture in a single file, decnet-state.json,
at the project root. Every command that touches a running deployment
(decnet status, decnet teardown, the web dashboard, the sniffer, the
collector) loads it; decnet deploy writes it.
Without this file, teardown cannot find the compose project, the sniffer cannot map IPs to deckies, and the collector does not know which containers to tail.
See also: Environment Variables, Database Drivers, Systemd.
Layout
decnet-state.json has exactly two top-level keys:
{
"config": { ... DecnetConfig.model_dump() ... },
"compose_path": "/absolute/path/to/decnet-compose.yml"
}
config— the serialisedDecnetConfigpydantic model (decnet/models.py):mode,interface,subnet,gateway,ipvlan,mutate_interval,log_file, and the fulldeckies[]list. EachDeckyConfigentry carries name, IP, services, distro, base image, hostname, archetype, per-service config,nmap_os, and rotation timestamps.compose_path— absolute path to the generateddecnet-compose.yml. Teardown uses it as the-fargument todocker compose.
Example decnet-state.json
{
"config": {
"mode": "unihost",
"interface": "eth0",
"subnet": "192.168.1.0/24",
"gateway": "192.168.1.1",
"ipvlan": false,
"mutate_interval": 30,
"log_file": "/var/log/decnet/decnet.log",
"deckies": [
{
"name": "decky-01",
"ip": "192.168.1.201",
"services": ["ssh", "smb"],
"distro": "debian",
"base_image": "debian:bookworm-slim",
"build_base": "debian:bookworm-slim",
"hostname": "fileserver-02",
"archetype": "office-fileshare",
"service_config": {},
"nmap_os": "linux",
"mutate_interval": null,
"last_mutated": 0.0,
"last_login_attempt": 0.0
},
{
"name": "decky-02",
"ip": "192.168.1.202",
"services": ["rdp"],
"distro": "ubuntu22",
"base_image": "ubuntu:22.04",
"build_base": "debian:bookworm-slim",
"hostname": "WIN-DESK01",
"archetype": null,
"service_config": {},
"nmap_os": "windows",
"mutate_interval": null,
"last_mutated": 0.0,
"last_login_attempt": 0.0
}
]
},
"compose_path": "/home/anti/Tools/DECNET/decnet-compose.yml"
}
API
All three helpers live in decnet/config.py:
save_state(config: DecnetConfig, compose_path: Path) -> None
Dumps {"config": config.model_dump(), "compose_path": str(compose_path)}
as pretty-printed JSON (indent=2) to STATE_FILE
(<project root>/decnet-state.json). Overwrites any existing file.
Called by decnet/engine/deployer.py::deploy after the compose file is
written and before docker compose up.
load_state() -> tuple[DecnetConfig, Path] | None
Returns None when the file does not exist. Otherwise parses the JSON,
re-hydrates DecnetConfig, and returns (config, Path(compose_path)).
Callers:
decnet/engine/deployer.py—teardown()andstatus().decnet/sniffer/worker.py— builds the IP-to-decky-name map.decnet/collector/worker.py— resolves the exact set of service container names to tail. Wrapped inasyncio.to_thread()to keep the event loop clean.decnet/web/db/sqlmodel_repo.py— usesasyncio.to_thread(load_state)to surface deployment metadata through the dashboard API.
clear_state() -> None
unlink()s the state file if present. A no-op otherwise. Called once by
teardown() after docker compose down and host-interface cleanup succeed.
How teardown cleans host interfaces
decnet/engine/deployer.py::teardown(decky_id=None) runs, in order:
load_state(). If it returnsNone, printsNo active deployment found (no decnet-state.json).and exits.- If
decky_idis given,docker compose stop <decky>-<svc>...thendocker compose rm -f ...for that decky only. No host-interface cleanup and no state clear — the rest of the fleet is still alive. - If no
decky_id(full teardown):docker compose downwith thecompose_pathfrom state.- Compute the decky IP range with
ips_to_range([d.ip for d in config.deckies]). - Remove the host-side L2 interface:
teardown_host_ipvlan(decky_range)whenconfig.ipvlanistrue, orteardown_host_macvlan(decky_range)otherwise.
remove_macvlan_network(client)drops the docker network.clear_state()deletesdecnet-state.json.- Logs
teardown completeand prints the driver that was removed.
If step 3 never runs (you ctrl-C'd, or one of the subprocess calls errored),
decnet-state.json stays on disk and so do the host interfaces. Re-running
sudo decnet teardown --all is idempotent and safe.
When you need sudo
Anything that touches host networking — creating or removing a MACVLAN /
IPvlan parent interface, opening a raw socket for the sniffer — needs
CAP_NET_ADMIN, which in practice means sudo:
sudo decnet deploy ...— creates the host interface, writesdecnet-state.json, brings up the compose project.sudo decnet teardown/sudo decnet teardown --all— removes host interfaces, clears state. Withoutsudothe ip-link calls fail and the state file is left behind.sudo decnet teardown --id decky-01— still needssudoif the compose project was created by root.sudo decnet sniffer --daemon— raw packet capture on the parent iface.
Read-only commands that only consult decnet-state.json and the dashboard
DB do not need root:
decnet statusdecnet servicesdecnet deploy --dry-run(generates the compose file only)decnet api/decnet webonce the deployment is up — as long as the state file andDECNET_SYSTEM_LOGSare readable by the invoking user.decnet/config.pydrops root ownership of the system log when invoked viasudoprecisely so the follow-up non-root commands can append to it.
Troubleshooting
No active deployment found—decnet-state.jsonis missing. Either the deploy never completed, or a previous teardown already ran.- Orphan host interfaces after a crash — re-run
sudo decnet teardown --all. If state is gone, remove them manually withip link del decnet-mv0(or the ipvlan equivalent) and delete the docker network. PermissionErrorwriting the state file — you randecnet deploywithoutsudoon a fresh checkout; the project root is not writable by the current user. Eitherchmodthe directory or run as root.- Stale
compose_path— moving the project directory after deploy breaks teardown. Tear down first, move, redeploy.
DECNET
User docs
- Quick-Start
- Installation
- Requirements-and-Python-Versions
- CLI-Reference
- INI-Config-Format
- Custom-Services
- Services-Catalog
- Service-Personas
- Archetypes
- Distro-Profiles
- OS-Fingerprint-Spoofing
- Networking-MACVLAN-IPVLAN
- Deployment-Modes
- SWARM-Mode
- MazeNET
- Remote-Updates
- Environment-Variables
- Teardown-and-State
- Database-Drivers
- Systemd-Setup
- Logging-and-Syslog
- Service-Bus
- Web-Dashboard
- REST-API-Reference
- Mutation-and-Randomization
- Troubleshooting
Developer docs
DECNET — honeypot deception-network framework. Pre-1.0, active development — use with caution. See Sponsors to support the project. Contact: samuel@securejump.cl