Skip to content

fix: kiosk restart loop, PC HDMI audio, server not saved after Wi-Fi join, join/scan race, Wi-Fi power save - #14

Merged
madeofpendletonwool merged 5 commits into
mainfrom
fix/box-first-run-field-issues
Oct 18, 2026
Merged

madeofpendletonwool merged 5 commits into
mainfrom
fix/box-first-run-field-issues

Conversation

@madeofpendletonwool

Copy link
Copy Markdown
Owner

From a night running the x86 box (a Framework laptop) at a friend's house: the join failed on the first network, the server had to be set twice, there was no audio on the TV, and the kiosk died back to the console every ~5 minutes for two hours.

Kiosk restart loop (affects every box on a public server)

Since Chrome 142, a public site needs the Local Network Access permission to call 127.0.0.1. A kiosk has nobody to answer the prompt, so /tv's heartbeats and events never reached boxd. The watchdog then saw a page that "stopped beating while the server answers": it restarted the kiosk after the 4-minute settle, and rebooted after three restarts.

  • boxd config apply (every boot) and the setup save write /etc/chromium/policies/managed/syncphony-box.json, allowing the configured server's origin under LocalNetworkAccessAllowedForUrls, LocalNetworkAllowedForUrls and LoopbackNetworkAllowedForUrls (the 146+ split). Chromium ignores names it doesn't know. With no server there's no policy.
  • config.ServerOrigin is now shared with the bridge's Origin check.

Audio on a PC

audio-setup took the first HDMI/DP sink, but a laptop has one per USB-C port. audio=hdmi on a PC now:

  • takes the sink whose port reports available
  • otherwise switches the card to the available HDMI profile (output-only first), and never re-switches an active one, so the monitor can't loop

The TV-off fallback and all Pi behavior are unchanged, and a Pi's cards are never switched. ADR 0013 is updated.

Server not saved after a Wi-Fi join

A fresh box boots months behind (no RTC, and timesyncd's clock file lived on the tmpfs), so https failed and the 30-second server check gave up.

  • The join restarts timesyncd, checks for 2 minutes, and logs why the last check failed.
  • data-persist saves and restores timesyncd's clock file (its mtime) through /data, ordered before timesyncd, so boots start at the last known time.

"Couldn't find " right after the hotspot

nmcli device wifi rescan is async, and the scan list is empty right after AP mode. Connect now polls --rescan yes (which waits) up to 4 times for the SSID before connecting. The comma in the SSID was not the cause; the test pins it.

Wi-Fi power save off

A NetworkManager conf.d drop-in sets wifi.powersave = 2. The mt7921 box answered ARP but not ping or SSH while idle.

Testing

  • make test (69 bats + Go) and make lint pass in golang:1.26-trixie
  • New tests: the Chromium policy write and removal; the scan wait (found, never found, comma SSID); the clock file mtime round trip; PC HDMI pick, profile switch, no re-switch, Pi untouched
  • Not verified on hardware. Most important: on a box pointed at a public server, journalctl -u boxd | grep watchdog should stay quiet past 5 minutes, and chrome://policy should show the policy. The Chromium policy names come from vendor docs (Okta, Truu, Google's Samsung-hosted policy reference), not from a test against Chromium 155.

…work Access)

Since Chrome 142 a public site needs the Local Network Access permission
to call 127.0.0.1, and a kiosk has nobody to answer the prompt. /tv's
heartbeats and events never reached boxd, so the watchdog took the page
for stuck and restarted the kiosk every few minutes (then rebooted the
box after three).

boxd config apply (every boot) and the setup save write a Chromium
managed policy allowing the configured server's origin, under all three
names the policy has had (LocalNetworkAccess, and the 146+ LocalNetwork /
LoopbackNetwork split). config.ServerOrigin is shared with the bridge's
Origin check.
…power saving off

Right after the setup access point went down the scan list was empty,
and 'nmcli device wifi rescan' returns before the scan ends, so a join
could fail with "couldn't find <network>" for a network in range. Connect
now rescans with --rescan yes (which waits) until the SSID shows, up to
four times, before connecting. Commas in a name were never the problem:
the SSID is one argument to nmcli (now pinned by the test).

NetworkManager enables Wi-Fi power saving by default; with it, cards like
the mt7921 stop answering incoming traffic while idle (the box answered
ARP but not ping or SSH). A conf.d drop-in turns it off.
…p the last known time on /data

A fresh box boots months behind (no RTC, and timesyncd's clock file lived
on the overlay's tmpfs), so every https certificate looked invalid until
NTP answered. The check after a join gave up after 30 s and didn't save
the server, so it had to be set a second time from a phone.

- the join restarts timesyncd (it had been backing off while offline) and
  checks the server for two minutes, logging why the last check failed
- data-persist saves timesyncd's clock file (its mtime) to /data and
  restores it before timesyncd starts, so a box starts at its last known
  time instead of the image's build date
audio-setup took the first HDMI/DisplayPort sink. A PC has one per port (a
Framework laptop: one per USB-C port), so the TV on another port got
silence while the page played. And when the card sat on its analog
profile (WirePlumber's preference on a laptop), the TV's output wasn't a
sink at all.

audio=hdmi on a PC now takes the sink whose port reports a display, and
if none does, switches the card to the available HDMI profile (output
only first; never re-switched once active, so the hotplug monitor can't
loop). The TV-off fallback (first/second sink) and Pi behavior are
unchanged; a Pi's cards are never switched.
@madeofpendletonwool
madeofpendletonwool merged commit a7c5396 into main Oct 18, 2026
4 checks passed
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.

1 participant