93 lines
3.4 KiB
Bash
Executable File
93 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Install and enable the radar headless daemon (systemd system service), plus a
|
|
# passwordless sudoers rule that lets the service user stop/start it (start.sh
|
|
# stops the daemon before launching the interactive GUI).
|
|
#
|
|
# Run once as root, from anywhere inside the project:
|
|
# sudo bash deploy/install-daemon.sh
|
|
#
|
|
# Re-running is safe: it overwrites the unit/sudoers with current paths.
|
|
set -euo pipefail
|
|
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "Must run as root: sudo bash $0" >&2
|
|
exit 1
|
|
fi
|
|
|
|
PROJECT_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
SERVICE_USER="${SUDO_USER:-root}"
|
|
START_SH="${PROJECT_ROOT}/start.sh"
|
|
SERVICE_NAME="radar.service"
|
|
UNIT_PATH="/etc/systemd/system/${SERVICE_NAME}"
|
|
SUDOERS_PATH="/etc/sudoers.d/radar"
|
|
SYSTEMCTL="$(command -v systemctl)"
|
|
|
|
if [[ -z "${SYSTEMCTL}" ]]; then
|
|
echo "systemctl not found; this installer requires systemd." >&2
|
|
exit 1
|
|
fi
|
|
if [[ ! -x "${START_SH}" ]]; then
|
|
echo "start.sh not found or not executable: ${START_SH}" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "${SERVICE_USER}" == "root" ]]; then
|
|
echo "Run via sudo from your normal login user (got SUDO_USER=root)." >&2
|
|
echo "Example: sudo bash deploy/install-daemon.sh" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "[install] project_root = ${PROJECT_ROOT}"
|
|
echo "[install] service_user = ${SERVICE_USER}"
|
|
|
|
# --- systemd unit -----------------------------------------------------------
|
|
# No network-online dependency: the appliance runs offline and the radar is on
|
|
# USB/loopback. Restart=on-failure self-heals crashes but leaves an intentional
|
|
# `systemctl stop` (done by start.sh for GUI handover) deactivated.
|
|
cat > "${UNIT_PATH}" <<EOF
|
|
[Unit]
|
|
Description=Radar system (headless autonomous mode)
|
|
# Ensure the project filesystem is mounted before start; no network-online
|
|
# dependency (offline appliance, radar on USB/loopback). USB device readiness is
|
|
# handled by the producer's wait-for-device retry, not a boot-time gate.
|
|
After=local-fs.target
|
|
RequiresMountsFor=${PROJECT_ROOT}
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=${SERVICE_USER}
|
|
WorkingDirectory=${PROJECT_ROOT}
|
|
ExecStart=${START_SH} --headless --skip-build
|
|
Restart=on-failure
|
|
RestartSec=3
|
|
TimeoutStopSec=25
|
|
KillMode=mixed
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
echo "[install] wrote ${UNIT_PATH}"
|
|
|
|
# --- sudoers: passwordless stop/start/restart for the service user ----------
|
|
TMP_SUDO="$(mktemp)"
|
|
cat > "${TMP_SUDO}" <<EOF
|
|
# Allow ${SERVICE_USER} to control ${SERVICE_NAME} without a password so
|
|
# start.sh can stop the headless daemon before launching the interactive GUI.
|
|
${SERVICE_USER} ALL=(root) NOPASSWD: ${SYSTEMCTL} stop ${SERVICE_NAME}, ${SYSTEMCTL} start ${SERVICE_NAME}, ${SYSTEMCTL} restart ${SERVICE_NAME}
|
|
EOF
|
|
visudo -cf "${TMP_SUDO}"
|
|
install -m 0440 -o root -g root "${TMP_SUDO}" "${SUDOERS_PATH}"
|
|
rm -f "${TMP_SUDO}"
|
|
echo "[install] wrote ${SUDOERS_PATH}"
|
|
|
|
# --- enable -----------------------------------------------------------------
|
|
"${SYSTEMCTL}" daemon-reload
|
|
"${SYSTEMCTL}" enable "${SERVICE_NAME}"
|
|
|
|
echo
|
|
echo "[install] Done. The daemon will start headless on every boot."
|
|
echo "[install] Start now: sudo systemctl start ${SERVICE_NAME}"
|
|
echo "[install] Status: systemctl status ${SERVICE_NAME}"
|
|
echo "[install] Live log: journalctl -u ${SERVICE_NAME} -f"
|
|
echo "[install] Launch GUI: ./start.sh (auto-stops the daemon first)"
|
|
echo "[install] Uninstall: sudo systemctl disable --now ${SERVICE_NAME} && sudo rm ${UNIT_PATH} ${SUDOERS_PATH} && sudo systemctl daemon-reload"
|