feat(nixos): add PipeWire and fix UxPlay audio on sunken-ship 🔊

Enable PipeWire with ALSA/PulseAudio compat so GStreamer can output
audio. Move UxPlay to a user service with linger so it can reach
PipeWire. Add danny to audio group, add alsa-utils for debugging.
This commit is contained in:
DannyDannyDanny 2026-03-30 15:49:35 +02:00
parent ee2fa1e5f1
commit 84715596f5

View file

@ -41,7 +41,7 @@ in
users.users.danny = { users.users.danny = {
isNormalUser = true; isNormalUser = true;
extraGroups = [ "wheel" "video" ]; # video: backlight control via sysfs / brightnessctl extraGroups = [ "wheel" "video" "audio" ]; # video: backlight; audio: sound devices
# SSH keys: push via scp, don't commit. NixOS does not manage authorized_keys so scp'd keys persist. # SSH keys: push via scp, don't commit. NixOS does not manage authorized_keys so scp'd keys persist.
# Example: scp ~/.ssh/id_ed25519_sunken_ship.pub danny@server:/tmp/ then on server: mkdir -p ~/.ssh; cat /tmp/*.pub >> ~/.ssh/authorized_keys # Example: scp ~/.ssh/id_ed25519_sunken_ship.pub danny@server:/tmp/ then on server: mkdir -p ~/.ssh; cat /tmp/*.pub >> ~/.ssh/authorized_keys
}; };
@ -62,8 +62,19 @@ in
git # clone/bootstrap and dotfiles-rebuild timer git # clone/bootstrap and dotfiles-rebuild timer
brightnessctl # manual backlight; replaces removed `light` from nixpkgs brightnessctl # manual backlight; replaces removed `light` from nixpkgs
uxplay # AirPlay mirroring receiver uxplay # AirPlay mirroring receiver
alsa-utils # aplay, amixer, arecord for audio debugging
]; ];
# PipeWire — sound server for UxPlay / GStreamer.
services.pipewire = {
enable = true;
alsa.enable = true;
pulse.enable = true; # PulseAudio compat for GStreamer pulsesink
};
# PipeWire runs as a user service; ensure it starts for danny even without a login session.
systemd.user.services.pipewire.wantedBy = [ "default.target" ];
systemd.user.services.pipewire-pulse.wantedBy = [ "default.target" ];
# Avahi (mDNS) — required for AirPlay discovery. # Avahi (mDNS) — required for AirPlay discovery.
services.avahi = { services.avahi = {
enable = true; enable = true;
@ -77,19 +88,21 @@ in
allowedUDPPorts = [ 5353 6000 6001 7011 ]; allowedUDPPorts = [ 5353 6000 6001 7011 ];
}; };
# UxPlay AirPlay receiver — audio-only, runs as a persistent service. # UxPlay AirPlay receiver — audio-only, runs as a user service under danny.
systemd.services.uxplay = { # Runs inside danny's user session so it can reach PipeWire/PulseAudio.
systemd.user.services.uxplay = {
description = "UxPlay AirPlay receiver"; description = "UxPlay AirPlay receiver";
after = [ "network-online.target" "avahi-daemon.service" ]; after = [ "pipewire-pulse.service" ];
wants = [ "network-online.target" "avahi-daemon.service" ]; wants = [ "pipewire-pulse.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "default.target" ];
serviceConfig = { serviceConfig = {
ExecStart = "${pkgs.uxplay}/bin/uxplay -n sunken-ship -p -vs 0"; ExecStart = "${pkgs.uxplay}/bin/uxplay -n sunken-ship -p -vs 0";
Restart = "on-failure"; Restart = "on-failure";
RestartSec = 5; RestartSec = 5;
User = "danny";
}; };
}; };
# Ensure danny's user services start at boot (not just on login).
users.users.danny.linger = true;
# Pull dotfiles and rebuild if the repo has new commits. # Pull dotfiles and rebuild if the repo has new commits.
systemd.services.dotfiles-rebuild = { systemd.services.dotfiles-rebuild = {