Packaging, Installation and Setup
How Lauschkiste is packaged, installed, set up and updated.
- Installable as a package:
pip install <wheel>(oruv tool install) gives a complete Lauschkiste: core, bundled plugins, web app, default settings and sounds. No git checkout needed. - Runnable from source, equally supported: clone the repository,
uv sync,uv run lauschkiste. The code never assumes it runs from a checkout. - Setup in Python: everything that configures the machine is an idempotent
lauschctl setup <step>command. An install script only bootstraps: base packages,uv, the Lauschkiste itself (package or source), thenlauschctl setup. - Plugins from the CLI:
lauschctl plugin list|enable|disable|install. - Distribution: wheels attached to GitHub releases and the packages on PyPI; see “Packages and releases”.
Where things live: LAUSCHKISTE_HOME
Section titled “Where things live: LAUSCHKISTE_HOME”All runtime data lives in one directory, LAUSCHKISTE_HOME, with this layout:
$LAUSCHKISTE_HOME/ settings/ lauschkiste.yaml, logger.yaml, cards.yaml, rfid.yaml, library.sqlite, status files library/ music/ and audiobooks/ playlists/ logs/ cache/ cover art, ...- Default:
~/lauschkisteon a Raspberry Pi (visible, easy to reach via Samba), else$XDG_DATA_HOME/lauschkiste(usually~/.local/share/lauschkiste); override with theLAUSCHKISTE_HOMEenvironment variable orlauschctl --home. - The home cannot be a setting (it says where the settings are), so it is the environment variable or
--home.install.sh --home DIR(and--from source) puts the variable into the shell profile and the systemd unit; for development in a checkout useexport LAUSCHKISTE_HOME=$PWD/shared. A.envfile is not read by Lauschkiste; the git-ignored.env/.env.localonly hold local test credentials for scripts. - Relative paths in the configuration are resolved against
LAUSCHKISTE_HOME, not against the working directory. - The configuration file is
$LAUSCHKISTE_HOME/settings/lauschkiste.yamlunless--conf/LAUSCHKISTE_CONFsays otherwise. Missing files are created from the packaged templates on first run.
Package data
Section titled “Package data”- Default settings, sounds and the autohotspot templates are part of the
lauschkistepackage (lauschkiste/resources/), read withimportlib.resources. Source and package installs use the same files. - The web app build is included in the wheel (
lauschkiste/webapp/). A source checkout servespackages/webapp/buildinstead;api.webapp_dir/LAUSCHKISTE_WEBAPP_DIRoverride both. - Configuration values that point at packaged files use the value
default(e.g.jingle.startup_sound: default); any other value is a path.
Command line
Section titled “Command line”lauschkiste start the daemonlauschctl home print LAUSCHKISTE_HOME and the config file in uselauschctl plugin list installed plugins, enabled or not, and why one failed to loadlauschctl plugin enable <name> add to `plugins:`; installs the plugin package's extras if askedlauschctl plugin disable <name>lauschctl plugin install <spec> install a plugin package (pip/uv) into Lauschkiste's environmentlauschctl setup run all setup steps for this machine (interactive by default)lauschctl setup <step> run one step (`lauschctl setup --list` lists them)lauschctl setup --check report which steps are applied, change nothinglauschctl update update Lauschkiste (package: newer release; source: git pull + uv sync) and re-apply the setuplauschctl uninstall remove what Lauschkiste created (--check lists it), and itself at the endSetup steps
Section titled “Setup steps”Each step is a small Python class with check() (is it applied?), apply() and the questions it
asks. Steps are idempotent: running lauschctl setup again repairs or updates, it doesn’t duplicate.
Answers are stored in $LAUSCHKISTE_HOME/settings/setup.yaml so unattended re-runs
(lauschctl setup --yes) reuse them.
The steps: system packages, Raspberry Pi boot settings, the systemd user service, plugins, Samba, port 80, autohotspot, kiosk mode, RFID readers, audio output, quiet
boot and the login message. Steps needing root run their commands through sudo.
Uninstalling
Section titled “Uninstalling”lauschctl uninstall (lauschkiste_cli/uninstall.py) removes what Lauschkiste created and can recognise: its systemd
units and files by their names, blocks marked with ## Lauschkiste ... in system files (kiosk, boot, Samba), the
profile lines of the installer, optionally the data, and the installation (pip venv, uv tool uninstall, or only the
links of a source checkout) as the very last action, after everything that needs the program. What belongs to the system
stays and is listed. It does not remember the state before the setup, so it cannot restore settings it changed
(boot, network, packages). ci/test_install.sh installs, sets up, runs and uninstalls.
Packages and releases
Section titled “Packages and releases”| Distribution | Directory | Import package | Contents |
|---|---|---|---|
lauschkiste |
packages/cli |
lauschkiste_cli |
what users install: lauschkiste, lauschctl |
lauschkiste-core |
packages/lauschkiste |
lauschkiste |
player, library, cards, API, web app |
lauschkiste-plugins |
packages/plugins/general |
lauschkiste_plugin_* |
PC devices, RFID readers, Samba, Audiobookshelf, directories |
lauschkiste-plugins-raspberry-pi |
packages/plugins/raspberry-pi |
lauschkiste_plugin_* |
the Pi device and the peripherals |
- One version for all. The packages are released together and depend on each other with exact
pins (
lauschkiste-core==0.1.0a4), so a plugin never meets a different core. Change the version withci/set_version.py 0.1.0-alpha.4(allpyproject.tomlfiles, the pins andversion.py);test/test_packaging.pyfails when they drift apart. - PyPI page. Each package has a
README.md(shown as the project description, links absolute), a copy of theLICENSE, authors, keywords, classifiers and URLs; the test checks them too. - Build.
ci/build_wheels.shbuilds the web app, then a source distribution and a wheel of every package (the wheel from the source distribution, which carries the web app, so what is published works). The GitHub release gets the wheels, PyPI the wheels and source distributions. - Check before publishing:
uvx twine check dist/*. How a release is made and the one-time PyPI setup: Releasing.
Install script
Section titled “Install script”install.sh (in the repository’s main branch, run via curl ... | bash):
- Checks the OS, installs base packages (
python3,curl, build tools). - Installs Lauschkiste, either
- package (default): from PyPI (or the wheels of a GitHub release) with pip into a venv, or with
uv tool installwhen uv is there (uvis installed only for the cases that need it), or - source (
--source):git clone,uv syncin the checkout, withLAUSCHKISTE_HOME(--home, default<checkout>/shared) in the shell profile and the service.
- package (default): from PyPI (or the wheels of a GitHub release) with pip into a venv, or with
- Tells you to run
lauschctl setup. Everything that configures the machine is done there, not by the script.
Details
Section titled “Details”- Paths:
LAUSCHKISTE_HOME, path resolution against it, resources as package data, web app directory configurable. - Wheels:
ci/build_wheels.sh(alsobam wheels) builds the web app, copies it into thelauschkistepackage and builds the wheels of core, CLI and bundled plugins..github/workflows/wheels.ymlbuilds them on every push/PR, installs them into a fresh environment and starts Lauschkiste; a tagv<version>attaches them to a GitHub release (the tag is compared after PEP 440 normalization:v0.1.0-alpha.1matches0.1.0a1; tags with a-become pre-releases). Without a stable release,install.shandlauschctl updateuse the newest pre-release. - Plugin commands:
lauschctl plugin list|enable|disable|install(packages/cli/src/lauschkiste_cli/plugin.py).Plugin.extras(contract 1.1) names the extras of the plugin’s package thatenable --with-extrasinstalls; installs go throughuv pipinto the Lauschkiste’s own environment,pipas fallback. - Setup framework and steps:
packages/cli/src/lauschkiste_cli/setup/.Systemwraps commands, files and machine facts (tests swap in a fake with a temporary root); steps:packages,hardware,raspi,plugins,service,samba,rfid,kiosk,autohotspot,boot,welcome(lauschctl setup --list). Missing Debian packages of all chosen steps are installed in oneapt-getcall before the steps run. Notes:- The service is a user unit in
~/.config/systemd/user/, generated with the actuallauschkisteexecutable andLAUSCHKISTE_HOME;loginctl enable-lingerstarts it at boot (default on a Pi) instead of relying on autologin. It only wantsmpd.serviceif thempdplugin is enabled. - Autologin is only set up for the kiosk mode, which needs it.
- Autohotspot supports NetworkManager only (Bookworm and later); dhcpcd systems don’t offer the step.
- The Samba share is called
lauschkisteand shares only the library; the password is asked for (no default), files keep normal permissions. rfidruns the interactive reader configuration and is skipped with--yes.- Runtime packages only: the default player needs neither ffmpeg nor mpg123; the PipeWire stack is installed on a Pi only (desktops bring their own sound server).
- The service is a user unit in
- Install script:
install.sh(options in its header and indocumentation/developers/installer.md). Package mode:uv tool installof the release wheels (or--wheels DIR) with the systempython3. Source mode: clone (or reuse) a checkout,uv sync --no-dev --frozen, web app built with npm if available, else taken from the latest release wheel;~/.local/bin/lauschctllinks to the checkout’s venv.LAUSCHKISTE_HOME(Pi:~/lauschkiste, source:<checkout>/shared) and~/.local/binonPATHgo into~/.profileand~/.bashrc.ci/test_install.shruns it and thenlauschctl setup --yesin a freshdebian:<codename>-slimcontainer and starts Lauschkiste; the wheels workflow does that for the wheels (trixie, bookworm) and the checkout (trixie). No systemd in those containers, so theservicestep is not covered there. lauschctl update– done (packages/cli/src/lauschkiste_cli/update.py). Source checkout:git pull --ff-only,uv sync --no-dev --frozen, web app rebuilt with npm if it changed. Package install: newest (or--version) GitHub release, if newer than the installedlauschkiste; its wheels are installed withuv pipinto the running environment, so other installed plugins stay, and the extras of enabled plugins are kept. Afterwardslauschctl setup --yesruns in a new process (the updated steps) and an active service is restarted.--checkonly reports.
Open points
Section titled “Open points”- The
servicestep is covered by unit tests only; the CI containers have no systemd.
Decisions
Section titled “Decisions”- On a Raspberry Pi the install script sets
LAUSCHKISTE_HOME=~/lauschkiste(visible, easy to reach via Samba); the code’s default stays$XDG_DATA_HOME/lauschkiste. - The install script lives in the repository’s
mainbranch.