Run the kiosk on Chromium, and take the stray media server off musicdolphin

Chromium: same page, same machine, idle, Firefox 24.2% of a core against Chromium's
11.4%. The build comes from archive.raspberrypi.com (a "+rpt" version) and is patched
for this board's V3D GPU; Debian ships a much older chromium, so the archive matters.
The whole userland here is 32-bit armhf on a 64-bit kernel, which Firefox handles worse
than Chromium does. --use-gl=egl, --enable-gpu-rasterization, --ignore-gpu-blocklist
and --enable-zero-copy are what keep rasterization on the GPU: Chromium's blocklist
does not recognise this driver and silently falls back to software without them.
pi_kiosk_browser: firefox still works, as the fallback if an update ever regresses.

Debug mode also gains xdotool, scrot and --remote-debugging-port=9222 (on 127.0.0.1),
because firing XTEST key events at a window lands about half the time and a benchmark
you cannot verify the state of is worse than none.

pi_squeezeserver gains an absent path, and mediapis.yml derives its state from
mediapi_has_squeezeserver, which defaults to false for the whole group. false means
"actively remove", not "skip": musicdolphin has been running a Logitech Media Server
that no playbook installs and nothing talks to - every squeezelite in the fleet points
at pi_squeezelite_squeezeserver (192.168.178.80, the server) - while costing ~30 MB
resident and ~47 MB of swap on a 2 GB Pi that also drives the kiosk. The absent path
stops it, purges the package, unregisters it from sysdweb, drops the port 80 -> 9000
redirect and deletes its database and logs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-20 15:13:16 +02:00
parent 0cb199c403
commit 831a1b50a4
15 changed files with 288 additions and 75 deletions

View File

@@ -1,4 +1,22 @@
# pi_squeezeserver
Installs and enables the Logitech Media Server (`squeezeserver`) package,
and registers it with `pi_sysdweb`.
The Logitech Media Server (`logitechmediaserver`, the daemon formerly known as
squeezeboxserver), plus its `pi_sysdweb` registration and a port 80 -> 9000 redirect.
`pi_squeezeserver_state` picks a direction:
- `present` - install it and run it (`tasks/present.yml`).
- `absent` - stop it, purge the package, unregister it from sysdweb, drop the iptables
redirect and delete `/var/lib/squeezeboxserver` and `/var/log/squeezeboxserver`
(`tasks/absent.yml`).
`mediapis.yml` derives the state from `mediapi_has_squeezeserver`, which defaults to
`false` in `group_vars/mediapis.yml`. That default is deliberate and is a policy, not
an oversight: **no media pi runs its own LMS.** Every `squeezelite` in the fleet is
pointed at `pi_squeezelite_squeezeserver` (192.168.178.80, the server) by
`inventory.yml`, so a server running on a pi has no clients. musicdolphin had one
anyway - left over from earlier provisioning, since no playbook has installed it - and
on a 2 GB Pi also driving a kiosk browser it was costing ~30 MB resident and ~47 MB of
swap for nothing.
Set `mediapi_has_squeezeserver: true` in a host's vars if one ever genuinely needs it.

View File

@@ -0,0 +1,6 @@
---
# "present" installs and runs the Logitech Media Server; "absent" removes it and
# everything the present path put in place. Driven from mediapis.yml by
# `mediapi_has_squeezeserver`, so a host that does not ask for LMS actively has it
# taken away rather than merely not being given it.
pi_squeezeserver_state: present

View File

@@ -0,0 +1,8 @@
---
- name: Restart sysdweb after dropping the LMS entry
# This role's own handler rather than pi_sysdweb's: handlers only exist once the role
# defining them has been included, and role ordering does not guarantee pi_sysdweb has
# been by the time this one runs.
ansible.builtin.systemd:
name: sysdweb-system
state: restarted

View File

