Nix-Vibe public snapshot (squashed history)
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
---
|
||||
name: flake-update
|
||||
description: 'Safely update flake inputs: ensure a clean committed/pushed working tree, run nix flake update, then dry-build EVERY host before committing flake.lock. Use when the user asks to update the flake, refresh flake.lock, bump inputs, or upgrade nixpkgs/dependencies.'
|
||||
---
|
||||
|
||||
# Flake Update
|
||||
|
||||
## When to Use
|
||||
- When the user asks to "update the flake", "bump inputs", "refresh flake.lock", or "update nixpkgs"
|
||||
- Before a planned fleet-wide input upgrade
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Clean Working Tree (MANDATORY)
|
||||
|
||||
Never run `nix flake update` with uncommitted changes — mixing unrelated edits with a lockfile bump makes rollback painful.
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
- If there are uncommitted changes: validate and commit them first (follow the **nix-flake-rebuild** skill: stage, `nixpkgs-fmt .`, `nix flake check`, dry-build affected hosts, commit).
|
||||
- Then push everything to the remote:
|
||||
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
|
||||
Only proceed when `git status` is clean and the branch is fully pushed.
|
||||
|
||||
### 2. Update Inputs
|
||||
|
||||
```bash
|
||||
# All inputs
|
||||
nix flake update
|
||||
|
||||
# OR a single input, if the user asked for one
|
||||
nix flake update <input-name>
|
||||
```
|
||||
|
||||
### 3. Flake Check
|
||||
|
||||
```bash
|
||||
nix flake check
|
||||
```
|
||||
|
||||
Fix any evaluation errors before building. Input bumps often surface deprecated/renamed NixOS and Home Manager options — check warnings and refer to release notes for replacements.
|
||||
|
||||
### 4. Dry-Build EVERY Host
|
||||
|
||||
An input update affects the whole fleet — dry-build every host, no exceptions. Generate the host list dynamically from the flake so new hosts are never missed:
|
||||
|
||||
```bash
|
||||
for host in $(nix eval .#nixosConfigurations --apply 'attrs: builtins.concatStringsSep " " (builtins.attrNames attrs)' --raw); do
|
||||
echo "=== $host ==="
|
||||
nixos-rebuild dry-build --flake .#$host || break
|
||||
done
|
||||
```
|
||||
|
||||
If any host fails, do NOT commit. Either fix the breakage or roll back (see below).
|
||||
|
||||
### 5. Commit & Push Lockfile (only if ALL hosts pass)
|
||||
|
||||
```bash
|
||||
git add flake.lock
|
||||
git commit -m "flake: update inputs"
|
||||
git push
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
Because step 1 guaranteed a clean, pushed tree, the previous lockfile is always recoverable:
|
||||
|
||||
```bash
|
||||
git restore --source=HEAD~1 flake.lock
|
||||
```
|
||||
|
||||
Or check out an older known-good lockfile from history.
|
||||
|
||||
## Notes
|
||||
- This skill only **validates** the update. Actually applying it (`nixos-rebuild switch`) is a separate, per-host step.
|
||||
- Review the `git diff flake.lock` before committing if the user wants to know which inputs moved.
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: nix-flake-rebuild
|
||||
description: 'Validate Nix Flake changes end-to-end: stage, check, dry-build, and commit. Use after ANY change to .nix files, flake inputs, or module imports. Use when the user asks to apply, test, validate, rebuild, or commit NixOS config changes.'
|
||||
argument-hint: '[hostname]'
|
||||
---
|
||||
|
||||
# Nix Flake Rebuild Validation
|
||||
|
||||
## When to Use
|
||||
- After ANY modification to `.nix` files, `flake.nix`, or module imports
|
||||
- Before applying configs with `nixos-rebuild switch`
|
||||
- When the user asks to "test", "validate", "rebuild", or "apply" changes
|
||||
- After adding new files, modules, or hosts
|
||||
|
||||
## Critical Pre-Check: Git Staging
|
||||
|
||||
Nix flakes ONLY see Git-tracked files. If you created new files or directories, **you must stage them first**:
|
||||
```bash
|
||||
git add <new-file> <new-directory/>
|
||||
```
|
||||
Failure to do this will cause `nix flake check` to fail with confusing "file not found" errors.
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Sync Documentation (if needed)
|
||||
If software was added/removed or a host role changed, update the software inventory table and host overview in `README.md`.
|
||||
|
||||
### 2. Stage ALL Changes
|
||||
```bash
|
||||
git add -A
|
||||
```
|
||||
This ensures flake evaluation can see every file.
|
||||
|
||||
### 3. Format Code
|
||||
```bash
|
||||
nixpkgs-fmt .
|
||||
```
|
||||
|
||||
### 4. Run Flake Check
|
||||
```bash
|
||||
nix flake check
|
||||
```
|
||||
Fix any errors before proceeding. Common issues:
|
||||
- Missing `git add` on new files
|
||||
- Deprecated NixOS/Home Manager options
|
||||
- Syntax errors in `.nix` files
|
||||
|
||||
### 5. Dry-Build for Affected Hosts
|
||||
```bash
|
||||
nixos-rebuild dry-build --flake .#<hostname>
|
||||
```
|
||||
Run for EACH host affected by the changes. If unsure which hosts are affected, run for all. Generate the host list dynamically from the flake so new hosts are never missed:
|
||||
```bash
|
||||
for host in $(nix eval .#nixosConfigurations --apply 'attrs: builtins.concatStringsSep " " (builtins.attrNames attrs)' --raw); do
|
||||
echo "=== $host ==="
|
||||
nixos-rebuild dry-build --flake .#$host || break
|
||||
done
|
||||
```
|
||||
|
||||
### 6. Commit (only if ALL checks pass)
|
||||
```bash
|
||||
git commit -m "descriptive message"
|
||||
```
|
||||
Do NOT commit if `nix flake check` or any dry-build failed.
|
||||
|
||||
## Host Reference
|
||||
|
||||
> Informational only — the dry-build loop above generates the host list dynamically and is authoritative. Keep this table roughly in sync when adding hosts (used to check which overlay a host gets).
|
||||
|
||||
| Host | Type | Overlay |
|
||||
|------|------|---------|
|
||||
| `x1carbon` | Desktop/laptop | Full (`overlays`: CUDA/NDI/stable) |
|
||||
| `caitlin-x1` | Desktop/laptop | `desktopOverlays` |
|
||||
| `x470` | Desktop/laptop | `desktopOverlays` |
|
||||
| `mary-x270` | Desktop | `desktopOverlays` |
|
||||
| `richmond-server` | Server | `serverOverlays` |
|
||||
| `homeserver-1` | Server | `serverOverlays` |
|
||||
| `mcf-server` | Server | `serverOverlays` |
|
||||
| `mcf-stream` | Desktop/laptop | `desktopOverlays` |
|
||||
| `hp-laptop` | Desktop/laptop | `desktopOverlays` |
|
||||
|
||||
## Post-Validation
|
||||
After a successful commit, to actually apply:
|
||||
```bash
|
||||
# Local
|
||||
sudo nixos-rebuild switch --flake .#<hostname>
|
||||
|
||||
# Remote
|
||||
nixos-rebuild switch --target-host <user@host> --flake .#<hostname> --use-remote-sudo
|
||||
```
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
name: nix-module
|
||||
description: 'Create or update a NixOS or Home Manager module following Nix-Vibe conventions. Use when adding a new service, desktop app, hardware support, or shared configuration module. Use when the user asks to add a package, service, or application module.'
|
||||
argument-hint: '<module-name> [service|desktop|hardware|core]'
|
||||
---
|
||||
|
||||
# Nix Module Creation
|
||||
|
||||
## When to Use
|
||||
- Adding a new service (e.g., a new containerized app, daemon, or web service)
|
||||
- Adding a new desktop application module
|
||||
- Adding hardware support (e.g., new device driver, firmware)
|
||||
- Creating a new shared core module
|
||||
- The user asks to "add support for X" or "create a module for X"
|
||||
|
||||
## Module Pattern
|
||||
|
||||
All service/feature modules MUST follow this pattern:
|
||||
|
||||
```nix
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
options.services.<name> = {
|
||||
enable = lib.mkEnableOption "description of the service";
|
||||
# Additional options as needed
|
||||
};
|
||||
|
||||
config = lib.mkIf config.services.<name>.enable {
|
||||
# Configuration here
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Reference implementation: [modules/services/immich.nix](../../modules/services/immich.nix)
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Determine Module Type
|
||||
|
||||
| Type | Directory | Example |
|
||||
|------|-----------|---------|
|
||||
| Service (daemon, container, webapp) | `modules/services/` | immich, jellyfin, ntfy |
|
||||
| Desktop app | `modules/desktop/apps/` | soundux, opencode, freeshow |
|
||||
| Desktop environment | `modules/desktop/` | gnome.nix, gui.nix |
|
||||
| Hardware support | `modules/hardware/` | fingerprint.nix |
|
||||
| Core system config | `modules/core/` | common.nix, settings.nix, fonts.nix |
|
||||
|
||||
### 2. Create the Module File
|
||||
|
||||
#### Service Module Template
|
||||
```nix
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
options.services.<service-name> = {
|
||||
enable = lib.mkEnableOption "<Service Description>";
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = <default-port>;
|
||||
description = "Port for <service>";
|
||||
};
|
||||
# Add data directories, user config, etc. as needed
|
||||
};
|
||||
|
||||
config = lib.mkIf config.services.<service-name>.enable {
|
||||
# Service-specific configuration
|
||||
|
||||
# For stateful services, ensure data directories exist
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/<service> 0700 <user> <group> -"
|
||||
];
|
||||
|
||||
# Open firewall if needed
|
||||
networking.firewall.allowedTCPPorts = [ config.services.<service-name>.port ];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Desktop App Module Template
|
||||
```nix
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
<package-name>
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Register in Host Configuration
|
||||
|
||||
Import the module in the target host's `configuration.nix`:
|
||||
```nix
|
||||
imports = [
|
||||
# ...existing imports...
|
||||
../../modules/services/<module-name>.nix
|
||||
];
|
||||
```
|
||||
|
||||
Then enable it:
|
||||
```nix
|
||||
services.<service-name>.enable = true;
|
||||
```
|
||||
|
||||
### 4. Update README.md
|
||||
Add the new software to the Software Inventory table with the appropriate host columns.
|
||||
|
||||
### 5. Validate
|
||||
Run the full validation workflow. See [nix-flake-rebuild](../nix-flake-rebuild/SKILL.md).
|
||||
|
||||
## Key Conventions
|
||||
|
||||
### Secrets
|
||||
Never hardcode secrets. Use SOPS:
|
||||
```nix
|
||||
sops.secrets."<host>/<secret-name>" = {
|
||||
owner = "<user>";
|
||||
group = "users";
|
||||
mode = "0440";
|
||||
};
|
||||
```
|
||||
See [docs/sops-secrets.md](../../docs/sops-secrets.md) for details.
|
||||
|
||||
### Overlay Awareness
|
||||
- If a package needs NVIDIA/CUDA or NDI, it should only be added to `x1carbon` (the only host using the full `overlays` set)
|
||||
- Desktops/laptops use `desktopOverlays` (`stable` without CUDA); servers use `serverOverlays`
|
||||
|
||||
### Module Composition
|
||||
- Core modules (`modules/core/common.nix`) apply to ALL hosts
|
||||
- Desktop modules only apply to GUI hosts
|
||||
- Service modules are imported per-host as needed
|
||||
@@ -0,0 +1,246 @@
|
||||
---
|
||||
name: nix-new-host
|
||||
description: 'Scaffold a new NixOS host in this flake: create host directory, config files, wire into flake.nix, and set up Home Manager users. Use when adding a new machine (desktop, laptop, or server) to the Nix-Vibe configuration.'
|
||||
argument-hint: '<hostname> [desktop|server]'
|
||||
---
|
||||
|
||||
# New Host Scaffolding
|
||||
|
||||
## When to Use
|
||||
- Adding a brand new machine to the Nix-Vibe configuration
|
||||
- User asks to "add a host", "create a new machine config", or "scaffold a server/laptop"
|
||||
- Migrating a new device into this flake-based setup
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Gather Information
|
||||
Before creating files, confirm with the user:
|
||||
- **Hostname** (e.g., `new-laptop`)
|
||||
- **Type**: Desktop/laptop (needs GUI) or Server (headless, CLI only)
|
||||
- **Users** who will have Home Manager configs on this host
|
||||
- **Any special hardware** (NVIDIA GPU, fingerprint sensor, etc.)
|
||||
- **Any services** this host should run
|
||||
|
||||
### 2. Create Host Directory
|
||||
```bash
|
||||
mkdir -p hosts/<hostname>
|
||||
```
|
||||
|
||||
### 3. Create Required Host Files
|
||||
|
||||
#### `hosts/<hostname>/hardware-configuration.nix`
|
||||
Generate on the target machine after NixOS install:
|
||||
```bash
|
||||
nixos-generate-config --show-hardware-config > hosts/<hostname>/hardware-configuration.nix
|
||||
```
|
||||
If the target machine isn't available yet, create a minimal placeholder:
|
||||
```nix
|
||||
# hardware-configuration.nix for <hostname>
|
||||
# Generated placeholder — run nixos-generate-config on the target machine
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [ ];
|
||||
boot.initrd.availableKernelModules = [ ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
swapDevices = [ ];
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
```
|
||||
|
||||
#### `hosts/<hostname>/disko-config.nix`
|
||||
Copy from an existing host of the same type (desktop vs server) and adjust disk layout:
|
||||
```bash
|
||||
cp hosts/x1carbon/disko-config.nix hosts/<hostname>/disko-config.nix
|
||||
# Then edit to match the target disk layout
|
||||
```
|
||||
|
||||
#### `hosts/<hostname>/configuration.nix`
|
||||
Use the appropriate template below.
|
||||
|
||||
**Desktop/laptop template:**
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules/core/common.nix
|
||||
../../modules/desktop/gui.nix
|
||||
(import ../../modules/storage/disko.nix {
|
||||
inherit inputs lib config;
|
||||
diskoConfigPath = ./disko-config.nix;
|
||||
})
|
||||
../../modules/desktop/gnome.nix
|
||||
../../modules/core/management.nix
|
||||
../../modules/core/podman.nix
|
||||
../../modules/core/dev.nix
|
||||
];
|
||||
|
||||
networking.hostName = "<hostname>";
|
||||
|
||||
hardware.graphics.enable = true;
|
||||
hardware.graphics.enable32Bit = true;
|
||||
}
|
||||
```
|
||||
|
||||
**Server template:**
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
../../modules/core/common.nix
|
||||
(import ../../modules/storage/disko.nix {
|
||||
inherit inputs lib config;
|
||||
diskoConfigPath = ./disko-config.nix;
|
||||
})
|
||||
./hardware-configuration.nix
|
||||
../../modules/core/podman.nix
|
||||
];
|
||||
|
||||
networking.hostName = "<hostname>";
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Wire into `flake.nix`
|
||||
|
||||
#### Add users in `hostUsers`:
|
||||
```nix
|
||||
hostUsers = {
|
||||
# ...existing hosts...
|
||||
<hostname> = [ "user1" "user2" ];
|
||||
};
|
||||
```
|
||||
|
||||
#### Add nixosConfiguration:
|
||||
If **desktop/laptop** (uses full overlays):
|
||||
```nix
|
||||
nixosConfigurations = {
|
||||
# ...existing configs...
|
||||
<hostname> = mkNixosSystem "<hostname>" { };
|
||||
};
|
||||
```
|
||||
|
||||
If **server** (uses serverOverlays):
|
||||
```nix
|
||||
nixosConfigurations = {
|
||||
# ...existing configs...
|
||||
<hostname> = mkNixosSystem "<hostname>" {
|
||||
hostOverlays = serverOverlays;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### 5. Create Home Manager User Configs (if needed)
|
||||
If the host has users without existing Home Manager configs, create:
|
||||
```bash
|
||||
mkdir -p home-manager/users
|
||||
```
|
||||
|
||||
Minimal user template (`home-manager/users/<username>.nix`):
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
home-manager.users.<username> = {
|
||||
home.username = "<username>";
|
||||
home.homeDirectory = "/home/<username>";
|
||||
home.stateVersion = "24.11";
|
||||
|
||||
programs.home-manager.enable = true;
|
||||
programs.git.enable = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Update README.md
|
||||
Add the new host to:
|
||||
- The **Host Roles** section with role description and key features
|
||||
- The **Software Inventory** table (add a column for the new host)
|
||||
|
||||
### 7. Register Host in nix-flake-rebuild Skill
|
||||
The dry-build loop in [nix-flake-rebuild](../nix-flake-rebuild/SKILL.md) is dynamic (hosts are read from `nixosConfigurations`), so nothing breaks if you skip this — but add `<hostname>` to its **Host Reference** table (with the correct Type and Overlay — `serverOverlays` for servers, Full for desktops/laptops) to keep the overlay reference accurate.
|
||||
|
||||
### 8. Validate
|
||||
Follow the [nix-flake-rebuild](../nix-flake-rebuild/SKILL.md) skill to validate all changes.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Adding Desktop Apps
|
||||
Import app modules in the host config:
|
||||
```nix
|
||||
imports = [
|
||||
# ...existing imports...
|
||||
../../modules/desktop/apps/soundux.nix
|
||||
../../modules/desktop/apps/opencode.nix
|
||||
];
|
||||
```
|
||||
|
||||
### Adding Services
|
||||
Import service modules and enable:
|
||||
```nix
|
||||
imports = [
|
||||
# ...existing imports...
|
||||
../../modules/services/immich.nix
|
||||
];
|
||||
services.immich-server.enable = true;
|
||||
```
|
||||
|
||||
### Hardware-Specific Modules
|
||||
```nix
|
||||
imports = [
|
||||
# ...existing imports...
|
||||
../../modules/hardware/fingerprint.nix # if fingerprint reader
|
||||
../../modules/hardware/nvidia.nix # if NVIDIA GPU
|
||||
];
|
||||
```
|
||||
|
||||
For an NVIDIA GPU, enable via the shared option (instead of hand-writing
|
||||
`hardware.nvidia`):
|
||||
```nix
|
||||
my.hardware.nvidia = {
|
||||
enable = true;
|
||||
nvidiaSettings = true;
|
||||
package = config.boot.kernelPackages.nvidiaPackages.legacy_580; # optional
|
||||
};
|
||||
```
|
||||
|
||||
### Shared Users (petere)
|
||||
|
||||
The admin user `petere` is defined once in `modules/core/users.nix` (imported via
|
||||
`common.nix`). New hosts do **not** re-declare the full `users.users.petere`
|
||||
block — override only what differs:
|
||||
```nix
|
||||
my.users.petere = {
|
||||
hashedPasswordFile = config.sops.secrets."users/petere-password".path;
|
||||
subUidStart = 165536; # optional rootless-podman range
|
||||
subGidStart = 165536;
|
||||
};
|
||||
```
|
||||
`petere` also needs a Home Manager config in `hostUsers` (step 4).
|
||||
Reference in New Issue
Block a user