Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4535616799 | ||
|
|
ad459e2b4b |
@@ -0,0 +1,84 @@
|
||||
{...}: {
|
||||
# `nix run .#sync-hardware`
|
||||
#
|
||||
# Refreshes the calling host's generated hardware module in-repo, replacing the
|
||||
# old habit of importing /etc/nixos/hardware-configuration.nix by absolute path.
|
||||
#
|
||||
# Why bother: that absolute import left the flake impure (every eval needed
|
||||
# --impure, since the file lives outside the store) and — worse — meant *both*
|
||||
# hosts resolved to whichever machine's hardware file was on disk at build
|
||||
# time. Building t480 from shadow silently baked in shadow's disk UUIDs.
|
||||
#
|
||||
# Run this on a host after changing its hardware, then commit the result.
|
||||
perSystem = {pkgs, ...}: let
|
||||
script = pkgs.writeShellApplication {
|
||||
name = "sync-hardware";
|
||||
runtimeInputs = [pkgs.nixos-install-tools pkgs.git pkgs.coreutils pkgs.nettools];
|
||||
text = ''
|
||||
set -euo pipefail
|
||||
|
||||
host="''${1:-$(hostname)}"
|
||||
|
||||
root=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
||||
if [ -z "$root" ]; then
|
||||
echo "sync-hardware: run this from inside the config repo." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dir="$root/modules/hosts/$host"
|
||||
if [ ! -d "$dir" ]; then
|
||||
echo "sync-hardware: no host directory at $dir" >&2
|
||||
echo " known hosts: $(cd "$root/modules/hosts" && echo *)" >&2
|
||||
echo " pass an explicit name with: nix run .#sync-hardware -- <host>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
out="$dir/_hardware.nix"
|
||||
|
||||
# --no-filesystems is load-bearing: fileSystems/swapDevices are declared
|
||||
# by hand in the host's disks.nix. Without the flag this would emit
|
||||
# entries for whatever is mounted right now, duplicating (and conflicting
|
||||
# with) those definitions.
|
||||
header=$(cat <<'EOF'
|
||||
# GENERATED FILE — do not edit by hand.
|
||||
#
|
||||
# Regenerate on the host itself with: nix run .#sync-hardware
|
||||
#
|
||||
# Produced by `nixos-generate-config --show-hardware-config --no-filesystems`.
|
||||
# The --no-filesystems flag is deliberate: fileSystems and swapDevices are
|
||||
# declared by hand in ./disks.nix, so regenerating this file can never clobber
|
||||
# them or emit duplicates for whatever happened to be mounted at the time.
|
||||
#
|
||||
# Leading underscore keeps import-tree from auto-importing this as a
|
||||
# flake-parts module (its filter drops any path containing "/_"); it is
|
||||
# imported explicitly from ./default.nix instead.
|
||||
EOF
|
||||
)
|
||||
|
||||
tmp=$(mktemp)
|
||||
trap 'rm -f "$tmp"' EXIT
|
||||
|
||||
# Strip the upstream 3-line "Do not modify" banner; ours replaces it.
|
||||
{
|
||||
printf '%s\n' "$header" | sed 's/^ //'
|
||||
nixos-generate-config --show-hardware-config --no-filesystems | tail -n +4
|
||||
} > "$tmp"
|
||||
|
||||
if [ -f "$out" ] && cmp -s "$tmp" "$out"; then
|
||||
echo "sync-hardware: $out already up to date."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cp "$tmp" "$out"
|
||||
echo "sync-hardware: wrote $out"
|
||||
echo " review with: git diff -- $out"
|
||||
'';
|
||||
};
|
||||
in {
|
||||
apps.sync-hardware = {
|
||||
type = "app";
|
||||
program = "${script}/bin/sync-hardware";
|
||||
meta.description = "Regenerate modules/hosts/<host>/_hardware.nix from the running machine";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -27,6 +27,32 @@
|
||||
services.xserver.enable = true;
|
||||
security.polkit.enable = true;
|
||||
|
||||
# Removable-media automounting.
|
||||
#
|
||||
# udiskie is only a tray frontend to the udisks2 D-Bus daemon, so the daemon
|
||||
# has to be enabled or udiskie runs but can never mount anything. Note this
|
||||
# covers removable media *only*: udisks2 reports the internal SATA disks as
|
||||
# HintSystem=true, so udiskie leaves them alone. Permanently attached drives
|
||||
# are declared in the host's disks.nix instead.
|
||||
services.udisks2.enable = true;
|
||||
|
||||
# Run udiskie as a user unit rather than from the hypr autostart — it was
|
||||
# previously only installed, never actually launched. Binding it to
|
||||
# graphical-session.target (which UWSM manages properly) means it starts and
|
||||
# stops with the session instead of leaking across logins.
|
||||
systemd.user.services.udiskie = {
|
||||
description = "udiskie removable media automounter";
|
||||
partOf = ["graphical-session.target"];
|
||||
after = ["graphical-session.target"];
|
||||
wantedBy = ["graphical-session.target"];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
# -s = smart tray: the icon appears only while removable media is present.
|
||||
ExecStart = "${pkgs.udiskie}/bin/udiskie -s";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# hypr* ecosystem (keybinds / hypridle / autostart)
|
||||
hyprlock
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# GENERATED FILE — do not edit by hand.
|
||||
#
|
||||
# Regenerate on the host itself with: nix run .#sync-hardware
|
||||
#
|
||||
# Produced by `nixos-generate-config --show-hardware-config --no-filesystems`.
|
||||
# The --no-filesystems flag is deliberate: fileSystems and swapDevices are
|
||||
# declared by hand in ./disks.nix, so regenerating this file can never clobber
|
||||
# them or emit duplicates for whatever happened to be mounted at the time.
|
||||
#
|
||||
# Leading underscore keeps import-tree from auto-importing this as a
|
||||
# flake-parts module (its filter drops any path containing "/_"); it is
|
||||
# imported explicitly from ./default.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "uas" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
@@ -5,8 +5,12 @@
|
||||
}: {
|
||||
flake.nixosConfigurations.shadow = inputs.nixpkgs.lib.nixosSystem {
|
||||
modules = with self.nixosModules; [
|
||||
# Generated hardware scan, in-repo so the flake stays pure.
|
||||
# Refresh with `nix run .#sync-hardware` (run on shadow itself).
|
||||
./_hardware.nix
|
||||
desktop
|
||||
shadowConfiguration
|
||||
shadowDisks
|
||||
cpuAmd
|
||||
gpuNvidia
|
||||
development
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{...}: {
|
||||
# Every filesystem on shadow lives here, hand-maintained.
|
||||
#
|
||||
# hardware.nix is generated with `--no-filesystems` precisely so it never
|
||||
# emits fileSystems/swapDevices entries of its own. That keeps regeneration
|
||||
# (`nix run .#sync-hardware`) safe: re-running it can never clobber these
|
||||
# definitions, nor produce duplicates for whichever data drives happened to
|
||||
# be mounted at the time it ran.
|
||||
flake.nixosModules.shadowDisks = {...}: let
|
||||
# Secondary data drive, addressed by filesystem label.
|
||||
#
|
||||
# noauto + x-systemd.automount makes systemd generate an .automount unit and
|
||||
# mount on first access to the path rather than at boot — the two 2.7T
|
||||
# spinners stay parked until something actually touches them. idle-timeout
|
||||
# unmounts them again once quiet so they can spin back down.
|
||||
#
|
||||
# nofail matters even with automount: it stops a missing or dying disk from
|
||||
# becoming a failed dependency that drops the boot into emergency mode.
|
||||
#
|
||||
# On-disk ownership is already ahmza mode 755 on all three, so no uid mapping
|
||||
# is needed — ext4 stores ownership in the filesystem and ignores uid=/gid=.
|
||||
dataDrive = label: {
|
||||
device = "/dev/disk/by-label/${label}";
|
||||
fsType = "ext4";
|
||||
options = [
|
||||
"nofail"
|
||||
"noauto"
|
||||
"x-systemd.automount"
|
||||
"x-systemd.idle-timeout=600"
|
||||
"x-systemd.device-timeout=10"
|
||||
];
|
||||
};
|
||||
in {
|
||||
fileSystems = {
|
||||
# Boot essentials, by UUID. UUIDs rather than labels here on purpose:
|
||||
# these two must resolve unambiguously, and a label is only as unique as
|
||||
# the last disk someone plugged in.
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/deff63fc-1738-4cfc-a79c-06e58c78471a";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/5873-AD05";
|
||||
fsType = "vfat";
|
||||
options = ["fmask=0077" "dmask=0077"];
|
||||
};
|
||||
|
||||
"/mnt/dump" = dataDrive "DUMP";
|
||||
"/mnt/games" = dataDrive "GAMES";
|
||||
"/mnt/bak" = dataDrive "BAK";
|
||||
};
|
||||
|
||||
swapDevices = [];
|
||||
};
|
||||
}
|
||||
@@ -5,6 +5,17 @@
|
||||
}: {
|
||||
flake.nixosConfigurations.t480 = inputs.nixpkgs.lib.nixosSystem {
|
||||
modules = with self.nixosModules; [
|
||||
# TODO: still importing by absolute path, so evaluating t480 requires
|
||||
# --impure and picks up the hardware file of whatever machine you build
|
||||
# from (on shadow, that means shadow's disk UUIDs — wrong but harmless
|
||||
# until you actually deploy). Fix by running, ON THE T480 ITSELF:
|
||||
#
|
||||
# nix run .#sync-hardware
|
||||
#
|
||||
# then create modules/hosts/t480/disks.nix (mirroring shadow's) and swap
|
||||
# this line for `./_hardware.nix` + `t480Disks`. Cannot be done remotely:
|
||||
# the hardware scan has to happen on the target machine.
|
||||
/etc/nixos/hardware-configuration.nix
|
||||
desktop
|
||||
t480Configuration
|
||||
# CPU microcode + integrated Intel GPU. The T480 also has an NVIDIA MX150;
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
nix-ld
|
||||
];
|
||||
in {
|
||||
imports =
|
||||
[
|
||||
/etc/nixos/hardware-configuration.nix
|
||||
]
|
||||
++ modules;
|
||||
# Hardware/disk config is deliberately NOT imported here. It is per-host and
|
||||
# lives in modules/hosts/<host>/{_hardware.nix,disks.nix}, wired up by that
|
||||
# host's default.nix. Importing it from this shared module used to mean both
|
||||
# hosts resolved to whichever machine's /etc/nixos file existed at build time.
|
||||
imports = modules;
|
||||
services = {
|
||||
openssh.enable = true;
|
||||
avahi.enable = true;
|
||||
|
||||
Reference in New Issue
Block a user