Files
ansible/roles/pi_kiosk/tasks/main.yml
Martin Bauer a973bc8d75 Make the kiosk autologin survive a reboot, and allow forcing a display mode
Two problems on musicdolphin, found after its first reboot.

getty@tty1 was never enabled. The role installed the autologin drop-in and the
handler restarted the unit, which works until the next boot - these images do
not enable getty@tty1 themselves, getty.target pulls in getty-static.service and
nothing else, so after a reboot nobody logs in and the kiosk never starts. Enable
it as well as starting it.

And the attached screen reads back 0 bytes of EDID on both micro-HDMI ports while
reporting "disconnected", so the kernel offers no modes, no framebuffer is
created, and X exits with "no screens found". That is the signature of a cable or
adapter whose DDC/HPD lines are broken but whose video pairs are fine. Forcing
the connector on is not enough on its own - with no EDID there is still no mode
to set - so allow a `video=` kernel parameter, which forces the output and names
the mode. hdmi_force_hotplug=1 is no use here; vc4-kms-v3d ignores it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 12:10:34 +02:00

91 lines
2.8 KiB
YAML

---
- name: Packages
ansible.builtin.apt:
name:
- xserver-xorg
- xinit
- x11-xserver-utils
- firefox-esr
- unclutter
cache_valid_time: 7200
- name: Create kiosk user
ansible.builtin.user:
name: "{{ pi_kiosk_user }}"
groups: [video, input, tty]
shell: /bin/bash
create_home: true
- name: Autologin the kiosk user on tty1
ansible.builtin.file:
path: /etc/systemd/system/getty@tty1.service.d
state: directory
mode: "0755"
- name: Install getty autologin override
ansible.builtin.template:
src: autologin.conf.j2
dest: /etc/systemd/system/getty@tty1.service.d/autologin.conf
mode: "0644"
notify: Reload systemd and restart getty
- name: Enable the autologin getty on tty1
# Enabling it is the part that survives a reboot. These images do not enable
# getty@tty1 themselves - getty.target pulls in getty-static.service and nothing
# else - so without this the drop-in above is installed, the handler starts the unit
# once, and the kiosk then silently stops coming up after the next reboot.
ansible.builtin.systemd:
name: "getty@tty1"
enabled: true
state: started
daemon_reload: true
- name: Install .bash_profile (starts X on tty1 login)
ansible.builtin.template:
src: bash_profile.j2
dest: "/home/{{ pi_kiosk_user }}/.bash_profile"
owner: "{{ pi_kiosk_user }}"
group: "{{ pi_kiosk_user }}"
mode: "0644"
- name: Install .xinitrc (launches Firefox kiosk, no window manager)
ansible.builtin.template:
src: xinitrc.j2
dest: "/home/{{ pi_kiosk_user }}/.xinitrc"
owner: "{{ pi_kiosk_user }}"
group: "{{ pi_kiosk_user }}"
mode: "0755"
- name: Ensure firefox-esr policy directory exists
ansible.builtin.file:
path: /etc/firefox-esr
state: directory
mode: "0755"
# apt normally creates this; a backstop in case the package layout doesn't
- name: Install Firefox enterprise policy (suppress session-restore/update prompts)
ansible.builtin.copy:
src: policies.json
dest: /etc/firefox-esr/policies.json
mode: "0644"
- name: Read the current kernel command line
ansible.builtin.slurp:
src: /boot/firmware/cmdline.txt
register: pi_kiosk_cmdline
when: pi_kiosk_force_mode | length > 0
- name: Force a mode on the kiosk output
# cmdline.txt is a single line of space-separated parameters. Rebuild it by dropping
# any video= we set before and appending the current one, so changing the mode
# replaces it rather than stacking a second one.
ansible.builtin.copy:
dest: /boot/firmware/cmdline.txt
content: >-
{{ ((pi_kiosk_cmdline.content | b64decode).split()
| reject('match', '^video=') | list
+ ['video=' ~ pi_kiosk_force_mode]) | join(' ') }}
mode: "0755"
when: pi_kiosk_force_mode | length > 0
notify: Warn that a reboot is needed