Root cause: systemd PrivateDevices=yes hid /dev/ttyUSB* from the service, preventing .198 from connecting to its Heltec V3 after the security hardening. Changes: - Set PrivateDevices=no in systemd service (serial access needs physical devices; other hardening layers remain: NoNewPrivileges, ProtectSystem, RestrictNamespaces) - Add SupplementaryGroups=dialout for explicit serial permissions - Add fallback auto-detect when configured serial path fails to open - Add exponential backoff on reconnect (5s→60s cap) to reduce log spam - Add pre-open device existence check with actionable error messages - Add udev rule (99-mesh-radio.rules) for stable /dev/mesh-radio symlink - Add /dev/mesh-radio to serial candidate list (checked first) - Add Connect button per detected device in Mesh UI - Deploy udev rule to both servers and ISO build - Fix FEDI_HASH unbound variable in deploy script - Fix deploy binary step to handle hung service stop gracefully Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.3 KiB
Desktop File
53 lines
1.3 KiB
Desktop File
[Unit]
|
|
Description=Archipelago Backend
|
|
After=network-online.target archipelago-setup-tor.service
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=notify
|
|
User=archipelago
|
|
Environment="ARCHIPELAGO_BIND=0.0.0.0:5678"
|
|
Environment="ARCHIPELAGO_DEV_MODE=true"
|
|
ExecStartPre=/bin/bash -c 'mkdir -p /var/lib/archipelago && echo "ARCHIPELAGO_HOST_IP=$(hostname -I 2>/dev/null | awk "{print $$1}")" > /var/lib/archipelago/host-ip.env'
|
|
ExecStart=/usr/local/bin/archipelago
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
WatchdogSec=300
|
|
TimeoutStartSec=300
|
|
|
|
# Filesystem protection
|
|
ProtectSystem=strict
|
|
ProtectHome=yes
|
|
PrivateTmp=yes
|
|
ReadWritePaths=/var/lib/archipelago
|
|
|
|
# Privilege restriction
|
|
NoNewPrivileges=yes
|
|
# PrivateDevices=no: serial access to /dev/ttyUSB* needed for mesh radios.
|
|
# Device access still gated by Unix permissions (dialout group) + other sandboxing.
|
|
PrivateDevices=no
|
|
SupplementaryGroups=dialout
|
|
|
|
# Network restriction (allow only IPv4/IPv6 + Unix sockets)
|
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
|
|
|
# Restrict what the process can do
|
|
RestrictNamespaces=yes
|
|
RestrictRealtime=yes
|
|
RestrictSUIDSGID=yes
|
|
|
|
# Only allow needed syscalls
|
|
SystemCallArchitectures=native
|
|
SystemCallFilter=@system-service
|
|
SystemCallFilter=~@privileged @resources
|
|
|
|
# Memory protection
|
|
MemoryDenyWriteExecute=yes
|
|
|
|
# Logging
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|