@@ -0,0 +1,60 @@
---
# The mirror image of present.yml. Worth having as a real code path rather than a
# one-off ssh session: musicdolphin had LMS running because some earlier provisioning
# put it there, no playbook has installed it since, and nothing on the network used
# it - every squeezelite in the fleet points at `pi_squeezelite_squeezeserver`
# (192.168.178.80, the server), not at the pi it happens to be running on. On a 2 GB Pi
# that is also driving a kiosk browser, a stray Perl daemon holding ~30 MB resident and
# ~47 MB of swap is worth reclaiming.
- name: Check whether the Logitech Media Server unit is there at all
ansible.builtin.stat:
path: /lib/systemd/system/logitechmediaserver.service
register: pi_squeezeserver_unit
- name: Stop and disable the Logitech Media Server
# Before the package goes, so systemd is told rather than left holding a unit file
# that vanishes underneath it.
ansible.builtin.systemd:
name: logitechmediaserver
state: stopped
enabled: false
when: pi_squeezeserver_unit.stat.exists
- name: Purge the Logitech Media Server package
ansible.builtin.apt:
name: logitechmediaserver
state: absent
purge: true
autoremove: true
- name: Drop the Logitech Media Server from sysdweb
# Same marker pi_sysdweb writes, so this removes exactly the block that role added.
ansible.builtin.blockinfile:
path: /etc/sysdweb.conf
marker: "# {mark} ansible managed for logitechmediaserver"
state: absent
notify: Restart sysdweb after dropping the LMS entry
- name: Undo the port 80 -> 9000 redirect the install added
ansible.builtin.iptables:
table: nat
chain: PREROUTING
in_interface: eth0
protocol: tcp
match: tcp
destination_port: "80"
jump: REDIRECT
to_ports: "9000"
comment: Redirect web traffic to port 9000
state: absent
- name: Remove the server's database and logs
# apt purge takes /usr/share/squeezeboxserver (118 MB) with it but leaves these. They
# are a scan cache and a log of a server nobody talked to.
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /var/lib/squeezeboxserver
- /var/log/squeezeboxserver

View File

@@ -1,45 +1,8 @@
---
- name: Install packages required for squeeze server
ansible.builtin.apt:
name:
- libsox-fmt-all
- libflac-dev
- libfaad2
- libmad0
- perl-openssl-defaults
- libnet-ssleay-perl
- libio-socket-ssl-perl
- nasm
- build-essential
- iptables-persistent
cache_valid_time: 7200
state: present
- name: Copy squeezeserver package
ansible.builtin.copy:
src: logitechmediaserver_8.4.0_arm.deb
dest: /tmp
mode: "0644"
- name: Install squeezeserver package
ansible.builtin.apt:
deb: /tmp/logitechmediaserver_8.4.0_arm.deb
- name: Enable sysdweb autostart
ansible.builtin.systemd:
name: logitechmediaserver
state: started
enabled: "yes"
- name: Add to sysdweb
ansible.builtin.include_role:
name: pi_sysdweb
vars:
pi_sysdweb_name: logitechmediaserver
- name: Forward port 80 to 9000
ansible.builtin.iptables:
table: nat
chain: PREROUTING
in_interface: eth0
protocol: tcp
match: tcp
destination_port: "80"
jump: REDIRECT
to_ports: "9000"
comment: Redirect web traffic to port 9000
- name: Install the Logitech Media Server
ansible.builtin.include_tasks: present.yml
when: pi_squeezeserver_state == 'present'
- name: Remove the Logitech Media Server
ansible.builtin.include_tasks: absent.yml
when: pi_squeezeserver_state == 'absent'

View File

@@ -0,0 +1,45 @@
---
- name: Install packages required for squeeze server
ansible.builtin.apt:
name:
- libsox-fmt-all
- libflac-dev
- libfaad2
- libmad0
- perl-openssl-defaults
- libnet-ssleay-perl
- libio-socket-ssl-perl
- nasm
- build-essential
- iptables-persistent
cache_valid_time: 7200
state: present
- name: Copy squeezeserver package
ansible.builtin.copy:
src: logitechmediaserver_8.4.0_arm.deb
dest: /tmp
mode: "0644"
- name: Install squeezeserver package
ansible.builtin.apt:
deb: /tmp/logitechmediaserver_8.4.0_arm.deb
- name: Enable sysdweb autostart
ansible.builtin.systemd:
name: logitechmediaserver
state: started
enabled: "yes"
- name: Add to sysdweb
ansible.builtin.include_role:
name: pi_sysdweb
vars:
pi_sysdweb_name: logitechmediaserver
- name: Forward port 80 to 9000
ansible.builtin.iptables:
table: nat
chain: PREROUTING
in_interface: eth0
protocol: tcp
match: tcp
destination_port: "80"
jump: REDIRECT
to_ports: "9000"
comment: Redirect web traffic to port 9000