diff --git a/.claude-context.md b/.claude-context.md
new file mode 100644
index 0000000..08c48fe
--- /dev/null
+++ b/.claude-context.md
@@ -0,0 +1,44 @@
+# Claude Session Context
+
+## Current Status
+- T480 is booted into an **old NixOS generation** due to a kernel panic after the last rebuild
+- A rebuild is in progress (or needs to be re-run with `nixos-rebuild switch`)
+
+## Boot Panic Fix
+- **Cause:** `linuxPackages_latest` pulled a bad kernel after nixpkgs was bumped in commit `b3eeccf`
+- **Fix:** Already applied — `hosts/t480/configuration.nix` now uses `pkgs.linuxPackages_6_6`
+- **Cache key** was also wrong and is now fixed in `configuration.nix`
+
+## Drive Encryption Plan
+Goal: encrypt T480 root partition requiring **YubiKey + passphrase** (LUKS2 + FIDO2).
+
+- Drive is currently **not encrypted**
+- Home directory has been **backed up to external drive** via rsync
+- NixOS config is in git — no reinstall needed, doing **in-place encryption**
+
+### Steps
+1. Flash Kali ISO to USB (`dd if=kali.iso of=/dev/sdX bs=4M status=progress oflag=sync`)
+2. Boot Kali live USB
+3. Encrypt root partition in-place:
+ ```bash
+ sudo cryptsetup reencrypt --encrypt --reduce-device-size 32M /dev/nvme0n1p2
+ # verify partition name first with: lsblk
+ ```
+4. Enroll YubiKey as FIDO2 token:
+ ```bash
+ sudo systemd-cryptenroll --fido2-device=auto --fido2-with-client-pin=yes /dev/nvme0n1p2
+ ```
+5. Chroot into NixOS and update config + bootloader
+6. Add to `hosts/t480/configuration.nix`:
+ ```nix
+ boot.initrd.luks.devices."cryptroot" = {
+ device = "/dev/nvme0n1p2";
+ crypttabExtraOpts = [ "fido2-device=auto" ];
+ };
+ ```
+7. Rebuild and reboot
+
+## YubiKey PAM Setup
+- `modules/nixos/yubikey-pam.nix` configures PAM u2f with `control = "required"`
+- Requires **both** YubiKey touch and password for sudo/login
+- Auth file at `/etc/u2f-mappings` (already enrolled and correct)
diff --git a/.claw.json b/.claw.json
new file mode 100644
index 0000000..e0e4c18
--- /dev/null
+++ b/.claw.json
@@ -0,0 +1,5 @@
+{
+ "permissions": {
+ "defaultMode": "dontAsk"
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..387cc9f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+# Claw Code local artifacts
+.claw/settings.local.json
+.claw/sessions/
+.clawhip/
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..3da951b
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,12 @@
+# CLAUDE.md
+
+This file provides shared guidance to both Claude Code and Claw Code when working with this repository.
+
+## Detected stack
+- No specific language markers were detected yet; document the primary language and verification commands once the project structure settles.
+- Frameworks: none detected from the supported starter markers.
+
+## Working agreement
+- Prefer small, reviewable changes and keep generated bootstrap files aligned with actual repo workflows.
+- Keep shared defaults in `.claw.json`; reserve `.claw/settings.local.json` for machine-local overrides.
+- Do not overwrite existing `CLAUDE.md` content automatically; update it intentionally when repo workflows change.
diff --git a/flake.lock b/flake.lock
index 98bfadf..af3efa2 100644
--- a/flake.lock
+++ b/flake.lock
@@ -6,11 +6,11 @@
"nixpkgs": "nixpkgs"
},
"locked": {
- "lastModified": 1775271377,
- "narHash": "sha256-0ru4G0uQeokPTlJGuRHf3ApBZMeuIRdUyp0SYi//RWM=",
+ "lastModified": 1777436347,
+ "narHash": "sha256-RD/HyNMkmeN4zqENph5Xzks/fz/ZwdUyL1x8rr5tQyA=",
"owner": "sadjow",
"repo": "claude-code-nix",
- "rev": "214fdf6592f40a8bb472e80283c029d01fb6653d",
+ "rev": "bf3e43090b15d1e335f08e21c80678d6457458e8",
"type": "github"
},
"original": {
@@ -20,6 +20,21 @@
}
},
"crane": {
+ "locked": {
+ "lastModified": 1776635034,
+ "narHash": "sha256-OEOJrT3ZfwbChzODfIH4GzlNTtOFuZFWPtW7jIeR8xU=",
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "dc7496d8ea6e526b1254b55d09b966e94673750f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ipetkov",
+ "repo": "crane",
+ "type": "github"
+ }
+ },
+ "crane_2": {
"locked": {
"lastModified": 1775236976,
"narHash": "sha256-gCgX+AXN7K1gAIEqcLcZHxmC+QoZcwn9m6Z9r2Az+N8=",
@@ -142,6 +157,24 @@
"type": "github"
}
},
+ "flake-utils_7": {
+ "inputs": {
+ "systems": "systems_7"
+ },
+ "locked": {
+ "lastModified": 1731533236,
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
"gtkapps": {
"inputs": {
"flake-utils": "flake-utils_2",
@@ -221,13 +254,34 @@
"type": "github"
}
},
+ "hyprmwh": {
+ "inputs": {
+ "crane": "crane",
+ "flake-utils": "flake-utils_4",
+ "nixpkgs": "nixpkgs_4",
+ "rust-overlay": "rust-overlay"
+ },
+ "locked": {
+ "lastModified": 1776890943,
+ "narHash": "sha256-KVvXWMABYfML0sttIwG41FRNuZUxhl+bqaAiulXzA9A=",
+ "owner": "JackMechem",
+ "repo": "hyprmwh",
+ "rev": "b7bbe057e9f701ae4b07e4f01eac724f398e43be",
+ "type": "github"
+ },
+ "original": {
+ "owner": "JackMechem",
+ "repo": "hyprmwh",
+ "type": "github"
+ }
+ },
"nixpkgs": {
"locked": {
- "lastModified": 1775126147,
- "narHash": "sha256-J0dZU4atgcfo4QvM9D92uQ0Oe1eLTxBVXjJzdEMQpD0=",
+ "lastModified": 1777270315,
+ "narHash": "sha256-yKB4G6cKsQsWN7M6rZGk6gkJPDNPIzT05y4qzRyCDlI=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "8d8c1fa5b412c223ffa47410867813290cdedfef",
+ "rev": "6368eda62c9775c38ef7f714b2555a741c20c72d",
"type": "github"
},
"original": {
@@ -270,6 +324,22 @@
}
},
"nixpkgs_4": {
+ "locked": {
+ "lastModified": 1776548001,
+ "narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_5": {
"locked": {
"lastModified": 1775036866,
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
@@ -285,7 +355,7 @@
"type": "github"
}
},
- "nixpkgs_5": {
+ "nixpkgs_6": {
"locked": {
"lastModified": 1774709303,
"narHash": "sha256-D3Q07BbIA2KnTcSXIqqu9P586uWxN74zNoCH3h2ESHg=",
@@ -301,7 +371,7 @@
"type": "github"
}
},
- "nixpkgs_6": {
+ "nixpkgs_7": {
"locked": {
"lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
@@ -323,7 +393,8 @@
"gtkapps": "gtkapps",
"gtkbar": "gtkbar",
"home-manager": "home-manager",
- "nixpkgs": "nixpkgs_4",
+ "hyprmwh": "hyprmwh",
+ "nixpkgs": "nixpkgs_5",
"rust-app-menu": "rust-app-menu",
"server-dash": "server-dash",
"server-dash-api": "server-dash-api",
@@ -332,12 +403,12 @@
},
"rust-app-menu": {
"inputs": {
- "crane": "crane",
- "flake-utils": "flake-utils_4",
+ "crane": "crane_2",
+ "flake-utils": "flake-utils_5",
"nixpkgs": [
"nixpkgs"
],
- "rust-overlay": "rust-overlay"
+ "rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1775688550,
@@ -354,6 +425,27 @@
}
},
"rust-overlay": {
+ "inputs": {
+ "nixpkgs": [
+ "hyprmwh",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1776741231,
+ "narHash": "sha256-k9G98qzn+7npROUaks8VqCFm7cFtEG8ulQLBBo5lItg=",
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "02061303f7c4c964f7b4584dabd9e985b4cd442b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "type": "github"
+ }
+ },
+ "rust-overlay_2": {
"inputs": {
"nixpkgs": [
"rust-app-menu",
@@ -374,7 +466,7 @@
"type": "github"
}
},
- "rust-overlay_2": {
+ "rust-overlay_3": {
"inputs": {
"nixpkgs": [
"server-dash-api",
@@ -397,8 +489,8 @@
},
"server-dash": {
"inputs": {
- "flake-utils": "flake-utils_5",
- "nixpkgs": "nixpkgs_5"
+ "flake-utils": "flake-utils_6",
+ "nixpkgs": "nixpkgs_6"
},
"locked": {
"lastModified": 1774932258,
@@ -416,9 +508,9 @@
},
"server-dash-api": {
"inputs": {
- "flake-utils": "flake-utils_6",
- "nixpkgs": "nixpkgs_6",
- "rust-overlay": "rust-overlay_2"
+ "flake-utils": "flake-utils_7",
+ "nixpkgs": "nixpkgs_7",
+ "rust-overlay": "rust-overlay_3"
},
"locked": {
"lastModified": 1775019268,
@@ -524,6 +616,21 @@
"type": "github"
}
},
+ "systems_7": {
+ "locked": {
+ "lastModified": 1681028828,
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+ "owner": "nix-systems",
+ "repo": "default",
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-systems",
+ "repo": "default",
+ "type": "github"
+ }
+ },
"zen-browser": {
"inputs": {
"home-manager": "home-manager_2",
diff --git a/flake.nix b/flake.nix
index ce817ce..16b34af 100755
--- a/flake.nix
+++ b/flake.nix
@@ -5,6 +5,7 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
gtkapps.url = "github:JackMechem/gtkapps";
gtkbar.url = "github:JackMechem/gtkbar";
+ hyprmwh.url = "github:JackMechem/hyprmwh";
# midirun.url = "path:/home/jack/Projects/midirun";
zen-browser = {
diff --git a/hosts/dellserv/configuration.nix b/hosts/dellserv/configuration.nix
index b7d20cc..f28f549 100644
--- a/hosts/dellserv/configuration.nix
+++ b/hosts/dellserv/configuration.nix
@@ -17,6 +17,7 @@
inputs.home-manager.nixosModules.default
../../modules/nixos/user-jack.nix
../../modules/nixos/syncthingServer.nix
+ ../../modules/nixos/yubikey-auth.nix
];
# Use the systemd-boot EFI boot loader.
@@ -25,6 +26,9 @@
networking.hostName = "dell-xps-nixos-serv"; # Define your hostname.
networking.networkmanager.enable = true;
+ networking.hosts = {
+ "127.0.0.1" = [ "gitssh.jackmechem.dev" ];
+ };
networking.firewall.allowedTCPPorts = [
80
3000
@@ -32,7 +36,9 @@
8080
443
22
+ 53
];
+ networking.firewall.allowedUDPPorts = [ 53 ];
nix.settings.experimental-features = [
"nix-command"
@@ -52,14 +58,13 @@
services.openssh.enable = true;
services.openssh.settings = {
- PasswordAuthentication = true;
- KbdInteractiveAuthentication = true;
- ChallengeResponseAuthentication = true;
+ PasswordAuthentication = false;
+ KbdInteractiveAuthentication = false;
};
-
- # 2FA
- security.pam.services.login.googleAuthenticator.enable = true;
- security.pam.services.sshd.googleAuthenticator.enable = true;
+ services.openssh.extraConfig = ''
+ Match User forgejo
+ PubkeyAcceptedAlgorithms +ssh-ed25519
+ '';
## services.nginx = {
## enable = true;
@@ -111,6 +116,16 @@
}
'';
};
+ virtualHosts."git.jackmechem.dev" = {
+ extraConfig = ''
+ reverse_proxy localhost:3002
+ '';
+ };
+ virtualHosts."adguard.jackmechem.dev" = {
+ extraConfig = ''
+ reverse_proxy localhost:3003
+ '';
+ };
};
services.server-dash = {
@@ -122,6 +137,38 @@
useNixBuild = false;
};
+ services.resolved.settings.Resolve.DNSStubListener = "no";
+
+ services.adguardhome = {
+ enable = true;
+ mutableSettings = false;
+ port = 3003;
+ settings = {
+ http.address = lib.mkForce "127.0.0.1:3003";
+ dns = {
+ bind_hosts = [ "0.0.0.0" ];
+ port = 53;
+ bootstrap_dns = [
+ "9.9.9.10"
+ "149.112.112.10"
+ ];
+ };
+ };
+ };
+
+ services.forgejo = {
+ enable = true;
+ settings = {
+ server = {
+ DOMAIN = "git.jackmechem.dev";
+ HTTP_PORT = 3002;
+ ROOT_URL = "https://git.jackmechem.dev";
+ SSH_DOMAIN = "gitssh.jackmechem.dev";
+ SSH_PORT = 22;
+ };
+ };
+ };
+
# Make sure jack is in the shadow group
users.users.jack.extraGroups = [ "shadow" ];
@@ -138,7 +185,7 @@
unzip
python3
nodejs
- google-authenticator
+ inputs.claude-code.packages.${pkgs.system}.claude-code
];
virtualisation.docker.enable = true;
diff --git a/hosts/desktop/configuration.nix b/hosts/desktop/configuration.nix
index 77d4ec5..08cf8f6 100644
--- a/hosts/desktop/configuration.nix
+++ b/hosts/desktop/configuration.nix
@@ -28,6 +28,7 @@
networking.hostName = "jackdesk";
networking.networkmanager.enable = true;
+ networking.nameservers = [ "192.168.1.164" ];
networking.firewall.allowedTCPPorts = [ 2200 3000 ];
@@ -42,6 +43,8 @@
programs.zsh.enable = true;
+ programs.nix-ld.enable = true;
+
programs.thunar.enable = true;
programs.dconf.enable = true;
@@ -82,11 +85,12 @@
services.openssh = {
enable = true;
- listenAddresses = [{ addr = "192.168.1.67"; port = 2200; }];
};
services.gvfs.enable = true;
+ services.input-remapper.enable = true;
+
system.stateVersion = "25.11";
}
diff --git a/hosts/desktop/home.nix b/hosts/desktop/home.nix
index 13ca4e7..6aa61ff 100644
--- a/hosts/desktop/home.nix
+++ b/hosts/desktop/home.nix
@@ -117,6 +117,23 @@
home.sessionVariables = {
EDITOR = "nvim";
+ # claw-code: route to local Ollama instead of Anthropic/OpenAI
+ OPENAI_BASE_URL = "http://127.0.0.1:11434/v1";
+ OPENAI_API_KEY = "ollama";
+ };
+
+ systemd.user.services.ydotoold = {
+ Unit = {
+ Description = "ydotool daemon";
+ After = [ "default.target" ];
+ };
+ Service = {
+ ExecStart = "${pkgs.ydotool}/bin/ydotoold";
+ Restart = "always";
+ };
+ Install = {
+ WantedBy = [ "default.target" ];
+ };
};
}
diff --git a/hosts/t480/configuration.nix b/hosts/t480/configuration.nix
index ebd8ad6..c98393e 100644
--- a/hosts/t480/configuration.nix
+++ b/hosts/t480/configuration.nix
@@ -17,15 +17,17 @@
../../modules/nixos/user-jack.nix
../../modules/nixos/sound.nix
../../modules/nixos/syncthing.nix
+ ../../modules/nixos/yubikey-pam.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
- boot.kernelPackages = pkgs.linuxPackages_latest;
+ boot.kernelPackages = pkgs.linuxPackages_6_6;
networking.hostName = "t480";
networking.networkmanager.enable = true;
+ networking.nameservers = [ "192.168.1.164" ];
nix.settings = {
# Use all cores for building
@@ -39,7 +41,7 @@
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
- "nix-community.cachix.org-1:mB9FSh9qf2dde0enLeymSlflN93qlwkTnNQsGbLFPzU="
+ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
# Avoid redundant downloads
@@ -97,6 +99,8 @@
};
};
+ services.logind.settings.Login.HandleLidSwitch = "suspend";
+
services.libinput.enable = true;
services.openssh.enable = true;
diff --git a/modules/home-manager/homepackages.nix b/modules/home-manager/homepackages.nix
index 14f07c1..f0d3149 100644
--- a/modules/home-manager/homepackages.nix
+++ b/modules/home-manager/homepackages.nix
@@ -1,4 +1,29 @@
-{ inputs, pkgs, ... }:
+{ inputs, pkgs, lib, ... }:
+
+let
+ claw-code = pkgs.rustPlatform.buildRustPackage {
+ pname = "claw-code";
+ version = "unstable-2026";
+
+ src = pkgs.fetchFromGitHub {
+ owner = "ultraworkers";
+ repo = "claw-code";
+ rev = "main";
+ hash = "sha256-jGJgKOMn2Un6ZbEPh+7RWB1isvFLD86HWMLKTIBMUNs=";
+ };
+
+ sourceRoot = "source/rust";
+
+ cargoHash = "sha256-bZKghBTbKrhm2Jiyg2su1c9Jlx2HVrMQjOTK6cgEc00=";
+
+ doCheck = false;
+
+ meta = {
+ description = "Open-source Rust implementation of the claw CLI agent harness";
+ homepage = "https://github.com/ultraworkers/claw-code";
+ };
+ };
+in
{
home.packages = with pkgs; [
### Desktop Stuff
@@ -23,6 +48,9 @@
### Note Taking
obsidian
+ ### Input Remapping
+ ydotool
+
### Random Libraries and Dependencies
gtk3
glib
@@ -37,5 +65,19 @@
jdk
gnumake
inputs.claude-code.packages.${pkgs.system}.claude-code
+ claw-code
+ opencode
+ postman
+
+ ### My Stuff
+ inputs.hyprmwh.packages.${pkgs.system}.default
+
+ ### Browsers
+ epiphany
+ chromium
+
+ ### Editors
+ zed-editor
+ # jetbrains.idea # Fuck InteliJ
];
}
diff --git a/modules/home-manager/hyprland-desktop.nix b/modules/home-manager/hyprland-desktop.nix
index 38a278d..44f0a20 100644
--- a/modules/home-manager/hyprland-desktop.nix
+++ b/modules/home-manager/hyprland-desktop.nix
@@ -38,15 +38,19 @@
exec-once = [
"waypaper --restore"
"gtkbar"
- "rust-app-menu -d"
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP"
"solaar -w hide"
+ "ydotoold"
+ "${pkgs.kdePackages.polkit-kde-agent-1}/libexec/polkit-kde-authentication-agent-1"
];
# --- Variables ---
"$terminal" = "ghostty";
"$fileManager" = "thunar";
- "$menu" = "rust-app-menu -ds";
+ "$appMenu" = "hyprmwh --apps";
+ "$windowMoveMenu" = "hyprmwh --windows";
+ "$browser" = "zen-twilight";
+ #"$menu" = "rust-app-menu -ds";
env = [
"XCURSOR_SIZE,24"
@@ -84,7 +88,9 @@
layerrule = [
"blur on, match:namespace Launcher"
- "ignore_alpha 0.3, match:namespace Launcher"
+ "ignore_alpha 0.1, match:namespace Launcher"
+ "blur on, match:namespace hyprmwh"
+ "ignore_alpha 0.1, match:namespace hyprmwh"
];
# --- Decoration ---
@@ -127,19 +133,19 @@
force_default_wallpaper = 0;
};
- # --- Keybinds ---
+ # --- Keybinds ---
bind = [
# System/Rice
- "${mainMod}, grave, exec, rice-settings"
"${mainMod}, RETURN, exec, $terminal"
"${mainMod} SHIFT, RETURN, exec, [float] $terminal"
"${mainMod}, Q, killactive"
"${mainMod} SHIFT, M, exit"
"${mainMod}, E, exec, $fileManager"
"${mainMod} SHIFT, E, exec, [float] $fileManager"
- "${mainMod}, W, exec, zen-browser"
+ "${mainMod}, W, exec, $browser"
"${mainMod}, TAB, togglefloating"
- "${mainMod}, SPACE, exec, $menu"
+ "${mainMod}, SPACE, exec, $appMenu"
+ "${mainMod}, grave, exec, $windowMoveMenu"
"${mainMod}, P, pseudo"
"${mainMod}, V, togglesplit"
"${mainMod}, M, fullscreen, 1"
@@ -208,6 +214,9 @@
# Custom scripts
"${mainMod}, b, exec, bash -c 'pgrep gtkbar &>/dev/null && killall gtkbar || gtkbar &'"
"${mainMod}, minus, exec, ~/.config/hypr/togglemonitor.sh ${monitor3}"
+
+ # Mouse: back thumb button -> middle click (mchose mouse)
+ ", mouse:275, exec, ydotool click 0xC2"
];
bindle = [
diff --git a/modules/home-manager/hyprland.nix b/modules/home-manager/hyprland.nix
index d134baf..dc500fb 100644
--- a/modules/home-manager/hyprland.nix
+++ b/modules/home-manager/hyprland.nix
@@ -1,5 +1,127 @@
{ pkgs, ... }:
{
+ programs.hyprlock = {
+ enable = true;
+ settings = {
+ general = {
+ disable_loading_bar = true;
+ grace = 0;
+ hide_cursor = true;
+ };
+ background = [{
+ monitor = "";
+ path = "screenshot";
+ blur_passes = 3;
+ blur_size = 8;
+ brightness = 0.5;
+ }];
+ label = [
+ {
+ monitor = "";
+ text = "Property of Jack Mechem — 702.201.4608";
+ color = "rgba(c5c9c5ff)";
+ font_size = 22;
+ font_family = "JetBrainsMono Nerd Font Bold";
+ position = "0, 200";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = "";
+ text = "If found — please contact me and return it ASAP.";
+ color = "rgba(c5c9c5ff)";
+ font_size = 13;
+ font_family = "JetBrainsMono Nerd Font";
+ position = "0, 166";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = "";
+ text = "If stolen — fuck you.";
+ color = "rgba(c4746eff)";
+ font_size = 16;
+ font_family = "JetBrainsMono Nerd Font Bold";
+ position = "0, 138";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = "";
+ text = "The drive is encrypted and the BIOS is locked. You'll get maybe $150 for it.";
+ color = "rgba(c5c9c580)";
+ font_size = 11;
+ font_family = "JetBrainsMono Nerd Font";
+ position = "0, 112";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = "";
+ text = "Contact me now and I won't involve the police. I also have a GPS tracker installed.";
+ color = "rgba(c5c9c580)";
+ font_size = 11;
+ font_family = "JetBrainsMono Nerd Font";
+ position = "0, 94";
+ halign = "center";
+ valign = "center";
+ }
+ {
+ monitor = "";
+ text = "If you're in my class messing with this — fuck you too, don't touch my shit.";
+ color = "rgba(c5c9c5ff)";
+ font_size = 11;
+ font_family = "JetBrainsMono Nerd Font";
+ position = "0, 76";
+ halign = "center";
+ valign = "center";
+ }
+ ];
+ input-field = [{
+ monitor = "";
+ size = "250, 50";
+ outline_thickness = 2;
+ dots_size = 0.33;
+ dots_spacing = 0.15;
+ dots_center = true;
+ outer_color = "rgba(e4687690)";
+ inner_color = "rgba(181616cc)";
+ font_color = "rgba(c5c9c5ff)";
+ fade_on_empty = true;
+ placeholder_text = "Password...";
+ rounding = 12;
+ check_color = "rgba(8a9a7bff)";
+ fail_color = "rgba(c4746eff)";
+ fail_text = "$FAIL ($ATTEMPTS)";
+ position = "0, 0";
+ halign = "center";
+ valign = "center";
+ }];
+ };
+ };
+
+ services.hypridle = {
+ enable = true;
+ settings = {
+ general = {
+ before_sleep_cmd = "loginctl lock-session";
+ after_sleep_cmd = "hyprctl dispatch dpms on";
+ lock_cmd = "pidof hyprlock || hyprlock";
+ };
+ listener = [
+ {
+ timeout = 300;
+ on-timeout = "loginctl lock-session";
+ }
+ {
+ timeout = 600;
+ on-timeout = "hyprctl dispatch dpms off";
+ on-resume = "hyprctl dispatch dpms on";
+ }
+ ];
+ };
+ };
+
wayland.windowManager.hyprland = {
enable = true;
@@ -130,6 +252,7 @@
# --- Keybinds ---
bind = [
# System/Rice
+ "${mainMod} SHIFT, D, exec, loginctl lock-session"
"${mainMod}, grave, exec, rice-settings"
"${mainMod}, RETURN, exec, $terminal"
"${mainMod} SHIFT, RETURN, exec, [float] $terminal"
diff --git a/modules/nixos/ollama.nix b/modules/nixos/ollama.nix
index 7bd41f8..e53b29b 100644
--- a/modules/nixos/ollama.nix
+++ b/modules/nixos/ollama.nix
@@ -15,8 +15,13 @@
nixpkgs.config.allowUnfree = true;
+ nixpkgs.config.permittedInsecurePackages = [
+ "openclaw-2026.3.12"
+ ];
+
environment.systemPackages = with pkgs; [
ollama
rocmPackages.rocminfo
+ openclaw
];
}
diff --git a/modules/nixos/system-packages.nix b/modules/nixos/system-packages.nix
index c67da9f..d6ef9f2 100644
--- a/modules/nixos/system-packages.nix
+++ b/modules/nixos/system-packages.nix
@@ -2,23 +2,30 @@
{
- programs.firefox.enable = true;
- programs.hyprland.enable = true;
+ programs.firefox.enable = true;
+ programs.hyprland.enable = true;
-
- # List packages installed in system profile.
- environment.systemPackages = with pkgs; [
+ # List packages installed in system profile.
+ environment.systemPackages = with pkgs; [
# neovim
- tree
- vim # Both vim and neovim just in case
- wget
- git
- gcc
- fastfetch
- brightnessctl
- killall
- unzip
- python3
- nodejs
- ];
+ tree
+ vim # Both vim and neovim just in case
+ wget
+ git
+ gcc
+ fastfetch
+ brightnessctl
+ killall
+ unzip
+ python3
+ nodejs
+ input-remapper
+ kdePackages.polkit-kde-agent-1
+ yubikey-manager
+ yubioath-flutter
+ ];
+
+ services.udev.packages = [ pkgs.yubikey-personalization ];
+ services.pcscd.enable = true;
+ programs.ssh.startAgent = true;
}
diff --git a/modules/nixos/user-jack.nix b/modules/nixos/user-jack.nix
index 2885bf2..7742e6e 100644
--- a/modules/nixos/user-jack.nix
+++ b/modules/nixos/user-jack.nix
@@ -11,6 +11,7 @@
"docker"
"video"
"render"
+ "input"
]; # Enable ‘sudo’ for the user.
group = "jack";
packages = with pkgs; [
@@ -21,4 +22,8 @@
};
users.groups.jack = {};
+
+ services.udev.extraRules = ''
+ KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"
+ '';
}
diff --git a/modules/nixos/yubikey-auth.nix b/modules/nixos/yubikey-auth.nix
new file mode 100644
index 0000000..e104c76
--- /dev/null
+++ b/modules/nixos/yubikey-auth.nix
@@ -0,0 +1,15 @@
+{ config, lib, pkgs, ... }:
+
+{
+ environment.systemPackages = with pkgs; [
+ yubikey-manager
+ libfido2
+ ];
+
+ # Only FIDO2-backed SSH keys (ed25519-sk / ecdsa-sk) are accepted.
+ # Every SSH login to every account requires a YubiKey touch.
+ # Add your sk public key to ~/.ssh/authorized_keys before deploying:
+ # ssh-keygen -t ed25519-sk
+ # ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub jack@dellserv
+ services.openssh.settings.PubkeyAcceptedAlgorithms = "sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com";
+}
diff --git a/modules/nixos/yubikey-pam.nix b/modules/nixos/yubikey-pam.nix
new file mode 100644
index 0000000..fd2e64f
--- /dev/null
+++ b/modules/nixos/yubikey-pam.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+{
+ environment.systemPackages = with pkgs; [
+ yubikey-manager
+ libfido2
+ ];
+
+ # pam_u2f: requires physical YubiKey touch for sudo and TTY login.
+ # Enroll your key BEFORE rebuilding (run on this machine):
+ # nix shell nixpkgs#pam_u2f -c pamu2fcfg -u jack | sudo tee /etc/u2f-mappings
+ # Touch the key when the LED blinks.
+ # Additional keys: nix shell nixpkgs#pam_u2f -c pamu2fcfg -n -u jack | sudo tee -a /etc/u2f-mappings
+ security.pam.u2f = {
+ enable = true;
+ control = "required";
+ settings = {
+ cue = true;
+ authfile = "/etc/u2f-mappings";
+ };
+ };
+
+ security.pam.services.sudo.u2fAuth = true;
+ security.pam.services.login.u2fAuth = true;
+ security.pam.services.hyprlock.u2fAuth = true;
+}
diff --git a/result b/result
new file mode 120000
index 0000000..6b6c4d8
--- /dev/null
+++ b/result
@@ -0,0 +1 @@
+/nix/store/wh5w5irf66v9kc87nl7zxywjzr1kqp7m-hm_hyprhyprlock.conf
\ No newline at end of file