CIS490/etc/cis490-shipper.service
Elliott Kolden 842918556b Add automated campaign runner, shipper, and systemd units
Implements the unattended episode loop described in docs/deploy.md but not
yet built. run_campaign.py boots a fresh VM per episode, drives the full
phase schedule via the existing EpisodeRunner/VMLoadController stack, writes
campaign.json atomically after each episode, and signals completion with
campaign_done.marker. shipper.py watches data/episodes/ for done.marker
files, tar+zstd-compresses each, and PUTs them to the receiver with
exponential backoff on failure. Both support SIGTERM gracefully, finishing
the current episode/scan before exiting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 14:53:40 -06:00

36 lines
909 B
Desktop File

[Unit]
Description=CIS490 episode shipper
Documentation=https://maxgit.wg/spectral/CIS490
After=network-online.target cis490-orchestrator.service
Wants=network-online.target
[Service]
Type=simple
User=cis490
Group=cis490
WorkingDirectory=/opt/cis490
ExecStart=/opt/cis490/.venv/bin/python tools/shipper.py \
--data-root /var/lib/cis490/data \
--receiver-url https://collector.wg \
--host-id lab-host-1 \
--ca-bundle /etc/cis490/certs/wg-ca.pem \
--client-cert /etc/cis490/certs/lab-host-1.pem \
--client-key /etc/cis490/certs/lab-host-1.key
Restart=on-failure
RestartSec=10
# Hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/cis490
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
LockPersonality=true
RestrictRealtime=true
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.target