The screen was a badly seated cable - the enclosure was fouling the connector, so the DDC and hotplug pins never mated while the video pairs partly did. That is why it read 0 bytes of EDID on both ports and why forcing a mode "fixed" it. With the cable seated properly HDMI-A-1 reports connected, hands over 256 bytes of EDID and identifies itself as a DELL P2419H, so the force has nothing left to do. Remove it and let EDID decide, which also means the mode is no longer hardcoded to something that happened to match. Separately, and the reason the screen then showed "Your Firefox profile cannot be loaded": Xorg runs as root under Debian's wrapper with HOME pointing at the kiosk user's, so the first mesa shader cache write created ~/.cache owned by root and mode 0700. Firefox could not create ~/.cache/mozilla inside it and never got as far as writing a profile - .mozilla/firefox held only Crash Reports and Pending Pings, with no profiles.ini. Create ~/.cache and ~/.mozilla up front owned by the user, so root only ever adds subdirectories to a directory the user already owns. Keeping the getty@tty1 enable and the userconfig.service mask: those were real faults, not workarounds for this one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
88 lines
2.8 KiB
YAML
88 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: Own the directories X and Firefox write into
|
|
# Xorg runs as root here (Debian's wrapper, allowed_users=console) with HOME set to
|
|
# the kiosk user's, so it creates ~/.cache itself - root-owned and 0700 - the first
|
|
# time it writes a mesa shader cache. Firefox then cannot create ~/.cache/mozilla and
|
|
# gives up with "Your Firefox profile cannot be loaded. It may be missing or
|
|
# inaccessible". Creating these up front, owned by the user, means root only ever
|
|
# adds subdirectories to a directory the user already owns.
|
|
ansible.builtin.file:
|
|
path: "/home/{{ pi_kiosk_user }}/{{ item }}"
|
|
state: directory
|
|
owner: "{{ pi_kiosk_user }}"
|
|
group: "{{ pi_kiosk_user }}"
|
|
mode: "0700"
|
|
loop:
|
|
- .cache
|
|
- .mozilla
|
|
|
|
- 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"
|