Skip to content

Guided daemon install and uninstall scripts, quick-start-first README - #79

Draft
chrisuthe wants to merge 6 commits into
mainfrom
chrisuthe/task/guided-daemon-install-and-uninstall-scripts-quick
Draft

chrisuthe wants to merge 6 commits into
mainfrom
chrisuthe/task/guided-daemon-install-and-uninstall-scripts-quick

Conversation

@chrisuthe

Copy link
Copy Markdown
Member

scripts/get_started_linux.sh now goes all the way to a running player: it asks for a name and an output device, writes them to the config and starts the service. It works as a curl | bash one-liner, and there is an uninstaller to match. The README opens with the quick start.

What changed

  • Guided install. After installing, the script lists the output devices, asks for name and output, writes them and starts the service. --name and --output answer up front. A key the config already sets is never asked for or replaced, so re-running on a configured host is still an upgrade with one confirmation.
  • Pipe-safe. Prompts are read from /dev/tty when the script arrives on stdin. The body is a function called from a final { main "$@"; }, so a truncated download is a syntax error. --help no longer reads $0.
  • Root plan. Still printed and confirmed before anything runs. The config is composed unprivileged in the temp directory and installed with one listed install/cp; the lines it sets are printed again just before the copy.
  • Missing libraries. ldd on an unprivileged copy of the binary runs before anything is installed. Missing libraries map to apt-get/dnf/pacman packages and the install command joins the plan. An unmapped library, no known package manager, or a too-old glibc stops with the reason and nothing installed.
  • --user-service. Runs as the invoking user under systemctl --user, with linger, audio membership and ~/.config/sendspin-cli/config. On a fresh interactive run the script asks which mode; the hardened system unit stays the default. Choosing one mode disables the other.
  • User unit in the payload, lib/systemd/user/sendspin-cli.service. It keeps the seccomp half of the hardening block. For a release that predates it (every release so far), the script writes a marked equivalent to ~/.config/systemd/user/ and removes it on the first upgrade that ships one.
  • scripts/uninstall_linux.sh. Removes the service in either mode and the payload; keeps config, state and the account unless --purge or a yes at its prompt.
  • Docs. README is quick-start-first. The Linux, Raspberry Pi, service and installation wiki pages describe the new flow, flags, user service and uninstaller. Payload assertions and BUILD-INFO.txt cover the new unit.

Compatibility

Nothing breaks for users of the binary: no flag, config key, control-socket, state-store or exit-code change.

Visible but not breaking:

  • The installer's interactive flow asks up to three more questions (mode, name, output) on a fresh host and ends with the service running.
  • Unattended --yes runs behave as before: system service, and with no --output and none configured, enabled but not started with the device list printed. One addition: --yes now also installs missing runtime packages, shown in the plan, where the old script died on the loader error.
  • The Linux payload gains one file, usr/local/lib/systemd/user/sendspin-cli.service. Nothing enables it unless asked.
  • On a host without systemd the script behaves as before.

What was run

In a privileged rootless podman container running systemd (Fedora 44), as an unprivileged sudo user, with SENDSPIN_CLI_TARBALL built from this branch and prompts answered on a pty:

  • Fresh interactive system install from a file, and piped into bash: name and output asked, config written, unmodified hardened unit active as sendspin-cli.
  • Re-run on the configured host: one confirmation, config byte-identical, service restarted.
  • --yes alone on a fresh host: enabled, not started, device list and next steps.
  • --yes --name … --output null: fully unattended, running, a name with &, \ and | written verbatim.
  • Piped with no terminal and no --yes: refuses, nothing installed. Declining the plan: nothing installed.
  • User mode, piped: user unit enabled and active, linger on, config in ~/.config, sendspin-cli status works with no sudo or flags, system unit not running.
  • Switching user → system and system → user: the other mode is stopped and disabled each time. Plain --yes re-run keeps the mode it finds.
  • A payload without the user unit, run as root through sudo: fallback unit written and owned by the user; upgrade to a payload with the unit removes it.
  • Uninstall: keep and purge, by flag and by prompt, in both modes, as a sudo user and as plain root; exits 0 with nothing installed.

With the real v0.3.0 release downloaded and checksummed, in plain containers (no systemd, root):

  • Ubuntu 24.04 and Debian trixie: missing libraries resolved to libasound2t64 libavahi-compat-libdnssd1 libpipewire-0.3-0t64 libportaudio2 libpulse0, installed, binary loads.
  • Fedora 44 (dnf) and Arch (pacman): packages installed, binary loads.
  • Debian bookworm: refused before installing, naming GLIBC_2.38.

Also:

  • Every seventh byte offset, every line boundary and the last 400 bytes of both scripts fed to bash as truncated input: none reaches main.
  • The user unit's directives applied through systemd-run --user on a Fedora 44 desktop with PipeWire: the player starts, stays up, and -l enumerates the PipeWire default.
  • shellcheck scripts/*.sh, scripts/smoke_test.sh, and ctest (518/520; the two failures are this checkout's path exceeding the Unix socket address limit, and pass from a short directory).

Not run: playback of a real stream through the user service (no server in the test setup), a real Raspberry Pi, and a real curl of the script from main, which only exists after merge.

Closes #71

For running as the invoking user and following the session's PipeWire or PulseAudio. It keeps the seccomp half of the system unit's hardening, which is what an unprivileged manager can apply.
The script now works piped into bash, with prompts read from the terminal and the body wrapped so a truncated download runs nothing. It offers to install missing runtime libraries and a --user-service mode. --yes with no --output on an unconfigured host still enables without starting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add daemon installation script

1 participant