mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
6f4aa495e6
* feat: reconcile systemd unit files on upgrade Unit files were written once at install time by install_systemd() in scripts/setup.sh and never re-asserted. A node upgraded by swapping the spx binary kept whatever units it was installed with, so any fix that lives in a unit rather than in code never reached it. This is not theoretical. A node whose spinifex-viperblock.service predates KillMode=process defaults to KillMode=control-group, so on a target stop TimeoutStopSec expires mid-flush and systemd cgroup-SIGKILLs every nbdkit while guest QEMU survives in the daemon's own cgroup: the guest keeps running with no storage path. Units are now stamped with a spinifex-unit-version marker, embedded in the binary via a generated file, and reconciled by spx admin upgrade. Missing or version-stale units are replaced after a timestamped backup; a unit at the current version whose content differs is reported as operator-modified and never overwritten. Drop-ins under <unit>.d are untouched, so systemctl edit overrides survive. Nothing is restarted. A daemon-reload is enough for KillMode and TimeoutStopSec to apply to the next stop, so drift is corrected without disturbing a running guest. Adds --dry-run, --units-only and --skip-units to spx admin upgrade. * test: cover systemd reconcile error paths and the admin upgrade CLI flow Diff coverage on the unit-migration PR sat at 45.8%, below the 60% gate. Adds tests for reconcile.go's error/edge paths (unreadable unit, backup and write failures, daemon-reload failure, malformed version markers, downgrade-is-conflict) and drives admin_upgrade.go's CLI flow directly via an injectable exit and a decision matrix extracted into validateUpgradeFlags/upgradeSummary for testability.
69 lines
2.3 KiB
Desktop File
69 lines
2.3 KiB
Desktop File
# spinifex-unit-version: 1
|
|
[Unit]
|
|
Description=Spinifex VPC Daemon (OVN Networking)
|
|
PartOf=spinifex.target
|
|
After=spinifex-nats.service spinifex-daemon.service systemd-networkd.service openvswitch-switch.service ovn-controller.service
|
|
Wants=spinifex-nats.service ovn-controller.service
|
|
|
|
[Service]
|
|
EnvironmentFile=-/etc/spinifex/telemetry.env
|
|
Type=simple
|
|
Slice=spinifex-system.slice
|
|
User=spinifex-vpcd
|
|
Group=spinifex
|
|
ExecStartPre=/var/lib/spinifex/wait-for-nats.sh
|
|
ExecStart=/usr/local/bin/spx service vpcd start
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
# Waits for an in-flight OVN drift-reconcile pass to return before exiting;
|
|
# no sub-timeout bounds that call today, so this covers a normal pass.
|
|
TimeoutStopSec=20
|
|
OOMScoreAdjust=-500
|
|
# Per-service ceiling: bounds a leak here instead of the slice-wide cap.
|
|
MemoryHigh=10%
|
|
MemoryMax=20%
|
|
Environment=SPINIFEX_CONFIG_PATH=/etc/spinifex/spinifex.toml
|
|
Environment=SPINIFEX_BASE_DIR=/var/lib/spinifex/vpcd/
|
|
|
|
# RG-9: network tier. Per-tap IMDS removed the in-process setns, so vpcd no
|
|
# longer enters a per-VPC netns: CAP_SYS_ADMIN is dropped and the filesystem
|
|
# sandbox is restored.
|
|
#
|
|
# RG-10: these are ambient so ip/iptables/sysctl/arping inherit them on exec and
|
|
# vpcd holds no sudoers rules at all. NoNewPrivileges stays off pending the ADR
|
|
# update that retires the last escalation path.
|
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID
|
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID
|
|
NoNewPrivileges=no
|
|
ProtectSystem=full
|
|
PrivateDevices=yes
|
|
ReadOnlyPaths=/etc/spinifex/spinifex.toml /etc/spinifex/server.pem /etc/spinifex/server.key /etc/spinifex/ca.pem
|
|
ReadWritePaths=/var/lib/spinifex/vpcd /var/log/spinifex
|
|
|
|
# RG-9: hardening baseline
|
|
ProtectHome=yes
|
|
PrivateTmp=yes
|
|
RestrictSUIDSGID=yes
|
|
LockPersonality=yes
|
|
RestrictRealtime=yes
|
|
RestrictNamespaces=yes
|
|
ProtectClock=yes
|
|
ProtectKernelTunables=yes
|
|
ProtectKernelModules=yes
|
|
ProtectKernelLogs=yes
|
|
ProtectControlGroups=yes
|
|
ProtectProc=invisible
|
|
SystemCallArchitectures=native
|
|
MemoryDenyWriteExecute=yes
|
|
# AF_PACKET: raw L2 BOOTP for the in-process DHCP client before the iface has an IP
|
|
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK AF_PACKET
|
|
ProtectHostname=yes
|
|
KeyringMode=private
|
|
RemoveIPC=yes
|
|
LimitCORE=0
|
|
LimitNOFILE=65536
|
|
LimitNPROC=4096
|
|
|
|
[Install]
|
|
WantedBy=spinifex.target
|