Add Systemd Setup page
373
Systemd-Setup.md
Normal file
373
Systemd-Setup.md
Normal file
@@ -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-<name>`.
|
||||||
|
- **`$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.
|
||||||
Reference in New Issue
Block a user