nixos: gen 113 @ nix-pad — 2026-07-22 23:02
26.05.20260717.293d6ab (Yarara)
This commit is contained in:
@@ -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 8000–8999. 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.
|
||||
@@ -3,6 +3,7 @@
|
||||
{
|
||||
imports = [
|
||||
./dunst.nix
|
||||
./gnome.nix
|
||||
./i3.nix
|
||||
./polybar.nix
|
||||
./rofi.nix
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
config = null;
|
||||
extraConfig = (builtins.readFile ./i3/config) + ''
|
||||
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
@@ -13,24 +13,24 @@
|
||||
# This file exists solely to prevent the zsh-newuser-install prompt.
|
||||
'';
|
||||
|
||||
home.sessionVariables = {
|
||||
WINIT_X11_SCALE_FACTOR = "1.0";
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
aider-chat
|
||||
animdl
|
||||
asciinema
|
||||
claude-code
|
||||
discord
|
||||
ffmpeg
|
||||
freetube
|
||||
gemini-cli
|
||||
intelli-shell
|
||||
jrnl
|
||||
keepass
|
||||
libreoffice
|
||||
mc
|
||||
scrot
|
||||
spotify
|
||||
vlc
|
||||
yt-dlp
|
||||
|
||||
(pkgs.writeShellScriptBin "find-open-port" ''
|
||||
if [ -z "$1" ]; then
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
family = "Hack Nerd Font";
|
||||
style = "Mono";
|
||||
};
|
||||
size = 8.0;
|
||||
size = 14.0;
|
||||
};
|
||||
|
||||
colors = {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
[ (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.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
@@ -25,12 +25,46 @@
|
||||
};
|
||||
|
||||
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";
|
||||
hardware = {
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./audio.nix
|
||||
./boot.nix
|
||||
./env.nix
|
||||
./locale.nix
|
||||
|
||||
+5
-1
@@ -8,6 +8,10 @@
|
||||
nerd-fonts.hack
|
||||
];
|
||||
|
||||
environment.sessionVariables = {
|
||||
NIXOS_OZONE_WL = "1";
|
||||
};
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
};
|
||||
@@ -26,10 +30,10 @@
|
||||
|
||||
shellAliases = {
|
||||
enix = "nvim $HOME/.dotfiles/flake.nix";
|
||||
unix = "sudo nixos-rebuild switch --flake $HOME/.dotfiles#thinkpad";
|
||||
ehome = "nvim $HOME/.dotfiles/home/jashton.nix";
|
||||
l = "ls -la";
|
||||
ports = "cat $HOME/.dotfiles/ports.registry";
|
||||
accentum = "bluetoothctl connect 80:C3:BA:50:43:DF";
|
||||
};
|
||||
|
||||
ohMyZsh = {
|
||||
|
||||
@@ -13,7 +13,16 @@
|
||||
firefox
|
||||
git
|
||||
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-network-displays
|
||||
google-chrome
|
||||
libnotify
|
||||
mypy
|
||||
@@ -23,13 +32,54 @@
|
||||
picom
|
||||
polkit_gnome
|
||||
pulseaudioFull
|
||||
rnote
|
||||
tldr
|
||||
tmux
|
||||
unrar
|
||||
unzip
|
||||
v4l-utils
|
||||
vim
|
||||
wget
|
||||
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;
|
||||
|
||||
@@ -10,5 +10,11 @@
|
||||
security = {
|
||||
polkit.enable = true;
|
||||
rtkit.enable = true;
|
||||
|
||||
tpm2 = {
|
||||
enable = true;
|
||||
pkcs11.enable = true;
|
||||
tctiEnvironment.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
isNormalUser = true;
|
||||
description = "Josh Ashton";
|
||||
group = "jashton";
|
||||
extraGroups = [ "networkmanager" "wheel" ];
|
||||
extraGroups = [ "networkmanager" "wheel" "tss" "video" ];
|
||||
|
||||
shell = pkgs.zsh;
|
||||
};
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
|
||||
{
|
||||
services = {
|
||||
displayManager = {
|
||||
ly.enable = true;
|
||||
displayManager.gdm.enable = true;
|
||||
desktopManager.gnome.enable = true;
|
||||
gnome = {
|
||||
core-apps.enable = true;
|
||||
core-developer-tools.enable = true;
|
||||
games.enable = true;
|
||||
};
|
||||
|
||||
xserver = {
|
||||
@@ -27,13 +31,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
picom = {
|
||||
enable = true;
|
||||
backend = "glx";
|
||||
vSync = true;
|
||||
};
|
||||
|
||||
|
||||
libinput = {
|
||||
enable = true;
|
||||
};
|
||||
@@ -46,13 +43,5 @@
|
||||
gvfs.enable = true;
|
||||
gnome.gnome-keyring.enable = true;
|
||||
blueman.enable = true;
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa = {
|
||||
enable = true;
|
||||
support32Bit = true;
|
||||
};
|
||||
pulse.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user