From fc0836aec7fb904e71ce024b627b099525afd5e8 Mon Sep 17 00:00:00 2001 From: mikkeli Date: Fri, 9 Oct 2026 00:01:51 +0900 Subject: [PATCH] Go headless: multi-user target, tty1 console, no sound servers The car unit has no display of its own (the tablet app is the display), and unified memory is better spent on the voice stack. GDM/GNOME no longer start, a text login stays on tty1, and PulseAudio/PipeWire are disabled for all users while ALSA stays for mic capture. Saves ~200 MB idle; every step is a reversible disable, not a removal. Also notes the pre-existing nightly logrotate failure from the NVIDIA jetson-logging config. Co-Authored-By: Claude Opus 5.5 --- docs/impl/reports/HEADLESS.md | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/impl/reports/HEADLESS.md diff --git a/docs/impl/reports/HEADLESS.md b/docs/impl/reports/HEADLESS.md new file mode 100644 index 0000000..813884f --- /dev/null +++ b/docs/impl/reports/HEADLESS.md @@ -0,0 +1,68 @@ +--- +type: report +date: 2026-10-09 +--- +# Headless: No Desktop, No Sound Server + +## Why + +The car unit has no display of its own; the display is the tablet app. Anything graphical on the Orin +uses unified memory, which the voice stack (GPT-SoVITS TTS, Whisper ASR) needs more. + +## Result + +| Item | State | +|------|-------| +| Default target | `multi-user.target` (was `graphical.target`): GDM, Xorg and GNOME no longer start | +| Local console | `getty@tty1` enabled, so a text login appears on a directly attached monitor/keyboard | +| Sound servers | PulseAudio and PipeWire disabled for all users. **ALSA kept**: devices are still there for mic capture | +| Camera | `nvargus-daemon` kept (used by `camera-webui` and the later vision service) | +| Memory | "used" went from 1206 MB to 1005 MB (~200 MB) on an idle system (GDM greeter only, nobody logged in graphically) | + +Per-process RSS for the desktop added up to ~550 MB, but that counts shared pages once per process. The `free` difference is the real saving. + +## Commands + +``` +sudo systemctl set-default multi-user.target +sudo systemctl enable getty@tty1 +sudo systemctl --global disable pulseaudio.socket pulseaudio.service \ + pipewire.socket pipewire.service pipewire-media-session.service +sudo systemctl isolate multi-user.target # apply now, without a reboot +``` + +`disable` rather than `mask`: nothing is removed, and each step reverses cleanly. + +``` +sudo systemctl set-default graphical.target +sudo systemctl --global enable pulseaudio.socket pulseaudio.service \ + pipewire.socket pipewire.service pipewire-media-session.service +``` + +To start the desktop once without changing the default: `sudo systemctl start gdm`. + +## Audio + +Project Yukart's plan keeps the **microphone on the Orin** (Whisper) and sends **TTS to the tablet** as chunked +utterances. Neither needs a desktop sound server: + +- capture: read the ALSA device directly (`arecord -l` lists it; a USB mic adds its own card); +- playback on the Orin itself isn't needed (only HDMI is present: `card 0: HDA`). + +If a service later needs PipeWire anyway, run it for that service's user with `loginctl enable-linger `, +so it starts at boot without a login session. Don't re-enable it globally. + +## Side effects seen when switching live + +`systemctl isolate` re-ran two NVIDIA oneshot units, which then failed because their setup was already done: + +- `nvzramconfig`: `mkswap: /dev/zram5 is mounted`. All six zram swap devices are active, so nothing is missing. +- `nv_nvsciipc_init`: exits 1 on re-run. + +Both run only once on a normal boot. **To check at the next boot:** `systemctl --failed` should list neither. + +## Unrelated, pre-existing + +`logrotate.service` fails every night: `stat of /data/logging-volume/*.log failed: Permission denied`. +`/etc/logrotate.d/jetson-logging` (package `nvidia-jetson-services`) rotates as user `logging`, but `/data` is `drwx------ root`. +Harmless because nothing logs there. Left as is, since it's a package-owned file.