patiodeck: add steam deck LCD host
This commit is contained in:
@@ -376,6 +376,7 @@
|
||||
nixosConfigurations = {
|
||||
mreow = mkDesktopHost "mreow";
|
||||
yarn = mkDesktopHost "yarn";
|
||||
patiodeck = mkDesktopHost "patiodeck";
|
||||
muffin = muffinHost;
|
||||
};
|
||||
|
||||
|
||||
66
hosts/patiodeck/default.nix
Normal file
66
hosts/patiodeck/default.nix
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
username,
|
||||
inputs,
|
||||
site_config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
../../modules/desktop-common.nix
|
||||
../../modules/desktop-steam-update.nix
|
||||
./disk.nix
|
||||
./impermanence.nix
|
||||
|
||||
inputs.impermanence.nixosModules.impermanence
|
||||
inputs.jovian-nixos.nixosModules.default
|
||||
];
|
||||
|
||||
networking.hostId = "a1b2c3d4";
|
||||
|
||||
# SSH for remote management from laptop
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ 22 ];
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.${username}.openssh.authorizedKeys.keys = [
|
||||
site_config.ssh_keys.laptop
|
||||
];
|
||||
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
site_config.ssh_keys.laptop
|
||||
];
|
||||
|
||||
nixpkgs.config.allowUnfreePredicate =
|
||||
pkg:
|
||||
builtins.elem (lib.getName pkg) [
|
||||
"steamdeck-hw-theme"
|
||||
"steam-jupiter-unwrapped"
|
||||
"steam"
|
||||
"steam-original"
|
||||
"steam-unwrapped"
|
||||
"steam-run"
|
||||
];
|
||||
|
||||
jovian = {
|
||||
devices.steamdeck.enable = true;
|
||||
steam = {
|
||||
enable = true;
|
||||
autoStart = true;
|
||||
desktopSession = "niri";
|
||||
user = username;
|
||||
};
|
||||
};
|
||||
|
||||
# Jovian-NixOS requires sddm
|
||||
services.displayManager.sddm.wayland.enable = true;
|
||||
|
||||
# disable gamescope from desktop-common.nix to avoid conflict with jovian
|
||||
programs.gamescope.enable = lib.mkForce false;
|
||||
}
|
||||
52
hosts/patiodeck/disk.nix
Normal file
52
hosts/patiodeck/disk.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
type = "EF00";
|
||||
size = "500M";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
persistent = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/persistent";
|
||||
};
|
||||
};
|
||||
nix = {
|
||||
size = "200G";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "f2fs";
|
||||
mountpoint = "/nix";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
nodev = {
|
||||
"/" = {
|
||||
fsType = "tmpfs";
|
||||
mountOptions = [
|
||||
"defaults"
|
||||
"size=2G"
|
||||
"mode=755"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems."/persistent".neededForBoot = true;
|
||||
fileSystems."/nix".neededForBoot = true;
|
||||
}
|
||||
7
hosts/patiodeck/home.nix
Normal file
7
hosts/patiodeck/home.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
../../home/profiles/gui.nix
|
||||
../../home/profiles/desktop.nix
|
||||
];
|
||||
}
|
||||
48
hosts/patiodeck/impermanence.nix
Normal file
48
hosts/patiodeck/impermanence.nix
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
username,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.persistence."/persistent" = {
|
||||
hideMounts = true;
|
||||
directories = [
|
||||
"/var/log"
|
||||
"/var/lib/systemd/coredump"
|
||||
"/var/lib/nixos"
|
||||
"/var/lib/systemd/timers"
|
||||
# agenix identity sealed by the TPM
|
||||
{
|
||||
directory = "/var/lib/agenix";
|
||||
mode = "0700";
|
||||
user = "root";
|
||||
group = "root";
|
||||
}
|
||||
];
|
||||
|
||||
files = [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
"/etc/machine-id"
|
||||
];
|
||||
|
||||
users.root = {
|
||||
files = [
|
||||
".local/share/fish/fish_history"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# bind mount home directory from persistent storage
|
||||
fileSystems."/home/${username}" = {
|
||||
device = "/persistent/home/${username}";
|
||||
fsType = "none";
|
||||
options = [ "bind" ];
|
||||
neededForBoot = true;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /etc 755 root"
|
||||
];
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
{
|
||||
imports = [
|
||||
../../modules/desktop-common.nix
|
||||
../../modules/desktop-steam-update.nix
|
||||
../../modules/no-rgb.nix
|
||||
./disk.nix
|
||||
./impermanence.nix
|
||||
@@ -83,58 +84,6 @@
|
||||
|
||||
systemd.services.lactd.serviceConfig.ExecStartPre = "${lib.getExe pkgs.bash} -c \"sleep 3s\"";
|
||||
|
||||
# root-level service that applies a pending update. Triggered by
|
||||
# steamos-update (via systemctl start) when the user accepts an update.
|
||||
# Runs as root so it can write the system profile and boot entry.
|
||||
systemd.services.pull-update-apply = {
|
||||
description = "Apply pending NixOS update pulled from binary cache";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = pkgs.writeShellScript "pull-update-apply" ''
|
||||
set -uo pipefail
|
||||
export PATH=${
|
||||
pkgs.lib.makeBinPath [
|
||||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.nix
|
||||
]
|
||||
}
|
||||
|
||||
STORE_PATH=$(curl -sf --max-time 30 "${site_config.binary_cache.url}/deploy/yarn" || true)
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
echo "server unreachable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
||||
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
||||
echo "already up to date: $STORE_PATH"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "applying $STORE_PATH (was $CURRENT)"
|
||||
nix-store -r --add-root /nix/var/nix/gcroots/pull-update-apply-latest --indirect "$STORE_PATH" \
|
||||
|| { echo "fetch failed"; exit 1; }
|
||||
nix-env -p /nix/var/nix/profiles/system --set "$STORE_PATH" \
|
||||
|| { echo "profile set failed"; exit 1; }
|
||||
"$STORE_PATH/bin/switch-to-configuration" boot \
|
||||
|| { echo "boot entry failed"; exit 1; }
|
||||
echo "update applied; reboot required"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Allow primary user to start pull-update-apply.service without a password
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
action.lookup("unit") == "pull-update-apply.service" &&
|
||||
subject.user == "${username}") {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
nixpkgs.config.allowUnfreePredicate =
|
||||
pkg:
|
||||
builtins.elem (lib.getName pkg) [
|
||||
@@ -146,68 +95,6 @@
|
||||
"steam-run"
|
||||
];
|
||||
|
||||
# Override jovian-stubs to disable steamos-update kernel check
|
||||
# This prevents Steam from requesting reboots for "system updates"
|
||||
# Steam client updates will still work normally
|
||||
nixpkgs.overlays = [
|
||||
(
|
||||
final: prev:
|
||||
let
|
||||
deploy-url = "${site_config.binary_cache.url}/deploy/yarn";
|
||||
|
||||
steamos-update-script = final.writeShellScript "steamos-update" ''
|
||||
export PATH=${
|
||||
final.lib.makeBinPath [
|
||||
final.curl
|
||||
final.coreutils
|
||||
final.systemd
|
||||
]
|
||||
}
|
||||
|
||||
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
||||
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] server unreachable"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
||||
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] no update available"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
# check-only mode: just report that an update exists
|
||||
if [ "''${1:-}" = "check" ] || [ "''${1:-}" = "--check-only" ]; then
|
||||
>&2 echo "[steamos-update] update available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# apply: trigger the root-running systemd service to install the update
|
||||
>&2 echo "[steamos-update] applying update..."
|
||||
if systemctl start --wait pull-update-apply.service; then
|
||||
>&2 echo "[steamos-update] update installed, reboot to apply"
|
||||
exit 0
|
||||
else
|
||||
>&2 echo "[steamos-update] apply failed; see 'journalctl -u pull-update-apply'"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
# Only replace holo-update (and its steamos-update alias) with our
|
||||
# binary-cache pull script. All other stubs (pkexec, sudo,
|
||||
# holo-reboot, holo-select-branch, …) come from upstream unchanged.
|
||||
jovian-stubs = prev.jovian-stubs.overrideAttrs (old: {
|
||||
buildCommand = (old.buildCommand or "") + ''
|
||||
install -D -m 755 ${steamos-update-script} $out/bin/holo-update
|
||||
install -D -m 755 ${steamos-update-script} $out/bin/steamos-update
|
||||
'';
|
||||
});
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
jovian = {
|
||||
devices.steamdeck.enable = false;
|
||||
steam = {
|
||||
|
||||
122
modules/desktop-steam-update.nix
Normal file
122
modules/desktop-steam-update.nix
Normal file
@@ -0,0 +1,122 @@
|
||||
# Binary-cache update mechanism for Jovian-NixOS desktops.
|
||||
#
|
||||
# Replaces the upstream holo-update/steamos-update stubs with a script that
|
||||
# checks the private binary cache for a newer system closure, and provides a
|
||||
# root-level systemd service to apply it. Steam's deck UI calls
|
||||
# `steamos-update check` periodically; exit 7 = no update, exit 0 = update
|
||||
# applied or available.
|
||||
#
|
||||
# The deploy endpoint is ${binary_cache_url}/deploy/${hostname} — a plain
|
||||
# text file containing the /nix/store path of the latest closure, published
|
||||
# by CI after a successful build.
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
hostname,
|
||||
username,
|
||||
site_config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
deploy-url = "${site_config.binary_cache.url}/deploy/${hostname}";
|
||||
|
||||
steamos-update-script = pkgs.writeShellScript "steamos-update" ''
|
||||
export PATH=${
|
||||
lib.makeBinPath [
|
||||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.systemd
|
||||
]
|
||||
}
|
||||
|
||||
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
||||
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] server unreachable"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
||||
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
||||
>&2 echo "[steamos-update] no update available"
|
||||
exit 7
|
||||
fi
|
||||
|
||||
# check-only mode: just report that an update exists
|
||||
if [ "''${1:-}" = "check" ] || [ "''${1:-}" = "--check-only" ]; then
|
||||
>&2 echo "[steamos-update] update available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# apply: trigger the root-running systemd service to install the update
|
||||
>&2 echo "[steamos-update] applying update..."
|
||||
if systemctl start --wait pull-update-apply.service; then
|
||||
>&2 echo "[steamos-update] update installed, reboot to apply"
|
||||
exit 0
|
||||
else
|
||||
>&2 echo "[steamos-update] apply failed; see 'journalctl -u pull-update-apply'"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(_final: prev: {
|
||||
jovian-stubs = prev.jovian-stubs.overrideAttrs (old: {
|
||||
buildCommand = (old.buildCommand or "") + ''
|
||||
install -D -m 755 ${steamos-update-script} $out/bin/holo-update
|
||||
install -D -m 755 ${steamos-update-script} $out/bin/steamos-update
|
||||
'';
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
systemd.services.pull-update-apply = {
|
||||
description = "Apply pending NixOS update pulled from binary cache";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = pkgs.writeShellScript "pull-update-apply" ''
|
||||
set -uo pipefail
|
||||
export PATH=${
|
||||
lib.makeBinPath [
|
||||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.nix
|
||||
]
|
||||
}
|
||||
|
||||
STORE_PATH=$(curl -sf --max-time 30 "${deploy-url}" || true)
|
||||
if [ -z "$STORE_PATH" ]; then
|
||||
echo "server unreachable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT=$(readlink -f /nix/var/nix/profiles/system)
|
||||
if [ "$CURRENT" = "$STORE_PATH" ]; then
|
||||
echo "already up to date: $STORE_PATH"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "applying $STORE_PATH (was $CURRENT)"
|
||||
nix-store -r --add-root /nix/var/nix/gcroots/pull-update-apply-latest --indirect "$STORE_PATH" \
|
||||
|| { echo "fetch failed"; exit 1; }
|
||||
nix-env -p /nix/var/nix/profiles/system --set "$STORE_PATH" \
|
||||
|| { echo "profile set failed"; exit 1; }
|
||||
"$STORE_PATH/bin/switch-to-configuration" boot \
|
||||
|| { echo "boot entry failed"; exit 1; }
|
||||
echo "update applied; reboot required"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# allow the primary user to trigger pull-update-apply without a password
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
action.lookup("unit") == "pull-update-apply.service" &&
|
||||
subject.user == "${username}") {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user