diff --git a/Systemd-Setup.md b/Systemd-Setup.md new file mode 100644 index 0000000..6077560 --- /dev/null +++ b/Systemd-Setup.md @@ -0,0 +1,373 @@ +# Systemd Setup + +End-to-end walkthrough: take DECNET from a fresh clone to a set of +systemd-managed services running as a non-root user with the minimum +Linux capabilities needed to manage MACVLAN interfaces. + +See also: [Environment variables](Environment-Variables), +[DB drivers](Database-Drivers), [CLI reference](CLI-Reference). + +## 1. Prerequisites + +- Linux host (bare metal or VM). WSL is not supported for the network + path. +- Docker Engine and the Docker Compose plugin. +- Python 3.11, 3.12 or 3.13. +- `sudo` / root access (needed once for `decnet deploy` to create + MACVLAN links, and to install unit files). +- A NIC placed in promiscuous mode if you plan to run the sniffer on + the host interface. +- A dedicated UNIX user and group named `decnet` (the unit files run + as that user): + +```bash +sudo useradd --system --create-home --shell /usr/sbin/nologin decnet +sudo usermod -aG docker decnet +``` + +## 2. Clone and install + +Install into a virtualenv owned by the `decnet` user so the service +files can point at `.venv/bin/decnet`. + +```bash +sudo -u decnet -H bash <<'EOF' +cd /opt +git clone https://git.resacachile.cl/anti/DECNET.git +cd DECNET +python3 -m venv .venv +.venv/bin/pip install --upgrade pip +.venv/bin/pip install -e . +EOF +``` + +After this, the CLI is available at `/opt/DECNET/.venv/bin/decnet`. + +## 3. Configure the environment + +DECNET loads configuration from a `.env` file in the working +directory. Create `.env.local` with real values and symlink (or +rename) it to `.env`, or point `EnvironmentFile=` at whichever file +you use. + +```bash +sudo -u decnet cp /opt/DECNET/env.config.example /opt/DECNET/.env +sudo -u decnet editor /opt/DECNET/.env +``` + +See [Environment variables](Environment-Variables) for the full list. +The services expect at least: + +- `DECNET_DB_URL` (or the SQLite default) - see [DB drivers](Database-Drivers) +- `DECNET_SYSTEM_LOGS` - path to the rotating system log file +- API / Web bind hosts and ports if you are overriding the defaults + +## 4. Deploy honeypots once + +`decnet deploy` provisions the MACVLAN network and the decky +containers. Run it once, as root, before enabling the long-lived +services: + +```bash +sudo /opt/DECNET/.venv/bin/decnet deploy \ + --mode unihost \ + --deckies 5 \ + --interface eth0 \ + --randomize-services +``` + +Confirm with: + +```bash +/opt/DECNET/.venv/bin/decnet status +``` + +Deploy only needs root for the MACVLAN setup; the long-running API / +web / microservice units run unprivileged with the capabilities +listed below. + +## 5. Install the bundled unit files + +Two unit files ship in `deploy/`: + +### `/etc/systemd/system/decnet-api.service` + +```ini +[Unit] +Description=DECNET API Service +After=network.target docker.service +Requires=docker.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet api + +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +### `/etc/systemd/system/decnet-web.service` + +```ini +[Unit] +Description=DECNET Web Dashboard Service +After=network.target decnet-api.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet web + +# Uncomment to bind to a privileged port (80/443) as non-root. +# CapabilityBoundingSet=CAP_NET_BIND_SERVICE +# AmbientCapabilities=CAP_NET_BIND_SERVICE + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +### Directive reference + +- `User`, `Group` - run as the unprivileged `decnet` account. +- `WorkingDirectory` - sets `$PWD`; DECNET resolves relative paths + (log files, sqlite URLs) from here. +- `EnvironmentFile` - loads `.env` the same way the CLI does when run + interactively. +- `ExecStart` - the venv's `decnet` entrypoint; no daemon flag is + needed because systemd already runs the process in the background + and handles restarts. +- `Restart=on-failure`, `RestartSec=5` - systemd restarts crashes + after five seconds; successful exits are not restarted. +- `CapabilityBoundingSet` / `AmbientCapabilities` - hand the process + `CAP_NET_ADMIN` (netlink, MACVLAN/IPVLAN) and `CAP_NET_RAW` (packet + capture, ARP) without making it root. `CAP_NET_BIND_SERVICE` is + only needed if a service binds a port below 1024. +- `NoNewPrivileges=yes` - blocks setuid escalation inside the + process tree. +- `ProtectSystem=full` - `/usr`, `/boot`, `/etc` become read-only for + the unit. +- `ProtectHome=read-only` - `/home` and `/root` become read-only. +- `After=` / `Requires=` - API needs Docker; Web starts after API. + +Copy them into place and fix the paths: + +```bash +sudo install -m 644 /opt/DECNET/deploy/decnet-api.service /etc/systemd/system/ +sudo install -m 644 /opt/DECNET/deploy/decnet-web.service /etc/systemd/system/ +sudo sed -i 's|/path/to/DECNET|/opt/DECNET|g' \ + /etc/systemd/system/decnet-api.service \ + /etc/systemd/system/decnet-web.service +``` + +## 6. Optional per-microservice units + +The CLI already supports detached mode for several subcommands +(`decnet profiler --daemon`, `decnet sniffer --daemon`, +`decnet collect --daemon`, `decnet mutate --daemon`, `decnet probe +--daemon`, `decnet correlate --daemon`). Under systemd you should +**omit** `--daemon`: systemd is the supervisor, and double-forking +breaks its child tracking. Set `Type=simple` and let the foreground +process run. + +All microservice units should order after the API. Use `Wants=` +unless the microservice cannot function at all without the API +(persistence-heavy units such as `collect` and `correlate`), in which +case use `Requires=`. + +### `/etc/systemd/system/decnet-profiler.service` + +Wants the API - it enriches sessions but can start independently. + +```ini +[Unit] +Description=DECNET Profiler +After=network.target decnet-api.service +Wants=decnet-api.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet profiler + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Required env: `DECNET_DB_URL`, `DECNET_SYSTEM_LOGS`. + +### `/etc/systemd/system/decnet-sniffer.service` + +Needs `CAP_NET_RAW` plus `CAP_NET_ADMIN` to attach to the decoy +interface. Wants the API. + +```ini +[Unit] +Description=DECNET Sniffer +After=network.target decnet-api.service +Wants=decnet-api.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet sniffer + +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Required env: `DECNET_SNIFFER_IFACE` (or the auto-probed interface), +`DECNET_SYSTEM_LOGS`. + +### `/etc/systemd/system/decnet-collect.service` + +Writes into the shared database - `Requires=` the API so schema and +migrations are in place first. + +```ini +[Unit] +Description=DECNET Collector +After=network.target decnet-api.service +Requires=decnet-api.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet collect + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Required env: `DECNET_DB_URL`, `DECNET_SYSTEM_LOGS`, and any input +source variables documented in [Environment variables](Environment-Variables). + +### `/etc/systemd/system/decnet-mutate.service` + +Stateless helper that rewrites decky personas; Wants the API. + +```ini +[Unit] +Description=DECNET Mutator +After=network.target decnet-api.service +Wants=decnet-api.service + +[Service] +Type=simple +User=decnet +Group=decnet +WorkingDirectory=/opt/DECNET +EnvironmentFile=/opt/DECNET/.env +ExecStart=/opt/DECNET/.venv/bin/decnet mutate --watch + +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=read-only + +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Required env: `DECNET_SYSTEM_LOGS` plus any per-service override +files referenced by the mutator. + +## 7. Enable and start + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now \ + decnet-api.service \ + decnet-web.service \ + decnet-profiler.service \ + decnet-sniffer.service \ + decnet-collect.service \ + decnet-mutate.service +``` + +Check status and tail logs: + +```bash +systemctl status decnet-api +journalctl -u decnet-api -f +journalctl -u decnet-web -f +``` + +## 8. Log locations + +DECNET writes logs in two places: + +- **journald**, via stdout/stderr from each unit. Query with + `journalctl -u decnet-`. +- **`$DECNET_SYSTEM_LOGS`**, a rotating file handler + (`InodeAwareRotatingFileHandler`) that survives external log + rotation. The default is `decnet.system.log` in the unit's + `WorkingDirectory` (so `/opt/DECNET/decnet.system.log` with the + layout above). Point it at `/var/log/decnet/system.log` for + multi-service deployments and make sure the `decnet` user owns the + target directory: + +```bash +sudo install -d -o decnet -g decnet /var/log/decnet +``` + +Then set `DECNET_SYSTEM_LOGS=/var/log/decnet/system.log` in `.env` +and restart the units.