nixos: gen 113 @ nix-pad — 2026-07-22 23:02

26.05.20260717.293d6ab (Yarara)
This commit is contained in:
2026-07-22 23:02:49 -06:00
parent 38819b3b23
commit 34d199639b
14 changed files with 280 additions and 28 deletions
+59
View File
@@ -0,0 +1,59 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
NixOS dotfiles using Flakes + Home Manager for a single user (`jashton`) across multiple hosts (`thinkpad`, `desktop`, `framework`). Pinned to `nixos-26.05`.
## Common Commands
```bash
# Rebuild and switch the current system (thinkpad)
sudo nixos-rebuild switch --flake ~/.dotfiles#thinkpad
# Check the flake for errors without applying
nix flake check
# Update flake inputs (e.g. nixpkgs, home-manager)
nix flake update
# Open the flake entrypoint in nvim
enix # alias: nvim ~/.dotfiles/flake.nix
# Open the home-manager user config in nvim
ehome # alias: nvim ~/.dotfiles/home/jashton.nix
# List registered ports
ports # alias: cat ~/.dotfiles/ports.registry
```
## Architecture
The repo is structured as a standard Nix Flakes configuration. `flake.nix` defines `nixosConfigurations` for each host and wires in Home Manager as a NixOS module. Each host's Home Manager is pointed at a single shared user config (`home/jashton.nix`).
```
flake.nix # Entrypoint; defines per-host nixosConfigurations
hosts/<host>/default.nix # Host-specific config (imports hardware.nix + system/)
hosts/<host>/hardware.nix # nixos-generate-config output (don't manually edit)
system/ # Shared NixOS system config (all hosts)
default.nix # Aggregates: packages, core, network, security, services, virtualisation
packages.nix # System-level packages + allowUnfree
core/ # Zsh, fonts, nix settings, locale, boot, audio, power
security/ # Users, sudo, polkit, TPM2, systemd hardening
services/ # Display manager (GDM), Xserver, i3 WM, picom, printing, Bluetooth
network/ # Pi-hole config
virtualisation/ # VM/container support
home/jashton.nix # Home Manager user config; shared across all hosts
home/programs/ # Per-program HM config: alacritty, git, nvim
home/desktop/ # Desktop environment: i3, polybar, rofi, dunst, gnome dconf
```
## Key Design Decisions
- **Dual desktop environment**: Both GNOME (GDM display manager) and i3 (window manager via Xserver) are configured and co-exist. GNOME extensions are declared via `dconf.settings` in `home/desktop/gnome.nix`.
- **Shell scripts as Nix packages**: Custom scripts (`find-open-port`, `lock-screen`, `power-menu`, `weather-cache`) are defined inline in `home/jashton.nix` using `pkgs.writeShellScriptBin` so they are on `$PATH` without a separate scripts directory.
- **Port registry**: `ports.registry` is a plain-text file tracking assigned dev ports 80008999. The `find-open-port` script appends to it; don't assign ports manually without checking it first.
- **Zsh configured at system level**: `programs.zsh` (aliases, Oh My Zsh, history) lives in `system/core/env.nix`. The `~/.zshrc` written by Home Manager is intentionally a stub to suppress the zsh-newuser-install prompt.
- **Host hardware files**: `hosts/thinkpad/hardware.nix` is auto-generated by `nixos-generate-config`. Edits here (e.g. Howdy IR camera path `/dev/video66`) are intentional overrides — don't regenerate and overwrite.
- **`stateVersion`**: Both `system.stateVersion` and `home.stateVersion` are set to `"26.05"`. Do not change these.
+1
View File
@@ -3,6 +3,7 @@
{ {
imports = [ imports = [
./dunst.nix ./dunst.nix
./gnome.nix
./i3.nix ./i3.nix
./polybar.nix ./polybar.nix
./rofi.nix ./rofi.nix
+29
View File
@@ -0,0 +1,29 @@
{ config, lib, pkgs, ... }:
{
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
accent-color = "purple";
};
"org/gnome/shell" = {
enabled-extensions = [
pkgs.gnomeExtensions.blur-my-shell.extensionUuid
pkgs.gnomeExtensions.caffeine.extensionUuid
pkgs.gnomeExtensions.clipboard-indicator.extensionUuid
pkgs.gnomeExtensions.dash-to-panel.extensionUuid
pkgs.gnomeExtensions.gjs-osk.extensionUuid
pkgs.gnomeExtensions.gsconnect.extensionUuid
pkgs.gnomeExtensions.just-perfection.extensionUuid
pkgs.gnomeExtensions.removable-drive-menu.extensionUuid
];
};
};
qt = {
enable = true;
platformTheme.name = "gnome";
style.name = "adwaita-dark";
};
}
+1
View File
@@ -6,6 +6,7 @@
config = null; config = null;
extraConfig = (builtins.readFile ./i3/config) + '' extraConfig = (builtins.readFile ./i3/config) + ''
exec --no-startup-id ${pkgs.feh}/bin/feh --bg-fill ${./assets/samuraii.jpg} exec --no-startup-id ${pkgs.feh}/bin/feh --bg-fill ${./assets/samuraii.jpg}
exec --no-startup-id ${pkgs.picom}/bin/picom --backend glx --vsync
''; '';
}; };
} }
+4 -4
View File
@@ -13,24 +13,24 @@
# This file exists solely to prevent the zsh-newuser-install prompt. # This file exists solely to prevent the zsh-newuser-install prompt.
''; '';
home.sessionVariables = {
WINIT_X11_SCALE_FACTOR = "1.0";
};
home.packages = with pkgs; [ home.packages = with pkgs; [
aider-chat aider-chat
animdl animdl
asciinema asciinema
claude-code claude-code
discord discord
ffmpeg
freetube freetube
gemini-cli gemini-cli
intelli-shell intelli-shell
jrnl jrnl
keepass keepass
libreoffice
mc mc
scrot scrot
spotify spotify
vlc
yt-dlp
(pkgs.writeShellScriptBin "find-open-port" '' (pkgs.writeShellScriptBin "find-open-port" ''
if [ -z "$1" ]; then if [ -z "$1" ]; then
+1 -1
View File
@@ -16,7 +16,7 @@
family = "Hack Nerd Font"; family = "Hack Nerd Font";
style = "Mono"; style = "Mono";
}; };
size = 8.0; size = 14.0;
}; };
colors = { colors = {
+38 -4
View File
@@ -8,7 +8,7 @@
[ (modulesPath + "/installer/scan/not-detected.nix") [ (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "usbhid" "sd_mod" ]; boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "usbhid" "sd_mod" "uvcvideo" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
@@ -25,12 +25,46 @@
}; };
swapDevices = swapDevices =
[ { device = "/dev/disk/by-uuid/332e7db3-3f68-4fd7-be2a-0d091ac936ae"; } [ { device = "/dev/disk/by-uuid/332e7db3-3f68-4fd7-be2a-0d091ac936ae"; } ];
];
services.udev.extraRules = ''
SUBSYSTEM=="video4linux", ATTRS{interface}=="Integrated IR Camera", ATTR{index}=="0", SYMLINK+="video-ir"
'';
services.howdy = {
enable = true;
control = "sufficient";
settings = {
video = {
device_path = "/dev/video-ir";
};
};
};
services.linux-enable-ir-emitter.enable = true;
powerManagement.resumeCommands = ''
${pkgs.linux-enable-ir-emitter}/bin/linux-enable-ir-emitter run
'';
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware = { hardware = {
cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
bluetooth.enable = true; sensor.iio.enable = true;
bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
Experimental = true;
KernelExperimental = true;
ControllerMode = "dual";
Enable = "Source,Sink,Media,Socket";
};
};
};
}; };
} }
+78
View File
@@ -0,0 +1,78 @@
{ config, lib, pkgs, ... }:
{
security.rtkit.enable = true;
services.avahi.enable = true;
services.pulseaudio.enable = false;
systemd.user.services.mpris-proxy = {
description = "Mpris proxy";
after = [ "network.target" "sound.target" ];
wantedBy = [ "default.target" ];
};
services.pipewire = {
enable = true;
alsa = {
enable = true;
support32Bit = true;
};
pulse.enable = true;
wireplumber.enable = true;
raopOpenFirewall = true;
# Dynamic, optimized buffer sizes to eliminate data starvation
extraConfig.pipewire = {
"context.properties" = {
"default.clock.rate" = 48000;
"default.clock.quantum" = 1024;
"default.clock.min-quantum" = 512;
"default.clock.max-quantum" = 2048;
};
"10-airplay" = {
"context-modules" = [
{
name = "libpipewire-module-raop-discover";
}
];
};
};
wireplumber.extraConfig = {
"10-bluetooth-policy" = {
"wireplumber.settings" = {
"bluetooth.autoswitch-to-headset" = false;
};
};
# Properly disables node suspension using WirePlumber 0.5+ syntax
"10-disable-suspend" = {
"monitor.bluez.rules" = [
{
matches = [
{
"node.name" = "~bluez_output.*";
}
];
actions = {
update-props = {
"session.suspend-timeout-seconds" = 0;
};
};
}
];
};
# Force High Quality Audio profiles ONLY (Blocks Handsfree Mic Downgrades)
"11-bluetooth-enhancements" = {
"monitor.bluez.properties" = {
"bluez5.roles" = [ "a2dp_sink" "a2dp_source" ];
"bluez5.codecs" = [ "aac" "aptx" "sbc" ];
"bluez5.enable-sbc-xq" = false;
"bluez5.enable-hw-volume" = true;
};
};
};
};
}
+1
View File
@@ -2,6 +2,7 @@
{ {
imports = [ imports = [
./audio.nix
./boot.nix ./boot.nix
./env.nix ./env.nix
./locale.nix ./locale.nix
+5 -1
View File
@@ -8,6 +8,10 @@
nerd-fonts.hack nerd-fonts.hack
]; ];
environment.sessionVariables = {
NIXOS_OZONE_WL = "1";
};
nix.settings = { nix.settings = {
experimental-features = [ "nix-command" "flakes" ]; experimental-features = [ "nix-command" "flakes" ];
}; };
@@ -26,10 +30,10 @@
shellAliases = { shellAliases = {
enix = "nvim $HOME/.dotfiles/flake.nix"; enix = "nvim $HOME/.dotfiles/flake.nix";
unix = "sudo nixos-rebuild switch --flake $HOME/.dotfiles#thinkpad";
ehome = "nvim $HOME/.dotfiles/home/jashton.nix"; ehome = "nvim $HOME/.dotfiles/home/jashton.nix";
l = "ls -la"; l = "ls -la";
ports = "cat $HOME/.dotfiles/ports.registry"; ports = "cat $HOME/.dotfiles/ports.registry";
accentum = "bluetoothctl connect 80:C3:BA:50:43:DF";
}; };
ohMyZsh = { ohMyZsh = {
+50
View File
@@ -13,7 +13,16 @@
firefox firefox
git git
github-cli github-cli
gnomeExtensions.blur-my-shell
gnomeExtensions.caffeine
gnomeExtensions.clipboard-indicator
gnomeExtensions.dash-to-panel
gnomeExtensions.gjs-osk
gnomeExtensions.gsconnect
gnomeExtensions.just-perfection
gnomeExtensions.removable-drive-menu
gnome-keyring gnome-keyring
gnome-network-displays
google-chrome google-chrome
libnotify libnotify
mypy mypy
@@ -23,13 +32,54 @@
picom picom
polkit_gnome polkit_gnome
pulseaudioFull pulseaudioFull
rnote
tldr tldr
tmux tmux
unrar unrar
unzip unzip
v4l-utils
vim vim
wget wget
xclip xclip
xournalpp
(pkgs.writeShellScriptBin "unix" ''
set -u
DOTFILES="$HOME/.dotfiles"
ERRFILE=$(mktemp)
trap "rm -f '$ERRFILE'" EXIT
echo "Building NixOS..."
sudo nixos-rebuild switch --flake "$DOTFILES#thinkpad" 2>&1 | tee "$ERRFILE"
STATUS=''${PIPESTATUS[0]}
if [ "$STATUS" -ne 0 ]; then
PATTERN=$(find "$DOTFILES" -type f -name "*.nix" -printf "%f\n" | sort -u | tr '\n' '|' | sed 's/|$//')
MATCHES=$(grep -E "$PATTERN" "$ERRFILE" | sort -u)
if [ -n "$MATCHES" ]; then
printf '\nErrors in repo files:\n%s\n' "$MATCHES"
fi
exit 1
fi
GEN=$(readlink /nix/var/nix/profiles/system | sed 's/system-\([0-9]*\)-link/\1/')
VER=$(nixos-version)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
cd "$DOTFILES"
if [ -z "$(${pkgs.git}/bin/git status --porcelain)" ]; then
echo "Generation $GEN active no config changes to commit."
exit 0
fi
${pkgs.git}/bin/git add -A
${pkgs.git}/bin/git commit -m "nixos: gen $GEN @ $(hostname) $TIMESTAMP
$VER"
${pkgs.git}/bin/git push
'')
]; ];
programs.firefox.enable = true; programs.firefox.enable = true;
+6
View File
@@ -10,5 +10,11 @@
security = { security = {
polkit.enable = true; polkit.enable = true;
rtkit.enable = true; rtkit.enable = true;
tpm2 = {
enable = true;
pkcs11.enable = true;
tctiEnvironment.enable = true;
};
}; };
} }
+1 -1
View File
@@ -6,7 +6,7 @@
isNormalUser = true; isNormalUser = true;
description = "Josh Ashton"; description = "Josh Ashton";
group = "jashton"; group = "jashton";
extraGroups = [ "networkmanager" "wheel" ]; extraGroups = [ "networkmanager" "wheel" "tss" "video" ];
shell = pkgs.zsh; shell = pkgs.zsh;
}; };
+6 -17
View File
@@ -2,8 +2,12 @@
{ {
services = { services = {
displayManager = { displayManager.gdm.enable = true;
ly.enable = true; desktopManager.gnome.enable = true;
gnome = {
core-apps.enable = true;
core-developer-tools.enable = true;
games.enable = true;
}; };
xserver = { xserver = {
@@ -27,13 +31,6 @@
}; };
}; };
picom = {
enable = true;
backend = "glx";
vSync = true;
};
libinput = { libinput = {
enable = true; enable = true;
}; };
@@ -46,13 +43,5 @@
gvfs.enable = true; gvfs.enable = true;
gnome.gnome-keyring.enable = true; gnome.gnome-keyring.enable = true;
blueman.enable = true; blueman.enable = true;
pipewire = {
enable = true;
alsa = {
enable = true;
support32Bit = true;
};
pulse.enable = true;
};
}; };
} }