Files
2026-10-09 00:55:21 +09:00

70 lines
3.1 KiB
Markdown

---
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 <user>`,
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. Confirmed at the next boot (2026-10-09): `systemctl --failed` lists nothing, the default target
is `multi-user.target`, and LTE, `can_onboard` and the USB tablet link (with mass storage still off) all came back unattended.
## 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.