1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# enzo — laptop. Gets the shared common/ base plus laptop-only settings.
{ inputs, pkgs, ... }:
{
imports = [
# Shared desktop base + enzo-only extras. Add ../../profiles/dev.nix or
# apps.nix here, or one-off packages below, as needed.
../../profiles/desktop.nix
../../profiles/dev.nix
../../profiles/sandbox.nix
./desktop.nix
inputs.disko.nixosModules.disko
./disko.nix
./hardware-configuration.nix
];
networking.hostName = "enzo";
lanDiscovery.interface = "wlp1s0";
# Set this to the NixOS release the laptop is first installed from, then
# leave it. (See the comment in machines/kusanagi/default.nix.)
system.stateVersion = "26.05";
# --- User account (hwebs) ---
# (Desktop groups audio/input come from ./desktop.nix.)
users.users.hwebs = {
isNormalUser = true;
description = "Henry J. Webster";
# (ikai — the sandbox group — is added by profiles/sandbox.nix.)
extraGroups = [
"networkmanager"
"wheel"
];
packages = with pkgs; [
git
tmux
neovim
# TODO figure out
#ripgrep
wl-clipboard
bc
psmisc
usbutils
stow
claude-code
];
};
# --- Sandbox account (yokai) ---
# The yokai user, ikai group, /srv/git drop dir, and the sudo de-escalation
# rule all live in profiles/sandbox.nix (imported above); that file also
# documents the local-clones workflow. Only the owner name is per-machine:
sandbox.owner = "hwebs";
nix.settings.trusted-users = [
"root"
"hwebs"
];
# Wifi is managed from the CLI (nmcli/nmtui); trim the rest.
networking.modemmanager.enable = false; # no cellular modem
# NOTE: iwd backend was tried but caused interface rename (wlp8s0 -> wlan0),
# stale-profile and secret-passing breakage. Back on the default wpa_supplicant.
# networking.networkmanager.wifi.backend = "iwd"; # auto-enables iwd, drops wpa_supplicant
# --- Disk encryption / hibernation / swap ---
# systemd in initrd is required for TPM2 unlock and clean hibernate resume.
boot.initrd.systemd.enable = true;
# TPM2 auto-unlock. Enroll the key WITH A PIN post-install:
# sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 \
# --tpm2-with-pin=yes /dev/nvme0n1p2
# The original LUKS passphrase stays as a fallback keyslot. disko already
# declares boot.initrd.luks.devices."crypted".device.
boot.initrd.luks.devices."crypted".crypttabExtraOpts = [ "tpm2-device=auto" ];
# zram for everyday paging; the encrypted LVM swap from disko.nix is the
# hibernation target (boot.resumeDevice comes from disko's resumeDevice=true).
zramSwap.enable = true;
# Suspend-to-RAM on lid close, auto-hibernate after a delay so a dying battery
# doesn't lose the session. Everyday resume needs only the login password; the
# LUKS PIN appears only on cold boot / hibernate resume.
services.logind.settings.Login.HandleLidSwitch = "suspend-then-hibernate";
systemd.sleep.settings.Sleep.HibernateDelaySec = "60min";
# Idle trigger. Bare niri has no power daemon watching for inactivity, so with
# the lid open the box never sleeps on its own. swayidle (a Wayland idle
# client) fires the same suspend-then-hibernate after 15 min of no input. niri
# binds it to graphical-session.target and exports WAYLAND_DISPLAY to the user
# manager, so this Just Works in the session. `-w` waits for the resume to
# finish before re-arming the timer.
systemd.user.services.swayidle = {
description = "Suspend-then-hibernate after idle";
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
after = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.swayidle}/bin/swayidle -w timeout 900 'systemctl suspend-then-hibernate'";
Restart = "on-failure";
};
};
# btrfs + SSD upkeep.
services.btrfs.autoScrub.enable = true;
services.fstrim.enable = true;
# --- Laptop power management ---
# power-profiles-daemon integrates with GNOME's power settings. If you prefer
# finer-grained control, disable this and enable services.tlp instead.
services.power-profiles-daemon.enable = true;
powerManagement.enable = true;
# Backlight control from the CLI / keybinds (programs.light was removed from
# nixpkgs; acpilight provides the udev rules and brightnessctl the CLI).
hardware.acpilight.enable = true;
environment.systemPackages = [ pkgs.brightnessctl ];
# --- GPU (AMD integrated) ---
# Load amdgpu in the initrd (early KMS) so the native mode is set before the
# console font is applied. Otherwise amdgpu loads late, resets the fbcon to
# the kernel's 8x16 font, and the greeter shows the wrong (tiny) font while
# the Terminus font only survives in the pre-driver LUKS prompt.
# (Merges with the dm-snapshot entry in hardware-configuration.nix. If the
# driver check shows `radeon` instead of `amdgpu`, swap the name.)
boot.initrd.kernelModules = [ "amdgpu" ];
}
|