Compare commits
193 Commits
436cc7ccc9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f51c362086 | |||
|
|
a158d401ae | ||
|
|
95842b22f0 | ||
|
|
3977227889 | ||
|
|
cb8ef87229 | ||
|
|
44b3459d49 | ||
|
|
c59ac2ccb6 | ||
|
|
1767debfd8 | ||
|
|
95f08a258e | ||
|
|
c5ba5d4164 | ||
|
|
004eb3c29c | ||
|
|
616d357a59 | ||
|
|
d4481923a8 | ||
|
|
246f65190e | ||
|
|
b6df62a875 | ||
|
|
8d81a1d6e1 | ||
|
|
7368968fd5 | ||
|
|
9a719479bc | ||
|
|
38922cd526 | ||
|
|
26e7fffbd1 | ||
|
|
9792f86548 | ||
|
|
dd9fa58c5c | ||
|
|
db620cd22a | ||
|
|
dab3a37b0a | ||
|
|
74b1825d4d | ||
|
|
c3abeb846d | ||
|
|
d676b6dc1e | ||
|
|
86fffbd512 | ||
|
|
1b5f695f40 | ||
|
|
9491c0356d | ||
| 152efb84da | |||
| 26d5a8c686 | |||
|
|
ee55a543fa | ||
|
|
7cc6732a7e | ||
|
|
b73ad049e7 | ||
|
|
5d23b3db93 | ||
|
|
aa609630a1 | ||
|
|
1e1eb9886c | ||
| 9c326f5768 | |||
| e8cae7fff1 | |||
| 88b9d5309f | |||
| d44d03d0b1 | |||
| 4ac7463a1f | |||
|
|
b354dc202a | ||
|
|
079493b55e | ||
|
|
d06a43bf06 | ||
|
|
6b8395ffdb | ||
|
|
7adbafb848 | ||
|
|
3af0d99f98 | ||
| 025ab854f0 | |||
|
|
5ce8433aa8 | ||
|
|
2e8c2ddd3a | ||
|
|
4cb746afc5 | ||
|
|
3234029ae5 | ||
|
|
928de1837b | ||
|
|
70002a19e2 | ||
| a418d03b19 | |||
|
|
8aff587014 | ||
| 909917f385 | |||
|
|
c8587da722 | ||
|
|
2ebe78981a | ||
|
|
c98d48b43b | ||
|
|
ff469102ea | ||
|
|
a363622659 | ||
|
|
07b1fc3618 | ||
|
|
159ad4cb83 | ||
|
|
c439495d7a | ||
|
|
14477a8d85 | ||
|
|
37b0c50821 | ||
|
|
10b906a27c | ||
|
|
f111b1c725 | ||
|
|
869b48d26f | ||
|
|
ffbb820be3 | ||
|
|
eda929b4eb | ||
|
|
8367c2c068 | ||
|
|
6d0f109564 | ||
|
|
657849140f | ||
|
|
13cf58de7c | ||
|
|
acc683bac3 | ||
|
|
166123e8fe | ||
| e4daf12f39 | |||
|
|
03f6b730cf | ||
|
|
57fa32bf9c | ||
|
|
c1efceef55 | ||
|
|
a125017c93 | ||
|
|
35154eb694 | ||
|
|
bd799661b9 | ||
|
|
6ca55504f0 | ||
|
|
0aa9a0f994 | ||
|
|
9728f49e42 | ||
|
|
c97e96f2da | ||
|
|
eec051b256 | ||
|
|
a88736cf6e | ||
|
|
8d8d49bd38 | ||
|
|
a673f379c7 | ||
|
|
2f8f5092c4 | ||
|
|
47b9c1ae98 | ||
| 6d6618a683 | |||
|
|
62736ed77c | ||
|
|
0967e27fca | ||
|
|
383013f425 | ||
|
|
23139fe492 | ||
|
|
add39956f7 | ||
|
|
4c1332e67a | ||
|
|
5fe8c897aa | ||
|
|
8217b83798 | ||
| 06c1ae13df | |||
| 9ae5c8ab6d | |||
|
|
515792132f | ||
| 53489fe173 | |||
| 979344917e | |||
| f80144d22b | |||
|
|
8732e65f1c | ||
|
|
f7a0460646 | ||
| 9515a5d317 | |||
| c4bc1b155a | |||
|
|
c15f0b0f0b | ||
|
|
a060a84cf1 | ||
|
|
5fe8c08653 | ||
| 832ac9d0df | |||
|
|
92358d0415 | ||
|
|
aed841d32e | ||
| 85ea3039f4 | |||
| 5e22760799 | |||
| 84f600eb04 | |||
|
|
6dc138bbf6 | ||
|
|
23a04934fb | ||
| 0e0ec54b5e | |||
| c252a07877 | |||
|
|
47d7d5b11e | ||
|
|
e119ffaabb | ||
|
|
ab81e78b60 | ||
|
|
2013804b17 | ||
|
|
7fcbd0bb7c | ||
|
|
78280d5150 | ||
|
|
ccd413d273 | ||
|
|
642cee5dc5 | ||
| 981b03b955 | |||
|
|
18e781d388 | ||
|
|
91ec603b62 | ||
|
|
a4c2cbdf7b | ||
|
|
f8a86f9b29 | ||
|
|
84eb2e3734 | ||
|
|
4cc58ab381 | ||
|
|
661c7c7771 | ||
|
|
35ac45f5ce | ||
|
|
540dabcb5d | ||
|
|
7798684d29 | ||
|
|
d1960837a0 | ||
| 99452eb470 | |||
| d75c05f74f | |||
|
|
2ad3e050fc | ||
|
|
da1cd27482 | ||
|
|
0f2239af05 | ||
|
|
0ffbeaaea1 | ||
|
|
cd6ea07e88 | ||
|
|
72014609a0 | ||
|
|
01d1086580 | ||
|
|
5952eddecb | ||
|
|
309e224a72 | ||
|
|
ecce28b498 | ||
|
|
bd569962ca | ||
|
|
068d6c8f94 | ||
|
|
0b9a301a92 | ||
|
|
23f29b6ca1 | ||
|
|
2c0b26ced0 | ||
|
|
e647794a0f | ||
|
|
6f77344d42 | ||
|
|
27790713be | ||
| 93aaf52b7e | |||
| 659cc20e38 | |||
|
|
3ee33e4bfd | ||
|
|
d229cdbf6a | ||
| dd04320fe7 | |||
| 5d14db352e | |||
|
|
af840f242b | ||
|
|
d9f17670e1 | ||
|
|
c1028fc0f0 | ||
|
|
5466c59dde | ||
|
|
d53093a6c1 | ||
|
|
5d1d3dc850 | ||
|
|
f4fd826c90 | ||
|
|
46b249560f | ||
|
|
4a7b2f835e | ||
|
|
cb82c6a6d7 | ||
|
|
b6ed51da26 | ||
|
|
23f39ffe6f | ||
|
|
676ec990e1 | ||
|
|
297f23fac8 | ||
|
|
a925fccda1 | ||
|
|
0346094f8e | ||
|
|
2c6ea8b9a4 | ||
|
|
cf40c72e7e |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -6,9 +6,9 @@ result*
|
||||
.direnv
|
||||
shell.nix
|
||||
.vscode
|
||||
**/*/*.py
|
||||
.envrc
|
||||
.DS_Store
|
||||
*.qcow2
|
||||
keys
|
||||
iso-*
|
||||
iso-*
|
||||
**/*/__pycache__
|
||||
@@ -14,7 +14,7 @@ keys:
|
||||
- &nuc age102el4snus37dj807rwvsmlvwu2sg2d8rw3vfmtntgczfkz04l9nshetcq0
|
||||
- &admin_nuc age1yn82e39pxt0d0pgny34ux4lkge4ff7wxvsye8ragvwngehemt4ps27phyw
|
||||
- &matt_allyx age18z4ctyyj7eq0cmt23eelfzjuacq4fa6hsplyg779d3rdg7ac2q5q2njxqh
|
||||
- &allyx age164xpf9cepfjqvcn7v5ahcaq9zmm5u3yl9t04d098e3e2zkfjcyws02rx42
|
||||
- &allyx age1er5qucsc2mugrzrr7n3xhzv7kemkrqrw4m84r544fkk7nkg5g5eswxkqj0
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
|
||||
303
AGENTS.md
Executable file
303
AGENTS.md
Executable file
@@ -0,0 +1,303 @@
|
||||
# Agent Guide
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
/etc/nixos/
|
||||
├── flake.nix # Main flake configuration
|
||||
├── flake.lock # Locked versions
|
||||
├── AGENTS.md # This file
|
||||
├── treefmt.nix # Code formatting config
|
||||
├── qemu.nix # QEMU testing config
|
||||
│
|
||||
├── systems/ # System configurations by architecture
|
||||
│ ├── aarch64-linux/
|
||||
│ │ ├── macbook-pro-nixos/ # Apple Silicon MacBook
|
||||
│ │ │ ├── default.nix
|
||||
│ │ │ ├── boot.nix
|
||||
│ │ │ ├── services.nix # logind, gdm, gnome, flatpak, etc.
|
||||
│ │ │ ├── filesystems.nix
|
||||
│ │ │ ├── hardware-configuration.nix
|
||||
│ │ │ └── firmware/ # Asahi firmware
|
||||
│ │ └── pi5/ # Raspberry Pi 5
|
||||
│ │ ├── default.nix
|
||||
│ │ ├── boot.nix
|
||||
│ │ ├── adguard.nix
|
||||
│ │ └── sops.nix
|
||||
│ ├── x86_64-linux/
|
||||
│ │ ├── matt-nixos/ # Desktop AMD system
|
||||
│ │ │ ├── default.nix
|
||||
│ │ │ ├── boot.nix
|
||||
│ │ │ ├── filesystems.nix
|
||||
│ │ │ ├── sops.nix
|
||||
│ │ │ └── services/
|
||||
│ │ │ ├── lsfg-vk/
|
||||
│ │ │ ├── ratbagd/
|
||||
│ │ │ └── restic/
|
||||
│ │ ├── allyx/ # ASUS ROG Ally X
|
||||
│ │ │ ├── default.nix
|
||||
│ │ │ └── boot.nix
|
||||
│ │ ├── nuc-nixos/ # Intel NUC
|
||||
│ │ ├── jallen-nas/ # NAS server
|
||||
│ │ └── iso-minimal/
|
||||
│ └── aarch64-darwin/
|
||||
│ └── macbook-pro/ # macOS (nix-darwin)
|
||||
│
|
||||
├── homes/ # Home-manager configurations
|
||||
│ ├── aarch64-linux/
|
||||
│ │ └── matt@macbook-pro-nixos/
|
||||
│ │ └── default.nix
|
||||
│ ├── x86_64-linux/
|
||||
│ └── aarch64-darwin/
|
||||
│
|
||||
├── modules/ # Shared modules
|
||||
│ ├── nixos/ # NixOS system modules
|
||||
│ ├── home/ # Home-manager modules
|
||||
│ └── darwin/ # nix-darwin modules
|
||||
│
|
||||
├── packages/ # Custom package overlays
|
||||
│ ├── omnissa/
|
||||
│ ├── bcachefs/
|
||||
│ ├── raspberrypi/
|
||||
│ ├── comfyui/
|
||||
│ ├── homeassistant/
|
||||
│ ├── librepods-beta/
|
||||
│ └── ...
|
||||
│
|
||||
└── secrets/ # SOPS secrets
|
||||
├── secrets.yaml # Master key config
|
||||
└── *-secrets.yaml # Per-host secrets
|
||||
```
|
||||
|
||||
## System Configurations
|
||||
|
||||
### macbook-pro-nixos (Apple Silicon MacBook)
|
||||
- **Path**: `systems/aarch64-linux/macbook-pro-nixos/`
|
||||
- **Key files**:
|
||||
- `services.nix:72-81` - logind/sleep settings
|
||||
- `default.nix` - main config, imports all parts
|
||||
- `boot.nix` - systemd-boot, kernel params
|
||||
- **Features**: Asahi Linux, GNOME, Hyprland option, battery management
|
||||
|
||||
### matt-nixos (AMD Desktop)
|
||||
- **Path**: `systems/x86_64-linux/matt-nixos/`
|
||||
- **Features**: AMD GPU (LACT), GNOME, gaming, Lanzaboote
|
||||
|
||||
### allyx (ASUS ROG Ally X)
|
||||
- **Path**: `systems/x86_64-linux/allyx/`
|
||||
- **Features**: Jovian NixOS, Steam, handheld-daemon, AMD GPU
|
||||
|
||||
### pi5 (Raspberry Pi 5)
|
||||
- **Path**: `systems/aarch64-linux/pi5/`
|
||||
- **Features**: Headless, AdGuard, Docker, static IP, UEFI boot
|
||||
|
||||
### jallen-nas (NAS Server)
|
||||
- **Path**: `systems/x86_64-linux/jallen-nas/`
|
||||
- **Features**: Headless, VPN, bcachefs, restic backups
|
||||
|
||||
## NixOS Modules (`modules/nixos/`)
|
||||
|
||||
### Desktop Environments
|
||||
- `desktop/gnome/default.nix` - GNOME configuration
|
||||
- `desktop/hyprland/default.nix` - Hyprland configuration
|
||||
- `desktop/cosmic/default.nix` - Cosmic DE configuration
|
||||
|
||||
### Hardware
|
||||
- `hardware/amd/default.nix` - AMD GPU (LACT)
|
||||
- `hardware/nvidia/default.nix` - NVIDIA GPU
|
||||
- `hardware/battery/default.nix` - Battery management
|
||||
- `hardware/raspberry-pi/` - Raspberry Pi support
|
||||
|
||||
### Boot & System
|
||||
- `boot/common/` - Common boot settings
|
||||
- `boot/lanzaboote/` - Lanzaboote (secure boot)
|
||||
- `boot/systemd-boot/` - Systemd-boot config
|
||||
- `boot/plymouth/` - Plymouth splash screen
|
||||
|
||||
### Networking
|
||||
- `network/default.nix` - Network configuration (hostname, firewall, NM)
|
||||
- `network/options.nix` - Network module options
|
||||
|
||||
### Other Services
|
||||
- `headless/default.nix` - Headless server config (watchdog, no suspend)
|
||||
- `gaming/default.nix` - Steam, Gamescope, Gamemode
|
||||
- `programs/default.nix` - System programs (nix-index, gnupg, etc.)
|
||||
|
||||
## Home-Manager Modules (`modules/home/`)
|
||||
|
||||
### Programs
|
||||
- `programs/waybar/` - Wayland bar
|
||||
- `programs/hyprland/` - Hyprland config
|
||||
- `programs/kitty/` - Kitty terminal
|
||||
- `programs/wofi/` - Wofi launcher
|
||||
- `programs/wlogout/` - Logout menu
|
||||
- `programs/btop/` - System monitor
|
||||
- `programs/git/` - Git configuration
|
||||
- `programs/zsh/` - Zsh configuration
|
||||
- `programs/mako/` - Notification daemon
|
||||
|
||||
### Desktop
|
||||
- `desktop/gnome/` - GNOME settings
|
||||
- `desktop/stylix/` - Stylix theming
|
||||
|
||||
### Services
|
||||
- `services/sops/` - SOPS integration
|
||||
|
||||
## Custom Packages (`packages/`)
|
||||
|
||||
- `omnissa/` - Omnissa Horizon client
|
||||
- `bcachefs/` - Bcachefs tools
|
||||
- `raspberrypi/` - Raspberry Pi firmware/tools
|
||||
- `comfyui/` - ComfyUI packages
|
||||
- `homeassistant/` - Home Assistant components
|
||||
- `librepods-beta/` - LibrePODS beta (AirPods support)
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Enable a desktop environment
|
||||
```nix
|
||||
${namespace}.desktop.gnome.enable = true;
|
||||
${namespace}.desktop.hyprland.enable = true;
|
||||
```
|
||||
|
||||
### Enable SOPS
|
||||
```nix
|
||||
${namespace}.sops.enable = true;
|
||||
```
|
||||
|
||||
### Enable headless mode
|
||||
```nix
|
||||
${namespace}.headless.enable = true;
|
||||
```
|
||||
|
||||
### System imports
|
||||
```nix
|
||||
imports = [
|
||||
./boot.nix
|
||||
./filesystems.nix
|
||||
./hardware-configuration.nix
|
||||
./services.nix
|
||||
];
|
||||
```
|
||||
|
||||
### Namespace options (flake.nix:253)
|
||||
```nix
|
||||
namespace = "mjallen";
|
||||
```
|
||||
|
||||
## SOPS Secrets
|
||||
|
||||
Secrets are encrypted with SOPS. Each system has its own secrets file:
|
||||
- `secrets/mac-secrets.yaml` - macbook-pro-nixos
|
||||
- `secrets/pi5-secrets.yaml` - pi5
|
||||
- `secrets/allyx-secrets.yaml` - allyx
|
||||
- `secrets/nuc-secrets.yaml` - nuc-nixos
|
||||
- `secrets/nas-secrets.yaml` - jallen-nas
|
||||
|
||||
## Flake Inputs (flake.nix)
|
||||
|
||||
Key inputs:
|
||||
- `nixpkgs-unstable` - Unstable channel
|
||||
- `nixpkgs-stable` - Stable channel (25.11)
|
||||
- `home-manager-unstable` - Home-manager
|
||||
- `nixos-apple-silicon` - Apple Silicon support
|
||||
- `nixos-hardware` - Common hardware configs
|
||||
- `disko` - Disk partitioning
|
||||
- `sops-nix` - Secrets management
|
||||
- `lanzaboote` - Secure boot
|
||||
- `jovian` - Steam Deck support (allyx)
|
||||
|
||||
## Lib Module (`lib/`)
|
||||
|
||||
Custom utility library exposed via `lib.mjallen.*` through Snowfall Lib. Used for creating modules and managing versions.
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
lib/
|
||||
├── default.nix # Entry point: exports module, file, versioning
|
||||
├── README.md # Detailed documentation
|
||||
├── module/ # Module creation helpers
|
||||
│ └── default.nix
|
||||
├── file/ # File/path utilities
|
||||
│ └── default.nix
|
||||
└── versioning/ # Multi-source version pinning
|
||||
└── default.nix
|
||||
```
|
||||
|
||||
### Module Utilities (`lib.mjallen.module`)
|
||||
|
||||
**`mkModule`** - Create NixOS service modules with standardized options:
|
||||
```nix
|
||||
lib.mjallen.module.mkModule {
|
||||
config, name, description, options, moduleConfig, domain ? "services"
|
||||
}
|
||||
```
|
||||
Standard options: `enable`, `port`, `reverseProxy`, `firewall`, `createUser`, `configureDb`, `redis`, `puid`, `pgid`, `timeZone`, etc.
|
||||
|
||||
**`mkContainerService`** - For Podman/OCI containers (auto-generates container definition):
|
||||
```nix
|
||||
lib.mjallen.module.mkContainerService {
|
||||
config, name, image, internalPort, description, options, volumes, environment
|
||||
}
|
||||
```
|
||||
|
||||
**`mkSopsEnvFile`** - Generate SOPS secrets + template env-file:
|
||||
```nix
|
||||
lib.mjallen.module.mkSopsEnvFile {
|
||||
secrets, name, content, restartUnit, owner, group, mode, sopsFile
|
||||
}
|
||||
```
|
||||
|
||||
**Option Helpers:**
|
||||
- `mkOpt type default description` - Standard option
|
||||
- `mkBoolOpt default description` - Boolean option
|
||||
- `mkReverseProxyOpt name` - Caddy reverse proxy sub-options
|
||||
|
||||
**Convenience Shorthands:**
|
||||
- `enabled` = `{ enable = true; }`
|
||||
- `disabled` = `{ enable = false; }`
|
||||
|
||||
### Home Manager Utilities
|
||||
|
||||
**`mkHomeModule`** - Create Home Manager modules:
|
||||
```nix
|
||||
lib.mjallen.module.mkHomeModule {
|
||||
config, domain, name, description, options, moduleConfig
|
||||
}
|
||||
```
|
||||
|
||||
### File Utilities (`lib.mjallen.file`)
|
||||
|
||||
- `readFile path` - Read file contents
|
||||
- `pathExists path` - Check if path exists
|
||||
- `safeImport path default` - Safe Nix import
|
||||
- `getFile relativePath` - Get path relative to flake root
|
||||
- `importModulesRecursive path` - Recursively discover Nix modules
|
||||
- `scanSystems systemsPath` - Discover system configurations
|
||||
- `filterNixOSSystems systems` - Filter for Linux systems
|
||||
- `filterDarwinSystems systems` - Filter for macOS systems
|
||||
- `scanHomes homesPath` - Parse home-manager configurations
|
||||
|
||||
### Versioning Utilities (`lib.mjallen.versioning`)
|
||||
|
||||
For packages with `version.json` (multi-variant source pinning):
|
||||
|
||||
- `selectVariant spec variantName system` - Select variant from spec
|
||||
- `render value variables` - Template substitution (`${var}`)
|
||||
- `mkSrc pkgs comp variables` - Build single source
|
||||
- `mkAllSources pkgs selected` - Build all sources for selected variant
|
||||
|
||||
See `lib/versioning/default.nix` for full API and `docs/version.schema.json` for schema.
|
||||
|
||||
### Usage in Packages
|
||||
|
||||
Create `packages/<name>/version.json` with variant definitions, then use:
|
||||
```nix
|
||||
let
|
||||
versioning = inputs.self.lib.mjallen.versioning;
|
||||
spec = inputs.self.lib.mjallen.file.readFile ./version.json;
|
||||
selected = versioning.selectVariant spec variantName system;
|
||||
sources = versioning.mkAllSources pkgs selected;
|
||||
in
|
||||
# Use sources.componentName for each source
|
||||
```
|
||||
118
README.md
118
README.md
@@ -71,7 +71,7 @@ A powerful AMD-based desktop with gaming capabilities, featuring:
|
||||
### NAS
|
||||
|
||||
A home server with various self-hosted services:
|
||||
- Media management (Jellyfin, Jellyseerr)
|
||||
- Media management (Jellyfin, seerr)
|
||||
- Download automation (Sonarr, Radarr, etc.)
|
||||
- Document management (Paperless)
|
||||
- File sharing (Samba, Nextcloud)
|
||||
@@ -113,6 +113,122 @@ sudo nixos-rebuild switch --flake .#hostname
|
||||
home-manager switch --flake .#username@hostname
|
||||
```
|
||||
|
||||
## Secrets Management
|
||||
|
||||
Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix). Each secret file is encrypted with [age](https://age-encryption.org/), using the SSH host key (`/etc/ssh/ssh_host_ed25519_key`) of each machine as a recipient, so that machine can decrypt its own secrets at boot without any passphrase.
|
||||
|
||||
### How age keys work
|
||||
|
||||
sops-nix derives an age key from the machine's ed25519 SSH host key automatically. The corresponding age **public key** must be added to `.sops.yaml` before you can encrypt secrets for that machine.
|
||||
|
||||
To get the age public key for a machine:
|
||||
|
||||
```bash
|
||||
# On the target machine (or from its host key file):
|
||||
nix-shell -p ssh-to-age --run \
|
||||
'ssh-keyscan localhost 2>/dev/null | ssh-to-age'
|
||||
|
||||
# Or directly from the key file:
|
||||
nix-shell -p ssh-to-age --run \
|
||||
'ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub'
|
||||
```
|
||||
|
||||
### Adding a new machine
|
||||
|
||||
1. **Get the age public key** for the new machine using the command above.
|
||||
|
||||
2. **Add it to `.sops.yaml`**:
|
||||
```yaml
|
||||
keys:
|
||||
- &new-machine age1<public-key-here>
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- age:
|
||||
- *new-machine
|
||||
# ... existing recipients
|
||||
```
|
||||
|
||||
3. **Re-encrypt all secret files** so the new machine becomes a recipient:
|
||||
```bash
|
||||
find secrets/ -name '*.yaml' -exec sops updatekeys {} \;
|
||||
```
|
||||
|
||||
### Adding a new secret
|
||||
|
||||
To add a secret to an existing file:
|
||||
|
||||
```bash
|
||||
# Edit the file interactively (sops decrypts, opens $EDITOR, re-encrypts on save)
|
||||
sops secrets/nas-secrets.yaml
|
||||
```
|
||||
|
||||
To create a new secrets file:
|
||||
|
||||
```bash
|
||||
sops secrets/mymachine-secrets.yaml
|
||||
```
|
||||
|
||||
The `.sops.yaml` `creation_rules` determine which keys encrypt the file based on its path.
|
||||
|
||||
### Generating Nebula VPN certificates
|
||||
|
||||
The Nebula module (`mjallen.services.nebula`) expects three secrets per host under a configurable prefix:
|
||||
- `<prefix>/ca-cert` — the CA certificate (shared across all nodes)
|
||||
- `<prefix>/host-cert` — this node's signed certificate
|
||||
- `<prefix>/host-key` — this node's private key
|
||||
|
||||
**Step 1 — Create the CA** (once per network, on a trusted machine):
|
||||
|
||||
```bash
|
||||
nebula-cert ca -name "jallen-nebula"
|
||||
# Produces: ca.crt, ca.key
|
||||
```
|
||||
|
||||
**Step 2 — Sign a certificate for each node**:
|
||||
|
||||
```bash
|
||||
# Lighthouse (assign an overlay IP, e.g. 10.1.1.1)
|
||||
nebula-cert sign -name "pi5" -ip "10.1.1.1/24" \
|
||||
-ca-crt ca.crt -ca-key ca.key \
|
||||
-out-crt lighthouse.crt -out-key lighthouse.key
|
||||
|
||||
# Regular node (assign a unique overlay IP, e.g. 10.1.1.2)
|
||||
nebula-cert sign -name "nas" -ip "10.1.1.2/24" \
|
||||
-ca-crt ca.crt -ca-key ca.key \
|
||||
-out-crt nas.crt -out-key nas.key
|
||||
```
|
||||
|
||||
**Step 3 — Add the secrets to SOPS**:
|
||||
|
||||
```bash
|
||||
# Edit the target host's secrets file
|
||||
sops secrets/pi5-secrets.yaml
|
||||
```
|
||||
|
||||
Add the certificate contents under the configured prefix (e.g. `pi5/nebula`):
|
||||
|
||||
```yaml
|
||||
pi5:
|
||||
nebula:
|
||||
ca-cert: |
|
||||
<contents of ca.crt>
|
||||
lighthouse-cert: |
|
||||
<contents of lighthouse.crt>
|
||||
lighthouse-key: |
|
||||
<contents of lighthouse.key>
|
||||
```
|
||||
|
||||
The key name for the cert/key pair matches the `hostSecretName` option (e.g. `hostSecretName = "lighthouse"` → looks for `lighthouse-cert` / `lighthouse-key`).
|
||||
|
||||
**Step 4 — Shred the plaintext key files** once they are in SOPS:
|
||||
|
||||
```bash
|
||||
shred -u ca.key lighthouse.key nas.key
|
||||
```
|
||||
|
||||
> Keep `ca.crt` accessible if you need to sign more nodes later, but store `ca.key` only in SOPS.
|
||||
|
||||
## Documentation
|
||||
|
||||
Comprehensive documentation is available in the [docs](./docs) directory:
|
||||
|
||||
383
WORKAROUNDS.md
Executable file
383
WORKAROUNDS.md
Executable file
@@ -0,0 +1,383 @@
|
||||
# Workarounds, Overrides & Temporary Fixes
|
||||
|
||||
This document tracks all known workarounds, patches, and temporary overrides in this flake.
|
||||
Each entry includes the file location, reason, and whether it is still required.
|
||||
|
||||
**Status legend:**
|
||||
- `ACTIVE` — still required, upstream fix not available
|
||||
- `REDUNDANT` — upstream has fixed the issue; this override can be removed
|
||||
- `UPSTREAM PENDING` — waiting on an upstream PR/issue
|
||||
- `INTENTIONAL` — permanent design decision, not a workaround
|
||||
|
||||
---
|
||||
|
||||
## Overlays (upstream package overrides)
|
||||
|
||||
### `overlays/cosmic-settings-daemon/default.nix`
|
||||
**Status:** `ACTIVE — UPSTREAM PENDING`
|
||||
|
||||
`cosmic-settings-daemon 1.0.8` has a buggy `Cargo.lock` that references
|
||||
`https://github.com/pop-os/dbus-settings-bindings` at two different commits
|
||||
(`3b86984` for `cosmic-dbus-a11y`/`locale1`/`upower_dbus`, and `0fa672f8`
|
||||
for the `cosmic-settings-daemon` subcrate). `cargoSetupHook` (used by
|
||||
`fetchCargoVendor`/`cargoHash`) rejects this: *"Sources are not allowed to be
|
||||
defined multiple times."*
|
||||
|
||||
The fix overrides `cargoDeps` with `rustPlatform.importCargoLock`, which uses
|
||||
a different vendoring strategy that handles multiple commits from the same repo.
|
||||
|
||||
**Removal condition:** When nixpkgs updates `cosmic-settings-daemon` past 1.0.8
|
||||
with a fixed `Cargo.lock`, or applies `cargoLock` in its own package definition.
|
||||
|
||||
---
|
||||
|
||||
### `overlays/cosmic-applets/default.nix`
|
||||
**Status:** `ACTIVE — UPSTREAM PENDING`
|
||||
|
||||
`cosmic-applets 1.0.8` has the same class of bug: its `Cargo.lock` references
|
||||
`https://github.com/pop-os/cosmic-settings` at two different commits (`b46a55d`
|
||||
for `cosmic-pipewire` and `cosmic-settings-sound-subscription`, and `55b502d`
|
||||
for `cosmic-settings-a11y-manager-subscription` and several other crates).
|
||||
`cargoSetupHook` rejects this with the same "Sources are not allowed to be
|
||||
defined multiple times" error.
|
||||
|
||||
Same fix as `cosmic-settings-daemon`: overrides `cargoDeps` with
|
||||
`rustPlatform.importCargoLock`.
|
||||
|
||||
**Removal condition:** When nixpkgs updates `cosmic-applets` past 1.0.8 with a
|
||||
fixed `Cargo.lock`, or applies `cargoLock` in its own package definition.
|
||||
|
||||
---
|
||||
|
||||
### ~~`overlays/waybar/default.nix`~~ — REMOVED
|
||||
**Status:** `REMOVED`
|
||||
|
||||
Previously added `-Dexperimental=true` to waybar's meson flags. nixpkgs now
|
||||
includes `-Dexperimental=true` in its waybar definition, making the overlay
|
||||
redundant. Removed.
|
||||
|
||||
---
|
||||
|
||||
### `overlays/radios/default.nix`
|
||||
**Status:** `ACTIVE` (protective — needed after next `flake update`)
|
||||
|
||||
`radios` requires `pycountry>=24.0.0,<25.0.0` (PEP 440: `^24.0.0`). The
|
||||
current locked nixpkgs has `pycountry 24.6.1` (in range), but nixpkgs HEAD
|
||||
has already bumped `pycountry` to `26.2.16`, which will break `radios` after
|
||||
the next `flake update`. The overlay applies `pythonRelaxDepsHook` to loosen
|
||||
the upper bound.
|
||||
|
||||
**Removal condition:** When the upstream `radios` package (`frenck/python-radios`)
|
||||
or nixpkgs relaxes the pycountry version constraint.
|
||||
|
||||
---
|
||||
|
||||
### `overlays/redis/default.nix`
|
||||
**Status:** `INTENTIONAL`
|
||||
|
||||
Replaces `redis` with `valkey` (the Redis community fork) globally. This is a
|
||||
deliberate preference for the open-source fork over the Redis 7.x+ license change.
|
||||
|
||||
---
|
||||
|
||||
### `overlays/stable/default.nix`
|
||||
**Status:** `INTENTIONAL`
|
||||
|
||||
Injects `pkgs.stable` as an attribute pointing to the stable nixpkgs channel,
|
||||
so modules can selectively pull in stable packages. Not a workaround.
|
||||
|
||||
---
|
||||
|
||||
## Flake Inputs (forks and custom branches)
|
||||
|
||||
### `nixpkgs-otbr` — `github:mrene/nixpkgs/openthread-border-router`
|
||||
**File:** `flake.nix:8`
|
||||
**Status:** `ACTIVE — UPSTREAM PENDING`
|
||||
|
||||
`openthread-border-router` is not yet packaged in nixpkgs-unstable. A community
|
||||
member's nixpkgs fork provides the package, used by
|
||||
`modules/nixos/homeassistant/services/thread/default.nix`.
|
||||
|
||||
The fork is ~52,000 commits behind `nixos-unstable`, so it is pulled
|
||||
only via `pkgs.callPackage` from the fork's path, not as a full channel overlay.
|
||||
|
||||
**Removal condition:** When `openthread-border-router` is merged into nixpkgs.
|
||||
Check: https://github.com/NixOS/nixpkgs/pulls?q=openthread-border-router
|
||||
|
||||
---
|
||||
|
||||
### `snowfall-lib` — `github:mjallen18/snowfall-lib`
|
||||
**File:** `flake.nix:26`
|
||||
**Status:** `INTENTIONAL`
|
||||
|
||||
Personal fork of `snowfallorg/lib` with 46 commits ahead of upstream, including:
|
||||
- `fix: pass namespace argument to overlays`
|
||||
- `fix: pass namespace argument to home-manager modules`
|
||||
- `feat: support same username across multiple targets`
|
||||
- `feat: enable per-channel configuration and fix pkgs selection`
|
||||
- Performance improvements and additional features
|
||||
|
||||
These are custom changes required by this flake's structure that have not been
|
||||
upstreamed.
|
||||
|
||||
---
|
||||
|
||||
### `steam-rom-manager` — `github:mjallen18/nix-steam-rom-manager`
|
||||
**File:** `flake.nix:41`
|
||||
**Status:** `INTENTIONAL`
|
||||
|
||||
Personal fork/packaging of nix-steam-rom-manager. The upstream
|
||||
(`nix-community/nix-steam-rom-manager`) may or may not exist; this is a
|
||||
maintained fork.
|
||||
|
||||
---
|
||||
|
||||
### Commented-out: `nvmd/disko` fork
|
||||
**File:** `flake.nix:59-61`
|
||||
**Status:** `REDUNDANT` (already disabled)
|
||||
|
||||
```nix
|
||||
# the fork is needed for partition attributes support
|
||||
# url = "github:nvmd/disko/gpt-attrs";
|
||||
```
|
||||
|
||||
A community fork of disko with GPT partition attribute support was previously
|
||||
used but has since been switched back to upstream `nix-community/disko`. The
|
||||
comment can be cleaned up if the feature is no longer needed.
|
||||
|
||||
---
|
||||
|
||||
## Build Fixes & postPatch
|
||||
|
||||
### `packages/edk2-basetools/default.nix` — OpenSSL vendoring FIXME
|
||||
**File:** `packages/edk2-basetools/default.nix:50-52`
|
||||
**Status:** `UPSTREAM PENDING` (verify PR reference)
|
||||
|
||||
```nix
|
||||
# FIXME: unvendor OpenSSL again once upstream updates
|
||||
# to a compatible version.
|
||||
# Upstream PR: https://github.com/tianocore/edk2/pull/10946
|
||||
```
|
||||
|
||||
The comment references tianocore/edk2 PR #10946, but that PR's title is
|
||||
*"update to openssl 3.5.1"* (now merged), not an unvendoring PR. The FIXME
|
||||
comment may be referencing the wrong PR number or the issue may have evolved.
|
||||
The edk2 build still vendor-patches OpenSSL compatibility; this should be
|
||||
re-evaluated against the current edk2 upstream.
|
||||
|
||||
**Action:** Verify whether the OpenSSL vendoring is still needed with current
|
||||
edk2, and update or remove the FIXME comment.
|
||||
|
||||
---
|
||||
|
||||
### `packages/bcachefs/default.nix` — Tests disabled
|
||||
**File:** `packages/bcachefs/default.nix:100`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
```nix
|
||||
# FIXME: Try enabling this once the default linux kernel is at least 6.7
|
||||
doCheck = false; # needs bcachefs module loaded on builder
|
||||
```
|
||||
|
||||
Tests require a live bcachefs kernel module in the build sandbox, which is
|
||||
not available. The comment mentions kernel ≥ 6.7, which is now the case
|
||||
(nixpkgs is on 6.12+), but the underlying sandbox limitation still applies —
|
||||
the build sandbox cannot load kernel modules regardless of kernel version.
|
||||
|
||||
**Action:** The `6.7` condition is now met but irrelevant; update the comment
|
||||
to reflect that the real blocker is sandbox access to kernel modules.
|
||||
|
||||
---
|
||||
|
||||
### `packages/raspberrypi/linux-rpi/default.nix` — Failed kernel attempts
|
||||
**File:** `packages/raspberrypi/linux-rpi/default.nix:25-43`
|
||||
**Status:** `ACTIVE` (informational)
|
||||
|
||||
Four newer RPi kernel versions (6.15.11 through 6.19.0-rc5) are commented out
|
||||
because they "fail for various reasons." The active version is pinned to an
|
||||
older working commit.
|
||||
|
||||
**Action:** Periodically attempt to enable a newer kernel tag. The comments
|
||||
serve as a history of failed attempts.
|
||||
|
||||
---
|
||||
|
||||
### `packages/raspberrypi/linux-rpi/default.nix` — DTB aliasing hack
|
||||
**File:** `packages/raspberrypi/linux-rpi/default.nix:110-148`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
```nix
|
||||
# Make copies of the DTBs named after the upstream names so that U-Boot finds them.
|
||||
# This is ugly as heck, but I don't know a better solution so far.
|
||||
```
|
||||
|
||||
RPi's kernel ships DTBs with non-standard names (e.g. `bcm2708-rpi-zero-w.dtb`);
|
||||
U-Boot expects canonical upstream names (e.g. `bcm2835-rpi-zero.dtb`). DTBs
|
||||
are duplicated in `postFixup`.
|
||||
|
||||
---
|
||||
|
||||
### `packages/homeassistant/ha-mail-and-packages/default.nix` — Hardcoded paths
|
||||
**File:** `packages/homeassistant/ha-mail-and-packages/default.nix:25-37`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
The upstream HA integration hard-codes paths relative to its source directory,
|
||||
which breaks in the Nix store. `postPatch` rewrites them to
|
||||
`/var/lib/homeassistant/images/`.
|
||||
|
||||
---
|
||||
|
||||
### `packages/homeassistant/ha-wyzeapi/default.nix` — Version pin relaxation
|
||||
**File:** `packages/homeassistant/ha-wyzeapi/default.nix:24-27`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
Relaxes the minimum `wyzeapy` version pin from `0.5.28` to `0.5.27` to match
|
||||
the version packaged in this flake.
|
||||
|
||||
---
|
||||
|
||||
## Raspberry Pi — Structural Overrides
|
||||
|
||||
### `modules/nixos/hardware/raspberry-pi/default.nix` — jemalloc 16K pages
|
||||
**File:** `modules/nixos/hardware/raspberry-pi/default.nix:458-470`
|
||||
**Status:** `ACTIVE` (structural)
|
||||
|
||||
```nix
|
||||
# https://github.com/nvmd/nixos-raspberrypi/issues/64
|
||||
jemalloc = prev.jemalloc.overrideAttrs (old: {
|
||||
configureFlags = ... ++ [ "${pageSizeFlag}=14" ];
|
||||
});
|
||||
```
|
||||
|
||||
RPi5 uses 16K memory pages (2^14). jemalloc must be compiled with
|
||||
`--with-lg-page=14`, otherwise it will use incorrect page size assumptions
|
||||
and likely crash or corrupt memory.
|
||||
|
||||
**References:** https://github.com/nvmd/nixos-raspberrypi/issues/64
|
||||
|
||||
---
|
||||
|
||||
### `systems/aarch64-linux/pi5/boot.nix` — 16K page kernel
|
||||
**File:** `systems/aarch64-linux/pi5/boot.nix:22-35`
|
||||
**Status:** `ACTIVE` (structural)
|
||||
|
||||
Forces `CONFIG_ARM64_16K_PAGES=y` in the kernel config via `linux_6_19.override`.
|
||||
`ignoreConfigErrors = true` is required because some kernel config options are
|
||||
unavailable and would otherwise fail validation.
|
||||
|
||||
---
|
||||
|
||||
### `packages/raspberrypi/ffmpeg-rpi/default.nix` — RPi hardware codec ffmpeg
|
||||
**File:** `packages/raspberrypi/ffmpeg-rpi/default.nix`
|
||||
**Status:** `ACTIVE` (structural)
|
||||
|
||||
Custom ffmpeg build from `jc-kynesim/rpi-ffmpeg` fork with RPi hardware codec
|
||||
support (`--enable-v4l2-request`, `--enable-sand`, etc.). Tests disabled
|
||||
(`doCheck = false`) because the `imgutils` test fails on this build.
|
||||
|
||||
---
|
||||
|
||||
## systemd Service Overrides
|
||||
|
||||
### `systems/x86_64-linux/matt-nixos/default.nix` — networkd-wait-online
|
||||
**File:** `systems/x86_64-linux/matt-nixos/default.nix:78`
|
||||
**Status:** `INTENTIONAL`
|
||||
|
||||
```nix
|
||||
systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
|
||||
```
|
||||
|
||||
The `systemd-networkd-wait-online` service times out on this desktop,
|
||||
blocking boot. Standard workaround for desktop systems that don't require
|
||||
all interfaces to be up before proceeding.
|
||||
|
||||
---
|
||||
|
||||
### `systems/x86_64-linux/allyx/default.nix` — Jovian NixOS conflicts
|
||||
**File:** `systems/x86_64-linux/allyx/default.nix:121-123`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
```nix
|
||||
systemd-networkd-wait-online.enable = lib.mkForce false;
|
||||
power-profiles-daemon.enable = lib.mkForce false;
|
||||
inputplumber.enable = lib.mkForce false;
|
||||
```
|
||||
|
||||
On the ASUS ROG Ally X with Jovian NixOS and `handheld-daemon`:
|
||||
- `power-profiles-daemon` conflicts with `handheld-daemon`'s power management
|
||||
- `inputplumber` conflicts with `handheld-daemon`'s input handling
|
||||
- `systemd-networkd-wait-online` times out as on matt-nixos
|
||||
|
||||
---
|
||||
|
||||
### `modules/nixos/services/crowdsec/default.nix` — DynamicUser conflict
|
||||
**File:** `modules/nixos/services/crowdsec/default.nix:133-143`
|
||||
**Status:** `ACTIVE — UPSTREAM PENDING`
|
||||
|
||||
```nix
|
||||
systemd.services.crowdsec.serviceConfig.DynamicUser = lib.mkForce false;
|
||||
systemd.services.crowdsec-firewall-bouncer.serviceConfig.DynamicUser = lib.mkForce false;
|
||||
systemd.services.crowdsec-firewall-bouncer-register.serviceConfig.DynamicUser = lib.mkForce false;
|
||||
```
|
||||
|
||||
The upstream NixOS crowdsec module uses `ReadWritePaths` (not `StateDirectory`)
|
||||
on the main `crowdsec.service`, expecting `/var/lib/crowdsec` to be a real
|
||||
directory. However, `crowdsec-firewall-bouncer-register` declares
|
||||
`StateDirectory=crowdsec` with `DynamicUser=true`, which conflicts — it tries
|
||||
to create `/var/lib/private/crowdsec` and symlink `/var/lib/crowdsec` to it,
|
||||
but the directory already exists as a real path. Disabling `DynamicUser` on
|
||||
all three services resolves the conflict by using the real `crowdsec` user.
|
||||
|
||||
Additionally, `crowdsec-firewall-bouncer-register` calls `cscli` without `-c`,
|
||||
expecting `/etc/crowdsec/config.yaml` to exist, but the upstream NixOS module
|
||||
uses a Nix store path via `-c` and never creates that file. The module works
|
||||
around this by extracting the store path at eval time.
|
||||
|
||||
**Removal condition:** When the NixOS crowdsec module is fixed upstream to
|
||||
handle state directory ownership consistently.
|
||||
|
||||
---
|
||||
|
||||
## Incomplete / TODO Items
|
||||
|
||||
These are not workarounds but known incomplete configurations:
|
||||
|
||||
| File | Line | Description |
|
||||
|------|------|-------------|
|
||||
| `systems/x86_64-linux/jallen-nas/sops.nix` | 89, 113 | Collabora and MariaDB secrets not configured |
|
||||
| `systems/x86_64-linux/jallen-nas/apps.nix` | 47 | Authentik environment secrets file not wired up |
|
||||
| `modules/nixos/services/sparky-fitness/default.nix` | — | ~~DB passwords not yet moved to SOPS~~ — resolved; secrets now via `mkSopsEnvFile`; run `sops secrets/nas-secrets.yaml` to add real values for `jallen-nas/sparky-fitness/{db-password,api-encryption-key,auth-secret}` |
|
||||
| `modules/nixos/services/your-spotify/default.nix` | 36 | Spotify API keys not yet moved to SOPS |
|
||||
| `modules/nixos/services/booklore/default.nix` | 28 | Database password not yet a SOPS secret |
|
||||
| `packages/raspberrypi/udev-rules/default.nix` | 33 | `15-i2c-modprobe.rules` disabled; `i2cprobe` script not ported |
|
||||
| `modules/nixos/homeassistant/services/homeassistant/default.nix` | 214 | `roborock` integration marked broken |
|
||||
|
||||
---
|
||||
|
||||
## Kernel Boot Parameters
|
||||
|
||||
### `systems/x86_64-linux/matt-nixos/boot.nix` — NVMe power saving
|
||||
**File:** `systems/x86_64-linux/matt-nixos/boot.nix:46-48`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
```nix
|
||||
"nvme_core.default_ps_max_latency_us=0"
|
||||
"pcie_aspm=off"
|
||||
```
|
||||
|
||||
NVMe SSD power-saving states cause latency/stability issues on this machine.
|
||||
Disabling ASPM and NVMe power states is a standard workaround for affected
|
||||
hardware.
|
||||
|
||||
---
|
||||
|
||||
### `systems/aarch64-linux/macbook-pro-nixos/boot.nix` — Fan control
|
||||
**File:** `systems/aarch64-linux/macbook-pro-nixos/boot.nix:28`
|
||||
**Status:** `ACTIVE`
|
||||
|
||||
```nix
|
||||
"melt_my_mac=1"
|
||||
```
|
||||
|
||||
Undocumented Asahi Linux kernel parameter that enables fan control on Apple
|
||||
Silicon Macs. The name is intentional (set by the Asahi kernel developers).
|
||||
20
checks/pre-commit-hooks/default.nix
Normal file → Executable file
20
checks/pre-commit-hooks/default.nix
Normal file → Executable file
@@ -10,7 +10,13 @@ in
|
||||
pre-commit-hooks-nix.lib.${pkgs.stdenv.hostPlatform.system}.run {
|
||||
src = ../..;
|
||||
hooks = {
|
||||
pre-commit-hook-ensure-sops.enable = true;
|
||||
pre-commit-hook-ensure-sops = {
|
||||
enable = true;
|
||||
excludes = [
|
||||
"secrets/.*\\.jwe$"
|
||||
"secrets/.*\\.key$"
|
||||
];
|
||||
};
|
||||
treefmt = {
|
||||
enable = lib.mkForce true;
|
||||
settings.fail-on-change = lib.mkForce false;
|
||||
@@ -18,5 +24,17 @@ pre-commit-hooks-nix.lib.${pkgs.stdenv.hostPlatform.system}.run {
|
||||
lib.snowfall.fs.get-file "treefmt.nix"
|
||||
);
|
||||
};
|
||||
nixfmt-rfc-style = {
|
||||
enable = true;
|
||||
package = pkgs.nixfmt;
|
||||
};
|
||||
# statix disabled - too many false positives (manual_inherit warnings)
|
||||
# statix = {
|
||||
# enable = true;
|
||||
# args = [
|
||||
# "--config"
|
||||
# (lib.snowfall.fs.get-file "statix.toml")
|
||||
# ];
|
||||
# };
|
||||
};
|
||||
}
|
||||
|
||||
0
docs/README.md
Normal file → Executable file
0
docs/README.md
Normal file → Executable file
220
docs/architecture.md
Normal file → Executable file
220
docs/architecture.md
Normal file → Executable file
@@ -4,101 +4,177 @@ This document provides an overview of the repository architecture, explaining ho
|
||||
|
||||
## Overview
|
||||
|
||||
This NixOS configuration repository is built using [Nix Flakes](https://nixos.wiki/wiki/Flakes) and [Snowfall Lib](https://github.com/snowfallorg/lib) to provide a modular, maintainable configuration for multiple systems.
|
||||
This NixOS configuration repository is built using [Nix Flakes](https://nixos.wiki/wiki/Flakes) and [Snowfall Lib](https://github.com/snowfallorg/lib) to provide a modular, maintainable configuration for multiple systems. The Snowfall namespace is `mjallen`, so all custom options are accessed as `mjallen.<domain>.<name>`.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── checks/ # Pre-commit hooks and other checks
|
||||
├── flake.nix # Main flake configuration
|
||||
├── homes/ # Home-manager configurations for users
|
||||
│ ├── aarch64-darwin/ # macOS home configurations
|
||||
│ ├── aarch64-linux/ # ARM Linux home configurations
|
||||
│ └── x86_64-linux/ # x86 Linux home configurations
|
||||
├── flake.nix # Main flake — inputs, outputs, Snowfall config
|
||||
├── flake.lock # Locked dependency versions
|
||||
├── .sops.yaml # SOPS key management rules
|
||||
├── treefmt.nix # Code formatter configuration
|
||||
├── qemu.nix # QEMU VM testing config
|
||||
│
|
||||
├── checks/ # Pre-commit hooks and CI checks
|
||||
│
|
||||
├── docs/ # Documentation (this directory)
|
||||
│
|
||||
├── homes/ # Home Manager configurations
|
||||
│ ├── aarch64-darwin/ # macOS user configs
|
||||
│ ├── aarch64-linux/ # ARM Linux user configs
|
||||
│ └── x86_64-linux/ # x86 Linux user configs
|
||||
│
|
||||
├── lib/ # Custom Nix library utilities
|
||||
│ ├── module/ # mkModule, mkOpt, mkBoolOpt helpers
|
||||
│ ├── file/ # File/path utilities
|
||||
│ └── versioning/ # Package version pinning helpers
|
||||
│
|
||||
├── modules/ # Reusable configuration modules
|
||||
│ ├── home/ # Home-manager modules
|
||||
│ └── nixos/ # NixOS system modules
|
||||
│ ├── boot/ # Boot configuration modules
|
||||
│ ├── desktop/ # Desktop environment modules
|
||||
│ ├── hardware/ # Hardware-specific modules
|
||||
│ ├── homeassistant/ # Home Assistant modules
|
||||
│ ├── network/ # Network configuration modules
|
||||
│ ├── services/ # Service configuration modules
|
||||
│ └── ... # Other module categories
|
||||
│ ├── home/ # Home Manager modules
|
||||
│ ├── nixos/ # NixOS system modules
|
||||
│ └── darwin/ # nix-darwin modules (macOS)
|
||||
│
|
||||
├── overlays/ # Nixpkgs overlays
|
||||
│
|
||||
├── packages/ # Custom package definitions
|
||||
├── secrets/ # Encrypted secrets (managed with sops-nix)
|
||||
└── systems/ # System-specific configurations
|
||||
├── aarch64-darwin/ # macOS system configurations
|
||||
├── aarch64-linux/ # ARM Linux system configurations
|
||||
└── x86_64-linux/ # x86 Linux system configurations
|
||||
├── jallen-nas/ # NAS server configuration
|
||||
├── matt-nixos/ # Desktop configuration
|
||||
├── nuc-nixos/ # NUC configuration
|
||||
└── ... # Other system configurations
|
||||
│
|
||||
├── secrets/ # SOPS-encrypted secret files
|
||||
│
|
||||
└── systems/ # Per-host system configurations
|
||||
├── aarch64-darwin/ # macOS (nix-darwin) hosts
|
||||
├── aarch64-linux/ # ARM Linux hosts
|
||||
├── x86_64-install-iso/# Install ISO configurations
|
||||
└── x86_64-linux/ # x86_64 Linux hosts
|
||||
```
|
||||
|
||||
## Flake Structure
|
||||
## Flake Inputs
|
||||
|
||||
The `flake.nix` file defines the inputs (external dependencies) and outputs (configurations) of this repository:
|
||||
| Input | Source | Purpose |
|
||||
|---|---|---|
|
||||
| `nixpkgs-unstable` | `github:NixOS/nixpkgs/nixos-unstable` | Primary package set |
|
||||
| `nixpkgs-stable` | `github:NixOS/nixpkgs/nixos-25.11` | Stable package set |
|
||||
| `nixpkgs-otbr` | `github:mrene/nixpkgs` (fork) | OpenThread Border Router packages |
|
||||
| `home-manager-unstable` | `github:nix-community/home-manager` | User environment management |
|
||||
| `snowfall-lib` | `github:mjallen18/snowfall-lib` | Flake structure library (personal fork) |
|
||||
| `impermanence` | `github:nix-community/impermanence` | Ephemeral root filesystem support |
|
||||
| `lanzaboote` | `github:nix-community/lanzaboote/v1.0.0` | Secure Boot |
|
||||
| `nixos-hardware` | `github:NixOS/nixos-hardware` | Hardware-specific NixOS configs |
|
||||
| `sops-nix` | `github:Mic92/sops-nix` | Secret management |
|
||||
| `disko` | `github:nix-community/disko` | Declarative disk partitioning |
|
||||
| `cosmic` | `github:lilyinstarlight/nixos-cosmic` | COSMIC desktop environment |
|
||||
| `jovian` | `github:Jovian-Experiments/Jovian-NixOS` | Steam Deck / handheld support |
|
||||
| `nixos-apple-silicon` | `github:nix-community/nixos-apple-silicon` | Asahi Linux / Apple Silicon |
|
||||
| `darwin` | `github:nix-darwin/nix-darwin` | macOS system configuration |
|
||||
| `nix-homebrew` | `github:zhaofengli/nix-homebrew` | Declarative Homebrew (macOS) |
|
||||
| `stylix` | `github:nix-community/stylix` | System-wide theming |
|
||||
| `nix-vscode-extensions` | `github:nix-community/nix-vscode-extensions` | VS Code extension packages |
|
||||
| `authentik-nix` | `github:nix-community/authentik-nix` | Authentik SSO |
|
||||
| `nix-cachyos-kernel` | `github:xddxdd/nix-cachyos-kernel` | CachyOS optimised kernels |
|
||||
| `lsfg-vk` | `github:pabloaul/lsfg-vk-flake` | Lossless Scaling frame generation (Linux) |
|
||||
| `nix-index-database` | `github:nix-community/nix-index-database` | Pre-built nix-index database |
|
||||
| `steam-rom-manager` | `github:mjallen18/nix-steam-rom-manager` | Steam ROM Manager package |
|
||||
| `nix-plist-manager` | `github:sushydev/nix-plist-manager` | macOS plist management |
|
||||
| `nix-rosetta-builder` | `github:cpick/nix-rosetta-builder` | Rosetta build support (macOS) |
|
||||
| `pre-commit-hooks-nix` | `github:cachix/pre-commit-hooks.nix` | Pre-commit hooks |
|
||||
| `treefmt-nix` | `github:numtide/treefmt-nix` | Code formatting |
|
||||
|
||||
### Inputs
|
||||
|
||||
- **nixpkgs-unstable**: The unstable channel of Nixpkgs
|
||||
- **nixpkgs-stable**: The stable channel of Nixpkgs (25.11)
|
||||
- **home-manager**: User environment management
|
||||
- **snowfall-lib**: Library for structuring flake repositories
|
||||
- **impermanence**: Persistent state management
|
||||
- **lanzaboote**: Secure boot implementation
|
||||
- **nixos-hardware**: Hardware-specific configurations
|
||||
- **sops-nix**: Secret management
|
||||
- **disko**: Disk partitioning and formatting
|
||||
- **And more specialized inputs**
|
||||
|
||||
### Outputs
|
||||
|
||||
The outputs are generated using Snowfall Lib's `mkFlake` function, which automatically discovers and assembles:
|
||||
|
||||
- **NixOS system configurations**: For each system in the `systems/` directory
|
||||
- **Home Manager configurations**: For each configuration in the `homes/` directory
|
||||
- **Packages**: From the `packages/` directory
|
||||
- **Modules**: From the `modules/` directory
|
||||
- **Overlays**: From the `overlays/` directory
|
||||
`nixpkgs` and `home-manager` are aliases pointing to the unstable variants.
|
||||
|
||||
## Module System
|
||||
|
||||
The module system uses a modular approach where:
|
||||
### Structure
|
||||
|
||||
1. **Common modules** are defined in `modules/nixos/` and `modules/home/`
|
||||
2. **System-specific modules** are defined in `systems/<architecture>/<hostname>/`
|
||||
All modules follow a standard Snowfall Lib pattern and are automatically discovered. Each module exposes options under the `mjallen` namespace:
|
||||
|
||||
Each module follows the NixOS module pattern, with:
|
||||
- `default.nix`: Main module implementation
|
||||
- `options.nix`: Option declarations
|
||||
```nix
|
||||
# Enable a module
|
||||
mjallen.services.jellyfin.enable = true;
|
||||
mjallen.desktop.gnome.enable = true;
|
||||
mjallen.hardware.amd.enable = true;
|
||||
```
|
||||
|
||||
## Integration with Snowfall Lib
|
||||
### `mkModule` helper
|
||||
|
||||
Snowfall Lib provides:
|
||||
1. **Automatic discovery** of modules, overlays, and packages
|
||||
2. **Consistent structure** across the repository
|
||||
3. **Common utilities** for working with flakes
|
||||
Most service modules are built with `lib.mjallen.mkModule` (`lib/module/default.nix`), which provides a standard set of options:
|
||||
|
||||
| Option | Default | Description |
|
||||
|---|---|---|
|
||||
| `enable` | `false` | Enable/disable the module |
|
||||
| `port` | `80` | Service listen port |
|
||||
| `listenAddress` | `"0.0.0.0"` | Bind address |
|
||||
| `openFirewall` | `true` | Open firewall ports |
|
||||
| `configDir` | `/var/lib/<name>` | Config directory |
|
||||
| `dataDir` | `/var/lib/<name>/data` | Data directory |
|
||||
| `createUser` | `false` | Create a dedicated system user |
|
||||
| `configureDb` | `false` | Create a PostgreSQL database |
|
||||
| `environmentFile` | `null` | Path to an env-file |
|
||||
| `reverseProxy.enable` | `false` | Add a Caddy reverse proxy block |
|
||||
| `reverseProxy.subdomain` | `<name>` | Caddy subdomain |
|
||||
| `redis.enable` | `false` | Create a dedicated Redis instance |
|
||||
|
||||
### NixOS modules (`modules/nixos/`)
|
||||
|
||||
| Category | Paths | Description |
|
||||
|---|---|---|
|
||||
| Boot | `boot/common/`, `boot/lanzaboote/`, `boot/plymouth/`, `boot/systemd-boot/` | Bootloader configurations |
|
||||
| Desktop | `desktop/gnome/`, `desktop/hyprland/`, `desktop/cosmic/` | Desktop environments |
|
||||
| Development | `development/` | Dev tools, language support, containers |
|
||||
| Hardware | `hardware/amd/`, `hardware/nvidia/`, `hardware/battery/`, `hardware/raspberry-pi/`, `hardware/openrgb/`, ... | Hardware-specific configs |
|
||||
| Headless | `headless/` | Headless server profile (watchdog, no suspend) |
|
||||
| Home Assistant | `homeassistant/` | Smart home automation suite |
|
||||
| Impermanence | `impermanence/` | Ephemeral root + persistent state |
|
||||
| Monitoring | `monitoring/` | Prometheus/Grafana metrics |
|
||||
| Network | `network/` | Hostname, firewall, NetworkManager, static IP |
|
||||
| Power | `power/` | UPS support |
|
||||
| Programs | `programs/` | System-wide programs (nix-index, gnupg, etc.) |
|
||||
| Security | `security/common/`, `security/tpm/` | Common hardening, TPM unlock |
|
||||
| Services | `services/<name>/` | ~50 self-hosted service modules (see below) |
|
||||
| SOPS | `sops/` | Secret management setup |
|
||||
| System | `system/` | Miscellaneous system settings |
|
||||
| User | `user/` | User account management |
|
||||
| Virtualization | `virtualization/` | libvirt, containers |
|
||||
|
||||
### Home Manager modules (`modules/home/`)
|
||||
|
||||
| Category | Paths | Description |
|
||||
|---|---|---|
|
||||
| Desktop | `desktop/gnome/`, `desktop/theme/` | GNOME and theming |
|
||||
| GPG | `gpg/` | GPG agent configuration |
|
||||
| Programs | `programs/btop/`, `programs/git/`, `programs/zsh/`, `programs/kitty/`, `programs/waybar/`, `programs/hyprland/`, `programs/wofi/`, `programs/mako/`, `programs/wlogout/`, `programs/librewolf/`, `programs/opencode/`, `programs/update-checker/`, ... | User applications |
|
||||
| Services | `services/pass/` | Password store integration |
|
||||
| Shell | `shell-aliases/` | Common shell aliases |
|
||||
| SOPS | `sops/` | User-level secret integration |
|
||||
| Stylix | `stylix/` | System-wide theming |
|
||||
| User | `user/` | User environment defaults |
|
||||
|
||||
## Secrets Management
|
||||
|
||||
Secrets are managed using [sops-nix](https://github.com/Mic92/sops-nix), with:
|
||||
- Encrypted secret files in the `secrets/` directory
|
||||
- `.sops.yaml` configuration file in the root
|
||||
- Key management integrated into the configuration
|
||||
Secrets are encrypted with [SOPS](https://github.com/getsops/sops) using age keys derived from each machine's SSH host key (`/etc/ssh/ssh_host_ed25519_key`). The `.sops.yaml` file maps secret file path patterns to the set of age recipients that can decrypt them.
|
||||
|
||||
## Deployment Process
|
||||
Each host has its own secrets file:
|
||||
|
||||
| File | Host |
|
||||
|---|---|
|
||||
| `secrets/secrets.yaml` | Shared (all hosts) |
|
||||
| `secrets/nas-secrets.yaml` | jallen-nas |
|
||||
| `secrets/pi5-secrets.yaml` | pi5 |
|
||||
| `secrets/allyx-secrets.yaml` | allyx |
|
||||
| `secrets/nuc-secrets.yaml` | nuc-nixos |
|
||||
| `secrets/mac-secrets.yaml` | macbook-pro-nixos |
|
||||
| `secrets/desktop-secrets.yaml` | matt-nixos |
|
||||
|
||||
See the [Secrets Management](../README.md#secrets-management) section of the root README for full details on generating keys and adding secrets.
|
||||
|
||||
## Deployment
|
||||
|
||||
Systems are built and deployed using:
|
||||
```bash
|
||||
nixos-rebuild switch --flake .#hostname
|
||||
```
|
||||
# NixOS system
|
||||
sudo nixos-rebuild switch --flake .#hostname
|
||||
|
||||
This command:
|
||||
1. Evaluates the flake for the specified hostname
|
||||
2. Builds the resulting configuration
|
||||
3. Activates it on the current system
|
||||
# macOS (nix-darwin)
|
||||
darwin-rebuild switch --flake .#hostname
|
||||
|
||||
# Home Manager only
|
||||
home-manager switch --flake .#username@hostname
|
||||
```
|
||||
|
||||
348
docs/flake-improvements.md
Executable file
348
docs/flake-improvements.md
Executable file
@@ -0,0 +1,348 @@
|
||||
# Flake Improvement Suggestions
|
||||
|
||||
A methodical review of the flake against what Snowfall Lib provides and what the codebase currently does. Suggestions are grouped by theme and ordered roughly from highest to lowest impact.
|
||||
|
||||
---
|
||||
|
||||
## 1. Flake-level: HM module registration — single source of truth via snowfall-lib fix
|
||||
|
||||
**Root cause discovered**: Snowfall Lib's `mkFlake` previously merged `systems.modules.home` into `homes` only for standalone `homeConfigurations`. The `homes` attrset passed to `create-systems` (which builds `nixosConfigurations`) was the raw unmerged value, so `systems.modules.home` had no effect on NixOS-integrated homes.
|
||||
|
||||
**Fix applied**: Patched the personal snowfall-lib fork (`github:mjallen18/snowfall-lib`) to extract the merge into a shared `homes-with-system-modules` binding and pass it to both `create-homes` (standalone) and `create-systems` (NixOS-integrated). `flake.lock` updated to the new commit.
|
||||
|
||||
`modules/nixos/home/default.nix` no longer needs `sharedModules` — `systems.modules.home` in `flake.nix` is now the single authoritative list for all contexts.
|
||||
|
||||
---
|
||||
|
||||
## 2. Flake-level: Duplicated Darwin HM module registration
|
||||
|
||||
**Problem**: Same issue as above for Darwin. `flake.nix:160–167` registers Darwin HM modules via `systems.modules.darwin`, but none of those are actually Home Manager modules — `nix-homebrew`, `home-manager.darwinModules.home-manager`, `nix-plist-manager`, `nix-rosetta-builder`, `nix-index-database`, and `stylix.darwinModules.stylix` are all NixOS-style Darwin system modules, not HM `sharedModules`. This is the correct place for them. The `modules/darwin/home/default.nix` module handles the Darwin-side HM bridge.
|
||||
|
||||
**No change needed here**, but add a comment to clarify why this list stays in `flake.nix` while the `modules.home` list should move:
|
||||
|
||||
```nix
|
||||
# Common darwin system-level modules (not HM sharedModules — those live in modules/darwin/home/)
|
||||
modules.darwin = with inputs; [ ... ];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. System-level: Repeated nebula lighthouse config
|
||||
|
||||
**Problem**: Three systems (`matt-nixos`, `allyx`, `macbook-pro-nixos`) each independently spell out the same lighthouse peer config:
|
||||
|
||||
```nix
|
||||
# Repeated verbatim in 3 files:
|
||||
lighthouses = [ "10.1.1.1" ];
|
||||
staticHostMap = {
|
||||
"10.1.1.1" = [ "mjallen.dev:4242" ];
|
||||
};
|
||||
port = 4242;
|
||||
```
|
||||
|
||||
**Suggestion**: Add defaults to `modules/nixos/services/nebula/default.nix` options so that non-lighthouse nodes don't need to spell this out. Since this is a personal network with one lighthouse, the defaults can encode that:
|
||||
|
||||
```nix
|
||||
# In nebula/default.nix options:
|
||||
lighthouses = lib.mjallen.mkOpt (types.listOf types.str) [ "10.1.1.1" ]
|
||||
"Nebula overlay IPs of lighthouse nodes";
|
||||
|
||||
staticHostMap = lib.mjallen.mkOpt (types.attrsOf (types.listOf types.str))
|
||||
{ "10.1.1.1" = [ "mjallen.dev:4242" ]; }
|
||||
"Static host map";
|
||||
|
||||
port = lib.mjallen.mkOpt types.port 4242 "Nebula listen port";
|
||||
```
|
||||
|
||||
Client systems can then reduce to:
|
||||
|
||||
```nix
|
||||
services.nebula = {
|
||||
enable = true;
|
||||
secretsPrefix = "matt-nixos/nebula";
|
||||
secretsFile = lib.snowfall.fs.get-file "secrets/desktop-secrets.yaml";
|
||||
hostSecretName = "matt-nixos";
|
||||
};
|
||||
```
|
||||
|
||||
The lighthouse (`pi5`) already overrides `isLighthouse = true` and doesn't set `lighthouses`/`staticHostMap`, so it would be unaffected.
|
||||
|
||||
---
|
||||
|
||||
## 4. System-level: `systemd-networkd-wait-online` scattered disablement
|
||||
|
||||
**Problem**: `systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false` appears in:
|
||||
|
||||
- `systems/x86_64-linux/matt-nixos/default.nix:92`
|
||||
- `systems/x86_64-linux/allyx/default.nix:135`
|
||||
|
||||
`modules/nixos/network/default.nix` already disables `NetworkManager-wait-online` and `systemd.network.wait-online`, but not `systemd-networkd-wait-online`. These are the same underlying concern.
|
||||
|
||||
**Suggestion**: Add `systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;` unconditionally to `modules/nixos/network/default.nix` alongside the existing `NetworkManager-wait-online` disablement (line 89). Remove the per-system overrides.
|
||||
|
||||
---
|
||||
|
||||
## 5. System-level: `coolercontrol` and GNOME desktop environment variables
|
||||
|
||||
**Problem**: Two systems (`matt-nixos:91`, `allyx:82`) share identical config blocks:
|
||||
|
||||
```nix
|
||||
programs.coolercontrol.enable = true;
|
||||
|
||||
environment.variables = {
|
||||
GDK_SCALE = "1";
|
||||
EDITOR = "${lib.getExe' pkgs.vscodium "codium"} --wait";
|
||||
VISUAL = "${lib.getExe' pkgs.vscodium "codium"} --wait";
|
||||
};
|
||||
```
|
||||
|
||||
These belong to a desktop AMD gaming profile, not to the system configs themselves.
|
||||
|
||||
**Suggestions** (pick one or both):
|
||||
|
||||
- **A** — Add a `coolercontrol.enable` option to `modules/nixos/hardware/amd/default.nix` (default `false`) and wire `programs.coolercontrol.enable` inside it. Each system opts in with `hardware.amd.coolercontrol.enable = true`.
|
||||
- **B** — Add `vscodium` as the default `EDITOR`/`VISUAL` to `modules/nixos/desktop/gnome/default.nix` behind a `vscodium.enable` option (default `false`). The two systems that want it set `desktop.gnome.vscodium.enable = true`.
|
||||
- **C** — Create a shared `modules/nixos/desktop/common/default.nix` (or `profiles/desktop.nix`) that both GNOME and Hyprland modules consume, and put `GDK_SCALE` there.
|
||||
|
||||
---
|
||||
|
||||
## 6. System-level: `networking.networkmanager.wifi.backend = "iwd"` bypass
|
||||
|
||||
**Problem**: `matt-nixos:100` and `allyx:140` set `networking.networkmanager.wifi.backend = "iwd"` directly, bypassing the `${namespace}.network.iwd.enable` option that the `network` module already provides.
|
||||
|
||||
Looking at `modules/nixos/network/default.nix:143–154`, enabling `cfg.iwd.enable` does set this value via `mkForce`, but it also forces `networkmanager.enable = mkForce false` — which is unwanted on these systems that use NetworkManager with the iwd backend.
|
||||
|
||||
**Root cause**: The module conflates "use iwd" (the WiFi daemon) with "disable NetworkManager" (the connection manager). These are separate concerns. NetworkManager can use iwd as its WiFi backend while still being the connection manager.
|
||||
|
||||
**Suggestion**: Restructure the `network` module's iwd handling:
|
||||
|
||||
```nix
|
||||
# Instead of forcing NM off when iwd is enabled:
|
||||
networking = {
|
||||
wireless.iwd.enable = cfg.iwd.enable;
|
||||
networkmanager = mkIf cfg.networkmanager.enable {
|
||||
enable = true;
|
||||
wifi.backend = mkIf cfg.iwd.enable "iwd";
|
||||
# ... rest of NM config
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Then the per-system lines become:
|
||||
|
||||
```nix
|
||||
${namespace}.network = {
|
||||
hostName = "matt-nixos";
|
||||
iwd.enable = true;
|
||||
networkmanager.enable = true;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. System-level: `fileSystems."/etc".neededForBoot` not in impermanence module
|
||||
|
||||
**Problem**: `fileSystems."/etc".neededForBoot = true` is set manually in four system configs (`nuc-nixos`, `pi5`, `jallen-nas`, `graphical`). This is a prerequisite of impermanence (tmpfs root), not a per-system choice.
|
||||
|
||||
**Suggestion**: Add to `modules/nixos/impermanence/default.nix`:
|
||||
|
||||
```nix
|
||||
config = mkIf cfg.enable {
|
||||
fileSystems."/etc".neededForBoot = true;
|
||||
# ... existing config
|
||||
};
|
||||
```
|
||||
|
||||
Then remove the manual setting from each system. (`macbook-pro-nixos` and `matt-nixos` may already have this in their `filesystems.nix` — verify and remove duplicates there too.)
|
||||
|
||||
---
|
||||
|
||||
## 8. System-level: `system.stateVersion` and `time.timeZone` should be module options
|
||||
|
||||
**Problem**: In `modules/nixos/system/default.nix`:
|
||||
|
||||
- Line 3: `timezone = "America/Chicago"` is hardcoded
|
||||
- Line 54: `system.stateVersion = "23.11"` is hardcoded
|
||||
|
||||
Both are set unconditionally for every system with no way to override without using `lib.mkForce`.
|
||||
|
||||
**Suggestions**:
|
||||
|
||||
```nix
|
||||
# modules/nixos/system/default.nix
|
||||
{ config, lib, namespace, pkgs, system, ... }:
|
||||
let
|
||||
cfg = config.${namespace}.system;
|
||||
in
|
||||
{
|
||||
options.${namespace}.system = {
|
||||
timezone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "America/Chicago";
|
||||
description = "System timezone";
|
||||
};
|
||||
stateVersion = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "23.11";
|
||||
description = "NixOS state version. Should match the version used when the system was first installed.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
time.timeZone = cfg.timezone;
|
||||
system.stateVersion = cfg.stateVersion;
|
||||
# ... packages
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This maintains the current default for all systems (no change required) while allowing any system to say `${namespace}.system.stateVersion = "24.05"` cleanly.
|
||||
|
||||
---
|
||||
|
||||
## 9. Module-level: Darwin and NixOS `nix` modules share ~90% of their content
|
||||
|
||||
**Problem**: `modules/darwin/nix/default.nix` and `modules/nixos/nix/default.nix` differ only in:
|
||||
- Darwin lacks `daemonCPUSchedPolicy`/`daemonIOSchedClass`/`daemonIOSchedPriority`
|
||||
- Darwin lacks the `systemd.services.nix-gc.serviceConfig` block
|
||||
- Darwin lacks `cudaSupport`/`rocmSupport` in `nixpkgs.config`
|
||||
- Darwin's substituters list omits `attic.xuyh0120.win/lantian`
|
||||
|
||||
Everything else — substituters, trusted keys, `warn-dirty`, `experimental-features`, `trusted-users`, `builders-use-substitutes`, `connect-timeout`, `fallback`, `log-lines`, `max-free`, `min-free`, GC settings, `optimise` — is identical.
|
||||
|
||||
**Suggestion**: Extract a shared Nix attrset into `lib/nix-settings/default.nix` (or a plain `.nix` file imported by both):
|
||||
|
||||
```nix
|
||||
# lib/nix-settings/default.nix
|
||||
{ lib }:
|
||||
{
|
||||
commonSubstituters = [
|
||||
"http://jallen-nas.local:9012/nas-cache"
|
||||
"https://nixos-apple-silicon.cachix.org"
|
||||
"https://nixos-raspberrypi.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
commonTrustedPublicKeys = [ ... ];
|
||||
commonSettings = { warn-dirty = ...; experimental-features = ...; ... };
|
||||
commonGc = { automatic = true; options = "--delete-older-than 30d"; };
|
||||
}
|
||||
```
|
||||
|
||||
Both modules import and spread this. The NixOS module adds scheduler policies and systemd GC service tweaks on top.
|
||||
|
||||
---
|
||||
|
||||
## 10. Module-level: Home SOPS configuration is inconsistent across homes
|
||||
|
||||
**Problem**: Three different patterns are used to configure SOPS in home configs:
|
||||
|
||||
1. **`${namespace}.sops.enable = true`** — uses the module at `modules/home/sops/default.nix` (macbook-pro-nixos home, jallen-nas home)
|
||||
2. **Inline SOPS config** — sets `sops.*` directly (allyx home, pi5 home)
|
||||
3. **Nothing** — some homes don't configure sops at all (matt-nixos home relies on system-level secrets only)
|
||||
|
||||
The `modules/home/sops/default.nix` module already handles the `age.keyFile` path, `defaultSopsFile`, and SSH key setup. The inline patterns duplicate this.
|
||||
|
||||
**Suggestion**: Migrate all homes that configure sops inline to use `${namespace}.sops.enable = true`. If the home needs a different `defaultSopsFile` (e.g. pi5 uses `secrets/pi5-secrets.yaml`), that should be a module option:
|
||||
|
||||
```nix
|
||||
# modules/home/sops/default.nix — add option:
|
||||
options.${namespace}.sops = {
|
||||
enable = lib.mkEnableOption "home sops";
|
||||
defaultSopsFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null; # falls back to global secrets.yaml
|
||||
description = "Override the default SOPS file for this home";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Module-level: `modules/nixos/home/default.nix` — `home-manager` input key coupling
|
||||
|
||||
**Problem**: `systems.modules.nixos` in `flake.nix:147` explicitly includes `home-manager.nixosModules.home-manager`. However Snowfall Lib **automatically** injects the home-manager NixOS module when the `home-manager` input is present and there are home configurations (Snowfall Lib `system/default.nix` lines 265–270).
|
||||
|
||||
**Suggestion**: Verify (by temporarily removing the explicit entry) whether `home-manager.nixosModules.home-manager` can be dropped from `systems.modules.nixos`. If Snowfall Lib handles this automatically, removing it eliminates the manual coupling.
|
||||
|
||||
---
|
||||
|
||||
## 12. System-level: `nuc-nixos` — large monolithic default.nix
|
||||
|
||||
**Problem**: `systems/x86_64-linux/nuc-nixos/default.nix` is over 330 lines and contains everything inline: disk config, networking, Home Assistant dashboard definitions (~170 lines of inline Nix), kernel config, user setup, and services. Every other complex system (jallen-nas) already uses a split structure with `apps.nix`, `services.nix`, `nas-defaults.nix`, etc.
|
||||
|
||||
**Suggestion**: Extract into separate files following the jallen-nas pattern:
|
||||
|
||||
```
|
||||
systems/x86_64-linux/nuc-nixos/
|
||||
├── default.nix # thin: imports + top-level options
|
||||
├── boot.nix # disk/luks/filesystem config
|
||||
├── dashboard.nix # Home Assistant dashboard card definitions
|
||||
├── services.nix # postgres, redis, HA, OTBR etc.
|
||||
└── sops.nix # (or reuse the shared module)
|
||||
```
|
||||
|
||||
The dashboard in particular (currently lines ~88–260) should be isolated so HA configuration changes don't require touching system-level config.
|
||||
|
||||
---
|
||||
|
||||
## 13. System-level: Verify `admin@jallen-nas` steam-rom-manager double-import
|
||||
|
||||
**Problem**: `homes/x86_64-linux/admin@jallen-nas/default.nix:16` explicitly imports `steam-rom-manager.homeManagerModules.default`. This same module is injected globally via `modules/nixos/home/default.nix:92` for all x86_64 systems (the ARM guard is `!isArm`, and jallen-nas is x86_64).
|
||||
|
||||
**Suggestion**: Remove the explicit import from `admin@jallen-nas/default.nix`. If it was added for standalone `home-manager switch` builds (without NixOS), document that reason in a comment rather than keeping a potentially conflicting double-import.
|
||||
|
||||
---
|
||||
|
||||
## 14. Flake-level: `pi5` host entry with empty modules list
|
||||
|
||||
**Problem**: `flake.nix:218–221` defines:
|
||||
|
||||
```nix
|
||||
pi5 = {
|
||||
modules = [ ];
|
||||
};
|
||||
```
|
||||
|
||||
An empty modules list is the default behavior — this entry has no effect and can be removed. The comment `# disko is already in systems.modules.nixos above` is incorrect (disko is global for all systems, not specific to pi5). The comment itself is misleading.
|
||||
|
||||
**Suggestion**: Remove the `pi5` host entry from `flake.nix` entirely. If the comment is meant to remind future maintainers that disko is global, move that context to `AGENTS.md` or a comment near the global `systems.modules.nixos` list.
|
||||
|
||||
---
|
||||
|
||||
## 15. Flake-level: `home-manager-stable` input is pulled in but never used
|
||||
|
||||
**Problem**: `flake.nix:10–13` defines `home-manager-stable` but `home-manager = home-manager-unstable` is the alias (line 21). No system or module references `home-manager-stable` directly. It adds to lock file churn and evaluation time.
|
||||
|
||||
**Suggestion**: Remove `home-manager-stable` unless there is a concrete plan to use it for a stable-channel system. If stable Home Manager support is desired in the future, add it back at that point.
|
||||
|
||||
---
|
||||
|
||||
## 16. Flake-level: Consider using Snowfall Lib `alias` for formatter output
|
||||
|
||||
**Problem**: The `outputs-builder` in `flake.nix:277–280` is used only to register the `treefmt` formatter. Snowfall Lib supports an `alias` mechanism and also allows `outputs-builder` to be used, but this is the only use of `outputs-builder` in the entire flake.
|
||||
|
||||
**Suggestion**: This is fine as-is, but note that `outputs-builder` output can be overridden by auto-discovery. Since the formatter isn't auto-discovered, `outputs-builder` is the correct approach. No change needed — but the comment on line 279 about the mjallen-lib overlay being auto-discovered is accurate and good to keep.
|
||||
|
||||
---
|
||||
|
||||
## Summary Table
|
||||
|
||||
| # | Location | Type | Effort | Impact |
|
||||
|---|----------|------|--------|--------|
|
||||
| 1 | `flake.nix` | Deduplication | Low | High — removes confusing double-registration |
|
||||
| 2 | `flake.nix` | Documentation | Low | Low |
|
||||
| 3 | `nebula/default.nix` | Better defaults | Low | Medium — 3 systems simplified |
|
||||
| 4 | `network/default.nix` | Consolidation | Low | Medium — remove per-system workarounds |
|
||||
| 5 | `hardware/amd` + `desktop/gnome` | New options | Medium | Medium — DRY gaming desktop profile |
|
||||
| 6 | `network/default.nix` | Bug fix / refactor | Medium | High — current iwd handling is incorrect |
|
||||
| 7 | `impermanence/default.nix` | Consolidation | Low | Medium — remove 4 manual entries |
|
||||
| 8 | `system/default.nix` | New options | Low | Medium — allows per-system overrides cleanly |
|
||||
| 9 | `lib/` + `darwin/nix` + `nixos/nix` | Extraction | Medium | Medium — single source of truth for nix config |
|
||||
| 10 | `homes/*/` + `modules/home/sops` | Consistency | Low | Low — consistency improvement |
|
||||
| 11 | `flake.nix` | Simplification | Low | Low — possible dead entry |
|
||||
| 12 | `systems/nuc-nixos/` | Refactor | Medium | High — maintainability |
|
||||
| 13 | `homes/admin@jallen-nas` | Bug fix | Trivial | Low — potential double-import |
|
||||
| 14 | `flake.nix` | Cleanup | Trivial | Low — dead code |
|
||||
| 15 | `flake.nix` | Cleanup | Trivial | Low — reduces lock churn |
|
||||
| 16 | `flake.nix` | N/A | None | No change needed |
|
||||
245
docs/getting-started.md
Normal file → Executable file
245
docs/getting-started.md
Normal file → Executable file
@@ -6,167 +6,170 @@ This guide will help you get started with this NixOS configuration repository.
|
||||
|
||||
- Basic knowledge of NixOS and the Nix language
|
||||
- Git installed on your system
|
||||
- Physical access to the machine you want to configure
|
||||
- Physical or SSH access to the target machine
|
||||
|
||||
## Initial Setup
|
||||
|
||||
### 1. Cloning the Repository
|
||||
|
||||
Clone this repository to your local machine:
|
||||
## Cloning the Repository
|
||||
|
||||
```bash
|
||||
git clone ssh://nix-apps@localhost:2222/mjallen/nix-config.git
|
||||
cd nix-config
|
||||
```
|
||||
|
||||
### 2. Setting Up a New System
|
||||
## Installing on a New Machine
|
||||
|
||||
#### Option 1: Using an Existing Configuration
|
||||
### Option 1: Using an existing system configuration
|
||||
|
||||
If you're setting up a new machine that should be identical to an existing configuration:
|
||||
If the machine matches an existing configuration (e.g. reinstalling `jallen-nas`):
|
||||
|
||||
1. Boot from a NixOS installation media
|
||||
2. Mount your target partitions to `/mnt`
|
||||
3. Clone this repository:
|
||||
1. Boot from a NixOS installation ISO
|
||||
2. Partition and mount disks (or use `disko`):
|
||||
```bash
|
||||
nixos-enter
|
||||
cd /mnt
|
||||
mkdir -p /mnt/etc/nixos
|
||||
git clone ssh://nix-apps@localhost:2222/mjallen/nix-config.git /mnt/etc/nixos
|
||||
nix run github:nix-community/disko -- --mode disko /path/to/disko-config.nix
|
||||
```
|
||||
4. Install NixOS with the desired system profile:
|
||||
3. Clone this repo into the target:
|
||||
```bash
|
||||
mkdir -p /mnt/etc/nixos
|
||||
git clone <repo-url> /mnt/etc/nixos
|
||||
```
|
||||
4. Install:
|
||||
```bash
|
||||
nixos-install --flake /mnt/etc/nixos#hostname
|
||||
```
|
||||
Replace `hostname` with the target system name (e.g., `matt-nixos`, `jallen-nas`, etc.)
|
||||
|
||||
#### Option 2: Creating a New System Configuration
|
||||
### Option 2: Adding a new system configuration
|
||||
|
||||
If you're adding a completely new system:
|
||||
|
||||
1. Create a new directory for your system configuration:
|
||||
1. **Create the system directory** under the appropriate architecture:
|
||||
```bash
|
||||
mkdir -p systems/$(uname -m)-linux/new-hostname
|
||||
mkdir -p systems/x86_64-linux/new-hostname
|
||||
```
|
||||
|
||||
2. Create the basic configuration files:
|
||||
```bash
|
||||
cat > systems/$(uname -m)-linux/new-hostname/default.nix << EOF
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
2. **Write the configuration** — at minimum a `default.nix`:
|
||||
```nix
|
||||
{ namespace, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
# Add other needed module imports here
|
||||
];
|
||||
|
||||
networking.hostName = "new-hostname";
|
||||
|
||||
# Add your system-specific configuration here
|
||||
mjallen = {
|
||||
sops.enable = true;
|
||||
network.hostName = "new-hostname";
|
||||
user.name = "admin";
|
||||
};
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
3. Generate the hardware configuration:
|
||||
3. **Generate hardware configuration** (on the target machine):
|
||||
```bash
|
||||
nixos-generate-config --no-filesystems --dir systems/$(uname -m)-linux/new-hostname/
|
||||
nixos-generate-config --no-filesystems --dir systems/x86_64-linux/new-hostname/
|
||||
```
|
||||
|
||||
4. Add your new system to the flake by adding it to the `hosts` section in `flake.nix`
|
||||
4. **Add SOPS secrets** for the new host — see [Secrets Management](../README.md#secrets-management).
|
||||
|
||||
5. Build and install the configuration:
|
||||
5. **Build and switch**:
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake .#new-hostname
|
||||
```
|
||||
|
||||
## Secret Management
|
||||
## Day-to-Day Usage
|
||||
|
||||
### Setting Up Sops-Nix
|
||||
|
||||
1. Create a GPG key if you don't already have one:
|
||||
```bash
|
||||
gpg --full-generate-key
|
||||
```
|
||||
|
||||
2. Add your key to `.sops.yaml`:
|
||||
```bash
|
||||
# Get your key fingerprint
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
|
||||
# Edit the .sops.yaml file to add your key
|
||||
```
|
||||
|
||||
3. Create a new encrypted secret:
|
||||
```bash
|
||||
sops secrets/newsecret.yaml
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Updating the Repository
|
||||
### Applying configuration changes
|
||||
|
||||
```bash
|
||||
git pull
|
||||
sudo nixos-rebuild switch --flake .#hostname
|
||||
# On the local machine
|
||||
sudo nixos-rebuild switch --flake .#$(hostname)
|
||||
|
||||
# On a remote machine
|
||||
nixos-rebuild switch --flake .#hostname --target-host user@host --use-remote-sudo
|
||||
```
|
||||
|
||||
### Adding a New Package
|
||||
### Updating flake inputs
|
||||
|
||||
1. For standard packages, add them to your system or home configuration:
|
||||
```bash
|
||||
# Update all inputs
|
||||
nix flake update
|
||||
|
||||
# Update a single input
|
||||
nix flake lock --update-input nixpkgs
|
||||
|
||||
# Apply after updating
|
||||
sudo nixos-rebuild switch --flake .#$(hostname)
|
||||
```
|
||||
|
||||
### Garbage collection
|
||||
|
||||
```bash
|
||||
# Remove old generations and unreferenced store paths
|
||||
sudo nix-collect-garbage -d
|
||||
|
||||
# Keep the last N generations
|
||||
sudo nix-collect-garbage --delete-older-than 30d
|
||||
```
|
||||
|
||||
## Enabling a Module
|
||||
|
||||
Most functionality is exposed through the `mjallen` namespace. To enable a module, set it in the system's `default.nix` (or a relevant sub-file):
|
||||
|
||||
```nix
|
||||
mjallen = {
|
||||
desktop.gnome.enable = true;
|
||||
hardware.amd.enable = true;
|
||||
gaming.enable = true;
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
port = 8096;
|
||||
reverseProxy.enable = true;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
See [Custom Modules](./modules/README.md) for the full list of available modules and options.
|
||||
|
||||
## Adding a New Service Module
|
||||
|
||||
1. **Create the module directory**:
|
||||
```bash
|
||||
mkdir -p modules/nixos/services/my-service
|
||||
```
|
||||
|
||||
2. **Write `default.nix`** using the `mkModule` helper:
|
||||
```nix
|
||||
environment.systemPackages = with pkgs; [
|
||||
new-package
|
||||
];
|
||||
```
|
||||
|
||||
2. For custom packages, add them to the `packages` directory:
|
||||
```bash
|
||||
mkdir -p packages/new-package
|
||||
# Create the necessary Nix files
|
||||
```
|
||||
|
||||
### Adding a New Module
|
||||
|
||||
1. Create a new module directory:
|
||||
```bash
|
||||
mkdir -p modules/nixos/new-module
|
||||
```
|
||||
|
||||
2. Create the module files:
|
||||
```bash
|
||||
# Create options.nix
|
||||
cat > modules/nixos/new-module/options.nix << EOF
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.new-module = {
|
||||
enable = mkEnableOption "Enable new module";
|
||||
# Add other options here
|
||||
};
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create default.nix
|
||||
cat > modules/nixos/new-module/default.nix << EOF
|
||||
{ config, lib, namespace, ... }:
|
||||
{ config, lib, namespace, pkgs, ... }:
|
||||
let
|
||||
cfg = config.${namespace}.new-module;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Add your configuration here
|
||||
name = "my-service";
|
||||
nebulaConfig = lib.${namespace}.mkModule {
|
||||
inherit config name;
|
||||
description = "my service description";
|
||||
options = { };
|
||||
moduleConfig = {
|
||||
services.my-service = {
|
||||
enable = true;
|
||||
port = config.${namespace}.services.${name}.port;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
EOF
|
||||
in
|
||||
{ imports = [ nebulaConfig ]; }
|
||||
```
|
||||
|
||||
3. Import your module in your system configuration:
|
||||
3. **Enable it** in a system configuration:
|
||||
```nix
|
||||
imports = [
|
||||
# ...
|
||||
../../../modules/nixos/new-module
|
||||
];
|
||||
|
||||
${namespace}.new-module.enable = true;
|
||||
```
|
||||
mjallen.services.my-service = {
|
||||
enable = true;
|
||||
port = 1234;
|
||||
};
|
||||
```
|
||||
|
||||
## Adding a New Package
|
||||
|
||||
1. Create a directory under `packages/`:
|
||||
```bash
|
||||
mkdir packages/my-package
|
||||
```
|
||||
|
||||
2. Write a `default.nix` that returns a derivation. The package will be available as `pkgs.mjallen.my-package` in all configurations.
|
||||
|
||||
## Secrets
|
||||
|
||||
See the [Secrets Management](../README.md#secrets-management) section of the root README for:
|
||||
- How age keys are derived from SSH host keys
|
||||
- Adding a new machine as a SOPS recipient
|
||||
- Adding/editing secrets
|
||||
- Generating Nebula VPN certificates
|
||||
|
||||
0
docs/home-assistant/README.md
Normal file → Executable file
0
docs/home-assistant/README.md
Normal file → Executable file
0
docs/home-assistant/automations.md
Normal file → Executable file
0
docs/home-assistant/automations.md
Normal file → Executable file
0
docs/home-assistant/fountain-automation.md
Normal file → Executable file
0
docs/home-assistant/fountain-automation.md
Normal file → Executable file
343
docs/modules/README.md
Normal file → Executable file
343
docs/modules/README.md
Normal file → Executable file
@@ -2,115 +2,294 @@
|
||||
|
||||
This directory contains documentation for the custom modules used in this NixOS configuration.
|
||||
|
||||
## Module Types
|
||||
## Overview
|
||||
|
||||
The repository uses two main types of modules:
|
||||
Modules are split into three categories:
|
||||
|
||||
1. **NixOS Modules** - System-level configurations in `modules/nixos/`
|
||||
2. **Home Manager Modules** - User-level configurations in `modules/home/`
|
||||
- **NixOS modules** (`modules/nixos/`) — system-level configuration
|
||||
- **Home Manager modules** (`modules/home/`) — user-level configuration
|
||||
- **Darwin modules** (`modules/darwin/`) — macOS-specific configuration
|
||||
|
||||
All modules are auto-discovered by Snowfall Lib and expose options under the `mjallen` namespace.
|
||||
|
||||
## NixOS Modules
|
||||
|
||||
These modules configure the system-level aspects of NixOS:
|
||||
### Boot (`modules/nixos/boot/`)
|
||||
|
||||
- [Boot Modules](./boot.md) - Boot loader and kernel configurations
|
||||
- [Desktop Modules](./desktop.md) - Desktop environment configurations
|
||||
- [Development Modules](./development.md) - Development tools and environments
|
||||
- [Hardware Modules](./hardware.md) - Hardware-specific configurations
|
||||
- [Home Assistant Modules](./homeassistant.md) - Home automation configuration
|
||||
- [Networking Modules](./network.md) - Network configuration and services
|
||||
- [Security Modules](./security.md) - Security-related configurations
|
||||
- [Services Modules](./services.md) - Various service configurations
|
||||
- [System Modules](./system.md) - General system configurations
|
||||
- [Virtualization Modules](./virtualization.md) - Virtualization and containerization
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `boot/common/` | Shared boot defaults (quiet boot, Plymouth) |
|
||||
| `boot/lanzaboote/` | Secure Boot via Lanzaboote |
|
||||
| `boot/systemd-boot/` | systemd-boot (non-secure-boot systems) |
|
||||
| `boot/plymouth/` | Plymouth splash screen |
|
||||
|
||||
### Desktop (`modules/nixos/desktop/`)
|
||||
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `desktop/gnome/` | GNOME desktop environment |
|
||||
| `desktop/hyprland/` | Hyprland compositor |
|
||||
| `desktop/cosmic/` | COSMIC desktop environment |
|
||||
|
||||
### Development (`modules/nixos/development/`)
|
||||
|
||||
Enables development tools and language support. Options:
|
||||
|
||||
```nix
|
||||
mjallen.development = {
|
||||
enable = true;
|
||||
includeLanguages = [ "python" "c" ];
|
||||
includeContainers = true;
|
||||
};
|
||||
```
|
||||
|
||||
### Hardware (`modules/nixos/hardware/`)
|
||||
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `hardware/amd/` | AMD GPU (AMDGPU driver, LACT) |
|
||||
| `hardware/nvidia/` | NVIDIA GPU |
|
||||
| `hardware/battery/` | Battery charge threshold management |
|
||||
| `hardware/raspberry-pi/` | Raspberry Pi hardware support and DT overlays |
|
||||
| `hardware/openrgb/` | OpenRGB for LED control |
|
||||
| `hardware/btrfs/` | btrfs-specific settings |
|
||||
| `hardware/common/` | Common hardware defaults |
|
||||
|
||||
### Headless (`modules/nixos/headless/`)
|
||||
|
||||
Server profile — disables suspend/hibernate, enables systemd watchdog, no display manager.
|
||||
|
||||
```nix
|
||||
mjallen.headless.enable = true;
|
||||
```
|
||||
|
||||
### Home Assistant (`modules/nixos/homeassistant/`)
|
||||
|
||||
Full smart home stack. See [Home Assistant docs](../home-assistant/README.md) for details.
|
||||
|
||||
```nix
|
||||
mjallen.services.home-assistant.enable = true;
|
||||
```
|
||||
|
||||
### Impermanence (`modules/nixos/impermanence/`)
|
||||
|
||||
Ephemeral root filesystem with explicit persistence declarations.
|
||||
|
||||
```nix
|
||||
mjallen.impermanence = {
|
||||
enable = true;
|
||||
extraDirectories = [ { directory = "/var/lib/myapp"; user = "myapp"; } ];
|
||||
};
|
||||
```
|
||||
|
||||
### Monitoring (`modules/nixos/monitoring/`)
|
||||
|
||||
Prometheus metrics and Grafana dashboards.
|
||||
|
||||
```nix
|
||||
mjallen.monitoring.enable = true;
|
||||
```
|
||||
|
||||
### Network (`modules/nixos/network/`)
|
||||
|
||||
Hostname, firewall, NetworkManager profiles, static IP configuration.
|
||||
|
||||
```nix
|
||||
mjallen.network = {
|
||||
hostName = "my-host";
|
||||
ipv4 = {
|
||||
method = "manual";
|
||||
address = "10.0.1.5/24";
|
||||
gateway = "10.0.1.1";
|
||||
dns = "1.1.1.1";
|
||||
interface = "eth0";
|
||||
};
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ 80 443 ];
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Power (`modules/nixos/power/`)
|
||||
|
||||
UPS (NUT) support.
|
||||
|
||||
```nix
|
||||
mjallen.power.ups.enable = true;
|
||||
```
|
||||
|
||||
### Security (`modules/nixos/security/`)
|
||||
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `security/common/` | Common hardening (kernel params, etc.) |
|
||||
| `security/tpm/` | TPM2 — Clevis disk unlock |
|
||||
|
||||
### Services (`modules/nixos/services/`)
|
||||
|
||||
~50 self-hosted service modules, all built with `mkModule`. Each exposes at minimum `enable`, `port`, `reverseProxy`, and `openFirewall`. Common usage pattern:
|
||||
|
||||
```nix
|
||||
mjallen.services.jellyfin = {
|
||||
enable = true;
|
||||
port = 8096;
|
||||
reverseProxy.enable = true;
|
||||
};
|
||||
```
|
||||
|
||||
Available services:
|
||||
|
||||
`actual`, `ai`, `appimage`, `arrs`, `attic`, `authentik`, `authentikRac`, `booklore`, `caddy`, `calibre`, `calibre-web`, `cockpit`, `code-server`, `collabora`, `coturn`, `crowdsec`, `dispatcharr`, `free-games-claimer`, `gitea`, `glance`, `glances`, `grafana`, `guacd`, `headscale`, `immich`, `jellyfin`, `seerr`, `lubelogger`, `manyfold`, `matrix`, `minecraft`, `mongodb`, `nebula`, `netbootxyz`, `nextcloud`, `ntfy`, `onlyoffice`, `opencloud`, `orca`, `paperless`, `paperless-ai`, `protonmail-bridge`, `restic`, `samba`, `sparky-fitness`, `sparky-fitness-server`, `sunshine`, `tdarr`, `termix`, `tunarr`, `unmanic`, `uptime-kuma`, `wyoming`, `your-spotify`
|
||||
|
||||
#### Nebula VPN (`services/nebula/`)
|
||||
|
||||
Unified module for both lighthouse and node roles:
|
||||
|
||||
```nix
|
||||
# Lighthouse
|
||||
mjallen.services.nebula = {
|
||||
enable = true;
|
||||
isLighthouse = true;
|
||||
port = 4242;
|
||||
secretsPrefix = "pi5/nebula";
|
||||
secretsFile = lib.snowfall.fs.get-file "secrets/pi5-secrets.yaml";
|
||||
hostSecretName = "lighthouse";
|
||||
};
|
||||
|
||||
# Node
|
||||
mjallen.services.nebula = {
|
||||
enable = true;
|
||||
port = 4242;
|
||||
lighthouses = [ "10.1.1.1" ];
|
||||
staticHostMap = { "10.1.1.1" = [ "mjallen.dev:4242" ]; };
|
||||
secretsPrefix = "mymachine/nebula";
|
||||
secretsFile = lib.snowfall.fs.get-file "secrets/mymachine-secrets.yaml";
|
||||
hostSecretName = "mymachine";
|
||||
};
|
||||
```
|
||||
|
||||
See [Secrets Management](../../README.md#generating-nebula-vpn-certificates) for how to generate the required certificates.
|
||||
|
||||
### SOPS (`modules/nixos/sops/`)
|
||||
|
||||
Configures sops-nix to decrypt secrets using the machine's SSH host key as an age key.
|
||||
|
||||
```nix
|
||||
mjallen.sops = {
|
||||
enable = true;
|
||||
sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; # default
|
||||
};
|
||||
```
|
||||
|
||||
### User (`modules/nixos/user/`)
|
||||
|
||||
System user account management.
|
||||
|
||||
```nix
|
||||
mjallen.user = {
|
||||
name = "matt";
|
||||
mutableUsers = false;
|
||||
extraGroups = [ "docker" "video" ];
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Home Manager Modules
|
||||
|
||||
These modules configure user environments:
|
||||
### Desktop
|
||||
|
||||
- [Applications](./home/applications.md) - User applications
|
||||
- [Desktop](./home/desktop.md) - User desktop environments
|
||||
- [Development](./home/development.md) - User development environments
|
||||
- [Media](./home/media.md) - Media applications
|
||||
- [Shell](./home/shell.md) - Shell configurations
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `desktop/gnome/` | GNOME user settings (extensions, keybindings, etc.) |
|
||||
| `desktop/theme/` | Theme configuration |
|
||||
|
||||
## Module Structure
|
||||
### Programs
|
||||
|
||||
Each module follows a standard structure:
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `programs/btop/` | btop system monitor |
|
||||
| `programs/code/` | VS Code / VSCodium settings |
|
||||
| `programs/git/` | Git user config |
|
||||
| `programs/hyprland/` | Hyprland compositor config |
|
||||
| `programs/kitty/` | Kitty terminal config |
|
||||
| `programs/librewolf/` | LibreWolf browser settings |
|
||||
| `programs/mako/` | Mako notification daemon |
|
||||
| `programs/nwg-dock/` | nwg-dock panel |
|
||||
| `programs/nwg-drawer/` | nwg-drawer app launcher |
|
||||
| `programs/nwg-panel/` | nwg-panel bar |
|
||||
| `programs/opencode/` | OpenCode AI coding assistant |
|
||||
| `programs/update-checker/` | Automatic flake update checker |
|
||||
| `programs/waybar/` | Waybar status bar |
|
||||
| `programs/wlogout/` | Logout menu |
|
||||
| `programs/wofi/` | Wofi launcher |
|
||||
| `programs/zsh/` | Zsh shell config |
|
||||
|
||||
```
|
||||
modules/nixos/example-module/
|
||||
├── default.nix # Main implementation
|
||||
├── options.nix # Option declarations
|
||||
└── submodule/ # Optional submodules
|
||||
└── default.nix # Submodule implementation
|
||||
```
|
||||
### Other
|
||||
|
||||
### default.nix
|
||||
| Module | Description |
|
||||
|---|---|
|
||||
| `gpg/` | GPG agent configuration |
|
||||
| `services/pass/` | Password store |
|
||||
| `shell-aliases/` | Common shell aliases |
|
||||
| `sops/` | User-level SOPS secrets |
|
||||
| `stylix/` | System-wide theming (colours, fonts, wallpaper) |
|
||||
| `user/` | User environment defaults |
|
||||
|
||||
The `default.nix` file contains the main implementation of the module:
|
||||
---
|
||||
|
||||
## Module Development
|
||||
|
||||
### Using `mkModule`
|
||||
|
||||
The `lib.mjallen.mkModule` helper (`lib/module/default.nix`) creates a fully-featured NixOS module from a minimal spec:
|
||||
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
{ config, lib, namespace, pkgs, ... }:
|
||||
let
|
||||
cfg = config.${namespace}.example-module;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
name = "my-service";
|
||||
cfg = config.${namespace}.services.${name};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Module implementation when enabled
|
||||
serviceConfig = lib.${namespace}.mkModule {
|
||||
inherit config name;
|
||||
description = "my service";
|
||||
options = {
|
||||
# extra options beyond the standard set
|
||||
myOption = lib.${namespace}.mkOpt lib.types.str "default" "Description";
|
||||
};
|
||||
moduleConfig = {
|
||||
services.my-service = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
in
|
||||
{ imports = [ serviceConfig ]; }
|
||||
```
|
||||
|
||||
### options.nix
|
||||
Standard options provided by `mkModule` for free: `enable`, `port`, `listenAddress`, `openFirewall`, `configDir`, `dataDir`, `createUser`, `configureDb`, `environmentFile`, `reverseProxy.*`, `redis.*`, `extraEnvironment`, `hashedPassword`, `puid`, `pgid`, `timeZone`.
|
||||
|
||||
The `options.nix` file declares the module's configuration options:
|
||||
### Using `mkContainerService`
|
||||
|
||||
For Podman/OCI container services, use `mkContainerService` instead:
|
||||
|
||||
```nix
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
let
|
||||
inherit (lib.${namespace}) mkOpt;
|
||||
in
|
||||
{
|
||||
options.${namespace}.example-module = {
|
||||
enable = mkEnableOption "enable example module";
|
||||
# Other option declarations
|
||||
};
|
||||
}
|
||||
lib.${namespace}.mkContainerService {
|
||||
inherit config name;
|
||||
image = "ghcr.io/example/my-app:latest";
|
||||
internalPort = 8080;
|
||||
volumes = [ "${cfg.configDir}:/config" ];
|
||||
};
|
||||
```
|
||||
|
||||
## Using Modules
|
||||
|
||||
To use a module in your system configuration:
|
||||
|
||||
1. Enable the module in your system configuration:
|
||||
### Option helpers
|
||||
|
||||
```nix
|
||||
{ config, ... }:
|
||||
{
|
||||
mjallen.example-module = {
|
||||
enable = true;
|
||||
# Other options
|
||||
};
|
||||
}
|
||||
lib.mjallen.mkOpt types.str "default" "description"
|
||||
lib.mjallen.mkBoolOpt false "description"
|
||||
lib.mjallen.mkOpt' types.int 80 # no description
|
||||
lib.mjallen.enabled # { enable = true; }
|
||||
lib.mjallen.disabled # { enable = false; }
|
||||
```
|
||||
|
||||
## Creating New Modules
|
||||
|
||||
To create a new module:
|
||||
|
||||
1. Create a new directory in `modules/nixos/` or `modules/home/`
|
||||
2. Create `default.nix` and `options.nix` files
|
||||
3. Implement your module functionality
|
||||
4. Import the module in your system configuration
|
||||
|
||||
See the [Getting Started](../getting-started.md) guide for more details on creating modules.
|
||||
0
docs/modules/homeassistant.md
Normal file → Executable file
0
docs/modules/homeassistant.md
Normal file → Executable file
90
docs/services.md
Executable file
90
docs/services.md
Executable file
@@ -0,0 +1,90 @@
|
||||
# Services
|
||||
|
||||
All services are derived from `lib.mjallen.network` (`lib/network/default.nix`).
|
||||
Domain: `mjallen.dev`
|
||||
|
||||
Services are grouped by host. The **URL** column is only present when a reverse proxy
|
||||
is configured (i.e. `reverseProxy.enable = true`) or a well-known public URL exists.
|
||||
Services without a public URL are accessible only on the LAN or internally.
|
||||
|
||||
---
|
||||
|
||||
## NAS (`jallen-nas` — `10.0.1.3`)
|
||||
|
||||
| Service | Enabled | Port | URL |
|
||||
|---------|---------|------|-----|
|
||||
| actual | No | 3333 | https://actual.mjallen.dev |
|
||||
| ai (Ollama + llama.cpp + Open-WebUI) | Yes | 8127 / 11434 / various | https://chat.mjallen.dev |
|
||||
| arrs (Sonarr + Radarr + SABnzbd) | Yes | 8989 / 7878 / 8280 | — |
|
||||
| attic | Yes | 9012 | https://cache.mjallen.dev |
|
||||
| authentik | Yes | 9000 | https://authentik.mjallen.dev |
|
||||
| authentikRac | Yes | 4823 | — |
|
||||
| caddy | Yes | 80 / 443 | — |
|
||||
| calibre | No | 8084 | https://calibre.mjallen.dev |
|
||||
| calibre-web | No | 8083 | https://calibre-web.mjallen.dev |
|
||||
| cockpit | Yes | 9091 | — |
|
||||
| code-server | Yes | 4444 | https://code.mjallen.dev |
|
||||
| collabora | Yes | 9980 | https://office.mjallen.dev |
|
||||
| coturn | Yes | 3478 | — |
|
||||
| crowdsec | Yes | 8181 | — |
|
||||
| dispatcharr | No | 9191 | https://dispatcharr.mjallen.dev |
|
||||
| free-games-claimer | No | 6080 | — |
|
||||
| gitea | Yes | 3000 / SSH 2222 | https://gitea.mjallen.dev |
|
||||
| glance | Yes | 5555 | https://glance.mjallen.dev |
|
||||
| glances | Yes | 61208 | https://glances.mjallen.dev |
|
||||
| grafana | Yes | 9999 | https://grafana.mjallen.dev |
|
||||
| grimmory | No | 6066 | https://grimmory.mjallen.dev |
|
||||
| guacd | Yes | 4822 | — |
|
||||
| headscale | No | 2112 | https://headscale.mjallen.dev |
|
||||
| immich | Yes | 2283 | https://immich.mjallen.dev |
|
||||
| jellyfin | Yes | 8096 | https://jellyfin.mjallen.dev |
|
||||
| seerr | Yes | 5055 | https://seerr.mjallen.dev |
|
||||
| kavita | Yes | 5000 | — |
|
||||
| lemonade | No | 8001 | — |
|
||||
| lubelogger | Yes | 6754 | https://lubelogger.mjallen.dev |
|
||||
| manyfold | Yes | 3214 | — |
|
||||
| matrix | Yes | 8448 | https://matrix.mjallen.dev |
|
||||
| minecraft | No | 25565 | — |
|
||||
| mongodb | No | 27017 | — |
|
||||
| nebula | Yes | 4242 | — |
|
||||
| netbootxyz | No | 4000 | https://netbootxyz.mjallen.dev |
|
||||
| nextcloud | Yes | 9988 | https://cloud.mjallen.dev |
|
||||
| ntfy | Yes | 2586 | https://ntfy.mjallen.dev |
|
||||
| ocis | No | 9200 | — |
|
||||
| onlyoffice | No | 9943 | — |
|
||||
| opencloud | No | 9200 | — |
|
||||
| orca-slicer | No | 3100 | https://orca-slicer.mjallen.dev |
|
||||
| paperless | Yes | 28981 | — |
|
||||
| paperless-ai | Yes | 28982 | — |
|
||||
| protonmail-bridge | Yes | SMTP 1025 / IMAP 1143 | — |
|
||||
| restic-server | Yes | 8008 | — |
|
||||
| sparky-fitness (frontend) | Yes | 3004 | https://sparky.mjallen.dev |
|
||||
| sparky-fitness-server (backend) | Yes | 3010 | — |
|
||||
| sunshine | Yes | 47989 | — |
|
||||
| tdarr | No | 8265 / 8266 | https://tdarr.mjallen.dev |
|
||||
| termix | Yes | 7777 | https://termix.mjallen.dev |
|
||||
| tunarr | Yes | 8000 | https://tunarr.mjallen.dev |
|
||||
| unmanic | Yes | 8265 | https://unmanic.mjallen.dev |
|
||||
| uptime-kuma | Yes | 3001 | — |
|
||||
| wyoming (Whisper + Piper) | Yes | 10300 / 10200 | — |
|
||||
|
||||
---
|
||||
|
||||
## NUC (`nuc-nixos` — `10.0.1.4`)
|
||||
|
||||
| Service | Enabled | Port | URL |
|
||||
|---------|---------|------|-----|
|
||||
| home-assistant | Yes | 8123 | https://hass.mjallen.dev |
|
||||
| esphome | Yes | 6052 | — |
|
||||
| otbr (OpenThread Border Router) | Yes | 8880 / REST 8881 | — |
|
||||
| mosquitto (MQTT) | Yes | 1883 | — |
|
||||
|
||||
---
|
||||
|
||||
## Pi5 (`pi5` — `10.0.1.2`)
|
||||
|
||||
| Service | Enabled | Port | URL |
|
||||
|---------|---------|------|-----|
|
||||
| adguard | Yes | 3000 | — |
|
||||
| nebula (lighthouse) | Yes | 4242 | — |
|
||||
| dns | Yes | 53 | — |
|
||||
39
docs/systems/README.md
Normal file → Executable file
39
docs/systems/README.md
Normal file → Executable file
@@ -4,19 +4,34 @@ This directory contains documentation for each system configuration in this repo
|
||||
|
||||
## Systems
|
||||
|
||||
- [Desktop (matt-nixos)](./matt-nixos.md) - Main desktop computer
|
||||
- [NAS (jallen-nas)](./jallen-nas.md) - Home server and NAS
|
||||
- [NUC (nuc-nixos)](./nuc-nixos.md) - Intel NUC
|
||||
- [Raspberry Pi 5](./pi5.md) - Raspberry Pi 5
|
||||
- [MacBook Pro (nixOS)](./macbook-pro-nixos.md) - MacBook Pro running NixOS
|
||||
| Host | Architecture | OS | Role |
|
||||
|---|---|---|---|
|
||||
| [matt-nixos](./matt-nixos.md) | x86_64-linux | NixOS | Primary AMD desktop |
|
||||
| [jallen-nas](./jallen-nas.md) | x86_64-linux | NixOS | Home server / NAS |
|
||||
| [nuc-nixos](./nuc-nixos.md) | x86_64-linux | NixOS | Intel NUC — Home Assistant hub |
|
||||
| [allyx](./allyx.md) | x86_64-linux | NixOS | ASUS ROG Ally X handheld |
|
||||
| [pi5](./pi5.md) | aarch64-linux | NixOS | Raspberry Pi 5 — network services |
|
||||
| [macbook-pro-nixos](./macbook-pro-nixos.md) | aarch64-linux | NixOS (Asahi) | Apple Silicon MacBook Pro |
|
||||
| [macbook-pro](./macbook-pro.md) | aarch64-darwin | nix-darwin | macOS on the same MacBook Pro |
|
||||
|
||||
There are also two ISO targets (`x86_64-install-iso/graphical`, `x86_64-linux/iso-minimal`) used for installation media builds.
|
||||
|
||||
## Network
|
||||
|
||||
All hosts are on the `10.0.1.0/24` LAN with static IPs:
|
||||
|
||||
| Host | LAN IP | Overlay (Nebula) |
|
||||
|---|---|---|
|
||||
| pi5 | 10.0.1.2 | 10.1.1.1 (lighthouse) |
|
||||
| jallen-nas | 10.0.1.3 | 10.1.1.x (node) |
|
||||
| nuc-nixos | 10.0.1.4 | — |
|
||||
|
||||
## Common Configuration
|
||||
|
||||
All systems share certain common configurations through the modules system. These include:
|
||||
All systems share:
|
||||
- SOPS secret management (age keys from SSH host keys)
|
||||
- Impermanence (ephemeral root, explicit persistence)
|
||||
- Nix flake-based configuration via Snowfall Lib
|
||||
- The `mjallen` module namespace
|
||||
|
||||
- Base system configuration
|
||||
- User management
|
||||
- Network configuration
|
||||
- Security settings
|
||||
|
||||
Each system then adds its specific configurations on top of these common modules.
|
||||
Each system then layers its own modules and hardware configuration on top.
|
||||
|
||||
57
docs/systems/allyx.md
Executable file
57
docs/systems/allyx.md
Executable file
@@ -0,0 +1,57 @@
|
||||
# ASUS ROG Ally X (allyx)
|
||||
|
||||
`systems/x86_64-linux/allyx/`
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Device**: ASUS ROG Ally X handheld gaming PC
|
||||
- **CPU/GPU**: AMD (LACT, CoolerControl)
|
||||
- **Disk**: NVMe with LUKS encryption
|
||||
- **Security**: Lanzaboote (Secure Boot)
|
||||
|
||||
## Key Features
|
||||
|
||||
- Jovian NixOS for Steam Deck-compatible experience
|
||||
- Steam auto-starts into Game Mode on boot
|
||||
- Decky Loader for Steam Deck plugins
|
||||
- Handheld Daemon for power/TDP/fan control
|
||||
- GNOME available as a desktop session (selectable from Steam)
|
||||
- SDDM (Wayland) as display manager — GDM disabled
|
||||
- Gaming enabled (Gamemode, Gamescope, etc.)
|
||||
- AMD GPU management via LACT
|
||||
- CoolerControl for fan curves
|
||||
- iwd as the Wi-Fi backend
|
||||
- Impermanence (ephemeral root)
|
||||
|
||||
## Jovian NixOS
|
||||
|
||||
The allyx uses [Jovian NixOS](https://github.com/Jovian-Experiments/Jovian-NixOS) to provide Steam Deck compatibility:
|
||||
|
||||
```nix
|
||||
jovian.steam = {
|
||||
enable = true;
|
||||
autoStart = true;
|
||||
desktopSession = "gnome"; # fall-through desktop session
|
||||
};
|
||||
|
||||
jovian.decky-loader = {
|
||||
enable = true;
|
||||
extraPackages = [ pkgs.python3 pkgs.systemd ];
|
||||
};
|
||||
```
|
||||
|
||||
## Network
|
||||
|
||||
- **Hostname**: allyx
|
||||
- **Wi-Fi backend**: iwd (via NetworkManager)
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config — Jovian, gaming, hardware |
|
||||
| `boot.nix` | Lanzaboote, kernel |
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are in `secrets/allyx-secrets.yaml`, encrypted for: `matt`, `desktop`, `deck`, `steamdeck`, `admin`, `jallen-nas`, `matt_allyx`, `allyx`.
|
||||
167
docs/systems/jallen-nas.md
Normal file → Executable file
167
docs/systems/jallen-nas.md
Normal file → Executable file
@@ -1,101 +1,104 @@
|
||||
# NAS Server (jallen-nas)
|
||||
|
||||
This document describes the configuration for the NAS server system.
|
||||
`systems/x86_64-linux/jallen-nas/`
|
||||
|
||||
## Hardware
|
||||
|
||||
The NAS server is built on AMD hardware:
|
||||
- **CPU**: AMD (x86_64)
|
||||
- **GPU**: AMD (LACT for fan/power control)
|
||||
- **Disk**: NVMe system drive + bcachefs NAS pool
|
||||
- **Security**: TPM2 (Clevis disk unlock), Lanzaboote (Secure Boot)
|
||||
|
||||
- CPU: AMD processor
|
||||
- Hardware-specific modules:
|
||||
- `nixos-hardware.nixosModules.common-pc`
|
||||
- `nixos-hardware.nixosModules.common-cpu-amd`
|
||||
- `nixos-hardware.nixosModules.common-cpu-amd-pstate`
|
||||
- `nixos-hardware.nixosModules.common-hidpi`
|
||||
## Key Features
|
||||
|
||||
## Services
|
||||
- bcachefs storage pool mounted at `/media/nas/main`
|
||||
- Clevis-based TPM disk unlock at boot (no passphrase required)
|
||||
- Impermanence — root is ephemeral; state persists to `/media/nas/main/persist`
|
||||
- Samba shares (Windows file sharing, Time Machine)
|
||||
- Nebula VPN node (overlay peer, lighthouse at pi5)
|
||||
- ~40 self-hosted services behind a Caddy reverse proxy
|
||||
- Authentik SSO protecting most web UIs
|
||||
- CrowdSec for intrusion detection
|
||||
- Restic backups
|
||||
|
||||
The NAS hosts various services:
|
||||
## Network
|
||||
|
||||
### Media Services
|
||||
- **LAN IP**: 10.0.1.3 (static, `enp197s0`)
|
||||
- **Gateway**: 10.0.1.1
|
||||
- **Nebula**: overlay peer, lighthouse at `mjallen.dev:4242`
|
||||
|
||||
- **Jellyfin** - Media server
|
||||
- **Jellyseerr** - Media request manager
|
||||
- **Sonarr** - TV show management
|
||||
- **Radarr** - Movie management
|
||||
- **Lidarr** - Music management
|
||||
- **Bazarr** - Subtitle management
|
||||
- **Music Assistant** - Music streaming integration with Home Assistant
|
||||
## Storage
|
||||
|
||||
### Download Services
|
||||
| Mount | Filesystem | Description |
|
||||
|---|---|---|
|
||||
| `/media/nas/main` | bcachefs | Primary NAS pool (media, appdata, documents) |
|
||||
| `/media/nas/test` | bcachefs | Secondary test pool |
|
||||
|
||||
- **Transmission** - Torrent client
|
||||
- **NZBGet** - Usenet downloader
|
||||
- **Prowlarr** - Indexer manager
|
||||
### Samba Shares
|
||||
|
||||
### Document Management
|
||||
| Share | Time Machine |
|
||||
|---|---|
|
||||
| `3d_printer` | no |
|
||||
| `Backup` | no |
|
||||
| `Documents` | no |
|
||||
| `isos` | no |
|
||||
| `app_data` | no |
|
||||
| `TimeMachine` | yes (max 1 TB) |
|
||||
|
||||
- **Paperless-ngx** - Document management system
|
||||
## Enabled Services
|
||||
|
||||
### File Sharing
|
||||
| Service | Port | Notes |
|
||||
|---|---|---|
|
||||
| Caddy | 443/80 | Reverse proxy for all services |
|
||||
| Authentik | 9000 | SSO / identity provider |
|
||||
| Attic | 9012 | Nix binary cache (`cache.mjallen.dev`) |
|
||||
| Immich | 2283 | Photo management |
|
||||
| Jellyfin | 8096 | Media server |
|
||||
| Seerr | 5055 | Media request manager |
|
||||
| Nextcloud | 9988 | Cloud storage |
|
||||
| Paperless | 28981 | Document management |
|
||||
| Paperless AI | 28982 | AI-assisted document tagging |
|
||||
| Gitea | 3000 | Self-hosted Git |
|
||||
| Matrix | 8448 | Matrix homeserver |
|
||||
| Ntfy | 2586 | Push notifications |
|
||||
| Glance | 5555 | Dashboard |
|
||||
| Immich | 2283 | Photo library |
|
||||
| Uptime Kuma | 3001 | Uptime monitoring |
|
||||
| Code Server | 4444 | VS Code in the browser |
|
||||
| Cockpit | 9090 | System management UI |
|
||||
| Collabora | 9980 | Online office suite |
|
||||
| CrowdSec | 8181 | Intrusion detection |
|
||||
| Glances | 61208 | System stats |
|
||||
| Coturn | 3478 | TURN/STUN server |
|
||||
| Nebula | 4242 | Overlay VPN node |
|
||||
| Restic | 8008 | Backup service |
|
||||
| Sunshine | 47989 | Remote desktop (Moonlight) |
|
||||
| Unmanic | 8265 | Media transcoding |
|
||||
| Lubelogger | 6754 | Vehicle maintenance log |
|
||||
| Manyfold | 3214 | 3D model library |
|
||||
| Booklore | 6066 | Book library |
|
||||
| Tunarr | 8000 | Virtual TV channels |
|
||||
| Termix | 7777 | Web terminal |
|
||||
| Sparky Fitness | 3004/3010 | Fitness tracking |
|
||||
| Protonmail Bridge | 1025/1143 | SMTP/IMAP bridge |
|
||||
| Arrs | various | Sonarr, Radarr, etc. |
|
||||
| AI | various | Ollama, etc. |
|
||||
| Wyoming | various | Voice assistant pipeline |
|
||||
|
||||
- **Samba** - Windows file sharing
|
||||
- **Nextcloud** - Self-hosted cloud storage
|
||||
## Configuration Files
|
||||
|
||||
### AI Services
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config — network, hardware, filesystems, packages |
|
||||
| `apps.nix` | All service enable/disable declarations |
|
||||
| `nas-defaults.nix` | Sets `configDir`/`dataDir` defaults for all services |
|
||||
| `boot.nix` | Lanzaboote, kernel, initrd |
|
||||
| `services.nix` | Home Assistant, samba, and other platform services |
|
||||
| `users.nix` | User accounts (`admin`, `nix-apps`) |
|
||||
| `sops.nix` | Secret declarations |
|
||||
| `vpn.nix` | Nebula VPN configuration |
|
||||
| `disabled.nix` | Services explicitly disabled |
|
||||
|
||||
- **Ollama** - Local AI model hosting
|
||||
## Secrets
|
||||
|
||||
### Smart Home
|
||||
|
||||
- **Home Assistant** - Smart home controller
|
||||
- **Zigbee2MQTT** - Zigbee device integration
|
||||
- **MQTT** - Message broker for IoT devices
|
||||
- **Thread Border Router** - Thread network for smart home devices
|
||||
|
||||
## Storage Configuration
|
||||
|
||||
The NAS uses multiple storage devices:
|
||||
|
||||
1. **System Drive** - For the operating system
|
||||
2. **Data Drives** - Configured as a storage array for media and data
|
||||
|
||||
## Network Configuration
|
||||
|
||||
The NAS is configured with:
|
||||
|
||||
- Static IP address
|
||||
- Firewall rules for the various services
|
||||
- Tailscale for secure remote access
|
||||
|
||||
## Backup Strategy
|
||||
|
||||
The NAS implements a comprehensive backup strategy:
|
||||
|
||||
1. **System Backup** - Regular backups of the NixOS configuration
|
||||
2. **Data Backup** - Backups of important data to secondary storage
|
||||
3. **Off-site Backup** - Critical data is backed up off-site
|
||||
|
||||
## Usage and Management
|
||||
|
||||
### Accessing Services
|
||||
|
||||
Most services are available through a reverse proxy, which provides:
|
||||
- HTTPS access
|
||||
- Authentication via Authentik
|
||||
- Subdomain-based routing
|
||||
|
||||
### Adding Storage
|
||||
|
||||
To add additional storage to the NAS:
|
||||
|
||||
1. Add the physical drive to the system
|
||||
2. Update the disko configuration
|
||||
3. Rebuild the system with `nixos-rebuild switch`
|
||||
|
||||
### Monitoring
|
||||
|
||||
The system can be monitored through:
|
||||
- Prometheus metrics
|
||||
- Grafana dashboards
|
||||
- Home Assistant sensors
|
||||
Secrets are in `secrets/nas-secrets.yaml`, encrypted for: `matt`, `desktop`, `admin`, `jallen-nas`.
|
||||
|
||||
69
docs/systems/macbook-pro-nixos.md
Executable file
69
docs/systems/macbook-pro-nixos.md
Executable file
@@ -0,0 +1,69 @@
|
||||
# MacBook Pro — NixOS / Asahi Linux (macbook-pro-nixos)
|
||||
|
||||
`systems/aarch64-linux/macbook-pro-nixos/`
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Device**: Apple Silicon MacBook Pro (M-series)
|
||||
- **OS**: NixOS via [Asahi Linux](https://asahilinux.org/) (`nixos-apple-silicon`)
|
||||
- **Boot**: Asahi boot chain (not traditional EFI)
|
||||
|
||||
## Key Features
|
||||
|
||||
- Asahi Linux kernel with full Apple Silicon support (sound, GPU, etc.)
|
||||
- GNOME as the primary desktop; Hyprland available but disabled
|
||||
- x86_64 emulation via binfmt (enables running x86 binaries)
|
||||
- Waydroid and libvirtd available (Waydroid disabled by default)
|
||||
- Battery management — charge threshold set via `macsmc-battery`
|
||||
- Omnissa Horizon client (custom package) for remote desktop
|
||||
- Distrobox for containerised Linux environments
|
||||
- iwd as the Wi-Fi backend
|
||||
|
||||
## x86_64 Emulation
|
||||
|
||||
```nix
|
||||
nix.settings.extra-platforms = [ "x86_64-linux" ];
|
||||
boot.binfmt.emulatedSystems = [ "x86_64-linux" ];
|
||||
```
|
||||
|
||||
This allows building and running x86_64 packages on the ARM host.
|
||||
|
||||
## Asahi Hardware
|
||||
|
||||
The Asahi hardware module provides:
|
||||
- Firmware loading from `./firmware/`
|
||||
- Sound setup (`setupAsahiSound = true`)
|
||||
- Apple-specific kernel patches and device drivers
|
||||
|
||||
Useful packages installed:
|
||||
`asahi-bless`, `asahi-btsync`, `asahi-nvram`, `asahi-wifisync`, `apfs-fuse`, `apfsprogs`, `muvm`, `fex`
|
||||
|
||||
## Network
|
||||
|
||||
- **Hostname**: macbook-pro-nixos
|
||||
- **Wi-Fi backend**: iwd (via NetworkManager)
|
||||
- Firewall: extra rules for multicast (ports 1990, 2021)
|
||||
|
||||
## Battery Management
|
||||
|
||||
```nix
|
||||
mjallen.hardware.battery = {
|
||||
enable = true;
|
||||
chargeLimitPath = "/sys/class/power_supply/macsmc-battery/charge_control_end_threshold";
|
||||
};
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config — Asahi hardware, users, network |
|
||||
| `boot.nix` | Asahi boot configuration |
|
||||
| `filesystems.nix` | Disk layout |
|
||||
| `hardware-configuration.nix` | Generated hardware config |
|
||||
| `services.nix` | logind, GDM, GNOME, Flatpak, power settings |
|
||||
| `firmware/` | Asahi firmware blobs |
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are in `secrets/mac-secrets.yaml`, encrypted for: `matt`, `matt_pi5`, `desktop`, `pi5`, `admin`, `jallen-nas`, `matt_macbook-pro`, `macbook-pro`.
|
||||
40
docs/systems/macbook-pro.md
Executable file
40
docs/systems/macbook-pro.md
Executable file
@@ -0,0 +1,40 @@
|
||||
# MacBook Pro — macOS / nix-darwin (macbook-pro)
|
||||
|
||||
`systems/aarch64-darwin/macbook-pro/`
|
||||
|
||||
## Overview
|
||||
|
||||
This is the [nix-darwin](https://github.com/nix-darwin/nix-darwin) configuration for the same MacBook Pro running macOS. It provides declarative macOS system management alongside Homebrew.
|
||||
|
||||
## Key Features
|
||||
|
||||
- Touch ID for `sudo`
|
||||
- Declarative Homebrew (casks and formulae managed via `nix-homebrew`)
|
||||
- `nh` for easy NixOS/darwin rebuilds
|
||||
- `attic-client` for accessing the Nix binary cache
|
||||
- `macpm` for Apple Silicon power monitoring
|
||||
- Rosetta builder available (disabled, on-demand)
|
||||
- Linux builder available (disabled)
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config — packages, users, environment |
|
||||
| `homebrew.nix` | Declarative Homebrew casks and formulae |
|
||||
| `programs.nix` | macOS program settings |
|
||||
| `system.nix` | System defaults (dock, finder, etc.) |
|
||||
|
||||
## User
|
||||
|
||||
- **Username**: `mattjallen`
|
||||
- **Home**: `/Users/mattjallen`
|
||||
- **Flake path**: `/Users/mattjallen/nix-config` (set via `NH_OS_FLAKE`)
|
||||
|
||||
## Rebuilding
|
||||
|
||||
```bash
|
||||
darwin-rebuild switch --flake .#macbook-pro
|
||||
# or using nh:
|
||||
nh darwin switch
|
||||
```
|
||||
50
docs/systems/matt-nixos.md
Executable file
50
docs/systems/matt-nixos.md
Executable file
@@ -0,0 +1,50 @@
|
||||
# Desktop (matt-nixos)
|
||||
|
||||
`systems/x86_64-linux/matt-nixos/`
|
||||
|
||||
## Hardware
|
||||
|
||||
- **CPU**: AMD
|
||||
- **GPU**: AMD (LACT for fan/power control, OpenRGB)
|
||||
- **Disk**: NVMe with LUKS encryption (disko)
|
||||
- **Security**: TPM2, Lanzaboote (Secure Boot)
|
||||
|
||||
## Key Features
|
||||
|
||||
- GNOME as the primary desktop (Hyprland available but disabled)
|
||||
- COSMIC available as a specialisation (`nixos-rebuild switch --specialisation cosmic`)
|
||||
- Gaming — Steam, Gamemode, Gamescope, Lossless Scaling (`lsfg-vk`)
|
||||
- AMD GPU management via LACT
|
||||
- CoolerControl for fan curves
|
||||
- Impermanence (ephemeral root)
|
||||
- iwd as the Wi-Fi backend
|
||||
- VSCodium as `$EDITOR`/`$VISUAL`
|
||||
|
||||
## Desktop Specialisations
|
||||
|
||||
| Specialisation | Description |
|
||||
|---|---|
|
||||
| *(default)* | GNOME |
|
||||
| `cosmic` | COSMIC DE (enables `mjallen.desktop.cosmic`, disables GNOME/Hyprland) |
|
||||
|
||||
## Network
|
||||
|
||||
- **Hostname**: matt-nixos
|
||||
- **Wi-Fi backend**: iwd (via NetworkManager)
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config |
|
||||
| `boot.nix` | Lanzaboote, kernel |
|
||||
| `filesystems.nix` | Disk layout |
|
||||
| `sops.nix` | Secret declarations |
|
||||
| `wifi-fixer.nix` | NetworkManager Wi-Fi workaround |
|
||||
| `services/lsfg-vk/` | Lossless Scaling frame generation |
|
||||
| `services/ratbagd/` | Gaming mouse config (libratbag) |
|
||||
| `services/restic/` | Restic backup jobs |
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are in `secrets/desktop-secrets.yaml`, encrypted for: `matt`, `desktop`, `admin`, `jallen-nas`.
|
||||
57
docs/systems/nuc-nixos.md
Executable file
57
docs/systems/nuc-nixos.md
Executable file
@@ -0,0 +1,57 @@
|
||||
# Intel NUC (nuc-nixos)
|
||||
|
||||
`systems/x86_64-linux/nuc-nixos/`
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Device**: Intel NUC
|
||||
- **Disk**: btrfs with LUKS encryption
|
||||
- **Security**: TPM2, Lanzaboote (Secure Boot)
|
||||
- **Kernel**: CachyOS `linux-cachyos-lto` (x86_64-v4 build)
|
||||
|
||||
## Key Features
|
||||
|
||||
- Headless server (no display manager, watchdog enabled)
|
||||
- Home Assistant — the primary smart home controller
|
||||
- OpenThread Border Router (OTBR) for Matter/Thread devices
|
||||
- Impermanence (ephemeral root, persistent state for HA and related services)
|
||||
- btrfs filesystem (unlike the bcachefs-based NAS and Pi5)
|
||||
|
||||
## Network
|
||||
|
||||
- **LAN IP**: 10.0.1.4 (static, `enp2s0`)
|
||||
- **Gateway / DNS**: 10.0.1.1
|
||||
- **Firewall**: 1883 (MQTT), 8880/8881 (OTBR), 8192
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Port | Description |
|
||||
|---|---|---|
|
||||
| Home Assistant | 8097 | Smart home controller |
|
||||
| Mosquitto (MQTT) | 1883 | IoT message broker |
|
||||
| Zigbee2MQTT | 8080 | Zigbee device bridge |
|
||||
| Music Assistant | 8095 | Music streaming |
|
||||
| OTBR | 8880/8881 | OpenThread Border Router (Matter/Thread) |
|
||||
| ESPHome | — | ESP microcontroller firmware |
|
||||
| PostgreSQL | — | HA database backend |
|
||||
|
||||
## Persistent Directories
|
||||
|
||||
The following directories survive reboots via impermanence:
|
||||
|
||||
- `/esphome`
|
||||
- `/var/lib/homeassistant`
|
||||
- `/var/lib/mosquitto`
|
||||
- `/var/lib/music-assistant`
|
||||
- `/var/lib/postgresql`
|
||||
- `/var/lib/zigbee2mqtt`
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | All config in one file — HA, OTBR, network, hardware, impermanence |
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are in `secrets/nuc-secrets.yaml`, encrypted for: `nuc`, `admin_nuc`, `matt`, `admin`, `jallen-nas`.
|
||||
62
docs/systems/pi5.md
Executable file
62
docs/systems/pi5.md
Executable file
@@ -0,0 +1,62 @@
|
||||
# Raspberry Pi 5 (pi5)
|
||||
|
||||
`systems/aarch64-linux/pi5/`
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Board**: Raspberry Pi 5
|
||||
- **Boot**: UEFI (via `rpi5-uefi`)
|
||||
- **Storage**: bcachefs
|
||||
- **Connectivity**: Ethernet (`end0`); Wi-Fi and Bluetooth disabled via device tree overlays
|
||||
|
||||
## Key Features
|
||||
|
||||
- Headless server (no display, no desktop)
|
||||
- Nebula VPN **lighthouse** — the central relay for the `jallen-nebula` overlay network
|
||||
- AdGuard Home DNS server (port 53)
|
||||
- Docker
|
||||
- Impermanence (ephemeral root)
|
||||
- Extensive Raspberry Pi device tree overlays configured (I²C, SPI, UART, SDIO, etc.)
|
||||
|
||||
## Network
|
||||
|
||||
- **LAN IP**: 10.0.1.2 (static, `end0`)
|
||||
- **Gateway**: 10.0.1.1
|
||||
- **DNS**: 1.1.1.1
|
||||
- **Nebula**: lighthouse at `10.1.1.1`, listening on UDP 4242 (public: `mjallen.dev:4242`)
|
||||
- Firewall: TCP/UDP 53 open (DNS)
|
||||
|
||||
## Nebula Lighthouse
|
||||
|
||||
The pi5 acts as the Nebula VPN lighthouse for the whole network. All other Nebula nodes connect to it to discover peers.
|
||||
|
||||
```nix
|
||||
mjallen.services.nebula = {
|
||||
enable = true;
|
||||
isLighthouse = true;
|
||||
port = 4242;
|
||||
secretsPrefix = "pi5/nebula";
|
||||
secretsFile = lib.snowfall.fs.get-file "secrets/pi5-secrets.yaml";
|
||||
hostSecretName = "lighthouse";
|
||||
};
|
||||
```
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Port | Description |
|
||||
|---|---|---|
|
||||
| AdGuard Home | 53 | DNS ad-blocking |
|
||||
| Nebula | 4242 (UDP) | VPN lighthouse |
|
||||
|
||||
## Configuration Files
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `default.nix` | Main config |
|
||||
| `boot.nix` | UEFI boot, kernel |
|
||||
| `adguard.nix` | AdGuard Home configuration |
|
||||
| `sops.nix` | Secret declarations (SSH keys, system keys) |
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are in `secrets/pi5-secrets.yaml`, encrypted for: `matt`, `matt_pi5`, `desktop`, `pi5`, `admin`, `jallen-nas`.
|
||||
354
docs/troubleshooting.md
Normal file → Executable file
354
docs/troubleshooting.md
Normal file → Executable file
@@ -1,213 +1,217 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
This guide provides solutions for common issues that may arise when using this NixOS configuration.
|
||||
Common issues and solutions for this NixOS configuration.
|
||||
|
||||
## System Issues
|
||||
## Build Failures
|
||||
|
||||
### Failed System Build
|
||||
### `nixos-rebuild switch` fails
|
||||
|
||||
**Problem**: `nixos-rebuild switch` fails with an error.
|
||||
1. **Syntax error** — the error message includes the file and line number. Common causes: missing `;`, unmatched `{`, wrong type passed to an option.
|
||||
|
||||
**Solutions**:
|
||||
2. **Evaluation error** — read the full error trace. Often caused by a module option receiving the wrong type, or a missing `cfg.enable` guard.
|
||||
|
||||
1. **Syntax Errors**:
|
||||
- Check the error message for file and line number information
|
||||
- Verify the syntax in the mentioned file
|
||||
- Common issues include missing semicolons, curly braces, or mismatched quotes
|
||||
|
||||
2. **Missing Dependencies**:
|
||||
- If the error mentions a missing package or dependency:
|
||||
```
|
||||
git pull # Update to the latest version
|
||||
nix flake update # Update the flake inputs
|
||||
```
|
||||
|
||||
3. **Conflicting Modules**:
|
||||
- Look for modules that might be configuring the same options incompatibly
|
||||
- Disable one of the conflicting modules or adjust their configurations
|
||||
|
||||
4. **Disk Space Issues**:
|
||||
- Check available disk space with `df -h`
|
||||
- Clear old generations: `sudo nix-collect-garbage -d`
|
||||
|
||||
### Boot Issues
|
||||
|
||||
**Problem**: System fails to boot after a configuration change.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Boot into a Previous Generation**:
|
||||
- At the boot menu, select an older generation
|
||||
- Once booted, revert the problematic change:
|
||||
```
|
||||
cd /etc/nixos
|
||||
git revert HEAD # Or edit the files directly
|
||||
sudo nixos-rebuild switch
|
||||
```
|
||||
|
||||
2. **Boot from Installation Media**:
|
||||
- Boot from a NixOS installation media
|
||||
- Mount your system:
|
||||
```
|
||||
sudo mount /dev/disk/by-label/nixos /mnt
|
||||
sudo mount /dev/disk/by-label/boot /mnt/boot # If separate boot partition
|
||||
```
|
||||
- Chroot into your system:
|
||||
```
|
||||
sudo nixos-enter --root /mnt
|
||||
cd /etc/nixos
|
||||
git revert HEAD # Or edit the files directly
|
||||
nixos-rebuild switch --install-bootloader
|
||||
```
|
||||
|
||||
## Home Assistant Issues
|
||||
|
||||
### Home Assistant Fails to Start
|
||||
|
||||
**Problem**: Home Assistant service fails to start.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check Service Status**:
|
||||
```
|
||||
systemctl status home-assistant
|
||||
journalctl -u home-assistant -n 100
|
||||
3. **Fetch failure** — a flake input or package source can't be downloaded. Check network connectivity, or try:
|
||||
```bash
|
||||
nix flake update --update-input <input-name>
|
||||
```
|
||||
|
||||
2. **Database Issues**:
|
||||
- Check PostgreSQL is running: `systemctl status postgresql`
|
||||
- Verify database connection settings in Home Assistant configuration
|
||||
|
||||
3. **Permission Issues**:
|
||||
- Check ownership and permissions on config directory:
|
||||
```
|
||||
ls -la /var/lib/homeassistant
|
||||
sudo chown -R hass:hass /var/lib/homeassistant
|
||||
sudo chmod -R 750 /var/lib/homeassistant
|
||||
```
|
||||
|
||||
4. **Custom Component Issues**:
|
||||
- Try disabling custom components to isolate the issue:
|
||||
- Edit `modules/nixos/homeassistant/services/homeassistant/default.nix`
|
||||
- Comment out the `customComponents` section
|
||||
- Rebuild: `sudo nixos-rebuild switch`
|
||||
|
||||
### Zigbee Device Connection Issues
|
||||
|
||||
**Problem**: Zigbee devices fail to connect or are unstable.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Verify Device Path**:
|
||||
- Check the Zigbee coordinator is properly detected:
|
||||
```
|
||||
ls -la /dev/ttyUSB*
|
||||
```
|
||||
- Update the device path if needed:
|
||||
- Edit your system configuration
|
||||
- Set `mjallen.services.home-assistant.zigbeeDevicePath` to the correct path
|
||||
- Rebuild: `sudo nixos-rebuild switch`
|
||||
|
||||
2. **Interference Issues**:
|
||||
- Move the Zigbee coordinator away from other wireless devices
|
||||
- Try a USB extension cable to improve positioning
|
||||
- Change Zigbee channel in Zigbee2MQTT configuration
|
||||
|
||||
3. **Reset Zigbee2MQTT**:
|
||||
```
|
||||
systemctl restart zigbee2mqtt
|
||||
4. **Disk space** — build sandbox fills up. Free space:
|
||||
```bash
|
||||
sudo nix-collect-garbage -d
|
||||
df -h /nix
|
||||
```
|
||||
|
||||
### Automation Issues
|
||||
### Assertion failures
|
||||
|
||||
**Problem**: Automations don't run as expected.
|
||||
If you see `assertion failed`, read the `message` field. For example:
|
||||
```
|
||||
error: assertion failed at …/nebula/sops.nix
|
||||
mjallen.services.nebula.secretsPrefix must be set
|
||||
```
|
||||
Set the required option in the system configuration.
|
||||
|
||||
**Solutions**:
|
||||
## Boot Issues
|
||||
|
||||
1. **Check Automation Status**:
|
||||
- In Home Assistant UI, verify the automation is enabled
|
||||
- Check Home Assistant logs for automation execution errors
|
||||
### System won't boot after a config change
|
||||
|
||||
2. **Entity Issues**:
|
||||
- Verify entity IDs are correct
|
||||
- Check if entities are available/connected
|
||||
- Test direct service calls to verify entity control works
|
||||
1. At the boot menu, select a previous generation.
|
||||
2. Once booted, revert the change:
|
||||
```bash
|
||||
cd /etc/nixos
|
||||
git revert HEAD
|
||||
sudo nixos-rebuild switch --flake .#$(hostname)
|
||||
```
|
||||
|
||||
3. **Trigger Issues**:
|
||||
- Test the automation manually via Developer Tools > Services
|
||||
- Use `automation.trigger` service with the automation's entity_id
|
||||
### Booting from installation media to recover
|
||||
|
||||
## Flake Issues
|
||||
```bash
|
||||
# Mount the system (adjust device paths as needed)
|
||||
sudo mount /dev/disk/by-label/nixos /mnt
|
||||
sudo mount /dev/disk/by-label/boot /mnt/boot
|
||||
|
||||
### Flake Input Update Errors
|
||||
# Chroot in
|
||||
sudo nixos-enter --root /mnt
|
||||
cd /etc/nixos
|
||||
|
||||
**Problem**: `nix flake update` fails or causes issues.
|
||||
# Revert and rebuild
|
||||
git revert HEAD
|
||||
nixos-rebuild switch --flake .#hostname --install-bootloader
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
### Lanzaboote / Secure Boot issues
|
||||
|
||||
1. **Selective Updates**:
|
||||
- Update specific inputs instead of all at once:
|
||||
```
|
||||
nix flake lock --update-input nixpkgs
|
||||
```
|
||||
If Secure Boot enrolment fails or the system won't verify:
|
||||
|
||||
2. **Rollback Flake Lock**:
|
||||
- If an update causes issues, revert to previous flake.lock:
|
||||
```
|
||||
git checkout HEAD^ -- flake.lock
|
||||
```
|
||||
```bash
|
||||
# Check enrolled keys
|
||||
sbctl status
|
||||
|
||||
3. **Pin to Specific Revisions**:
|
||||
- In `flake.nix`, pin problematic inputs to specific revisions:
|
||||
```nix
|
||||
nixpkgs-stable.url = "github:NixOS/nixpkgs/5233fd2ba76a3accb05f88b08917450363be8899";
|
||||
```
|
||||
# Re-enrol if needed (run as root)
|
||||
sbctl enrol-keys --microsoft
|
||||
|
||||
## Secret Management Issues
|
||||
# Sign bootloader files manually
|
||||
sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi
|
||||
```
|
||||
|
||||
### Sops Decryption Errors
|
||||
## SOPS / Secrets Issues
|
||||
|
||||
**Problem**: Sops fails to decrypt secrets.
|
||||
### `secret not found` or permission denied at boot
|
||||
|
||||
**Solutions**:
|
||||
1. Verify the secret key path matches what's declared in the module's `sops.nix`.
|
||||
2. Check the secret exists in the SOPS file:
|
||||
```bash
|
||||
sops --decrypt secrets/nas-secrets.yaml | grep "the-key"
|
||||
```
|
||||
3. Check the `owner`/`group` set on the secret matches the service user.
|
||||
|
||||
1. **Key Issues**:
|
||||
- Verify your GPG key is available and unlocked
|
||||
- Check `.sops.yaml` includes your key fingerprint
|
||||
### Can't decrypt — wrong age key
|
||||
|
||||
2. **Permission Issues**:
|
||||
- Check file permissions on secret files
|
||||
- Make sure the user running `nixos-rebuild` has access to the GPG key
|
||||
The machine's age key is derived from `/etc/ssh/ssh_host_ed25519_key`. If the host key was regenerated, the age key changed and existing secrets can no longer be decrypted.
|
||||
|
||||
To fix: re-encrypt the secrets file with the new public key:
|
||||
```bash
|
||||
# Get the new public key
|
||||
nix-shell -p ssh-to-age --run 'ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub'
|
||||
|
||||
# Update .sops.yaml with the new key, then:
|
||||
sops updatekeys secrets/nas-secrets.yaml
|
||||
```
|
||||
|
||||
### Adding a new secret to an existing file
|
||||
|
||||
```bash
|
||||
sops secrets/nas-secrets.yaml
|
||||
# Editor opens with decrypted YAML — add your key, save, sops re-encrypts
|
||||
```
|
||||
|
||||
## Nebula VPN Issues
|
||||
|
||||
### Peers can't connect
|
||||
|
||||
1. Verify the lighthouse is reachable on its public address:
|
||||
```bash
|
||||
nc -zvu mjallen.dev 4242
|
||||
```
|
||||
2. Check the nebula service on both hosts:
|
||||
```bash
|
||||
systemctl status nebula@jallen-nebula
|
||||
journalctl -u nebula@jallen-nebula -n 50
|
||||
```
|
||||
3. Confirm the CA cert, host cert, and host key are all present and owned by the `nebula-jallen-nebula` user:
|
||||
```bash
|
||||
ls -la /run/secrets/pi5/nebula/
|
||||
```
|
||||
4. Verify the host cert was signed by the same CA as the other nodes:
|
||||
```bash
|
||||
nebula-cert verify -ca ca.crt -crt host.crt
|
||||
```
|
||||
|
||||
### Certificate expired
|
||||
|
||||
Re-sign the host certificate:
|
||||
```bash
|
||||
nebula-cert sign -name "hostname" -ip "10.1.1.x/24" \
|
||||
-ca-crt ca.crt -ca-key ca.key \
|
||||
-out-crt host.crt -out-key host.key
|
||||
# Update SOPS, rebuild
|
||||
```
|
||||
|
||||
## Impermanence Issues
|
||||
|
||||
### Service fails because its data directory is missing after reboot
|
||||
|
||||
If a service stores state in a path that isn't in the persistence list, it will be wiped on reboot. Add it to `impermanence.extraDirectories`:
|
||||
|
||||
```nix
|
||||
mjallen.impermanence.extraDirectories = [
|
||||
{ directory = "/var/lib/my-service"; user = "my-service"; group = "my-service"; mode = "0750"; }
|
||||
];
|
||||
```
|
||||
|
||||
Then move the existing data if needed:
|
||||
```bash
|
||||
cp -a /var/lib/my-service /persist/var/lib/my-service
|
||||
```
|
||||
|
||||
## Flake Input Issues
|
||||
|
||||
### Input update breaks a build
|
||||
|
||||
Roll back the specific input:
|
||||
```bash
|
||||
git checkout HEAD^ -- flake.lock
|
||||
```
|
||||
|
||||
Or pin the input to a specific revision in `flake.nix`:
|
||||
```nix
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/abc123def";
|
||||
```
|
||||
|
||||
## Service Issues
|
||||
|
||||
### Service won't start
|
||||
|
||||
```bash
|
||||
systemctl status <service>
|
||||
journalctl -u <service> -n 100 --no-pager
|
||||
```
|
||||
|
||||
### Caddy reverse proxy not routing
|
||||
|
||||
1. Check that `reverseProxy.enable = true` is set on the service.
|
||||
2. Verify the subdomain matches: `reverseProxy.subdomain = "myapp"` → `myapp.mjallen.dev`.
|
||||
3. Check Caddy logs:
|
||||
```bash
|
||||
journalctl -u caddy -n 50
|
||||
```
|
||||
|
||||
### PostgreSQL database missing for a service
|
||||
|
||||
If `configureDb = true` is set, the database is created automatically. If it's missing:
|
||||
```bash
|
||||
sudo -u postgres createdb my-service
|
||||
sudo -u postgres psql -c "GRANT ALL ON DATABASE my-service TO my-service;"
|
||||
```
|
||||
|
||||
## Network Issues
|
||||
|
||||
### Firewall Blocks Services
|
||||
### Firewall blocking a service
|
||||
|
||||
**Problem**: Services are not accessible due to firewall rules.
|
||||
Check which ports are open:
|
||||
```bash
|
||||
sudo nft list ruleset | grep accept
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
Add ports in the system config:
|
||||
```nix
|
||||
mjallen.network.firewall.allowedTCPPorts = [ 8080 ];
|
||||
```
|
||||
|
||||
1. **Check Firewall Status**:
|
||||
```
|
||||
sudo nix-shell -p iptables --run "iptables -L"
|
||||
```
|
||||
|
||||
2. **Verify Firewall Configuration**:
|
||||
- Check if ports are properly allowed in the configuration
|
||||
- Add missing ports if necessary
|
||||
|
||||
3. **Temporary Disable Firewall** (for testing only):
|
||||
```
|
||||
sudo systemctl stop firewall
|
||||
# After testing
|
||||
sudo systemctl start firewall
|
||||
```
|
||||
Or if using `mkModule`, set `openFirewall = true` (it's the default).
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you encounter an issue not covered in this guide:
|
||||
|
||||
1. Check the NixOS Wiki: https://nixos.wiki/
|
||||
2. Search the NixOS Discourse forum: https://discourse.nixos.org/
|
||||
3. Join the NixOS Matrix/Discord community for real-time help
|
||||
4. File an issue in the repository if you believe you've found a bug
|
||||
- NixOS manual: `nixos-help` or https://nixos.org/manual/nixos/stable/
|
||||
- NixOS Wiki: https://nixos.wiki/
|
||||
- NixOS Discourse: https://discourse.nixos.org/
|
||||
- Nix package search: https://search.nixos.org/packages
|
||||
|
||||
2
docs/version.schema.json
Normal file → Executable file
2
docs/version.schema.json
Normal file → Executable file
@@ -76,6 +76,7 @@
|
||||
"repo": { "type": "string", "description": "GitHub repository (github fetcher)." },
|
||||
"tag": { "type": "string", "description": "Git tag (github fetcher). Mutually exclusive with 'rev'." },
|
||||
"rev": { "type": "string", "description": "Commit revision (github/git fetchers)." },
|
||||
"branch": { "type": "string", "description": "Branch to track for HEAD-commit updates (github/git fetchers). Stored alongside 'rev' to record which branch the pinned commit came from. Has no effect on the Nix fetcher itself — only used by the version management tooling." },
|
||||
"submodules": { "type": "boolean", "description": "Whether to fetch submodules (github/git fetchers)." },
|
||||
|
||||
"url": { "type": "string", "description": "Final URL (url fetcher). May be templated." },
|
||||
@@ -157,6 +158,7 @@
|
||||
"repo": { "type": "string" },
|
||||
"tag": { "type": "string" },
|
||||
"rev": { "type": "string" },
|
||||
"branch": { "type": "string" },
|
||||
"submodules": { "type": "boolean" },
|
||||
|
||||
"url": { "type": "string" },
|
||||
|
||||
371
flake.lock
generated
Normal file → Executable file
371
flake.lock
generated
Normal file → Executable file
@@ -25,7 +25,7 @@
|
||||
"flake-utils": "flake-utils",
|
||||
"napalm": "napalm",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
"nixpkgs-stable"
|
||||
],
|
||||
"pyproject-build-systems": "pyproject-build-systems",
|
||||
"pyproject-nix": "pyproject-nix",
|
||||
@@ -33,11 +33,11 @@
|
||||
"uv2nix": "uv2nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772909021,
|
||||
"narHash": "sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM=",
|
||||
"lastModified": 1776085803,
|
||||
"narHash": "sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "authentik-nix",
|
||||
"rev": "7e4730351fb6df479c46a1bf7e23d46a0b0c5d46",
|
||||
"rev": "4370b561c8bafb59773ce3a518506bcf1161dbdb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -49,16 +49,16 @@
|
||||
"authentik-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772567399,
|
||||
"narHash": "sha256-0Vpf1hj9C8r+rhrCgwoNazpQ+mwgjdjDhuoKCxYQFWw=",
|
||||
"lastModified": 1775573258,
|
||||
"narHash": "sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4=",
|
||||
"owner": "goauthentik",
|
||||
"repo": "authentik",
|
||||
"rev": "0dccbd4193c45c581e9fb7cd89df0c1487510f1f",
|
||||
"rev": "5249546862986202b901c2afd860992ec48c6ef6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "goauthentik",
|
||||
"ref": "version/2026.2.1",
|
||||
"ref": "version/2026.2.2",
|
||||
"repo": "authentik",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -134,16 +134,16 @@
|
||||
"brew-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1769363988,
|
||||
"narHash": "sha256-BiGPeulrDVetXP+tjxhMcGLUROZAtZIhU5m4MqawCfM=",
|
||||
"lastModified": 1774235677,
|
||||
"narHash": "sha256-0ryNYmzDAeRlrzPTAgmzGH/Cgc8iv/LBN6jWGUANvIk=",
|
||||
"owner": "Homebrew",
|
||||
"repo": "brew",
|
||||
"rev": "d01011cac6d72032c75fd2cd9489909e95d9faf2",
|
||||
"rev": "894a3d23ac0c8aaf561b9874b528b9cb2e839201",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Homebrew",
|
||||
"ref": "5.0.12",
|
||||
"ref": "5.1.1",
|
||||
"repo": "brew",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -151,11 +151,11 @@
|
||||
"cachyos-kernel": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773333570,
|
||||
"narHash": "sha256-Z+r3HFziyn0ExgJj8qkwoqPZwP8sQMESX6QBWa/8uwM=",
|
||||
"lastModified": 1776183001,
|
||||
"narHash": "sha256-lvLKB5dTqjO1S/YonS9ZyWemEjO6QXtN4D76rYEYy4s=",
|
||||
"owner": "CachyOS",
|
||||
"repo": "linux-cachyos",
|
||||
"rev": "261b59ccef1a9ca6a3a6344f585ee1ff593e4306",
|
||||
"rev": "4224303b6d7a50dd1cc3ffa78864050cc9536eec",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -167,11 +167,11 @@
|
||||
"cachyos-kernel-patches": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773330205,
|
||||
"narHash": "sha256-YVASxGrJYFHtL+5D71hlbc74VfgDnQGRpzVu0YiFHtw=",
|
||||
"lastModified": 1776355454,
|
||||
"narHash": "sha256-b9Hc0sTxjEzDbphzS9yQqxVha/7bsPIs2cQQQvaG45E=",
|
||||
"owner": "CachyOS",
|
||||
"repo": "kernel-patches",
|
||||
"rev": "8242bda544657099da69993f019ff3fb23cfe05f",
|
||||
"rev": "b5e029226df5cc30c103651072d49a7af2878202",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -223,11 +223,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773000227,
|
||||
"narHash": "sha256-zm3ftUQw0MPumYi91HovoGhgyZBlM4o3Zy0LhPNwzXE=",
|
||||
"lastModified": 1775037210,
|
||||
"narHash": "sha256-KM2WYj6EA7M/FVZVCl3rqWY+TFV5QzSyyGE2gQxeODU=",
|
||||
"owner": "nix-darwin",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "da529ac9e46f25ed5616fd634079a5f3c579135f",
|
||||
"rev": "06648f4902343228ce2de79f291dd5a58ee12146",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -244,11 +244,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773025010,
|
||||
"narHash": "sha256-khlHllTsovXgT2GZ0WxT4+RvuMjNeR5OW0UYeEHPYQo=",
|
||||
"lastModified": 1773889306,
|
||||
"narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "7b9f7f88ab3b339f8142dc246445abb3c370d3d3",
|
||||
"rev": "5ad85c82cc52264f4beddc934ba57f3789f28347",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -260,11 +260,11 @@
|
||||
"firefox-gnome-theme": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1764873433,
|
||||
"narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=",
|
||||
"lastModified": 1775176642,
|
||||
"narHash": "sha256-2veEED0Fg7Fsh81tvVDNYR6SzjqQxa7hbi18Jv4LWpM=",
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92",
|
||||
"rev": "179704030c5286c729b5b0522037d1d51341022c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -391,11 +391,11 @@
|
||||
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772408722,
|
||||
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
|
||||
"lastModified": 1730504689,
|
||||
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
|
||||
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -405,6 +405,24 @@
|
||||
}
|
||||
},
|
||||
"flake-parts_3": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775087534,
|
||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"stylix",
|
||||
@@ -412,11 +430,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767609335,
|
||||
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
|
||||
"lastModified": 1775087534,
|
||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
|
||||
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -545,20 +563,18 @@
|
||||
"gnome-shell": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"lastModified": 1767737596,
|
||||
"narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=",
|
||||
"owner": "GNOME",
|
||||
"repo": "gnome-shell",
|
||||
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
|
||||
"type": "gitlab"
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"owner": "GNOME",
|
||||
"ref": "gnome-49",
|
||||
"repo": "gnome-shell",
|
||||
"type": "gitlab"
|
||||
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
@@ -568,11 +584,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773367248,
|
||||
"narHash": "sha256-FFMc1uAwy2GYasd0rdNDVxKyAgzuoJH2M+GglBQbqf0=",
|
||||
"lastModified": 1776454077,
|
||||
"narHash": "sha256-7zSUFWsU0+jlD7WB3YAxQ84Z/iJurA5hKPm8EfEyGJk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "be0c641a6a5564caa33982faa1fe2c60d92131c7",
|
||||
"rev": "565e5349208fe7d0831ef959103c9bafbeac0681",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -581,27 +597,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager-stable": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs-stable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773264488,
|
||||
"narHash": "sha256-rK0507bDuWBrZo+0zts9bCs/+RRUEHuvFE5DHWPxX/Q=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "5c0f63f8d55040a7eed69df7e3fcdd15dfb5a04c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-25.11",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager-unstable": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -609,11 +604,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773367248,
|
||||
"narHash": "sha256-FFMc1uAwy2GYasd0rdNDVxKyAgzuoJH2M+GglBQbqf0=",
|
||||
"lastModified": 1776454077,
|
||||
"narHash": "sha256-7zSUFWsU0+jlD7WB3YAxQ84Z/iJurA5hKPm8EfEyGJk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "be0c641a6a5564caa33982faa1fe2c60d92131c7",
|
||||
"rev": "565e5349208fe7d0831ef959103c9bafbeac0681",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -663,11 +658,11 @@
|
||||
"homebrew-cask": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773417963,
|
||||
"narHash": "sha256-BdilqX31TH5WTRgKVSPNGJUHwOAHHT1xUe3oXC8GPEI=",
|
||||
"lastModified": 1776469040,
|
||||
"narHash": "sha256-IX5UflSmiXkJnRUCNjzBl4/HMw0NMLQqsfdwA4l0kyU=",
|
||||
"owner": "homebrew",
|
||||
"repo": "homebrew-cask",
|
||||
"rev": "294c9a01670be07a255cca3b4519ffe37d3130dc",
|
||||
"rev": "906ff3d493d3e9f50ceb5041fcc14bcfe3d63ff1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -679,11 +674,11 @@
|
||||
"homebrew-core": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773417171,
|
||||
"narHash": "sha256-QuAxK3GHyx/T8vJuv3Za7mCrUAjfZxsdP0zbkQyDNlE=",
|
||||
"lastModified": 1776461416,
|
||||
"narHash": "sha256-AqxPJs6cy7ZwsS2ovNuLxUJM+2kgnEi4ECXitf6nb18=",
|
||||
"owner": "homebrew",
|
||||
"repo": "homebrew-core",
|
||||
"rev": "538b810c144eb4b692c680b2da2dafee9f725e77",
|
||||
"rev": "2aab2c98676928d65d72ce7fc2abd5c7f3634319",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -719,11 +714,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773380813,
|
||||
"narHash": "sha256-6GDKki2AIkWgnnTGA1enQB3I1mI6rdPe4rrXafmmIiY=",
|
||||
"lastModified": 1776428236,
|
||||
"narHash": "sha256-+0SyQglnT2xUiyY07155G+O7aUWISELwqtTnfURufRU=",
|
||||
"owner": "Jovian-Experiments",
|
||||
"repo": "Jovian-NixOS",
|
||||
"rev": "8347eae3a900c26b8223ee98697f30f4e88dc226",
|
||||
"rev": "eac78fc379ca47f7e21be8539c405e5fb489a857",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -754,6 +749,27 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"llama-cpp": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776442631,
|
||||
"narHash": "sha256-8AXOo0Yhbi3jpQFe4Ql+0HZDz/p708GdrbZVepNjITo=",
|
||||
"owner": "ggml-org",
|
||||
"repo": "llama.cpp",
|
||||
"rev": "45cac7ca703fb9085eae62b9121fca01d20177f6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ggml-org",
|
||||
"repo": "llama.cpp",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"lsfg-vk": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -805,15 +821,15 @@
|
||||
"cachyos-kernel": "cachyos-kernel",
|
||||
"cachyos-kernel-patches": "cachyos-kernel-patches",
|
||||
"flake-compat": "flake-compat_4",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773339151,
|
||||
"narHash": "sha256-T4mZqOKMX3bbOKm/KvlkIOznaUPFpBbNKBT5bDMdRkQ=",
|
||||
"lastModified": 1776386586,
|
||||
"narHash": "sha256-eVAUaL/6n8mnmBiPpEVW1NDNVSKLWhYVfycG+P0SvWU=",
|
||||
"owner": "xddxdd",
|
||||
"repo": "nix-cachyos-kernel",
|
||||
"rev": "a984d014ba87dbefd8868d1fe967cc540d313766",
|
||||
"rev": "c65c3faf90ae07bae101c15ef502f0bcb06c5d74",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -850,11 +866,11 @@
|
||||
"brew-src": "brew-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769437432,
|
||||
"narHash": "sha256-8d7KnCpT2LweRvSzZYEGd9IM3eFX+A78opcnDM0+ndk=",
|
||||
"lastModified": 1774720267,
|
||||
"narHash": "sha256-YYftFe8jyfpQI649yfr0E+dqEXE2jznZNcYvy/lKV1U=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "nix-homebrew",
|
||||
"rev": "a5409abd0d5013d79775d3419bcac10eacb9d8c5",
|
||||
"rev": "a7760a3a83f7609f742861afb5732210fdc437ed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -870,11 +886,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772945408,
|
||||
"narHash": "sha256-PMt48sEQ8cgCeljQ9I/32uoBq/8t8y+7W/nAZhf72TQ=",
|
||||
"lastModified": 1775970782,
|
||||
"narHash": "sha256-7jt9Vpm48Yy5yAWigYpde+HxtYEpEuyzIQJF4VYehhk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "1c1d8ea87b047788fd7567adf531418c5da321ec",
|
||||
"rev": "bedba5989b04614fc598af9633033b95a937933f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -927,11 +943,11 @@
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773369788,
|
||||
"narHash": "sha256-32y9nyVU2rmXp/zMTNsVbIWNKMPUuBSj4bIAnaPiCVU=",
|
||||
"lastModified": 1776396489,
|
||||
"narHash": "sha256-lF3GX4VvQzff/5gpu5WytHKd2GQXJDrWChmK+JNNRO4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-vscode-extensions",
|
||||
"rev": "70e188702ad3b4dcf5de12ff64f0d31c906d6d7a",
|
||||
"rev": "64839596bff67e8280a2fcd829a858d88530aa6f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -946,11 +962,11 @@
|
||||
"nixpkgs": "nixpkgs_8"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772952158,
|
||||
"narHash": "sha256-RDR+7v1vaojweHI3FdPnuYPy4wRGfTKgeD5GXrXbfT0=",
|
||||
"lastModified": 1776370524,
|
||||
"narHash": "sha256-0Gt5qnjNkIZJdOBfu2u47zgyhYL3WmgUrguUhGSxUdk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixos-apple-silicon",
|
||||
"rev": "55b7c3c03e9b778d96a71f44400bbdda9a4cfda7",
|
||||
"rev": "f9f0650b45e31b3f6c3e2a0405fa198a286e2741",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -961,11 +977,11 @@
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1772972630,
|
||||
"narHash": "sha256-mUJxsNOrBMNOUJzN0pfdVJ1r2pxeqm9gI/yIKXzVVbk=",
|
||||
"lastModified": 1775490113,
|
||||
"narHash": "sha256-2ZBhDNZZwYkRmefK5XLOusCJHnoeKkoN95hoSGgMxWM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "3966ce987e1a9a164205ac8259a5fe8a64528f72",
|
||||
"rev": "c775c2772ba56e906cbeb4e0b2db19079ef11ff7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1008,32 +1024,28 @@
|
||||
},
|
||||
"nixpkgs-lib_2": {
|
||||
"locked": {
|
||||
"lastModified": 1772328832,
|
||||
"narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
|
||||
"type": "github"
|
||||
"lastModified": 1730504152,
|
||||
"narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz"
|
||||
}
|
||||
},
|
||||
"nixpkgs-otbr": {
|
||||
"nixpkgs-lib_3": {
|
||||
"locked": {
|
||||
"lastModified": 1766776257,
|
||||
"narHash": "sha256-MG9DnzBn6TdAztaMPVhW9sjYj2bi9Jcux0F0fJ6LeO4=",
|
||||
"owner": "mrene",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0c4c97066d555b7d27a0a56ee400130ec51f02ee",
|
||||
"lastModified": 1774748309,
|
||||
"narHash": "sha256-+U7gF3qxzwD5TZuANzZPeJTZRHS29OFQgkQ2kiTJBIQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "333c4e0545a6da976206c74db8773a1645b5870a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "mrene",
|
||||
"ref": "openthread-border-router",
|
||||
"repo": "nixpkgs",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
@@ -1055,11 +1067,11 @@
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1773222311,
|
||||
"narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=",
|
||||
"lastModified": 1776221942,
|
||||
"narHash": "sha256-FbQAeVNi7G4v3QCSThrSAAvzQTmrmyDLiHNPvTF2qFM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0590cd39f728e129122770c029970378a79d076a",
|
||||
"rev": "1766437c5509f444c1b15331e82b8b6a9b967000",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1071,11 +1083,11 @@
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1773389992,
|
||||
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
|
||||
"lastModified": 1776447299,
|
||||
"narHash": "sha256-fhkbQptSg6w3CG4TCxalK6UZkj4+Afsi+6p0PuofJ48=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
|
||||
"rev": "2c1b4e855f7cded41541747173c697b53c63de9b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1087,11 +1099,11 @@
|
||||
},
|
||||
"nixpkgs_10": {
|
||||
"locked": {
|
||||
"lastModified": 1772736753,
|
||||
"narHash": "sha256-au/m3+EuBLoSzWUCb64a/MZq6QUtOV8oC0D9tY2scPQ=",
|
||||
"lastModified": 1775888245,
|
||||
"narHash": "sha256-nwASzrRDD1JBEu/o8ekKYEXm/oJW6EMCzCRdrwcLe90=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "917fec990948658ef1ccd07cef2a1ef060786846",
|
||||
"rev": "13043924aaa7375ce482ebe2494338e058282925",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1135,11 +1147,11 @@
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1773276312,
|
||||
"narHash": "sha256-UujcRqoPEyi0Bd77+cqfAxa4aq0SoKOYTcJNWn+0ZvM=",
|
||||
"lastModified": 1776311487,
|
||||
"narHash": "sha256-9U8bL9X/0R9cZD3Uc/mN37AWvv5dB4WQqqjLRAxQfas=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "87fd45fc9269db8f7197d27c620606323bbf5efa",
|
||||
"rev": "cc1e0e027707ad53dddae39d3b3e992262c7d8c7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1199,11 +1211,11 @@
|
||||
},
|
||||
"nixpkgs_8": {
|
||||
"locked": {
|
||||
"lastModified": 1768305791,
|
||||
"narHash": "sha256-AIdl6WAn9aymeaH/NvBj0H9qM+XuAuYbGMZaP0zcXAQ=",
|
||||
"lastModified": 1774106199,
|
||||
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1412caf7bf9e660f2f962917c14b1ea1c3bc695e",
|
||||
"rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1215,11 +1227,11 @@
|
||||
},
|
||||
"nixpkgs_9": {
|
||||
"locked": {
|
||||
"lastModified": 1773389992,
|
||||
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
|
||||
"lastModified": 1776447299,
|
||||
"narHash": "sha256-fhkbQptSg6w3CG4TCxalK6UZkj4+Afsi+6p0PuofJ48=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
|
||||
"rev": "2c1b4e855f7cded41541747173c697b53c63de9b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1241,11 +1253,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767810917,
|
||||
"narHash": "sha256-ZKqhk772+v/bujjhla9VABwcvz+hB2IaRyeLT6CFnT0=",
|
||||
"lastModified": 1775228139,
|
||||
"narHash": "sha256-ebbeHmg+V7w8050bwQOuhmQHoLOEOfqKzM1KgCTexK4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "dead29c804adc928d3a69dfe7f9f12d0eec1f1a4",
|
||||
"rev": "601971b9c89e0304561977f2c28fa25e73aa7132",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1254,6 +1266,29 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"plasma-manager": {
|
||||
"inputs": {
|
||||
"home-manager": [
|
||||
"home-manager"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775856943,
|
||||
"narHash": "sha256-b7Mp7P+q2Md5AGt4rjHfMcBykzMumFTen10ST++AuTU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "plasma-manager",
|
||||
"rev": "a524a6160e6df89f7673ba293cf7d78b559eb1a5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "plasma-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_3",
|
||||
@@ -1286,11 +1321,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772893680,
|
||||
"narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=",
|
||||
"lastModified": 1775585728,
|
||||
"narHash": "sha256-8Psjt+TWvE4thRKktJsXfR6PA/fWWsZ04DVaY6PUhr4=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "8baab586afc9c9b57645a734c820e4ac0a604af9",
|
||||
"rev": "580633fa3fe5fc0379905986543fd7495481913d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1356,13 +1391,13 @@
|
||||
"darwin": "darwin",
|
||||
"disko": "disko",
|
||||
"home-manager": "home-manager",
|
||||
"home-manager-stable": "home-manager-stable",
|
||||
"home-manager-unstable": "home-manager-unstable",
|
||||
"homebrew-cask": "homebrew-cask",
|
||||
"homebrew-core": "homebrew-core",
|
||||
"impermanence": "impermanence",
|
||||
"jovian": "jovian",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"llama-cpp": "llama-cpp",
|
||||
"lsfg-vk": "lsfg-vk",
|
||||
"nix-cachyos-kernel": "nix-cachyos-kernel",
|
||||
"nix-homebrew": "nix-homebrew",
|
||||
@@ -1373,9 +1408,9 @@
|
||||
"nixos-apple-silicon": "nixos-apple-silicon",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs_9",
|
||||
"nixpkgs-otbr": "nixpkgs-otbr",
|
||||
"nixpkgs-stable": "nixpkgs-stable_2",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"plasma-manager": "plasma-manager",
|
||||
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
|
||||
"snowfall-lib": "snowfall-lib",
|
||||
"sops-nix": "sops-nix",
|
||||
@@ -1435,11 +1470,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773689564,
|
||||
"narHash": "sha256-TJmDl89HPGum3srhggVbcfHV5oN6XL5SgN7/dI3kB4M=",
|
||||
"lastModified": 1774478645,
|
||||
"narHash": "sha256-NeEWeisE2QLCCJg688/vaLp9/V7osVenn/EUm3JXsgg=",
|
||||
"owner": "mjallen18",
|
||||
"repo": "snowfall-lib",
|
||||
"rev": "3dd4e430e291d9f7d0e9c69f89fea8c175041e44",
|
||||
"rev": "23e5a04d70389d58b7c1447924d59cfb78218215",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1453,11 +1488,11 @@
|
||||
"nixpkgs": "nixpkgs_10"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773096132,
|
||||
"narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=",
|
||||
"lastModified": 1776119890,
|
||||
"narHash": "sha256-Zm6bxLNnEOYuS/SzrAGsYuXSwk3cbkRQZY0fJnk8a5M=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784",
|
||||
"rev": "d4971dd58c6627bfee52a1ad4237637c0a2fb0cd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1496,25 +1531,24 @@
|
||||
"base16-helix": "base16-helix",
|
||||
"base16-vim": "base16-vim",
|
||||
"firefox-gnome-theme": "firefox-gnome-theme",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"flake-parts": "flake-parts_4",
|
||||
"gnome-shell": "gnome-shell",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nur": "nur",
|
||||
"systems": "systems_3",
|
||||
"tinted-foot": "tinted-foot",
|
||||
"tinted-kitty": "tinted-kitty",
|
||||
"tinted-schemes": "tinted-schemes",
|
||||
"tinted-tmux": "tinted-tmux",
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772296853,
|
||||
"narHash": "sha256-pAtzPsgHRKw/2Kv8HgAjSJg450FDldHPWsP3AKG/Xj0=",
|
||||
"lastModified": 1776170745,
|
||||
"narHash": "sha256-Tl1aZVP5EIlT+k0+iAKH018GLHJpLz3hhJ0LNQOWxCc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"rev": "c4b8e80a1020e09a1f081ad0f98ce804a6e85acf",
|
||||
"rev": "e3861617645a43c9bbefde1aa6ac54dd0a44bfa9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1568,23 +1602,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-foot": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1726913040,
|
||||
"narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-kitty": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -1604,11 +1621,11 @@
|
||||
"tinted-schemes": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767710407,
|
||||
"narHash": "sha256-+W1EB79Jl0/gm4JqmO0Nuc5C7hRdp4vfsV/VdzI+des=",
|
||||
"lastModified": 1772661346,
|
||||
"narHash": "sha256-4eu3LqB9tPqe0Vaqxd4wkZiBbthLbpb7llcoE/p5HT0=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"rev": "2800e2b8ac90f678d7e4acebe4fa253f602e05b2",
|
||||
"rev": "13b5b0c299982bb361039601e2d72587d6846294",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1620,11 +1637,11 @@
|
||||
"tinted-tmux": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767489635,
|
||||
"narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=",
|
||||
"lastModified": 1772934010,
|
||||
"narHash": "sha256-x+6+4UvaG+RBRQ6UaX+o6DjEg28u4eqhVRM9kpgJGjQ=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184",
|
||||
"rev": "c3529673a5ab6e1b6830f618c45d9ce1bcdd829d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1636,11 +1653,11 @@
|
||||
"tinted-zed": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767488740,
|
||||
"narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=",
|
||||
"lastModified": 1772909925,
|
||||
"narHash": "sha256-jx/5+pgYR0noHa3hk2esin18VMbnPSvWPL5bBjfTIAU=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40",
|
||||
"rev": "b4d3a1b3bcbd090937ef609a0a3b37237af974df",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1678,11 +1695,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773297127,
|
||||
"narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=",
|
||||
"lastModified": 1775636079,
|
||||
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "71b125cd05fbfd78cab3e070b73544abe24c5016",
|
||||
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
109
flake.nix
Normal file → Executable file
109
flake.nix
Normal file → Executable file
@@ -3,15 +3,6 @@
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
|
||||
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
|
||||
# Fork required: openthread-border-router is not yet in nixpkgs-unstable.
|
||||
# Used by modules/nixos/homeassistant/services/thread/default.nix
|
||||
nixpkgs-otbr.url = "github:mrene/nixpkgs/openthread-border-router";
|
||||
|
||||
home-manager-stable = {
|
||||
url = "github:nix-community/home-manager/release-25.11";
|
||||
inputs.nixpkgs.follows = "nixpkgs-stable";
|
||||
};
|
||||
|
||||
home-manager-unstable = {
|
||||
url = "github:nix-community/home-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
@@ -27,11 +18,6 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# nixos-generators = {
|
||||
# url = "github:nix-community/nixos-generators";
|
||||
# inputs.nixpkgs.follows = "nixpkgs";
|
||||
# };
|
||||
|
||||
impermanence.url = "github:nix-community/impermanence";
|
||||
|
||||
lanzaboote.url = "github:nix-community/lanzaboote/v1.0.0";
|
||||
@@ -57,7 +43,7 @@
|
||||
|
||||
authentik-nix = {
|
||||
url = "github:nix-community/authentik-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.nixpkgs.follows = "nixpkgs-stable";
|
||||
};
|
||||
|
||||
disko = {
|
||||
@@ -121,6 +107,17 @@
|
||||
url = "github:Jovian-Experiments/Jovian-NixOS";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
llama-cpp = {
|
||||
url = "github:ggml-org/llama.cpp";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
plasma-manager = {
|
||||
url = "github:nix-community/plasma-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.home-manager.follows = "home-manager";
|
||||
};
|
||||
};
|
||||
|
||||
# We will handle this in the next section.
|
||||
@@ -138,37 +135,59 @@
|
||||
overlays = with inputs; [
|
||||
nix-vscode-extensions.overlays.default
|
||||
nix-cachyos-kernel.overlays.default
|
||||
# writeShellApplication uses lib.toShellVar which generates unquoted
|
||||
# variable assignments for simple strings (e.g. username=admin).
|
||||
# shellcheck SC2209 flags this as a warning, breaking the build when
|
||||
# the value matches a command name. Exclude SC2209 globally.
|
||||
(_final: prev: {
|
||||
writeShellApplication =
|
||||
args:
|
||||
prev.writeShellApplication (
|
||||
args
|
||||
// {
|
||||
excludeShellChecks = (args.excludeShellChecks or [ ]) ++ [ "SC2209" ];
|
||||
}
|
||||
);
|
||||
})
|
||||
];
|
||||
|
||||
# Add a module to a specific host.
|
||||
systems = {
|
||||
# common modules
|
||||
modules.nixos = with inputs; [
|
||||
# nix-cachyos-kernel.nixosModules.default
|
||||
authentik-nix.nixosModules.default
|
||||
disko.nixosModules.disko
|
||||
impermanence.nixosModules.impermanence
|
||||
lanzaboote.nixosModules.lanzaboote
|
||||
sops-nix.nixosModules.sops
|
||||
home-manager.nixosModules.home-manager
|
||||
nix-index-database.nixosModules.nix-index
|
||||
stylix.nixosModules.stylix
|
||||
];
|
||||
modules = {
|
||||
nixos = with inputs; [
|
||||
authentik-nix.nixosModules.default
|
||||
disko.nixosModules.disko
|
||||
impermanence.nixosModules.impermanence
|
||||
lanzaboote.nixosModules.lanzaboote
|
||||
sops-nix.nixosModules.sops
|
||||
home-manager.nixosModules.home-manager
|
||||
nix-index-database.nixosModules.nix-index
|
||||
stylix.nixosModules.stylix
|
||||
];
|
||||
|
||||
modules.home = with inputs; [
|
||||
nix-index-database.homeManagerModules.nix-index
|
||||
steam-rom-manager.homeManagerModules.default
|
||||
];
|
||||
# External HM modules injected into ALL homes — both standalone
|
||||
# homeConfigurations and homes embedded in nixosConfigurations.
|
||||
# The snowfall-lib fork patches create-systems to pass systems.modules.home
|
||||
# into create-home-system-modules so both paths are covered from here.
|
||||
# The ARM guard for steam-rom-manager is handled by that module itself.
|
||||
home = with inputs; [
|
||||
nix-index-database.homeModules.nix-index
|
||||
steam-rom-manager.homeManagerModules.default
|
||||
sops-nix.homeManagerModules.sops
|
||||
stylix.homeModules.stylix
|
||||
plasma-manager.homeModules.plasma-manager
|
||||
];
|
||||
|
||||
# common darwin modules
|
||||
modules.darwin = with inputs; [
|
||||
nix-homebrew.darwinModules.nix-homebrew
|
||||
home-manager.darwinModules.home-manager
|
||||
nix-plist-manager.darwinModules.default
|
||||
nix-rosetta-builder.darwinModules.default
|
||||
nix-index-database.darwinModules.nix-index
|
||||
stylix.darwinModules.stylix
|
||||
];
|
||||
darwin = with inputs; [
|
||||
nix-homebrew.darwinModules.nix-homebrew
|
||||
home-manager.darwinModules.home-manager
|
||||
nix-plist-manager.darwinModules.default
|
||||
nix-rosetta-builder.darwinModules.default
|
||||
nix-index-database.darwinModules.nix-index
|
||||
stylix.darwinModules.stylix
|
||||
];
|
||||
};
|
||||
|
||||
# Host config
|
||||
hosts = {
|
||||
@@ -216,14 +235,6 @@
|
||||
];
|
||||
};
|
||||
|
||||
# ######################################################
|
||||
# Pi5 #
|
||||
# ######################################################
|
||||
pi5 = {
|
||||
# disko is already in systems.modules.nixos above
|
||||
modules = [ ];
|
||||
};
|
||||
|
||||
# ######################################################
|
||||
# Mac #
|
||||
# ######################################################
|
||||
@@ -275,6 +286,10 @@
|
||||
# ...
|
||||
# "libsoup-2.74.3"
|
||||
# "mbedtls-2.28.10"
|
||||
# ecdsa is pulled in by srp → ha-icloud3 custom component.
|
||||
# CVE-2024-23342 applies to timing-sensitive cryptographic use cases,
|
||||
# not the SRP authentication usage here.
|
||||
"python3.14-ecdsa-0.19.1"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ let
|
||||
iproute2mac
|
||||
nebula
|
||||
nixfmt
|
||||
nodePackages.nodejs
|
||||
nodejs_25
|
||||
uv
|
||||
sops
|
||||
tree
|
||||
@@ -43,220 +43,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# programs.nix-plist-manager = {
|
||||
# enable = true;
|
||||
# options = {
|
||||
# applications = {
|
||||
# finder = {
|
||||
# settings = {
|
||||
# general = {
|
||||
# showTheseItemsOnTheDesktop = {
|
||||
# hardDisks = false;
|
||||
# externalDisks = true;
|
||||
# cdsDvdsAndiPods = false;
|
||||
# connectedServers = false;
|
||||
# };
|
||||
# openFoldersInTabsInsteadOfNewWindows = true;
|
||||
# };
|
||||
# sidebar = {
|
||||
# recentTags = true;
|
||||
# };
|
||||
# advanced = {
|
||||
# removeItemsFromTheTrashAfter30Days = true;
|
||||
# showAllFilenameExtensions = true;
|
||||
# showWarningBeforeChangingAnExtension = true;
|
||||
# showWarningBeforeRemovingFromiCloudDrive = true;
|
||||
# showWarningBeforeEmptyingTheTrash = true;
|
||||
# keepFoldersOnTop = {
|
||||
# inWindowsWhenSortingByName = true;
|
||||
# onDesktop = true;
|
||||
# };
|
||||
# whenPerformingASearch = "Search This Mac";
|
||||
# };
|
||||
# };
|
||||
# menuBar = {
|
||||
# view = {
|
||||
# showTabBar = true;
|
||||
# showSidebar = true;
|
||||
# showPathBar = true;
|
||||
# showStatusBar = true;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# systemSettings = {
|
||||
# appearance = {
|
||||
# appearance = "Dark";
|
||||
# accentColor = "Multicolor";
|
||||
# # clickInTheScrollBarTo = "Jump to the next page";
|
||||
# sidebarIconSize = "Medium";
|
||||
# showScrollBars = "When scrolling";
|
||||
# };
|
||||
# controlCenter = {
|
||||
# wifi = true;
|
||||
# bluetooth = true;
|
||||
# airdrop = true;
|
||||
# stageManager = true;
|
||||
# focusModes = "active";
|
||||
# screenMirroring = "active";
|
||||
# display = "never";
|
||||
# sound = "always";
|
||||
# nowPlaying = "active";
|
||||
# accessibilityShortcuts = "unset";
|
||||
# musicRecognition = {
|
||||
# showInMenuBar = false;
|
||||
# showInControlCenter = true;
|
||||
# };
|
||||
# hearing = "unset";
|
||||
# fastUserSwitching = {
|
||||
# showInMenuBar = false;
|
||||
# showInControlCenter = true;
|
||||
# };
|
||||
# keyboardBrightness = {
|
||||
# showInMenuBar = false;
|
||||
# showInControlCenter = true;
|
||||
# };
|
||||
# battery = {
|
||||
# showInMenuBar = false;
|
||||
# showInControlCenter = false;
|
||||
# };
|
||||
# batteryShowPercentage = true;
|
||||
# # menuBarOnly = {
|
||||
# # spotlight = false;
|
||||
# # siri = true;
|
||||
# # };
|
||||
# # automaticallyHideAndShowTheMenuBar = "In Full Screen Only";
|
||||
# };
|
||||
# desktopAndDock = {
|
||||
# desktopAndStageManager = {
|
||||
# showItems = {
|
||||
# onDesktop = true;
|
||||
# inStageManager = true;
|
||||
# };
|
||||
# clickWallpaperToRevealDesktop = "Always";
|
||||
# stageManager = false;
|
||||
# showRecentAppsInStageManager = true;
|
||||
# showWindowsFromAnApplication = "All at Once";
|
||||
# };
|
||||
# dock = {
|
||||
# animateOpeningApplications = true;
|
||||
# automaticallyHideAndShowTheDock = enabled;
|
||||
# doubleClickAWindowsTitleBarTo = "Minimize";
|
||||
# magnification = disabled;
|
||||
# minimizeWindowsIntoApplicationIcon = true;
|
||||
# minimizeWindowsUsing = "Genie Effect";
|
||||
# positionOnScreen = "Bottom";
|
||||
# showIndicatorsForOpenApplications = true;
|
||||
# showSuggestedAndRecentAppsInDock = false;
|
||||
# size = 64; # 16 - 128
|
||||
# # persistentApps = [
|
||||
# # { app = "/Applications/Clock.app"; }
|
||||
# # { folder = "/Applications"; }
|
||||
# # { app = "/Applications/Safari.app"; }
|
||||
# # { app = "/Applications/Firefox.app"; }
|
||||
# # { app = "/Applications/Tabby.app"; }
|
||||
# # { app = "/Applications/Termius.app"; }
|
||||
# # { app = "/Applications/Muic.app"; }
|
||||
# # { app = "/Applications/Vesktop.app"; }
|
||||
# # { app = "/Applications/Messages.app"; }
|
||||
# # { app = "/Applications/Calendar.app"; }
|
||||
# # { app = "/Applications/Reminders.app"; }
|
||||
# # { app = "/Applications/Notes.app"; }
|
||||
# # { app = "/Applications/Weather.app"; }
|
||||
# # { app = "/Applications/Maps.app"; }
|
||||
# # { app = "/Applications/App Store.app"; }
|
||||
# # { app = "/Applications/System Settings.app"; }
|
||||
# # { app = "/Applications/ChatGPT.app"; }
|
||||
# # { app = "/Applications/Nextcloud.app"; }
|
||||
# # { app = "/Applications/VSCodium.app"; }
|
||||
# # { app = "/Applications/Omnissa Horizon Client.app"; }
|
||||
# # { app = "/Applications/Proton Pass.app"; }
|
||||
# # { app = "/Applications/OrcaSlicer.app"; }
|
||||
# # { app = "/Applications/AlDente.app"; }
|
||||
# # ];
|
||||
# # persistentOthers = [
|
||||
# # "~/Downloads"
|
||||
# # ];
|
||||
# };
|
||||
# hotCorners = {
|
||||
# # ["-" "Mission Control" "Application Windows" "Desktop" "Start Screen Saver" "Disable Screen Saver" "Dashboard" "Put Display to Sleep" "Launchpad" "Notification Center" "Lock Screen" "Quick Note"]
|
||||
# topLeft = "-";
|
||||
# topRight = "-";
|
||||
# bottomLeft = "-";
|
||||
# bottomRight = "-";
|
||||
# };
|
||||
# missionControl = {
|
||||
# automaticallyRearrangeSpacesBasedOnMostRecentUse = true;
|
||||
# displaysHaveSeparateSpaces = true;
|
||||
# dragWindowsToTopOfScreenToEnterMissionControl = true;
|
||||
# groupWindowsByApplication = true;
|
||||
# whenSwitchingToAnApplicationSwitchToAspaceWithOpenWindowsForTheApplication = true;
|
||||
# };
|
||||
# widgets = {
|
||||
# showWidgets = {
|
||||
# onDesktop = true;
|
||||
# inStageManager = true;
|
||||
# };
|
||||
# widgetStyle = "Automatic";
|
||||
# useIphoneWidgets = true;
|
||||
# };
|
||||
# windows = {
|
||||
# askToKeepChangesWhenClosingDocuments = true;
|
||||
# closeWindowsWhenQuittingAnApplication = true;
|
||||
# dragWindowsToScreenEdgesToTile = true;
|
||||
# dragWindowsToMenuBarToFillScreen = true;
|
||||
# holdOptionKeyWhileDraggingWindowsToTile = true;
|
||||
# preferTabsWhenOpeningDocuments = "In Full Screen";
|
||||
# tiledWindowsHaveMargin = false;
|
||||
# };
|
||||
# };
|
||||
# focus = {
|
||||
# shareAcrossDevices = true;
|
||||
# };
|
||||
# # general.dateAndTime."24HourTime" = false;
|
||||
# notifications = {
|
||||
# notificationCenter = {
|
||||
# showPreviews = "When Unlocked";
|
||||
# summarizeNotifications = true;
|
||||
# };
|
||||
# };
|
||||
# sound = {
|
||||
# soundEffects = {
|
||||
# alertSound = "Boop";
|
||||
# alertVolume = 0.7;
|
||||
# playFeedbackWhenVolumeIsChanged = true;
|
||||
# playUserInterfaceSoundEffects = true;
|
||||
# };
|
||||
# };
|
||||
# spotlight = {
|
||||
# helpAppleImproveSearch = false;
|
||||
# # searchResults = {
|
||||
# # applications = true;
|
||||
# # calculator = true;
|
||||
# # contacts = true;
|
||||
# # conversion = true;
|
||||
# # definition = true;
|
||||
# # developer = true;
|
||||
# # documents = true;
|
||||
# # eventsAndReminders = true;
|
||||
# # folders = true;
|
||||
# # fonts = false;
|
||||
# # images = true;
|
||||
# # mailAndMessages = true;
|
||||
# # movies = true;
|
||||
# # music = true;
|
||||
# # other = false;
|
||||
# # pdfDocuments = true;
|
||||
# # presentations = true;
|
||||
# # siriSuggestions = false;
|
||||
# # systemSettings = true;
|
||||
# # tips = false;
|
||||
# # websites = true;
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
# Manage bug in compilations - who uses manpages in 2024 anyways? :P
|
||||
manual.manpages = enabled;
|
||||
|
||||
|
||||
@@ -15,12 +15,14 @@ let
|
||||
in
|
||||
{
|
||||
|
||||
home.username = "matt";
|
||||
home.homeDirectory = "/home/matt";
|
||||
home.stateVersion = "23.11";
|
||||
home = {
|
||||
username = "matt";
|
||||
homeDirectory = "/home/matt";
|
||||
stateVersion = "23.11";
|
||||
};
|
||||
|
||||
${namespace} = {
|
||||
desktop.gnome = enabled;
|
||||
desktop.plasma = lib.mkForce enabled;
|
||||
programs.hyprland = {
|
||||
enable = false;
|
||||
primaryDisplay = "eDP-1";
|
||||
@@ -78,11 +80,15 @@ in
|
||||
};
|
||||
programs = {
|
||||
btop = enabled;
|
||||
calibre = enabled;
|
||||
kitty = disabled;
|
||||
mako = disabled;
|
||||
nwg-dock = disabled;
|
||||
nwg-drawer = disabled;
|
||||
nwg-panel = disabled;
|
||||
opencode = enabled;
|
||||
thunderbird = enabled;
|
||||
vesktop = enabled;
|
||||
waybar = {
|
||||
enable = false;
|
||||
|
||||
@@ -121,6 +127,18 @@ in
|
||||
wlogout = disabled;
|
||||
wofi = disabled;
|
||||
};
|
||||
|
||||
services = {
|
||||
protonmail = enabled;
|
||||
};
|
||||
};
|
||||
|
||||
sops = {
|
||||
secrets = {
|
||||
"protonmail-password" = {
|
||||
sopsFile = lib.snowfall.fs.get-file "secrets/mac-secrets.yaml";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.packages =
|
||||
@@ -131,14 +149,33 @@ in
|
||||
]
|
||||
++ (with pkgs; [
|
||||
bolt-launcher
|
||||
bottles
|
||||
iw
|
||||
iwd
|
||||
orca-slicer
|
||||
rpi-imager
|
||||
vscodium
|
||||
|
||||
gnomeExtensions.notch-clock-offset
|
||||
]);
|
||||
|
||||
# Override the shared Plasma panel to add a standalone battery widget
|
||||
# (laptop-specific — not needed on desktop systems)
|
||||
programs.plasma.panels = lib.mkForce [
|
||||
{
|
||||
location = "bottom";
|
||||
floating = true;
|
||||
height = 44;
|
||||
widgets = [
|
||||
"org.kde.plasma.kickoff"
|
||||
"org.kde.plasma.icontasks"
|
||||
"org.kde.plasma.marginsseparator"
|
||||
{ battery = { }; }
|
||||
"org.kde.plasma.systemtray"
|
||||
"org.kde.plasma.digitalclock"
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
services = {
|
||||
kdeconnect = {
|
||||
enable = lib.mkForce true;
|
||||
@@ -150,26 +187,4 @@ in
|
||||
password-store = enabled;
|
||||
};
|
||||
|
||||
dconf = {
|
||||
enable = true;
|
||||
settings = {
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".name = "Keyboard Backlight +";
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".binding = "<Super>MonBrightnessUp";
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".command = "brightnessctl -d kbd_backlight s +10";
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".name = "Keyboard Backlight -";
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".binding = "<Super>MonBrightnessDown";
|
||||
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".command = "brightnessctl -d kbd_backlight s 10-";
|
||||
|
||||
"org/gnome/shell".enabled-extensions = [
|
||||
"notch-clock-offset@christophbrill.de"
|
||||
];
|
||||
|
||||
"org/gnome/shell/extensions/notch-clock-offset".percent = 40;
|
||||
|
||||
"org/gnome/settings-daemon/plugins/media-keys".custom-keybindings = [
|
||||
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
|
||||
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@ in
|
||||
|
||||
home.username = "matt";
|
||||
|
||||
${namespace}.sops.enable = true;
|
||||
|
||||
sops = {
|
||||
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
|
||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||
validateSopsFiles = false;
|
||||
secrets = {
|
||||
"ssh-keys-public/pi5" = {
|
||||
path = "/home/matt/.ssh/id_ed25519.pub";
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,10 +1,23 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) enabled;
|
||||
in
|
||||
{
|
||||
# steam-rom-manager is also injected globally via modules/nixos/home/default.nix
|
||||
# sharedModules for x86_64 NixOS builds. This explicit import ensures it is
|
||||
# also available for standalone `home-manager switch` runs (where sharedModules
|
||||
# are not applied). NixOS's module system deduplicates the import when both
|
||||
# paths resolve to the same derivation.
|
||||
imports = [
|
||||
inputs.steam-rom-manager.homeManagerModules.default
|
||||
];
|
||||
|
||||
home = {
|
||||
username = "admin";
|
||||
packages =
|
||||
@@ -17,59 +30,44 @@
|
||||
jq
|
||||
]
|
||||
++ (with pkgs.${namespace}; [
|
||||
hueforge
|
||||
moondeck-buddy
|
||||
]);
|
||||
};
|
||||
|
||||
${namespace} = {
|
||||
sops.enable = true;
|
||||
programs.opencode = enabled;
|
||||
desktop.plasma = enabled;
|
||||
};
|
||||
|
||||
sops = {
|
||||
age.keyFile = "/home/admin/.config/sops/age/keys.txt";
|
||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||
validateSopsFiles = false;
|
||||
secrets = {
|
||||
# NOTE: add the following key to secrets/secrets.yaml via `sops secrets/secrets.yaml`
|
||||
# before deploying: hass-mcp/token: <your HA long-lived access token>
|
||||
"hass-mcp/token" = { };
|
||||
|
||||
"ssh-keys-public/jallen-nas" = {
|
||||
path = "/home/admin/.ssh/id_ed25519.pub";
|
||||
mode = "0644";
|
||||
};
|
||||
"ssh-keys-private/jallen-nas" = {
|
||||
path = "/home/admin/.ssh/id_ed25519";
|
||||
mode = "0600";
|
||||
};
|
||||
"ssh-keys-public/desktop-nixos" = {
|
||||
path = "/home/admin/.ssh/authorized_keys";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
"ssh-keys-public/desktop-nixos-root" = {
|
||||
path = "/home/admin/.ssh/authorized_keys2";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
"ssh-keys-public/desktop-windows" = {
|
||||
path = "/home/admin/.ssh/authorized_keys3";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
"ssh-keys-public/macbook-macos" = {
|
||||
path = "/home/admin/.ssh/authorized_keys4";
|
||||
mode = "0600";
|
||||
};
|
||||
sops.secrets = {
|
||||
"ssh-keys-public/jallen-nas" = {
|
||||
path = "/home/admin/.ssh/id_ed25519.pub";
|
||||
mode = "0644";
|
||||
};
|
||||
"ssh-keys-private/jallen-nas" = {
|
||||
path = "/home/admin/.ssh/id_ed25519";
|
||||
mode = "0600";
|
||||
};
|
||||
"ssh-keys-public/desktop-nixos" = {
|
||||
path = "/home/admin/.ssh/authorized_keys";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
templates."hass-mcp.env" = {
|
||||
path = "/home/admin/.config/sops/hass-mcp.env";
|
||||
"ssh-keys-public/desktop-nixos-root" = {
|
||||
path = "/home/admin/.ssh/authorized_keys2";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
"ssh-keys-public/desktop-windows" = {
|
||||
path = "/home/admin/.ssh/authorized_keys3";
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
"ssh-keys-public/macbook-macos" = {
|
||||
path = "/home/admin/.ssh/authorized_keys4";
|
||||
mode = "0600";
|
||||
content = ''
|
||||
HA_URL=http://nuc-nixos.local:8123
|
||||
HA_TOKEN=${config.sops.placeholder."hass-mcp/token"}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -86,11 +84,14 @@
|
||||
viAlias = true;
|
||||
vimAlias = true;
|
||||
defaultEditor = true;
|
||||
withRuby = false;
|
||||
withPython3 = true;
|
||||
plugins = [
|
||||
pkgs.vimPlugins.nvim-tree-lua
|
||||
{
|
||||
plugin = pkgs.vimPlugins.vim-startify;
|
||||
config = "let g:startify_change_to_vcs_root = 0";
|
||||
type = "lua";
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -112,83 +113,5 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
opencode = {
|
||||
enable = true;
|
||||
enableMcpIntegration = true;
|
||||
settings = {
|
||||
provider = {
|
||||
nas = {
|
||||
npm = "@ai-sdk/openai-compatible";
|
||||
name = "llama-server (local)";
|
||||
options = {
|
||||
baseURL = "http://jallen-nas.local:8127/v1";
|
||||
};
|
||||
models = {
|
||||
Qwen3-Coder-Next-Q4_0 = {
|
||||
name = "Qwen3 Coder (local)";
|
||||
modalities = {
|
||||
input = [
|
||||
"image"
|
||||
"text"
|
||||
];
|
||||
output = [ "text" ];
|
||||
};
|
||||
limit = {
|
||||
context = 262144;
|
||||
output = 262144;
|
||||
};
|
||||
};
|
||||
# "GLM-4.7-Flash-REAP-23B-A3B-UD-Q3_K_XL": {
|
||||
# "name": "GLM 4.7 Flash (local)",
|
||||
# "modalities": { "input": ["image", "text"], "output": ["text"] },
|
||||
# "limit": {
|
||||
# "context": 262144,
|
||||
# "output": 262144
|
||||
# }
|
||||
# };
|
||||
# "Nemotron-3-Nano-30B-A3B-IQ4_XS": {
|
||||
# "name": "Nemotron-3-Nano (local)",
|
||||
# "modalities": { "input": ["image", "text"], "output": ["text"] },
|
||||
# "limit": {
|
||||
# "context": 262144,
|
||||
# "output": 262144
|
||||
# }
|
||||
# };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
nixos = {
|
||||
command = "nix";
|
||||
args = [
|
||||
"run"
|
||||
"github:utensils/mcp-nixos"
|
||||
"--"
|
||||
];
|
||||
};
|
||||
hass-mcp = {
|
||||
# Token is read at runtime from a sops-rendered env file.
|
||||
# The wrapper script sources ~/.config/sops/hass-mcp.env before launching uvx.
|
||||
command = "bash";
|
||||
args = [
|
||||
"-c"
|
||||
"set -a; source ${"\${HOME}"}/.config/sops/hass-mcp.env; set +a; exec uvx hass-mcp"
|
||||
];
|
||||
};
|
||||
mcp-server-code-runner = {
|
||||
command = "npm";
|
||||
args = [
|
||||
"-y"
|
||||
"mcp-server-code-runner@latest"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,21 +10,22 @@ in
|
||||
{
|
||||
home.username = "matt";
|
||||
|
||||
${namespace}.desktop.gnome = enabled;
|
||||
${namespace} = {
|
||||
desktop.gnome = enabled;
|
||||
sops.enable = true;
|
||||
programs = {
|
||||
vesktop = enabled;
|
||||
};
|
||||
};
|
||||
|
||||
sops = {
|
||||
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
|
||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||
validateSopsFiles = false;
|
||||
secrets = {
|
||||
"ssh-keys-public/matt" = {
|
||||
path = "/home/matt/.ssh/id_ed25519.pub";
|
||||
mode = "0644";
|
||||
};
|
||||
"ssh-keys-private/matt" = {
|
||||
path = "/home/matt/.ssh/id_ed25519";
|
||||
mode = "0600";
|
||||
};
|
||||
sops.secrets = {
|
||||
"ssh-keys-public/matt" = {
|
||||
path = "/home/matt/.ssh/id_ed25519.pub";
|
||||
mode = "0644";
|
||||
};
|
||||
"ssh-keys-private/matt" = {
|
||||
path = "/home/matt/.ssh/id_ed25519";
|
||||
mode = "0600";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -38,32 +39,35 @@ in
|
||||
steamDirectory = "/home/matt/.local/share/Steam";
|
||||
};
|
||||
|
||||
enabledProviders = [ "sgdb" "steamCDN" ];
|
||||
enabledProviders = [
|
||||
"sgdb"
|
||||
"steamCDN"
|
||||
];
|
||||
imageProviderSettings.sgdb = {
|
||||
nsfw = false;
|
||||
humor = false;
|
||||
nsfw = false;
|
||||
humor = false;
|
||||
imageMotionTypes = [ "static" ];
|
||||
};
|
||||
|
||||
emulators = {
|
||||
# --- Nintendo ---
|
||||
ryujinx.enable = true; # Switch (ryubing fork)
|
||||
yuzu.enable = true; # Switch (eden fork)
|
||||
dolphin-emu.enable = true; # GameCube / Wii
|
||||
cemu.enable = true; # Wii U
|
||||
melonDS.enable = true; # DS
|
||||
citra.enable = true; # 3DS (azahar fork)
|
||||
mgba.enable = true; # Game Boy / GBC
|
||||
mgba-gba.enable = true; # Game Boy Advance
|
||||
ryujinx.enable = true; # Switch (ryubing fork)
|
||||
yuzu.enable = true; # Switch (eden fork)
|
||||
dolphin-emu.enable = true; # GameCube / Wii
|
||||
cemu.enable = false; # Wii U
|
||||
melonDS.enable = true; # DS
|
||||
citra.enable = true; # 3DS (azahar fork)
|
||||
mgba.enable = true; # Game Boy / GBC
|
||||
mgba-gba.enable = true; # Game Boy Advance
|
||||
|
||||
# --- Sony ---
|
||||
duckstation.enable = false; # PS1
|
||||
pcsx2.enable = true; # PS2
|
||||
rpcs3.enable = true; # PS3
|
||||
ppsspp.enable = true; # PSP
|
||||
duckstation.enable = false; # PS1
|
||||
pcsx2.enable = true; # PS2
|
||||
rpcs3.enable = true; # PS3
|
||||
ppsspp.enable = true; # PSP
|
||||
|
||||
# --- Microsoft ---
|
||||
xemu.enable = true; # Xbox
|
||||
xemu.enable = true; # Xbox
|
||||
|
||||
# --- Platform parsers (no ROM scanning; artwork only / launcher integration) ---
|
||||
"Non-SRM Shortcuts".enable = true;
|
||||
|
||||
@@ -28,9 +28,12 @@ in
|
||||
enable = true;
|
||||
};
|
||||
|
||||
desktop.gnome = enabled;
|
||||
desktop.plasma = enabled;
|
||||
|
||||
programs = {
|
||||
vesktop = enabled;
|
||||
opencode = enabled;
|
||||
thunderbird = enabled;
|
||||
hyprland = {
|
||||
enable = false;
|
||||
primaryDisplay = "DP-1";
|
||||
@@ -163,10 +166,12 @@ in
|
||||
home.packages =
|
||||
with pkgs;
|
||||
[
|
||||
atlauncher
|
||||
bolt-launcher
|
||||
clevis
|
||||
compose2nix
|
||||
distrobox
|
||||
goverlay
|
||||
heroic
|
||||
home-manager
|
||||
omnissa-horizon-client
|
||||
@@ -177,13 +182,13 @@ in
|
||||
piper
|
||||
prismlauncher
|
||||
protontricks
|
||||
protonvpn-gui
|
||||
runelite
|
||||
smile
|
||||
via
|
||||
virt-manager
|
||||
vorta
|
||||
waydroid-helper
|
||||
winboat
|
||||
]
|
||||
++ (with pkgs.${namespace}; [
|
||||
discord-krisp
|
||||
@@ -191,8 +196,17 @@ in
|
||||
]);
|
||||
|
||||
specialisation = {
|
||||
"gnome".configuration = {
|
||||
${namespace} = {
|
||||
desktop = {
|
||||
plasma = lib.mkForce disabled;
|
||||
gnome = lib.mkForce enabled;
|
||||
};
|
||||
};
|
||||
};
|
||||
"cosmic".configuration = {
|
||||
${namespace} = {
|
||||
desktop.plasma = lib.mkForce disabled;
|
||||
programs = {
|
||||
hyprland = lib.mkForce disabled;
|
||||
kitty = lib.mkForce disabled;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "nixos";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) disabled;
|
||||
in
|
||||
{
|
||||
home.username = "root";
|
||||
services = {
|
||||
nextcloud-client = lib.mkForce disabled;
|
||||
kdeconnect = {
|
||||
enable = false;
|
||||
indicator = false;
|
||||
};
|
||||
};
|
||||
}
|
||||
257
lib/README.md
Normal file → Executable file
257
lib/README.md
Normal file → Executable file
@@ -1,130 +1,189 @@
|
||||
# mjallen-lib Utility Functions
|
||||
|
||||
This directory contains utility functions that can be used to enhance your Nix configuration. These functions are inspired by the khanelinix repository and provide a more explicit and modular approach to building Nix configurations.
|
||||
Utility functions for the NixOS/nix-darwin configuration. Exposed via Snowfall Lib as `lib.mjallen.*`.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- `default.nix`: Main entry point that imports and exposes all utility functions
|
||||
- `module/`: Utilities for module creation and option handling
|
||||
- `file/`: Utilities for file handling and module discovery
|
||||
- `system/`: Utilities for system configuration building
|
||||
- `default.nix` — Main entry point; exports `module`, `file`, and `versioning`
|
||||
- `module/` — Module creation helpers (`mkModule`, `mkContainerService`, `mkSopsEnvFile`, `mkOpt`, etc.)
|
||||
- `file/` — File and path utilities
|
||||
- `versioning/` — Multi-source version pinning helpers (used by packages)
|
||||
|
||||
## How to Use
|
||||
---
|
||||
|
||||
### 1. Import the Library
|
||||
## Module Utilities (`lib.mjallen.module`)
|
||||
|
||||
The library is already imported in your flake.nix file through the outputs-builder:
|
||||
### `mkModule`
|
||||
|
||||
Creates a NixOS service module with a standard set of options. All config is gated behind `cfg.enable`.
|
||||
|
||||
```nix
|
||||
outputs-builder = channels: {
|
||||
formatter = inputs.treefmt-nix.lib.mkWrapper channels.nixpkgs ./treefmt.nix;
|
||||
|
||||
# Add mjallen-lib to the flake outputs
|
||||
overlays = {
|
||||
mjallen-lib = final: prev: {
|
||||
mjallen-lib = (import ./lib { inherit inputs; }).mjallen-lib;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
This makes the mjallen-lib available to all your modules through the extended lib.
|
||||
|
||||
### 2. Use the Module Utilities
|
||||
|
||||
The module utilities provide functions for creating modules with consistent options:
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.module) mkModule mkOpt mkBoolOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "mymodule";
|
||||
description = "My awesome module";
|
||||
options = {
|
||||
setting1 = mkOpt lib.types.str "default" "Description of setting1";
|
||||
setting2 = mkBoolOpt false "Description of setting2";
|
||||
};
|
||||
config = {
|
||||
# Module implementation
|
||||
};
|
||||
lib.mjallen.mkModule {
|
||||
config # NixOS config attrset (pass-through from module args)
|
||||
name # Service name — used for option path and systemd unit
|
||||
description # Text for mkEnableOption (defaults to name)
|
||||
options # Extra options merged into the submodule
|
||||
moduleConfig # NixOS config body (applied when cfg.enable = true)
|
||||
domain # Option namespace domain (default: "services")
|
||||
serviceName # Systemd service name (default: name)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Use the File Utilities
|
||||
**Standard options provided for free:**
|
||||
|
||||
The file utilities provide functions for file handling and module discovery:
|
||||
| Option | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `enable` | bool | `false` | Enable/disable the service |
|
||||
| `port` | int | `80` | Service listen port |
|
||||
| `listenAddress` | str | `"0.0.0.0"` | Bind address |
|
||||
| `openFirewall` | bool | `true` | Open TCP+UDP firewall ports |
|
||||
| `configDir` | str | `/var/lib/<name>` | Config directory |
|
||||
| `dataDir` | str | `/var/lib/<name>/data` | Data directory |
|
||||
| `createUser` | bool | `false` | Create a dedicated system user |
|
||||
| `configureDb` | bool | `false` | Create a PostgreSQL database |
|
||||
| `environmentFile` | str\|null | `null` | Path to an env-file |
|
||||
| `extraEnvironment` | attrs | `{}` | Extra environment variables |
|
||||
| `hashedPassword` | str\|null | `null` | Hashed password for web auth |
|
||||
| `puid` / `pgid` | str | `"911"` / `"100"` | UID/GID for container services |
|
||||
| `timeZone` | str | `"UTC"` | Timezone for container services |
|
||||
| `redis.enable` | bool | `false` | Create a Redis instance for this service |
|
||||
| `redis.port` | int | `6379` | Redis port |
|
||||
| `reverseProxy.enable` | bool | `false` | Add a Caddy reverse proxy block |
|
||||
| `reverseProxy.subdomain` | str | `<name>` | Caddy subdomain |
|
||||
| `reverseProxy.domain` | str | `"mjallen.dev"` | Caddy base domain |
|
||||
| `reverseProxy.upstreamUrl` | str\|null | `null` | Override upstream URL |
|
||||
| `reverseProxy.extraCaddyConfig` | lines | `""` | Extra Caddyfile directives |
|
||||
|
||||
**Default behaviour when enabled:**
|
||||
|
||||
- Adds Caddy reverse proxy block (if `reverseProxy.enable = true`)
|
||||
- Opens firewall ports (if `openFirewall = true`)
|
||||
- Creates system user/group (if `createUser = true`)
|
||||
- Creates PostgreSQL database (if `configureDb = true`)
|
||||
- Creates Redis instance (if `redis.enable = true`)
|
||||
- Adds `RequiresMountsFor` systemd dependency for `configDir` and `dataDir`
|
||||
|
||||
---
|
||||
|
||||
### `mkContainerService`
|
||||
|
||||
Wraps `mkModule` for Podman/OCI container services. Generates the full container definition automatically.
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.file) safeImport importModulesRecursive;
|
||||
in
|
||||
{
|
||||
# Import a file with error handling
|
||||
myConfig = safeImport ./my-config.nix {};
|
||||
|
||||
# Import all modules recursively
|
||||
imports = importModulesRecursive ./modules;
|
||||
lib.mjallen.mkContainerService {
|
||||
config # NixOS config attrset
|
||||
name # Service/container name
|
||||
image # OCI image reference (e.g. "ghcr.io/example/app:latest")
|
||||
internalPort # Port the container listens on internally
|
||||
description # Human-readable description (defaults to name)
|
||||
options # Extra mkModule options
|
||||
volumes # Extra volume mount strings
|
||||
environment # Extra environment variables (merged with PUID/PGID/TZ)
|
||||
environmentFiles # List of env-file paths (e.g. SOPS template paths)
|
||||
extraOptions # Extra --opt strings for the container runtime
|
||||
devices # Device mappings
|
||||
extraConfig # Extra NixOS config merged into moduleConfig
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Use the System Utilities
|
||||
The systemd service is named `podman-<name>`, and the port binding is `<cfg.port>:<internalPort>`.
|
||||
|
||||
The system utilities provide functions for building system configurations:
|
||||
---
|
||||
|
||||
### `mkSopsEnvFile`
|
||||
|
||||
Generates a SOPS secrets block and a SOPS template env-file in a single call. Useful for services that need secrets injected as environment variables.
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.system.common) mkHomeManagerConfig;
|
||||
in
|
||||
{
|
||||
# Build home-manager configurations
|
||||
homeManagerConfig = mkHomeManagerConfig {
|
||||
extendedLib = lib;
|
||||
inputs = inputs;
|
||||
system = "x86_64-linux";
|
||||
matchingHomes = { ... };
|
||||
};
|
||||
lib.mjallen.mkSopsEnvFile {
|
||||
secrets # attrset: sops-key → extra attrs (owner, group, etc.)
|
||||
name # Template file name, e.g. "myapp.env"
|
||||
content # Template body (use config.sops.placeholder."key")
|
||||
restartUnit # Systemd unit to restart when secrets change
|
||||
owner # File owner (default: "nix-apps")
|
||||
group # File group (default: "jallen-nas")
|
||||
mode # File permissions (default: "660")
|
||||
sopsFile # Default SOPS file for all secrets
|
||||
}
|
||||
```
|
||||
|
||||
## Available Functions
|
||||
---
|
||||
|
||||
### Module Utilities
|
||||
### Option helpers
|
||||
|
||||
- `mkModule`: Create a module with common options
|
||||
- `mkOpt`: Create an option with a type, default value, and description
|
||||
- `mkOpt'`: Create an option with a type and default value (no description)
|
||||
- `mkBoolOpt`: Create a boolean option with a default value and description
|
||||
- `mkBoolOpt'`: Create a boolean option with a default value (no description)
|
||||
- `enabled`: Standard enable pattern
|
||||
- `disabled`: Standard disable pattern
|
||||
- `capitalize`: Capitalize a string
|
||||
- `boolToNum`: Convert a boolean to a number
|
||||
- `default-attrs`: Apply mkDefault to all attributes
|
||||
- `force-attrs`: Apply mkForce to all attributes
|
||||
- `nested-default-attrs`: Apply default-attrs to nested attributes
|
||||
- `nested-force-attrs`: Apply force-attrs to nested attributes
|
||||
| Function | Signature | Description |
|
||||
|---|---|---|
|
||||
| `mkOpt` | `type → default → description → mkOption` | Standard option shorthand |
|
||||
| `mkOpt'` | `type → default → mkOption` | `mkOpt` without description |
|
||||
| `mkBoolOpt` | `default → description → mkOption` | Boolean option shorthand |
|
||||
| `mkBoolOpt'` | `default → mkOption` | Boolean option without description |
|
||||
| `mkReverseProxyOpt` | `name → attrset` | Standard Caddy reverse proxy sub-options |
|
||||
|
||||
### File Utilities
|
||||
---
|
||||
|
||||
- `readFile`: Read a file and return its contents
|
||||
- `pathExists`: Check if a file exists
|
||||
- `safeImport`: Import a nix file with error handling
|
||||
- `scanDir`: Scan a directory and return directory names
|
||||
- `getFile`: Get a file path relative to the flake root
|
||||
- `importModulesRecursive`: Recursively discover and import all Nix modules in a directory tree
|
||||
- `scanSystems`: Recursively scan systems directory structure
|
||||
- `filterNixOSSystems`: Filter systems for NixOS (Linux)
|
||||
- `filterDarwinSystems`: Filter systems for Darwin (macOS)
|
||||
- `scanHomes`: Scan homes directory structure for home configurations
|
||||
### Convenience shorthands
|
||||
|
||||
### System Utilities
|
||||
| Value | Expands to |
|
||||
|---|---|
|
||||
| `enabled` | `{ enable = true; }` |
|
||||
| `disabled` | `{ enable = false; }` |
|
||||
|
||||
- `mkExtendedLib`: Extend the nixpkgs lib with mjallen-lib
|
||||
- `mkNixpkgsConfig`: Create a nixpkgs configuration
|
||||
- `mkHomeConfigs`: Create home configurations for a system and hostname
|
||||
- `mkHomeManagerConfig`: Create a home-manager configuration
|
||||
- `mkSpecialArgs`: Create special arguments for a system configuration
|
||||
---
|
||||
|
||||
### Attribute utilities
|
||||
|
||||
| Function | Description |
|
||||
|---|---|
|
||||
| `default-attrs` | Apply `lib.mkDefault` to every value in an attrset |
|
||||
| `force-attrs` | Apply `lib.mkForce` to every value in an attrset |
|
||||
| `nested-default-attrs` | Apply `default-attrs` one level deeper |
|
||||
| `nested-force-attrs` | Apply `force-attrs` one level deeper |
|
||||
|
||||
---
|
||||
|
||||
### String utilities
|
||||
|
||||
| Function | Description |
|
||||
|---|---|
|
||||
| `capitalize` | Capitalise the first character of a string |
|
||||
|
||||
---
|
||||
|
||||
### Boolean utilities
|
||||
|
||||
| Function | Description |
|
||||
|---|---|
|
||||
| `boolToNum` | `true → 1`, `false → 0` |
|
||||
|
||||
---
|
||||
|
||||
## Home Manager Utilities (`lib.mjallen.module`)
|
||||
|
||||
### `mkHomeModule`
|
||||
|
||||
Creates a Home Manager module with a standard `enable` option.
|
||||
|
||||
```nix
|
||||
lib.mjallen.mkHomeModule {
|
||||
config # HM config attrset
|
||||
domain # Option namespace domain, e.g. "programs" or "desktop"
|
||||
name # Module name, e.g. "btop"
|
||||
description # Text for mkEnableOption (defaults to name)
|
||||
options # Extra options merged into the submodule
|
||||
moduleConfig # HM config body (applied when cfg.enable = true)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Utilities (`lib.mjallen.file`)
|
||||
|
||||
Helpers for resolving paths relative to the flake root. Primarily used internally by modules and packages.
|
||||
|
||||
---
|
||||
|
||||
## Versioning Utilities (`lib.mjallen.versioning`)
|
||||
|
||||
Used by packages that track multiple upstream variants (e.g. `proton-cachyos`, `linux-rpi`). Reads a `version.json` file and resolves sources with optional variable substitution and per-variant overrides.
|
||||
|
||||
See `lib/versioning/default.nix` for the full API and `docs/version.schema.json` for the `version.json` schema.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
|
||||
@@ -1,62 +0,0 @@
|
||||
{ inputs }:
|
||||
let
|
||||
inherit (inputs.nixpkgs.lib)
|
||||
concatLists
|
||||
concatMapStrings
|
||||
foldl'
|
||||
genList
|
||||
hasSuffix
|
||||
imap0
|
||||
length
|
||||
mod
|
||||
nameValuePair
|
||||
stringToCharacters
|
||||
sublist
|
||||
substring
|
||||
take
|
||||
;
|
||||
in
|
||||
rec {
|
||||
base64Table = builtins.listToAttrs (
|
||||
imap0 (i: c: nameValuePair c i) (
|
||||
# The '=' is included so the main algorithm doesn't fail before we can trim the result
|
||||
stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
||||
)
|
||||
);
|
||||
|
||||
# Generated using python3:
|
||||
# print(''.join([ chr(n) for n in range(1, 256) ]), file=open('ascii', 'w'))
|
||||
ascii = builtins.readFile ./ascii;
|
||||
|
||||
decode =
|
||||
str:
|
||||
let
|
||||
paddingCount =
|
||||
if hasSuffix "==" str then
|
||||
2
|
||||
else if hasSuffix "=" str then
|
||||
1
|
||||
else
|
||||
0;
|
||||
|
||||
numbers64 = map (c: base64Table.${c}) (stringToCharacters str);
|
||||
|
||||
allBytes = concatLists (
|
||||
genList (
|
||||
i:
|
||||
let
|
||||
v = foldl' (acc: el: acc * 64 + el) 0 (sublist (i * 4) 4 numbers64);
|
||||
in
|
||||
[
|
||||
(mod (v / 256 / 256) 256)
|
||||
(mod (v / 256) 256)
|
||||
(mod v 256)
|
||||
]
|
||||
) (length numbers64 / 4)
|
||||
);
|
||||
|
||||
finalBytes = take (length allBytes - paddingCount) allBytes;
|
||||
|
||||
in
|
||||
concatMapStrings (n: substring (n - 1) 1 ascii) finalBytes;
|
||||
}
|
||||
17
lib/default.nix
Normal file → Executable file
17
lib/default.nix
Normal file → Executable file
@@ -1,24 +1,11 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
mjallen-lib = {
|
||||
# Import module utilities
|
||||
module = import ./module { inherit inputs; };
|
||||
|
||||
# Import file utilities
|
||||
file = import ./file { inherit inputs; };
|
||||
|
||||
# Import system utilities
|
||||
system = import ./system { inherit inputs; };
|
||||
|
||||
# Import reverse proxy utilities
|
||||
reverseproxy = import ./reverseproxy { inherit inputs; };
|
||||
|
||||
# Import examples
|
||||
examples = import ./examples { inherit inputs; };
|
||||
|
||||
# Import versioning utilities
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
versioning = import ./versioning {
|
||||
lib = inputs.nixpkgs.lib;
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
inherit inputs;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{ ... }:
|
||||
{
|
||||
# Import all examples
|
||||
sops = import ./sops.nix;
|
||||
homeSops = import ./home-sops.nix;
|
||||
fileUtils = import ./file-utils.nix;
|
||||
systemUtils = import ./system-utils.nix;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
let
|
||||
inherit (lib.${namespace}.file)
|
||||
readFile
|
||||
pathExists
|
||||
safeImport
|
||||
scanDir
|
||||
getFile
|
||||
importModulesRecursive
|
||||
scanSystems
|
||||
filterNixOSSystems
|
||||
filterDarwinSystems
|
||||
scanHomes
|
||||
;
|
||||
in
|
||||
{
|
||||
# Example of reading a file
|
||||
myFileContent = readFile ./example.txt;
|
||||
|
||||
# Example of checking if a file exists
|
||||
fileExists = pathExists ./example.txt;
|
||||
|
||||
# Example of safely importing a file
|
||||
myConfig = safeImport ./my-config.nix { };
|
||||
|
||||
# Example of scanning a directory
|
||||
directoryContents = scanDir ./modules;
|
||||
|
||||
# Example of getting a file path relative to the flake root
|
||||
flakeFile = getFile "flake.nix";
|
||||
|
||||
# Example of importing modules recursively
|
||||
modules = importModulesRecursive ./modules;
|
||||
|
||||
# Example of scanning systems
|
||||
allSystems = scanSystems ./systems;
|
||||
|
||||
# Example of filtering systems
|
||||
nixosSystems = filterNixOSSystems allSystems;
|
||||
darwinSystems = filterDarwinSystems allSystems;
|
||||
|
||||
# Example of scanning homes
|
||||
allHomes = scanHomes ./homes;
|
||||
|
||||
# Example of using these functions together
|
||||
nixosConfigurations = lib.mapAttrs' (
|
||||
_name:
|
||||
{ system, hostname, ... }:
|
||||
{
|
||||
name = hostname;
|
||||
value = lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
{ networking.hostName = hostname; }
|
||||
]
|
||||
++ importModulesRecursive ./modules/nixos;
|
||||
};
|
||||
}
|
||||
) nixosSystems;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}.module) mkModule mkOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "sops";
|
||||
description = "SOPS secret management for home-manager";
|
||||
options = {
|
||||
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||
|
||||
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [ ] "SSH Key paths to use.";
|
||||
};
|
||||
config = {
|
||||
home.packages = with pkgs; [
|
||||
age
|
||||
sops
|
||||
ssh-to-age
|
||||
];
|
||||
|
||||
sops = {
|
||||
inherit (config.${namespace}.sops) defaultSopsFile;
|
||||
defaultSopsFormat = "yaml";
|
||||
|
||||
age = {
|
||||
generateKey = true;
|
||||
keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
|
||||
sshKeyPaths = [
|
||||
"${config.home.homeDirectory}/.ssh/id_ed25519"
|
||||
]
|
||||
++ config.${namespace}.sops.sshKeyPaths;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
# Example usage of the reverse proxy utilities
|
||||
{ lib, namespace, ... }:
|
||||
let
|
||||
inherit (lib.${namespace} - lib.reverseproxy)
|
||||
mkReverseProxy
|
||||
mkReverseProxies
|
||||
templates
|
||||
middlewares
|
||||
urls
|
||||
;
|
||||
in
|
||||
{
|
||||
# Example 1: Simple reverse proxy for a local service
|
||||
simpleProxy = mkReverseProxy {
|
||||
name = "myapp";
|
||||
subdomain = "myapp";
|
||||
url = "http://127.0.0.1:3000";
|
||||
};
|
||||
|
||||
# Example 2: Authenticated service with custom middlewares
|
||||
authProxy = mkReverseProxy {
|
||||
name = "admin-panel";
|
||||
subdomain = "admin";
|
||||
url = "http://127.0.0.1:8080";
|
||||
middlewares = middlewares.authBasic;
|
||||
};
|
||||
|
||||
# Example 3: Container-based service
|
||||
containerProxy = mkReverseProxy {
|
||||
name = "nextcloud";
|
||||
subdomain = "cloud";
|
||||
url = urls.container "nextcloud" 80;
|
||||
middlewares = middlewares.basic;
|
||||
};
|
||||
|
||||
# Example 4: Multiple proxies at once
|
||||
multipleProxies = mkReverseProxies [
|
||||
{
|
||||
name = "grafana";
|
||||
subdomain = "grafana";
|
||||
url = urls.localhost 3000;
|
||||
middlewares = middlewares.authBasic;
|
||||
}
|
||||
{
|
||||
name = "prometheus";
|
||||
subdomain = "prometheus";
|
||||
url = urls.localhost 9090;
|
||||
middlewares = middlewares.internal;
|
||||
}
|
||||
{
|
||||
name = "alertmanager";
|
||||
subdomain = "alerts";
|
||||
url = urls.localhost 9093;
|
||||
middlewares = middlewares.authBasic;
|
||||
}
|
||||
];
|
||||
|
||||
# Example 5: Using templates for common patterns
|
||||
webappExample = templates.webapp {
|
||||
name = "webapp";
|
||||
subdomain = "app";
|
||||
port = 8080;
|
||||
};
|
||||
|
||||
authWebappExample = templates.authWebapp {
|
||||
name = "secure-app";
|
||||
subdomain = "secure";
|
||||
port = 9000;
|
||||
};
|
||||
|
||||
containerExample = templates.containerService {
|
||||
name = "gitea";
|
||||
subdomain = "git";
|
||||
containerName = "gitea";
|
||||
port = 3000;
|
||||
};
|
||||
|
||||
internalExample = templates.internalService {
|
||||
name = "internal-api";
|
||||
subdomain = "api-internal";
|
||||
port = 8000;
|
||||
};
|
||||
|
||||
# Example 6: Custom domain and advanced configuration
|
||||
customProxy = mkReverseProxy {
|
||||
name = "custom-service";
|
||||
subdomain = "custom";
|
||||
url = "http://10.0.1.100:8080";
|
||||
domain = "example.com";
|
||||
priority = 20;
|
||||
rule = "Host(`custom.example.com`) && PathPrefix(`/api`)";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"rate-limit"
|
||||
];
|
||||
};
|
||||
|
||||
# Example usage in a Traefik configuration:
|
||||
#
|
||||
# mjallen.services.traefik = {
|
||||
# enable = true;
|
||||
# extraServices = multipleProxies.extraServices;
|
||||
# extraRouters = multipleProxies.extraRouters;
|
||||
# };
|
||||
#
|
||||
# Or for individual proxies:
|
||||
#
|
||||
# mjallen.services.traefik = {
|
||||
# enable = true;
|
||||
# extraServices = [ simpleProxy.service ];
|
||||
# extraRouters = [{
|
||||
# inherit (simpleProxy.router) subdomain entryPoints middlewares;
|
||||
# service = simpleProxy.router.service;
|
||||
# }];
|
||||
# };
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}.module) mkModule mkOpt mkBoolOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "sops";
|
||||
description = "SOPS secret management";
|
||||
options = {
|
||||
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||
|
||||
generateAgeKey = mkBoolOpt true "Whether to automatically generate an age key if one doesn't exist.";
|
||||
|
||||
ageKeyPath =
|
||||
mkOpt (lib.types.nullOr lib.types.str) null
|
||||
"Custom path to the age key file. If null, will use the default path.";
|
||||
|
||||
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
] "SSH Key paths to use.";
|
||||
|
||||
validateSopsFiles = mkBoolOpt false "Whether to validate that sops files exist.";
|
||||
};
|
||||
config = {
|
||||
sops = {
|
||||
inherit (config.${namespace}.sops) defaultSopsFile validateSopsFiles;
|
||||
|
||||
age = {
|
||||
inherit (config.${namespace}.sops) generateAgeKey;
|
||||
|
||||
keyFile =
|
||||
if config.${namespace}.sops.ageKeyPath != null then
|
||||
config.${namespace}.sops.ageKeyPath
|
||||
else
|
||||
"${config.users.users.${config.${namespace}.user.name}.home}/.config/sops/age/keys.txt";
|
||||
|
||||
sshKeyPaths = config.${namespace}.sops.sshKeyPaths;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
{ inputs, namespace, ... }:
|
||||
let
|
||||
inherit (inputs.self.${namespace} - lib.system.common)
|
||||
mkExtendedLib
|
||||
mkNixpkgsConfig
|
||||
mkHomeConfigs
|
||||
mkHomeManagerConfig
|
||||
mkSpecialArgs
|
||||
;
|
||||
in
|
||||
{
|
||||
# Example of creating NixOS configurations
|
||||
nixosConfigurations =
|
||||
let
|
||||
# Get all systems
|
||||
allSystems = inputs.self.${namespace} - lib.file.scanSystems ../systems;
|
||||
|
||||
# Filter for NixOS systems
|
||||
nixosSystems = inputs.self.${namespace} - lib.file.filterNixOSSystems allSystems;
|
||||
in
|
||||
inputs.nixpkgs.lib.mapAttrs' (
|
||||
_name:
|
||||
{ system, hostname, ... }:
|
||||
let
|
||||
# Create extended lib with mjallen-lib
|
||||
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||
|
||||
# Find matching home configurations for this system
|
||||
matchingHomes = mkHomeConfigs {
|
||||
flake = inputs.self;
|
||||
inherit system hostname;
|
||||
};
|
||||
|
||||
# Create home-manager configuration
|
||||
homeManagerConfig = mkHomeManagerConfig {
|
||||
inherit
|
||||
extendedLib
|
||||
inputs
|
||||
system
|
||||
matchingHomes
|
||||
;
|
||||
isNixOS = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
name = hostname;
|
||||
value = inputs.nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
# Pass special arguments to modules
|
||||
specialArgs = mkSpecialArgs {
|
||||
inherit inputs hostname extendedLib;
|
||||
username = "mjallen";
|
||||
};
|
||||
|
||||
modules = [
|
||||
# Set lib to extended lib
|
||||
{ _module.args.lib = extendedLib; }
|
||||
|
||||
# Configure nixpkgs
|
||||
{
|
||||
nixpkgs = {
|
||||
inherit system;
|
||||
}
|
||||
// mkNixpkgsConfig inputs.self;
|
||||
}
|
||||
|
||||
# Import home-manager module
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
|
||||
# Auto-inject home configurations
|
||||
homeManagerConfig
|
||||
|
||||
# Import all nixos modules recursively
|
||||
../${system}/${hostname}
|
||||
]
|
||||
++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/nixos);
|
||||
};
|
||||
}
|
||||
) nixosSystems;
|
||||
|
||||
# Example of creating home-manager configurations
|
||||
homeConfigurations =
|
||||
let
|
||||
# Get all homes
|
||||
allHomes = inputs.self.${namespace} - lib.file.scanHomes ../homes;
|
||||
in
|
||||
inputs.nixpkgs.lib.mapAttrs' (
|
||||
_name:
|
||||
{
|
||||
system,
|
||||
username,
|
||||
hostname,
|
||||
userAtHost,
|
||||
path,
|
||||
...
|
||||
}:
|
||||
let
|
||||
# Create extended lib with mjallen-lib
|
||||
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||
in
|
||||
{
|
||||
name = userAtHost;
|
||||
value = inputs.home-manager.lib.homeManagerConfiguration {
|
||||
pkgs = import inputs.nixpkgs {
|
||||
inherit system;
|
||||
inherit ((mkNixpkgsConfig inputs.self)) config overlays;
|
||||
};
|
||||
|
||||
extraSpecialArgs = {
|
||||
inherit
|
||||
inputs
|
||||
hostname
|
||||
username
|
||||
system
|
||||
;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
};
|
||||
|
||||
modules = [
|
||||
# Set lib to extended lib
|
||||
{ _module.args.lib = extendedLib; }
|
||||
|
||||
# Import the home configuration
|
||||
path
|
||||
]
|
||||
++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/home);
|
||||
};
|
||||
}
|
||||
) allHomes;
|
||||
}
|
||||
2
lib/file/default.nix
Normal file → Executable file
2
lib/file/default.nix
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
{ inputs, ... }@args:
|
||||
let
|
||||
# Get self from args or default to ../.. (the flake root)
|
||||
self = if args ? self then args.self else ../..;
|
||||
self = args.self or ../..;
|
||||
|
||||
inherit (inputs.nixpkgs.lib)
|
||||
genAttrs
|
||||
|
||||
383
lib/module/default.nix
Normal file → Executable file
383
lib/module/default.nix
Normal file → Executable file
@@ -14,19 +14,16 @@ let
|
||||
mkDefault
|
||||
mkForce
|
||||
;
|
||||
|
||||
base64Lib = import ../base64 { inherit inputs; };
|
||||
in
|
||||
rec {
|
||||
|
||||
# Conditionally enable modules based on system
|
||||
enableForSystem =
|
||||
system: modules:
|
||||
builtins.filter (
|
||||
mod: mod.systems or [ ] == [ ] || builtins.elem system (mod.systems or [ ])
|
||||
) modules;
|
||||
# ---------------------------------------------------------------------------
|
||||
# NixOS service module helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Create a module with common options
|
||||
# Create a NixOS module with standard options (enable, port, reverseProxy,
|
||||
# firewall, user, postgresql, redis) and optional caller-supplied options and
|
||||
# config. All config is gated behind `cfg.enable`.
|
||||
mkModule =
|
||||
{
|
||||
name,
|
||||
@@ -50,17 +47,17 @@ rec {
|
||||
|
||||
defaultConfig = {
|
||||
# Caddy reverse proxy: when reverseProxy.enable = true, contribute this
|
||||
# service's virtual host block to the Caddy config. The TLS wildcard
|
||||
# cert is handled via a (cloudflare_tls) snippet defined in globalConfig.
|
||||
# services.caddy.virtualHosts.${fqdn} = lib.mkIf cfg.reverseProxy.enable {
|
||||
# extraConfig = ''
|
||||
# import cloudflare_tls
|
||||
# reverse_proxy ${upstreamUrl}
|
||||
# ${cfg.reverseProxy.extraCaddyConfig}
|
||||
# '';
|
||||
# };
|
||||
# service's named-matcher block into the shared wildcard virtual host.
|
||||
services.caddy.virtualHosts."*.${cfg.reverseProxy.domain}" = lib.mkIf cfg.reverseProxy.enable {
|
||||
extraConfig = ''
|
||||
@${name} host ${fqdn}
|
||||
handle @${name} {
|
||||
reverse_proxy ${upstreamUrl}
|
||||
${cfg.reverseProxy.extraCaddyConfig}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# Open firewall
|
||||
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
@@ -75,20 +72,12 @@ rec {
|
||||
groups.${name} = { };
|
||||
};
|
||||
|
||||
systemd.services.${serviceName} = {
|
||||
requires = [
|
||||
"media-nas-main.mount"
|
||||
# "openvpn-us.protonvpn.udp.service"
|
||||
];
|
||||
after = lib.mkForce [
|
||||
"media-nas-main.mount"
|
||||
# "openvpn-us.protonvpn.udp.service"
|
||||
];
|
||||
# serviceConfig = {
|
||||
# NetworkNamespacePath = lib.mkIf cfg.enableVpn "/run/netns/vpn";
|
||||
# # Consider also setting DNS *inside* the netns (see note below).
|
||||
# };
|
||||
};
|
||||
# RequiresMountsFor is silently ignored when the paths live on the root
|
||||
# filesystem, so this is safe on non-NAS hosts too.
|
||||
systemd.services.${serviceName}.unitConfig.RequiresMountsFor = [
|
||||
cfg.configDir
|
||||
cfg.dataDir
|
||||
];
|
||||
|
||||
services = {
|
||||
postgresql = lib.mkIf cfg.configureDb {
|
||||
@@ -102,18 +91,209 @@ rec {
|
||||
];
|
||||
};
|
||||
redis.servers.${name} = lib.mkIf cfg.redis.enable {
|
||||
enable = true;
|
||||
port = cfg.redis.port;
|
||||
inherit (cfg.redis) enable port;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{ lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
{ config = lib.mkIf cfg.enable defaultConfig; }
|
||||
{ config = lib.mkIf cfg.enable moduleConfig; }
|
||||
];
|
||||
|
||||
# systemd.tmpfiles.rules = [
|
||||
# "d ${cfg.configDir} 0700 ${name} ${name} - -"
|
||||
# # "d ${cfg.configDir}/server-files 0775 ${name} ${name} - -"
|
||||
# # "d ${cfg.configDir}/user-files 0775 ${name} ${name} - -"
|
||||
# ];
|
||||
}
|
||||
// moduleConfig;
|
||||
options.${namespace}.${domain}.${name} = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption description;
|
||||
|
||||
port = mkOpt types.int 80 "Port for ${name} to listen on";
|
||||
|
||||
configDir = mkOpt types.str "/var/lib/${name}" "Path to the config directory";
|
||||
|
||||
dataDir = mkOpt types.str "/var/lib/${name}/data" "Path to the data directory";
|
||||
|
||||
createUser = mkBoolOpt false "Create a dedicated system user for this service";
|
||||
|
||||
configureDb = mkBoolOpt false "Manage a PostgreSQL database for this service";
|
||||
|
||||
environmentFile =
|
||||
mkOpt (types.nullOr types.str) null
|
||||
"Path to an environment file (EnvironmentFile=)";
|
||||
|
||||
puid = mkOpt types.str "911" "User ID for container-based services";
|
||||
|
||||
pgid = mkOpt types.str "100" "Group ID for container-based services";
|
||||
|
||||
timeZone = mkOpt types.str "UTC" "Timezone for container-based services";
|
||||
|
||||
listenAddress = mkOpt types.str "0.0.0.0" "Listen address";
|
||||
|
||||
openFirewall = mkBoolOpt true "Open firewall ports for this service";
|
||||
|
||||
redis = {
|
||||
enable = lib.mkEnableOption "a dedicated Redis server for this service";
|
||||
port = mkOpt types.int 6379 "Redis port for ${name}";
|
||||
};
|
||||
|
||||
hashedPassword =
|
||||
mkOpt (types.nullOr types.str) null
|
||||
"Hashed password (e.g. for web-based authentication)";
|
||||
|
||||
extraEnvironment =
|
||||
mkOpt (types.attrsOf types.str) { }
|
||||
"Extra environment variables passed to the service";
|
||||
|
||||
reverseProxy = mkReverseProxyOpt name;
|
||||
|
||||
hostedService = {
|
||||
enable =
|
||||
mkOpt types.bool cfg.reverseProxy.enable
|
||||
"Expose this service in Glance dashboard (auto-enabled when reverseProxy is on)";
|
||||
title = mkOpt types.str name "Display title in Glance";
|
||||
icon = mkOpt types.str "si:glance" "Icon identifier for Glance (e.g. si:actualbudget)";
|
||||
group = mkOpt types.str "Services" "Glance group/category for this service";
|
||||
url = mkOpt types.str (
|
||||
if cfg.reverseProxy.enable then
|
||||
"https://${cfg.reverseProxy.subdomain}.${cfg.reverseProxy.domain}"
|
||||
else
|
||||
"http://127.0.0.1:${toString cfg.port}"
|
||||
) "Service URL for Glance (auto-derived from reverseProxy if enabled)";
|
||||
basicAuth = mkOpt types.bool false "Require basic auth for this service in Glance";
|
||||
};
|
||||
}
|
||||
// options;
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
# Wraps mkModule for Podman/OCI container services. Generates all the
|
||||
# standard mkModule options plus the container definition. The serviceName
|
||||
# is set to "podman-<name>" automatically.
|
||||
#
|
||||
# Required args:
|
||||
# config — the NixOS config attrset (pass through from the module args)
|
||||
# name — service name (used for the container name and option path)
|
||||
# image — OCI image reference string
|
||||
# internalPort — port the container listens on internally
|
||||
#
|
||||
# Optional args:
|
||||
# description — human-readable description (defaults to name)
|
||||
# options — extra mkModule options attrset
|
||||
# volumes — extra volume strings (in addition to none)
|
||||
# environment — extra environment variables (merged with PUID/PGID/TZ)
|
||||
# environmentFiles — list of paths to env-files (e.g. sops template paths)
|
||||
# extraOptions — list of extra --opt strings passed to the container runtime
|
||||
# devices — list of device mappings
|
||||
# extraConfig — extra NixOS config merged into moduleConfig
|
||||
mkContainerService =
|
||||
{
|
||||
config,
|
||||
name,
|
||||
image,
|
||||
internalPort,
|
||||
description ? name,
|
||||
options ? { },
|
||||
volumes ? [ ],
|
||||
environment ? { },
|
||||
environmentFiles ? [ ],
|
||||
extraOptions ? [ ],
|
||||
devices ? [ ],
|
||||
extraConfig ? { },
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.services.${name};
|
||||
in
|
||||
mkModule {
|
||||
inherit
|
||||
config
|
||||
name
|
||||
description
|
||||
options
|
||||
;
|
||||
serviceName = "podman-${name}";
|
||||
moduleConfig = lib.recursiveUpdate {
|
||||
virtualisation.oci-containers.containers.${name} = {
|
||||
autoStart = true;
|
||||
inherit
|
||||
image
|
||||
volumes
|
||||
environmentFiles
|
||||
extraOptions
|
||||
devices
|
||||
;
|
||||
ports = [ "${toString cfg.port}:${toString internalPort}" ];
|
||||
environment = {
|
||||
PUID = cfg.puid;
|
||||
PGID = cfg.pgid;
|
||||
TZ = cfg.timeZone;
|
||||
}
|
||||
// environment;
|
||||
};
|
||||
} extraConfig;
|
||||
};
|
||||
|
||||
# Generates a sops secrets block + a sops template env-file in a single call.
|
||||
#
|
||||
# secrets — attrset of sops secret keys → extra attrs (e.g. owner/group).
|
||||
# The sopsFile is set automatically to nas-secrets.yaml unless
|
||||
# overridden per-secret via { sopsFile = ...; }.
|
||||
# name — template file name, e.g. "glance.env"
|
||||
# content — the template body string (use config.sops.placeholder."key")
|
||||
# restartUnit — systemd unit to restart when the secret changes
|
||||
# owner, group, mode — file ownership/permissions (defaults match NAS convention)
|
||||
# sopsFile — default sops file for all secrets (can be overridden per-secret)
|
||||
mkSopsEnvFile =
|
||||
{
|
||||
secrets,
|
||||
name,
|
||||
content,
|
||||
restartUnit,
|
||||
owner ? "nix-apps",
|
||||
group ? "jallen-nas",
|
||||
mode ? "660",
|
||||
sopsFile ? lib.snowfall.fs.get-file "secrets/nas-secrets.yaml",
|
||||
}:
|
||||
{
|
||||
sops.secrets = mapAttrs (_key: extra: { inherit sopsFile; } // extra) secrets;
|
||||
|
||||
sops.templates.${name} = {
|
||||
inherit
|
||||
mode
|
||||
owner
|
||||
group
|
||||
content
|
||||
;
|
||||
restartUnits = [ restartUnit ];
|
||||
};
|
||||
};
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Home Manager module helper
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Create a Home Manager module with a standard enable option and optional
|
||||
# extra options, gating all config behind `cfg.enable`.
|
||||
#
|
||||
# domain — option namespace domain, e.g. "programs" or "desktop"
|
||||
# name — module name, e.g. "btop"
|
||||
# description — text for mkEnableOption (defaults to name)
|
||||
# options — attrset of extra options merged into the submodule
|
||||
# config — the NixOS/HM config attrset passed through from module args
|
||||
# moduleConfig — the Home Manager config body (already gated behind cfg.enable)
|
||||
mkHomeModule =
|
||||
{
|
||||
config,
|
||||
domain,
|
||||
name,
|
||||
description ? name,
|
||||
options ? { },
|
||||
moduleConfig,
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.${domain}.${name};
|
||||
in
|
||||
{ lib, ... }:
|
||||
{
|
||||
@@ -121,108 +301,26 @@ rec {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption description;
|
||||
|
||||
port = mkOpt types.int 80 "Port for ${name} to be hosted on";
|
||||
|
||||
configDir = mkOpt types.str "/media/nas/main/appdata" "Path to the config dir";
|
||||
|
||||
dataDir = mkOpt types.str "/media/nas/main" "Path to the data dir";
|
||||
|
||||
createUser = mkBoolOpt false "create a user for this module/service";
|
||||
|
||||
configureDb = mkBoolOpt false "Manage db for this service";
|
||||
|
||||
environmentFile = mkOpt types.str "" "Environment File";
|
||||
|
||||
puid = mkOpt types.str "911" "default user id";
|
||||
|
||||
pgid = mkOpt types.str "1000" "default group id";
|
||||
|
||||
timeZone = mkOpt types.str "America/Chicago" "default timezone";
|
||||
|
||||
listenAddress = mkOpt types.str "0.0.0.0" "Environment File";
|
||||
|
||||
openFirewall = mkBoolOpt true "Open the firewall";
|
||||
|
||||
enableVpn = mkBoolOpt true "Enable routing through VPN";
|
||||
|
||||
redis = {
|
||||
enable = lib.mkEnableOption "enable redis";
|
||||
|
||||
port = mkOpt types.int 80 "Port for ${name} redis to be hosted on";
|
||||
};
|
||||
|
||||
hashedPassword =
|
||||
mkOpt (types.nullOr types.str)
|
||||
"$y$j9T$EkPXmsmIMFFZ.WRrBYCxS1$P0kwo6e4.WM5DsqUcEqWC3MrZp5KfCjxffraMFZWu06"
|
||||
"Hashed password for code-server authentication";
|
||||
|
||||
extraEnvironment =
|
||||
mkOpt (types.attrsOf types.str) { }
|
||||
"Extra environment variables for code-server";
|
||||
|
||||
reverseProxy = mkReverseProxyOpt name;
|
||||
}
|
||||
// options;
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable defaultConfig;
|
||||
config = lib.mkIf cfg.enable moduleConfig;
|
||||
};
|
||||
|
||||
# container
|
||||
mkContainer =
|
||||
{
|
||||
name,
|
||||
localAddress ? "127.0.0.1",
|
||||
ports ? [ 80 ],
|
||||
bindMounts ? { },
|
||||
config ? { },
|
||||
}:
|
||||
{ lib, ... }:
|
||||
{
|
||||
containers.${name} = {
|
||||
inherit localAddress bindMounts;
|
||||
|
||||
config = config // {
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = ports;
|
||||
};
|
||||
# Use systemd-resolved inside the container
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = lib.mkForce false;
|
||||
};
|
||||
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
autoStart = lib.mkDefault true;
|
||||
privateNetwork = lib.mkDefault true;
|
||||
hostAddress = lib.mkDefault "10.0.1.3";
|
||||
};
|
||||
|
||||
networking = {
|
||||
nat.forwardPorts = map (port: {
|
||||
destination = lib.mkDefault "${localAddress}:${toString port}";
|
||||
sourcePort = lib.mkDefault port;
|
||||
}) ports;
|
||||
firewall = {
|
||||
allowedTCPPorts = ports;
|
||||
allowedUDPPorts = ports;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Migrated mjallen utilities
|
||||
# ---------------------------------------------------------------------------
|
||||
# Option creation helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
# Option creation helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
mkOpt =
|
||||
type: default: description:
|
||||
mkOption { inherit type default description; };
|
||||
|
||||
mkOpt' = type: default: mkOpt type default null;
|
||||
mkOpt' = type: default: mkOpt type default "";
|
||||
|
||||
mkBoolOpt = mkOpt types.bool;
|
||||
|
||||
@@ -235,26 +333,28 @@ rec {
|
||||
|
||||
domain = mkOpt types.str "mjallen.dev" "Base domain for the reverse proxy";
|
||||
|
||||
# Override the upstream URL if the backend is not on localhost at cfg.port.
|
||||
# Leave empty to use http://127.0.0.1:<port> automatically.
|
||||
upstreamUrl =
|
||||
mkOpt (types.nullOr types.str) null
|
||||
"Override upstream URL (e.g. for services on a different host). Defaults to http://127.0.0.1:<port>.";
|
||||
"Override upstream URL (e.g. for a service on a different host). Defaults to http://127.0.0.1:<port>.";
|
||||
|
||||
# Extra Caddyfile directives inserted inside the virtual host block.
|
||||
extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives for this virtual host block";
|
||||
extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives inside this virtual host block";
|
||||
};
|
||||
|
||||
# Standard enable/disable patterns
|
||||
# ---------------------------------------------------------------------------
|
||||
# Convenience shorthands
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
enabled = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
disabled = {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# String utilities
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
capitalize =
|
||||
s:
|
||||
let
|
||||
@@ -262,10 +362,16 @@ rec {
|
||||
in
|
||||
if len == 0 then "" else (toUpper (substring 0 1 s)) + (substring 1 len s);
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Boolean utilities
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
boolToNum = bool: if bool then 1 else 0;
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Attribute manipulation utilities
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
default-attrs = mapAttrs (_key: mkDefault);
|
||||
|
||||
force-attrs = mapAttrs (_key: mkForce);
|
||||
@@ -274,4 +380,3 @@ rec {
|
||||
|
||||
nested-force-attrs = mapAttrs (_key: force-attrs);
|
||||
}
|
||||
// base64Lib
|
||||
|
||||
185
lib/network/default.nix
Executable file
185
lib/network/default.nix
Executable file
@@ -0,0 +1,185 @@
|
||||
# Central network topology registry.
|
||||
#
|
||||
# Exposed as lib.<namespace>.network.* (Snowfall Lib merges lib/ sub-directories
|
||||
# automatically, so this file is reachable as lib.mjallen.network inside any
|
||||
# NixOS module, home-manager module, or package that receives `lib`).
|
||||
#
|
||||
# Usage examples:
|
||||
#
|
||||
# let net = lib.mjallen.network; in
|
||||
# net.hosts.nas.lan # "10.0.1.3"
|
||||
# net.hosts.nas.lan4 # "10.0.1.3/24" (CIDR notation)
|
||||
# net.hosts.nuc.lan # "10.0.1.4"
|
||||
# net.hosts.pi5.nebula # "10.1.1.1"
|
||||
# net.subnet.lan # "10.0.1.0/24"
|
||||
# net.subnet.nebula # "10.1.1.0/24"
|
||||
# net.ports.nas.nextcloud # 9988
|
||||
# net.domain # "mjallen.dev"
|
||||
#
|
||||
# All attributes intentionally use plain strings / ints so they can be
|
||||
# interpolated with `toString` or used directly in any context.
|
||||
{
|
||||
network = {
|
||||
# -----------------------------------------------------------------------
|
||||
# Global domain
|
||||
# -----------------------------------------------------------------------
|
||||
domain = "mjallen.dev";
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Subnets
|
||||
# -----------------------------------------------------------------------
|
||||
subnet = {
|
||||
lan = "10.0.1.0/24";
|
||||
nebula = "10.1.1.0/24";
|
||||
# Docker / container bridge used by Home Assistant
|
||||
docker = "172.30.33.0/24";
|
||||
};
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Hosts
|
||||
# Each host exposes:
|
||||
# lan — bare IPv4 address (no prefix length)
|
||||
# lan4 — IPv4 address with /24 CIDR suffix (for static IP config)
|
||||
# nebula — Nebula overlay IP (where applicable)
|
||||
# -----------------------------------------------------------------------
|
||||
hosts = {
|
||||
# ---- Raspberry Pi 5 (pi5) — DNS / Nebula lighthouse ----------------
|
||||
pi5 = {
|
||||
hostname = "pi5";
|
||||
lan = "10.0.1.2";
|
||||
lan4 = "10.0.1.2/24";
|
||||
nebula = "10.1.1.1";
|
||||
gateway = "10.0.1.1";
|
||||
};
|
||||
|
||||
# ---- NAS (jallen-nas) — primary server -----------------------------
|
||||
nas = {
|
||||
hostname = "jallen-nas";
|
||||
lan = "10.0.1.3";
|
||||
lan4 = "10.0.1.3/24";
|
||||
nebula = "10.1.1.3";
|
||||
gateway = "10.0.1.1";
|
||||
};
|
||||
|
||||
# ---- Intel NUC (nuc-nixos) — Home Assistant host -------------------
|
||||
nuc = {
|
||||
hostname = "nuc-nixos";
|
||||
lan = "10.0.1.4";
|
||||
lan4 = "10.0.1.4/24";
|
||||
nebula = "10.1.1.4";
|
||||
gateway = "10.0.1.1";
|
||||
};
|
||||
|
||||
# ---- MacBook Pro (macbook-pro-nixos) — Apple Silicon laptop --------
|
||||
macbook = {
|
||||
hostname = "macbook-pro-nixos";
|
||||
nebula = "10.1.1.8";
|
||||
};
|
||||
|
||||
# ---- ASUS ROG Ally X (allyx) ----------------------------------------
|
||||
allyx = {
|
||||
hostname = "allyx";
|
||||
nebula = "10.1.1.10";
|
||||
};
|
||||
|
||||
# ---- Router / gateway / AdGuard upstream ---------------------------
|
||||
router = {
|
||||
hostname = "router";
|
||||
lan = "10.0.1.1";
|
||||
lan4 = "10.0.1.1/24";
|
||||
};
|
||||
};
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Service ports
|
||||
# Grouped by host. Every entry matches the port set in apps.nix / the
|
||||
# corresponding mkModule option so there is a single source of truth.
|
||||
# -----------------------------------------------------------------------
|
||||
ports = {
|
||||
# ---- pi5 services --------------------------------------------------
|
||||
pi5 = {
|
||||
adguard = 3000;
|
||||
attic = 9012;
|
||||
nebula = 4242;
|
||||
dns = 53;
|
||||
};
|
||||
|
||||
# ---- NAS services --------------------------------------------------
|
||||
nas = {
|
||||
actual = 3333;
|
||||
attic = 9012;
|
||||
authentik = 9000;
|
||||
authentikRac = 4823;
|
||||
calibre = 8084;
|
||||
calibreWeb = 8083;
|
||||
codeServer = 4444;
|
||||
cockpit = 9091;
|
||||
collabora = 9980;
|
||||
coturn = 3478;
|
||||
crowdsec = 8181;
|
||||
dispatcharr = 9191;
|
||||
elasticsearch = 9200;
|
||||
gitea = 3000;
|
||||
giteaSsh = 2222;
|
||||
glance = 5555;
|
||||
glances = 61208;
|
||||
grafana = 9999;
|
||||
grimmory = 6066;
|
||||
guacd = 4822;
|
||||
headscale = 2112;
|
||||
immich = 2283;
|
||||
jellyfin = 8096;
|
||||
seerr = 5055;
|
||||
kavita = 5000;
|
||||
llamaCpp = 8127;
|
||||
lubelogger = 6754;
|
||||
manyfold = 3214;
|
||||
mariadb = 3306;
|
||||
matrix = 8448;
|
||||
mongodb = 27017;
|
||||
nebula = 4242;
|
||||
netbootxyz = 4000;
|
||||
netbootxyzWeb = 4080;
|
||||
nextcloud = 9988;
|
||||
ntfy = 2586;
|
||||
nutUpsd = 3493;
|
||||
ocis = 9200;
|
||||
onlyoffice = 9943;
|
||||
opencloud = 9200;
|
||||
orcaSlicer = 3100;
|
||||
paperless = 28981;
|
||||
paperlessAi = 28982;
|
||||
postgresql = 5432;
|
||||
protonmailSmtp = 1025;
|
||||
protonmailImap = 1143;
|
||||
redisCcache = 6363;
|
||||
redisManyfold = 6380;
|
||||
redisOnlyoffice = 6381;
|
||||
resticServer = 8008;
|
||||
sabnzbd = 8280;
|
||||
sonarr = 8989;
|
||||
radarr = 7878;
|
||||
sparkyFitnessFe = 3004;
|
||||
sparkyFitnessBe = 3010;
|
||||
sunshine = 47989;
|
||||
tdarr = 8265;
|
||||
tdarrServer = 8266;
|
||||
termix = 7777;
|
||||
tunarr = 8000;
|
||||
unmanic = 8265;
|
||||
uptimeKuma = 3001;
|
||||
wyomingPiper = 10200;
|
||||
wyomingWhisper = 10300;
|
||||
};
|
||||
|
||||
# ---- NUC services --------------------------------------------------
|
||||
nuc = {
|
||||
homeAssistant = 8123;
|
||||
mqtt = 1883;
|
||||
otbr = 8880;
|
||||
otbrRest = 8881;
|
||||
esphome = 6052;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
49
lib/nix-settings/default.nix
Executable file
49
lib/nix-settings/default.nix
Executable file
@@ -0,0 +1,49 @@
|
||||
# Shared nix daemon / nixpkgs settings used by both the NixOS and nix-darwin
|
||||
# modules (modules/nixos/nix/default.nix and modules/darwin/nix/default.nix).
|
||||
#
|
||||
# Snowfall Lib discovers this file and merges its return value into
|
||||
# lib.<namespace>.* — the nested attrset is accessed as:
|
||||
# lib.${namespace}.nixSettings.commonSubstituters
|
||||
# lib.${namespace}.nixSettings.commonTrustedPublicKeys
|
||||
# lib.${namespace}.nixSettings.commonSettings
|
||||
# lib.${namespace}.nixSettings.commonGc
|
||||
{ lib, ... }:
|
||||
{
|
||||
nixSettings = {
|
||||
commonSubstituters = [
|
||||
"https://nixos-apple-silicon.cachix.org"
|
||||
"https://nixos-raspberrypi.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
|
||||
commonTrustedPublicKeys = [
|
||||
"nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20="
|
||||
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
|
||||
commonSettings = {
|
||||
warn-dirty = lib.mkForce false;
|
||||
experimental-features = lib.mkForce [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
trusted-users = [
|
||||
"@wheel"
|
||||
"@admin"
|
||||
];
|
||||
builders-use-substitutes = true;
|
||||
connect-timeout = lib.mkDefault 5;
|
||||
fallback = true;
|
||||
log-lines = lib.mkDefault 25;
|
||||
max-free = lib.mkDefault (3000 * 1024 * 1024);
|
||||
min-free = lib.mkDefault (512 * 1024 * 1024);
|
||||
};
|
||||
|
||||
commonGc = {
|
||||
automatic = lib.mkDefault true;
|
||||
options = lib.mkDefault "--delete-older-than 30d";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
{ inputs }:
|
||||
let
|
||||
inherit (inputs.nixpkgs.lib)
|
||||
listToAttrs
|
||||
nameValuePair
|
||||
;
|
||||
in
|
||||
rec {
|
||||
# Create a service configuration for Traefik
|
||||
mkService =
|
||||
{
|
||||
name,
|
||||
url,
|
||||
loadBalancer ? { },
|
||||
}:
|
||||
{
|
||||
inherit name url;
|
||||
config = {
|
||||
loadBalancer = {
|
||||
servers = [ { inherit url; } ];
|
||||
}
|
||||
// loadBalancer;
|
||||
};
|
||||
};
|
||||
|
||||
# Create a router configuration for Traefik
|
||||
mkRouter =
|
||||
{
|
||||
subdomain,
|
||||
domain ? "mjallen.dev",
|
||||
service,
|
||||
entryPoints ? [ "websecure" ],
|
||||
middlewares ? [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
],
|
||||
priority ? null,
|
||||
rule ? null,
|
||||
tls ? {
|
||||
certResolver = "letsencrypt";
|
||||
},
|
||||
}:
|
||||
{
|
||||
inherit
|
||||
subdomain
|
||||
service
|
||||
entryPoints
|
||||
middlewares
|
||||
;
|
||||
config = {
|
||||
inherit
|
||||
entryPoints
|
||||
service
|
||||
middlewares
|
||||
tls
|
||||
;
|
||||
rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)";
|
||||
}
|
||||
// (if priority != null then { inherit priority; } else { });
|
||||
};
|
||||
|
||||
# Create both service and router for a simple reverse proxy setup
|
||||
mkReverseProxy =
|
||||
{
|
||||
name,
|
||||
subdomain,
|
||||
url,
|
||||
domain ? "mjallen.dev",
|
||||
entryPoints ? [ "websecure" ],
|
||||
middlewares ? [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
],
|
||||
priority ? null,
|
||||
rule ? null,
|
||||
tls ? {
|
||||
certResolver = "letsencrypt";
|
||||
},
|
||||
loadBalancer ? { },
|
||||
}:
|
||||
{
|
||||
service = mkService {
|
||||
inherit name url loadBalancer;
|
||||
};
|
||||
router = mkRouter {
|
||||
inherit
|
||||
subdomain
|
||||
domain
|
||||
entryPoints
|
||||
middlewares
|
||||
priority
|
||||
rule
|
||||
tls
|
||||
;
|
||||
service = name;
|
||||
};
|
||||
};
|
||||
|
||||
# Convert a list of services to the format expected by Traefik module
|
||||
servicesToConfig =
|
||||
services: listToAttrs (map (service: nameValuePair service.name service.config) services);
|
||||
|
||||
# Convert a list of routers to the format expected by Traefik module
|
||||
routersToConfig =
|
||||
routers: listToAttrs (map (router: nameValuePair router.subdomain router.config) routers);
|
||||
|
||||
# Helper to create multiple reverse proxies at once
|
||||
mkReverseProxies =
|
||||
proxies:
|
||||
let
|
||||
results = map mkReverseProxy proxies;
|
||||
services = map (result: result.service) results;
|
||||
routers = map (result: result.router) results;
|
||||
in
|
||||
{
|
||||
services = servicesToConfig services;
|
||||
routers = routersToConfig routers;
|
||||
extraServices = services;
|
||||
extraRouters = map (router: {
|
||||
inherit (router) subdomain entryPoints middlewares;
|
||||
service = router.service;
|
||||
}) routers;
|
||||
};
|
||||
|
||||
# Common middleware configurations
|
||||
middlewares = {
|
||||
# Authentication middleware
|
||||
auth = [ "authentik" ];
|
||||
|
||||
# Basic security (default)
|
||||
basic = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
|
||||
# Internal only access
|
||||
internal = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"internal-ipallowlist"
|
||||
];
|
||||
|
||||
# WebSocket support
|
||||
websocket = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"onlyoffice-websocket"
|
||||
];
|
||||
|
||||
# Authenticated with basic security
|
||||
authBasic = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"authentik"
|
||||
];
|
||||
};
|
||||
|
||||
# Common service URL builders
|
||||
urls = {
|
||||
# Local container service
|
||||
container =
|
||||
containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}";
|
||||
|
||||
# Local host service
|
||||
localhost = port: "http://127.0.0.1:${toString port}";
|
||||
|
||||
# Network service
|
||||
network = ip: port: "http://${ip}:${toString port}";
|
||||
|
||||
# Server IP service (using your server IP pattern)
|
||||
server = port: "http://\${serverIp}:${toString port}";
|
||||
};
|
||||
|
||||
# Pre-configured reverse proxy templates
|
||||
templates = {
|
||||
# Standard web application
|
||||
webapp =
|
||||
{ port, ... }@args:
|
||||
mkReverseProxy (
|
||||
{
|
||||
url = urls.localhost port;
|
||||
middlewares = middlewares.basic;
|
||||
}
|
||||
// args
|
||||
);
|
||||
|
||||
# Authenticated web application
|
||||
authWebapp =
|
||||
{ port, ... }@args:
|
||||
mkReverseProxy (
|
||||
{
|
||||
url = urls.localhost port;
|
||||
middlewares = middlewares.authBasic;
|
||||
}
|
||||
// args
|
||||
);
|
||||
|
||||
# Container-based service
|
||||
containerService =
|
||||
{ containerName, port, ... }@args:
|
||||
mkReverseProxy (
|
||||
{
|
||||
url = urls.container containerName port;
|
||||
middlewares = middlewares.basic;
|
||||
}
|
||||
// args
|
||||
);
|
||||
|
||||
# Internal-only service
|
||||
internalService =
|
||||
{ port, ... }@args:
|
||||
mkReverseProxy (
|
||||
{
|
||||
url = urls.localhost port;
|
||||
middlewares = middlewares.internal;
|
||||
}
|
||||
// args
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
{ inputs, namespace }:
|
||||
let
|
||||
inherit (inputs.nixpkgs.lib) filterAttrs mapAttrs';
|
||||
in
|
||||
{
|
||||
mkExtendedLib =
|
||||
flake: nixpkgs:
|
||||
nixpkgs.lib.extend (
|
||||
_final: _prev: {
|
||||
mjallen = flake.${namespace} - lib;
|
||||
}
|
||||
);
|
||||
|
||||
mkNixpkgsConfig = flake: {
|
||||
overlays = builtins.attrValues flake.overlays;
|
||||
config = {
|
||||
allowAliases = false;
|
||||
allowUnfree = true;
|
||||
permittedInsecurePackages = [
|
||||
# Add any permitted insecure packages here
|
||||
"mbedtls-2.28.10"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
mkHomeConfigs =
|
||||
{
|
||||
flake,
|
||||
system,
|
||||
hostname,
|
||||
}:
|
||||
let
|
||||
inherit (flake.${namespace} - lib.file) scanHomes;
|
||||
homesPath = ../../homes;
|
||||
allHomes = scanHomes homesPath;
|
||||
in
|
||||
filterAttrs (
|
||||
_name: homeConfig: homeConfig.system == system && homeConfig.hostname == hostname
|
||||
) allHomes;
|
||||
|
||||
mkHomeManagerConfig =
|
||||
{
|
||||
extendedLib,
|
||||
inputs,
|
||||
system,
|
||||
matchingHomes,
|
||||
isNixOS ? true,
|
||||
}:
|
||||
if matchingHomes != { } then
|
||||
{
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = {
|
||||
inherit inputs system;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
};
|
||||
sharedModules = [
|
||||
{ _module.args.lib = extendedLib; }
|
||||
]
|
||||
++ (extendedLib.${namespace}.file.importModulesRecursive ../../modules/home);
|
||||
users = mapAttrs' (_name: homeConfig: {
|
||||
name = homeConfig.username;
|
||||
value = {
|
||||
imports = [ homeConfig.path ];
|
||||
home = {
|
||||
inherit (homeConfig) username;
|
||||
homeDirectory = inputs.nixpkgs.lib.mkDefault (
|
||||
if isNixOS then "/home/${homeConfig.username}" else "/Users/${homeConfig.username}"
|
||||
);
|
||||
};
|
||||
}
|
||||
// (
|
||||
if isNixOS then
|
||||
{
|
||||
_module.args.username = homeConfig.username;
|
||||
}
|
||||
else
|
||||
{ }
|
||||
);
|
||||
}) matchingHomes;
|
||||
};
|
||||
}
|
||||
else
|
||||
{ };
|
||||
|
||||
mkSpecialArgs =
|
||||
{
|
||||
inputs,
|
||||
hostname,
|
||||
username,
|
||||
extendedLib,
|
||||
}:
|
||||
{
|
||||
inherit inputs hostname username;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
namespace = "mjallen";
|
||||
format = "system";
|
||||
host = hostname;
|
||||
};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ inputs }:
|
||||
{
|
||||
# Common utilities used by system builders
|
||||
common = import ./common.nix { inherit inputs; };
|
||||
}
|
||||
84
lib/versioning/default.nix
Normal file → Executable file
84
lib/versioning/default.nix
Normal file → Executable file
@@ -1,11 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
inputs,
|
||||
system ? "aarch64-linux",
|
||||
}:
|
||||
let
|
||||
pkgs = inputs.nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
let
|
||||
inherit (builtins)
|
||||
isAttrs
|
||||
@@ -14,12 +9,9 @@ let
|
||||
hasAttr
|
||||
getAttr
|
||||
attrNames
|
||||
toString
|
||||
replaceStrings
|
||||
;
|
||||
|
||||
mapAttrs = lib.mapAttrs;
|
||||
recursiveUpdate = lib.recursiveUpdate;
|
||||
inherit (lib) mapAttrs recursiveUpdate;
|
||||
|
||||
# Deep-merge attrsets (right-biased).
|
||||
deepMerge = a: b: recursiveUpdate a b;
|
||||
@@ -36,8 +28,8 @@ let
|
||||
applyVariantOnce =
|
||||
selected: variant:
|
||||
let
|
||||
vVars = if variant ? variables then variant.variables else { };
|
||||
vSrcs = if variant ? sources then variant.sources else { };
|
||||
vVars = variant.variables or { };
|
||||
vSrcs = variant.sources or { };
|
||||
in
|
||||
{
|
||||
variables = selected.variables // vVars;
|
||||
@@ -52,8 +44,8 @@ let
|
||||
else
|
||||
let
|
||||
p = variant.platforms.${system};
|
||||
pVars = if p ? variables then p.variables else { };
|
||||
pSrcs = if p ? sources then p.sources else { };
|
||||
pVars = p.variables or { };
|
||||
pSrcs = p.sources or { };
|
||||
in
|
||||
{
|
||||
variables = selected.variables // pVars;
|
||||
@@ -94,53 +86,48 @@ let
|
||||
# Decide fetcher for URL type based on optional extra.unpack hint.
|
||||
useFetchZip = comp: comp ? extra && comp.extra ? unpack && comp.extra.unpack == "zip";
|
||||
|
||||
# Build a single src from a rendered component spec.
|
||||
mkSrcFromRendered =
|
||||
comp:
|
||||
# Build a single src from a rendered component spec, using the given pkgs for fetchers.
|
||||
mkSrcFromRendered' =
|
||||
pkgs': comp:
|
||||
let
|
||||
fetcher = if comp ? fetcher then comp.fetcher else "none";
|
||||
fetcher = comp.fetcher or "none";
|
||||
in
|
||||
if fetcher == "github" then
|
||||
pkgs.fetchFromGitHub (
|
||||
pkgs'.fetchFromGitHub (
|
||||
{
|
||||
owner = comp.owner;
|
||||
repo = comp.repo;
|
||||
inherit (comp) owner repo hash;
|
||||
# Allow tag as rev (ignore null/empty tag)
|
||||
rev = if comp ? tag && comp.tag != null && comp.tag != "" then comp.tag else comp.rev;
|
||||
fetchSubmodules = if comp ? submodules then comp.submodules else false;
|
||||
hash = comp.hash;
|
||||
fetchSubmodules = comp.submodules or false;
|
||||
}
|
||||
// lib.optionalAttrs (comp ? name) { name = comp.name; }
|
||||
// lib.optionalAttrs (comp ? name) { inherit (comp) name; }
|
||||
)
|
||||
else if fetcher == "git" then
|
||||
pkgs.fetchgit {
|
||||
url = comp.url;
|
||||
rev = comp.rev;
|
||||
fetchSubmodules = if comp ? submodules then comp.submodules else false;
|
||||
hash = comp.hash;
|
||||
pkgs'.fetchgit {
|
||||
inherit (comp) url rev hash;
|
||||
fetchSubmodules = comp.submodules or false;
|
||||
}
|
||||
else if fetcher == "url" then
|
||||
let
|
||||
url = if comp ? url then comp.url else comp.urlTemplate;
|
||||
url = comp.url or comp.urlTemplate;
|
||||
in
|
||||
if useFetchZip comp then
|
||||
pkgs.fetchzip (
|
||||
pkgs'.fetchzip (
|
||||
{
|
||||
inherit (comp) hash;
|
||||
inherit url;
|
||||
hash = comp.hash;
|
||||
}
|
||||
// lib.optionalAttrs (comp ? extra && comp.extra ? stripRoot) { stripRoot = comp.extra.stripRoot; }
|
||||
// lib.optionalAttrs (comp ? extra && comp.extra ? stripRoot) { inherit (comp.extra) stripRoot; }
|
||||
)
|
||||
else
|
||||
pkgs.fetchurl {
|
||||
pkgs'.fetchurl {
|
||||
inherit (comp) hash;
|
||||
inherit url;
|
||||
hash = comp.hash;
|
||||
}
|
||||
else if fetcher == "pypi" then
|
||||
pkgs.python3Packages.fetchPypi {
|
||||
pkgs'.python3Packages.fetchPypi {
|
||||
inherit (comp) version hash;
|
||||
pname = comp.name;
|
||||
version = comp.version;
|
||||
hash = comp.hash;
|
||||
}
|
||||
else
|
||||
# fetcher == "none": pass-through (e.g., linux version/hash consumed by custom logic)
|
||||
@@ -160,14 +147,10 @@ rec {
|
||||
selectVariant =
|
||||
spec: variantName: system:
|
||||
let
|
||||
chosen =
|
||||
if variantName != null then
|
||||
variantName
|
||||
else
|
||||
(if spec ? defaultVariant then spec.defaultVariant else null);
|
||||
chosen = if variantName != null then variantName else (spec.defaultVariant or null);
|
||||
baseSelected = {
|
||||
variables = if spec ? variables then spec.variables else { };
|
||||
sources = if spec ? sources then spec.sources else { };
|
||||
variables = spec.variables or { };
|
||||
sources = spec.sources or { };
|
||||
};
|
||||
in
|
||||
resolveVariant spec baseSelected chosen system;
|
||||
@@ -181,30 +164,33 @@ rec {
|
||||
/*
|
||||
Render a component with variables and then build its src (or pass-through for fetcher "none").
|
||||
Prefer using mkAllSources, which handles rendering for all components.
|
||||
|
||||
pkgs: the nixpkgs instance to use for fetchers (must match the target system).
|
||||
*/
|
||||
mkSrc =
|
||||
comp: variables:
|
||||
pkgs': comp: variables:
|
||||
let
|
||||
rendered = renderValue comp variables;
|
||||
in
|
||||
mkSrcFromRendered rendered;
|
||||
mkSrcFromRendered' pkgs' rendered;
|
||||
|
||||
/*
|
||||
Produce an attrset of all sources for a selected spec:
|
||||
mkAllSources selected
|
||||
mkAllSources pkgs selected
|
||||
Where:
|
||||
pkgs: the nixpkgs instance to use for fetchers (must match the target system).
|
||||
selected = selectVariant spec variantName system
|
||||
Returns:
|
||||
{ componentName = src | renderedComp (for "none"); ... }
|
||||
*/
|
||||
mkAllSources =
|
||||
selected:
|
||||
pkgs': selected:
|
||||
mapAttrs (
|
||||
_name: comp:
|
||||
if comp ? fetcher && comp.fetcher == "none" then
|
||||
renderValue comp selected.variables
|
||||
else
|
||||
mkSrc (renderValue comp selected.variables) selected.variables
|
||||
mkSrc pkgs' (renderValue comp selected.variables) selected.variables
|
||||
) selected.sources;
|
||||
|
||||
# Expose deepMerge for convenience (right-biased).
|
||||
|
||||
8
modules/darwin/home/default.nix
Normal file → Executable file
8
modules/darwin/home/default.nix
Normal file → Executable file
@@ -38,12 +38,12 @@
|
||||
};
|
||||
|
||||
# Make ALL external HM modules available globally
|
||||
# Note: sops-nix, nix-index-database, and stylix are already injected
|
||||
# globally via systems.modules.home in flake.nix; only darwin-specific
|
||||
# modules that aren't in the global list should go here.
|
||||
sharedModules = with inputs; [
|
||||
sops-nix.homeManagerModules.sops
|
||||
nix-plist-manager.homeManagerModules.default
|
||||
nix-index-database.homeModules.nix-index
|
||||
stylix.homeModules.stylix
|
||||
# Add any other external HM modules here
|
||||
# Add any other darwin-specific external HM modules here
|
||||
];
|
||||
|
||||
users."mattjallen" = lib.mkAliasDefinitions options.${namespace}.home.extraOptions;
|
||||
|
||||
51
modules/darwin/nix/default.nix
Normal file → Executable file
51
modules/darwin/nix/default.nix
Normal file → Executable file
@@ -1,57 +1,28 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) nixSettings;
|
||||
in
|
||||
{
|
||||
nix = {
|
||||
settings = {
|
||||
# extra-sandbox-paths = [ config.programs.ccache.cacheDir ];
|
||||
substituters = [
|
||||
"http://jallen-nas.local:9012/nas-cache"
|
||||
"https://nixos-apple-silicon.cachix.org"
|
||||
"https://nixos-raspberrypi.cachix.org"
|
||||
"https://nix-community.cachix.org"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"nas-cache:eK0eRVAt9QNwbkLIyOo9N5Z5+zi6ukI4mSlL196C7Yg="
|
||||
"nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20="
|
||||
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
warn-dirty = lib.mkForce false;
|
||||
experimental-features = lib.mkForce [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
trusted-users = [
|
||||
"@wheel"
|
||||
"@admin"
|
||||
];
|
||||
|
||||
builders-use-substitutes = true;
|
||||
connect-timeout = lib.mkDefault 5;
|
||||
fallback = true;
|
||||
log-lines = lib.mkDefault 25;
|
||||
|
||||
max-free = lib.mkDefault (3000 * 1024 * 1024);
|
||||
min-free = lib.mkDefault (512 * 1024 * 1024);
|
||||
};
|
||||
# Garbage collect automatically every week
|
||||
gc = {
|
||||
automatic = lib.mkDefault true;
|
||||
options = lib.mkDefault "--delete-older-than 30d";
|
||||
settings = nixSettings.commonSettings // {
|
||||
substituters = nixSettings.commonSubstituters;
|
||||
trusted-public-keys = nixSettings.commonTrustedPublicKeys;
|
||||
};
|
||||
|
||||
gc = nixSettings.commonGc;
|
||||
|
||||
optimise.automatic = lib.mkDefault true;
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
config = {
|
||||
cudaSupport = lib.mkDefault config.${namespace}.hardware.nvidia.enable;
|
||||
rocmSupport = lib.mkDefault config.${namespace}.hardware.amd.enable;
|
||||
# CUDA and ROCm are not applicable on Darwin; those hardware modules are
|
||||
# NixOS-only. Unfree allowance is handled globally via channels-config in
|
||||
# the flake.
|
||||
allowUnsupportedSystem = true;
|
||||
};
|
||||
};
|
||||
|
||||
3
modules/darwin/programs/ssh/default.nix
Normal file → Executable file
3
modules/darwin/programs/ssh/default.nix
Normal file → Executable file
@@ -1,5 +1,4 @@
|
||||
{ ... }:
|
||||
{
|
||||
_: {
|
||||
config = {
|
||||
programs.ssh.knownHosts = {
|
||||
desktop = {
|
||||
|
||||
47
modules/home/accounts/default.nix
Executable file
47
modules/home/accounts/default.nix
Executable file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
accounts = {
|
||||
email.accounts = {
|
||||
gmail = {
|
||||
primary = true;
|
||||
realName = "Matt Jallen";
|
||||
address = "matt.l.jallen@gmail.com";
|
||||
userName = "matt.l.jallen@gmail.com";
|
||||
passwordCommand = "${pkgs.uutils-coreutils-noprefix}/bin/cat ${
|
||||
config.sops.secrets."gmail-smtp-password".path
|
||||
}";
|
||||
flavor = "gmail.com";
|
||||
thunderbird.enable = true;
|
||||
smtp = {
|
||||
tls = {
|
||||
enable = false;
|
||||
useStartTls = true;
|
||||
};
|
||||
host = "smtp.gmail.com";
|
||||
port = lib.mkForce 465;
|
||||
};
|
||||
};
|
||||
protonmail = {
|
||||
realName = "Matt Jallen";
|
||||
address = "jalle008@protonmail.com";
|
||||
userName = "jalle008@protonmail.com";
|
||||
passwordCommand = "${pkgs.uutils-coreutils-noprefix}/bin/cat ${
|
||||
config.sops.secrets."protonmail-password".path
|
||||
}";
|
||||
smtp = {
|
||||
tls = {
|
||||
enable = false;
|
||||
useStartTls = true;
|
||||
};
|
||||
host = "127.0.0.1";
|
||||
port = lib.mkForce 1025;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
3
modules/home/desktop/gnome/default.nix
Normal file → Executable file
3
modules/home/desktop/gnome/default.nix
Normal file → Executable file
@@ -30,8 +30,10 @@ in
|
||||
gnomeExtensions.tiling-assistant
|
||||
gnomeExtensions.user-themes
|
||||
gnomeExtensions.wikiart-wallpaper
|
||||
gnomeExtensions.boatman-winboat-monitor
|
||||
papirus-icon-theme
|
||||
pop-gtk-theme
|
||||
pkgs.mjallen.gnome-nebula-vpn
|
||||
];
|
||||
|
||||
dconf = {
|
||||
@@ -67,6 +69,7 @@ in
|
||||
"dash-to-dock@micxgx.gmail.com"
|
||||
"BingWallpaper@ineffable-gmail.com"
|
||||
"gsconnect@andyholmes.github.io"
|
||||
"nebula-vpn-status@mjallen"
|
||||
];
|
||||
"org/gnome/shell/extensions/bingwallpaper" = {
|
||||
override-lockscreen-blur = true;
|
||||
|
||||
0
modules/home/desktop/gnome/options.nix
Normal file → Executable file
0
modules/home/desktop/gnome/options.nix
Normal file → Executable file
104
modules/home/desktop/plasma/default.nix
Executable file
104
modules/home/desktop/plasma/default.nix
Executable file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.desktop.plasma;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages =
|
||||
(with pkgs.kdePackages; [
|
||||
plasma-browser-integration
|
||||
kdeplasma-addons
|
||||
])
|
||||
++ [
|
||||
# Caffeine-like tray applet: inhibits screensaver and sleep on demand
|
||||
pkgs.caffeine-ng
|
||||
];
|
||||
|
||||
programs.plasma = {
|
||||
enable = true;
|
||||
|
||||
configFile.kded5rc = {
|
||||
"Module-gtkconfig"."autoload" = false;
|
||||
};
|
||||
|
||||
# workspace = {
|
||||
# colorScheme = "BreezeDark";
|
||||
# cursor = {
|
||||
# theme = "breeze_cursors";
|
||||
# size = 24;
|
||||
# };
|
||||
# iconTheme = "breeze-dark";
|
||||
# theme = "breeze-dark";
|
||||
# lookAndFeel = "org.kde.breezedark.desktop";
|
||||
# # Explicitly set Breeze to prevent QT_STYLE_OVERRIDE=kvantum (set by
|
||||
# # Stylix's qt6ct target) from being picked up by KWin/plasmashell, which
|
||||
# # would cause a fatal "module kvantum is not installed" QML error and
|
||||
# # leave the desktop blank.
|
||||
# widgetStyle = "Breeze";
|
||||
# };
|
||||
|
||||
# # input.mice and input.touchpads require device-specific vendorId/productId
|
||||
# # identifiers — configure those per-host in the home config instead.
|
||||
|
||||
kscreenlocker = {
|
||||
autoLock = true;
|
||||
timeout = 10;
|
||||
};
|
||||
|
||||
kwin = {
|
||||
effects = {
|
||||
shakeCursor.enable = false;
|
||||
};
|
||||
nightLight = {
|
||||
enable = true;
|
||||
mode = "automatic";
|
||||
temperature = {
|
||||
day = 6500;
|
||||
night = 3500;
|
||||
};
|
||||
};
|
||||
virtualDesktops = {
|
||||
number = 4;
|
||||
rows = 1;
|
||||
};
|
||||
};
|
||||
|
||||
# panels = [
|
||||
# {
|
||||
# location = "bottom";
|
||||
# floating = true;
|
||||
# height = 44;
|
||||
# widgets = [
|
||||
# "org.kde.plasma.kickoff"
|
||||
# "org.kde.plasma.icontasks"
|
||||
# "org.kde.plasma.marginsseparator"
|
||||
# "org.kde.plasma.systemtray"
|
||||
# "org.kde.plasma.digitalclock"
|
||||
# ];
|
||||
# }
|
||||
# ];
|
||||
|
||||
shortcuts = {
|
||||
kwin = {
|
||||
"Switch to Desktop 1" = "Meta+1";
|
||||
"Switch to Desktop 2" = "Meta+2";
|
||||
"Switch to Desktop 3" = "Meta+3";
|
||||
"Switch to Desktop 4" = "Meta+4";
|
||||
"Window to Desktop 1" = "Meta+Shift+1";
|
||||
"Window to Desktop 2" = "Meta+Shift+2";
|
||||
"Window to Desktop 3" = "Meta+Shift+3";
|
||||
"Window to Desktop 4" = "Meta+Shift+4";
|
||||
"Toggle Overview" = "Meta+Tab";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/home/desktop/plasma/options.nix
Executable file
7
modules/home/desktop/plasma/options.nix
Executable file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.desktop.plasma = {
|
||||
enable = mkEnableOption "KDE Plasma 6 home-manager configuration via plasma-manager";
|
||||
};
|
||||
}
|
||||
4
modules/home/gpg/default.nix
Normal file → Executable file
4
modules/home/gpg/default.nix
Normal file → Executable file
@@ -1,8 +1,8 @@
|
||||
{ ... }:
|
||||
{
|
||||
_: {
|
||||
programs = {
|
||||
gpg = {
|
||||
enable = true;
|
||||
|
||||
scdaemonSettings = {
|
||||
disable-ccid = true;
|
||||
pcsc-shared = true;
|
||||
|
||||
149
modules/home/home/default.nix
Normal file → Executable file
149
modules/home/home/default.nix
Normal file → Executable file
@@ -10,81 +10,104 @@
|
||||
let
|
||||
inherit (lib.${namespace}) enabled;
|
||||
isArm = ("aarch64-linux" == system) || ("aarch64-darwin" == system);
|
||||
# Non-login / system accounts (root, nixos installer, etc.) should not get
|
||||
# desktop packages, tmux, nh, kdeconnect, nextcloud-client, etc.
|
||||
# Detect them by username so individual host home files are not needed.
|
||||
isSystemUser = lib.elem config.home.username [
|
||||
"root"
|
||||
"nixos"
|
||||
];
|
||||
in
|
||||
{
|
||||
home = {
|
||||
enableNixpkgsReleaseCheck = lib.mkDefault false;
|
||||
homeDirectory = lib.mkDefault "/home/${config.home.username}";
|
||||
homeDirectory = lib.mkDefault (
|
||||
if config.home.username == "root" then "/root" else "/home/${config.home.username}"
|
||||
);
|
||||
packages =
|
||||
with pkgs;
|
||||
[
|
||||
age
|
||||
clinfo
|
||||
cpufetch
|
||||
dbus
|
||||
deadnix
|
||||
lm_sensors
|
||||
nano
|
||||
nebula
|
||||
nix-prefetch-scripts
|
||||
nixfmt
|
||||
pciutils
|
||||
protonup-ng
|
||||
rsync
|
||||
smartmontools
|
||||
sops
|
||||
tailscale
|
||||
tree
|
||||
usbutils
|
||||
vim
|
||||
vulkan-tools
|
||||
wget
|
||||
]
|
||||
++ (
|
||||
if hasDestopEnvironment then
|
||||
[
|
||||
boxbuddy
|
||||
stable.chromium
|
||||
firefox
|
||||
gamescope
|
||||
gamescope-wsi
|
||||
gparted
|
||||
mission-center
|
||||
parted
|
||||
vesktop
|
||||
] ++ (
|
||||
if !isArm then
|
||||
[
|
||||
# goverlay
|
||||
# winboat
|
||||
]
|
||||
else [ ]
|
||||
)
|
||||
else
|
||||
(
|
||||
if isSystemUser then
|
||||
[ ]
|
||||
else
|
||||
[
|
||||
age
|
||||
clinfo
|
||||
cpufetch
|
||||
dbus
|
||||
deadnix
|
||||
lm_sensors
|
||||
nano
|
||||
nebula
|
||||
nix-prefetch-scripts
|
||||
nixfmt
|
||||
pciutils
|
||||
proton-pass-cli
|
||||
proton-vpn-cli
|
||||
proton-vpn
|
||||
protonup-ng
|
||||
rsync
|
||||
smartmontools
|
||||
sops
|
||||
tailscale
|
||||
tree
|
||||
usbutils
|
||||
vim
|
||||
vulkan-tools
|
||||
wget
|
||||
]
|
||||
++ (
|
||||
if hasDestopEnvironment then
|
||||
[
|
||||
boxbuddy
|
||||
cider-2
|
||||
stable.chromium
|
||||
firefox
|
||||
gamescope
|
||||
gamescope-wsi
|
||||
gparted
|
||||
mission-center
|
||||
parted
|
||||
vesktop
|
||||
]
|
||||
++ (
|
||||
if isArm then
|
||||
[ ]
|
||||
else
|
||||
[
|
||||
proton-pass
|
||||
]
|
||||
)
|
||||
else
|
||||
[ ]
|
||||
)
|
||||
);
|
||||
|
||||
file = {
|
||||
".face".source = "${pkgs.${namespace}.profile-pic}/profile-pic";
|
||||
};
|
||||
|
||||
stateVersion = lib.mkDefault "23.11";
|
||||
};
|
||||
|
||||
programs = {
|
||||
nix-index-database.comma = enabled;
|
||||
# nix-index-database is not available in all home configs (e.g. iso-minimal
|
||||
# standalone homes don't load the nix-index-database HM module).
|
||||
# Set it per-host in homes that explicitly load the module.
|
||||
btop = {
|
||||
enable = lib.mkDefault true;
|
||||
package = pkgs.unstable.btop;
|
||||
enable = lib.mkDefault (!isSystemUser);
|
||||
package = pkgs.btop;
|
||||
};
|
||||
fastfetch = lib.mkDefault enabled;
|
||||
fastfetch.enable = lib.mkDefault (!isSystemUser);
|
||||
home-manager = lib.mkDefault enabled;
|
||||
java = {
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
mangohud.enable = lib.mkDefault hasDestopEnvironment;
|
||||
password-store = enabled;
|
||||
java.enable = lib.mkDefault (!isSystemUser);
|
||||
mangohud.enable = lib.mkDefault (hasDestopEnvironment && !isSystemUser);
|
||||
password-store.enable = lib.mkDefault (!isSystemUser);
|
||||
nh = {
|
||||
enable = true;
|
||||
enable = lib.mkDefault (!isSystemUser);
|
||||
flake = "/etc/nixos";
|
||||
clean = {
|
||||
enable = true;
|
||||
enable = lib.mkDefault (!isSystemUser);
|
||||
extraArgs = "--keep 5";
|
||||
};
|
||||
};
|
||||
@@ -101,7 +124,7 @@ in
|
||||
};
|
||||
|
||||
tmux = {
|
||||
enable = lib.mkDefault true;
|
||||
enable = lib.mkDefault (!isSystemUser);
|
||||
terminal = "screen-256color";
|
||||
sensibleOnTop = true;
|
||||
focusEvents = true;
|
||||
@@ -123,7 +146,7 @@ in
|
||||
tmuxPlugins.better-mouse-mode
|
||||
];
|
||||
extraConfig = ''
|
||||
set -g status-right '#[fg=black,bg=color15] #{cpu_percentage} %H:%M '
|
||||
set -g status-right '#[fg=black,bg=color15] #{cpu_percentage} %H:%M '
|
||||
run-shell ${pkgs.tmuxPlugins.cpu}/share/tmux-plugins/cpu/cpu.tmux
|
||||
set -g default-terminal "xterm-256color"
|
||||
set -ga terminal-overrides ",*256col*:Tc"
|
||||
@@ -141,11 +164,13 @@ in
|
||||
};
|
||||
|
||||
services = {
|
||||
nextcloud-client.enable = false; # lib.mkDefault hasDestopEnvironment;
|
||||
pass-secret-service = lib.mkDefault enabled;
|
||||
# nextcloud-client is disabled by default for all users; systems that
|
||||
# want it enabled must opt in explicitly in their home configuration.
|
||||
nextcloud-client.enable = lib.mkDefault false;
|
||||
pass-secret-service.enable = lib.mkDefault (!isSystemUser);
|
||||
kdeconnect = {
|
||||
enable = lib.mkDefault hasDestopEnvironment;
|
||||
indicator = lib.mkDefault hasDestopEnvironment;
|
||||
enable = lib.mkDefault (hasDestopEnvironment && !isSystemUser);
|
||||
indicator = lib.mkDefault (hasDestopEnvironment && !isSystemUser);
|
||||
package = pkgs.kdePackages.kdeconnect-kde;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,79 +4,81 @@
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.programs.btop;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
config = mkIf cfg.enable {
|
||||
programs.btop = {
|
||||
enable = true;
|
||||
settings = {
|
||||
truecolor = true;
|
||||
force_tty = false;
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty";
|
||||
vim_keys = true;
|
||||
rounded_corners = true;
|
||||
graph_symbol = "braille";
|
||||
graph_symbol_cpu = "default";
|
||||
graph_symbol_mem = "default";
|
||||
graph_symbol_net = "default";
|
||||
graph_symbol_proc = "default";
|
||||
shown_boxes = "cpu mem net proc";
|
||||
update_ms = 2000;
|
||||
proc_sorting = "cpu lazy";
|
||||
proc_reversed = false;
|
||||
proc_tree = false;
|
||||
proc_colors = true;
|
||||
proc_gradient = true;
|
||||
proc_per_core = false;
|
||||
proc_mem_bytes = true;
|
||||
proc_cpu_graphs = true;
|
||||
proc_info_smaps = false;
|
||||
proc_left = false;
|
||||
proc_filter_kernel = false;
|
||||
cpu_graph_upper = "total";
|
||||
cpu_graph_lower = "total";
|
||||
cpu_invert_lower = true;
|
||||
cpu_single_graph = false;
|
||||
cpu_bottom = false;
|
||||
show_uptime = true;
|
||||
check_temp = true;
|
||||
cpu_sensor = "Auto";
|
||||
show_coretemp = true;
|
||||
cpu_core_map = "";
|
||||
temp_scale = "celsius";
|
||||
base_10_sizes = false;
|
||||
show_cpu_freq = true;
|
||||
clock_format = "%X";
|
||||
background_update = true;
|
||||
custom_cpu_name = "";
|
||||
disks_filter = "";
|
||||
mem_graphs = true;
|
||||
mem_below_net = false;
|
||||
zfs_arc_cached = true;
|
||||
show_swap = true;
|
||||
swap_disk = true;
|
||||
show_disks = true;
|
||||
only_physical = true;
|
||||
use_fstab = true;
|
||||
zfs_hide_datasets = false;
|
||||
disk_free_priv = false;
|
||||
show_io_stat = true;
|
||||
io_mode = false;
|
||||
io_graph_combined = false;
|
||||
io_graph_speeds = "";
|
||||
net_download = 100;
|
||||
net_upload = 100;
|
||||
net_auto = true;
|
||||
net_sync = true;
|
||||
net_iface = "";
|
||||
show_battery = true;
|
||||
selected_battery = "Auto";
|
||||
log_level = "WARNING";
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "btop";
|
||||
moduleConfig = {
|
||||
programs.btop = {
|
||||
enable = true;
|
||||
settings = {
|
||||
truecolor = true;
|
||||
force_tty = false;
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty";
|
||||
vim_keys = true;
|
||||
rounded_corners = true;
|
||||
graph_symbol = "braille";
|
||||
graph_symbol_cpu = "default";
|
||||
graph_symbol_mem = "default";
|
||||
graph_symbol_net = "default";
|
||||
graph_symbol_proc = "default";
|
||||
shown_boxes = "cpu mem net proc";
|
||||
update_ms = 2000;
|
||||
proc_sorting = "cpu lazy";
|
||||
proc_reversed = false;
|
||||
proc_tree = false;
|
||||
proc_colors = true;
|
||||
proc_gradient = true;
|
||||
proc_per_core = false;
|
||||
proc_mem_bytes = true;
|
||||
proc_cpu_graphs = true;
|
||||
proc_info_smaps = false;
|
||||
proc_left = false;
|
||||
proc_filter_kernel = false;
|
||||
cpu_graph_upper = "total";
|
||||
cpu_graph_lower = "total";
|
||||
cpu_invert_lower = true;
|
||||
cpu_single_graph = false;
|
||||
cpu_bottom = false;
|
||||
show_uptime = true;
|
||||
check_temp = true;
|
||||
cpu_sensor = "Auto";
|
||||
show_coretemp = true;
|
||||
cpu_core_map = "";
|
||||
temp_scale = "celsius";
|
||||
base_10_sizes = false;
|
||||
show_cpu_freq = true;
|
||||
clock_format = "%X";
|
||||
background_update = true;
|
||||
custom_cpu_name = "";
|
||||
disks_filter = "";
|
||||
mem_graphs = true;
|
||||
mem_below_net = false;
|
||||
zfs_arc_cached = true;
|
||||
show_swap = true;
|
||||
swap_disk = true;
|
||||
show_disks = true;
|
||||
only_physical = true;
|
||||
use_fstab = true;
|
||||
zfs_hide_datasets = false;
|
||||
disk_free_priv = false;
|
||||
show_io_stat = true;
|
||||
io_mode = false;
|
||||
io_graph_combined = false;
|
||||
io_graph_speeds = "";
|
||||
net_download = 100;
|
||||
net_upload = 100;
|
||||
net_auto = true;
|
||||
net_sync = true;
|
||||
net_iface = "";
|
||||
show_battery = true;
|
||||
selected_battery = "Auto";
|
||||
log_level = "WARNING";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.btop = {
|
||||
enable = mkEnableOption "enable btop";
|
||||
};
|
||||
}
|
||||
24
modules/home/programs/calibre/default.nix
Executable file
24
modules/home/programs/calibre/default.nix
Executable file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "calibre";
|
||||
moduleConfig = {
|
||||
programs.calibre = {
|
||||
enable = true;
|
||||
plugins = with pkgs.${namespace}; [
|
||||
dedrm
|
||||
];
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
47
modules/home/programs/code/default.nix
Normal file → Executable file
47
modules/home/programs/code/default.nix
Normal file → Executable file
@@ -2,22 +2,19 @@
|
||||
config,
|
||||
pkgs,
|
||||
system,
|
||||
namespace,
|
||||
hasDestopEnvironment ? true,
|
||||
...
|
||||
}:
|
||||
let
|
||||
isArm = ("aarch64-linux" == system) || ("aarch64-darwin" == system);
|
||||
isDarwin = ("aarch64-darwin" == system);
|
||||
|
||||
x86_only = with pkgs; [
|
||||
vscode-extensions.redhat.vscode-xml
|
||||
];
|
||||
open-remote-ssh = pkgs.${namespace}.open-remote-ssh;
|
||||
in
|
||||
{
|
||||
home.packages = with pkgs; [
|
||||
nodePackages.nodejs
|
||||
nodejs_25
|
||||
uv
|
||||
];
|
||||
|
||||
@@ -50,27 +47,27 @@ in
|
||||
nix-vscode-extensions.open-vsx.jeanp413.open-remote-ssh
|
||||
]
|
||||
++ (if !isArm then x86_only else [ ]);
|
||||
# ++ (if !isDarwin then [ open-remote-ssh ] else [ ]);
|
||||
# ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
|
||||
# {
|
||||
# name = "copilot-mcp";
|
||||
# publisher = "automatalabs";
|
||||
# version = "0.0.49";
|
||||
# sha256 = "sha256-+G2OQl5SCN7bh7MzGdYiRclIZefBE7lWnGg1kNpCvnA=";
|
||||
# }
|
||||
# {
|
||||
# name = "mcp-server-runner";
|
||||
# publisher = "zebradev";
|
||||
# version = "0.1.0";
|
||||
# sha256 = "sha256-StydVt3VzQUSS/pYp76jnIwtZlEj8gWAGzOARs93J+E=";
|
||||
# }
|
||||
# {
|
||||
# name = "claude-dev";
|
||||
# publisher = "saoudrizwan";
|
||||
# version = "3.17.9";
|
||||
# sha256 = "sha256-y3bFtMe5vZrO3DFb31KDvkzjD2jM76wK89mKhgJXC70=";
|
||||
# }
|
||||
# ];
|
||||
# ++ (if !isDarwin then [ open-remote-ssh ] else [ ]);
|
||||
# ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
|
||||
# {
|
||||
# name = "copilot-mcp";
|
||||
# publisher = "automatalabs";
|
||||
# version = "0.0.49";
|
||||
# sha256 = "sha256-+G2OQl5SCN7bh7MzGdYiRclIZefBE7lWnGg1kNpCvnA=";
|
||||
# }
|
||||
# {
|
||||
# name = "mcp-server-runner";
|
||||
# publisher = "zebradev";
|
||||
# version = "0.1.0";
|
||||
# sha256 = "sha256-StydVt3VzQUSS/pYp76jnIwtZlEj8gWAGzOARs93J+E=";
|
||||
# }
|
||||
# {
|
||||
# name = "claude-dev";
|
||||
# publisher = "saoudrizwan";
|
||||
# version = "3.17.9";
|
||||
# sha256 = "sha256-y3bFtMe5vZrO3DFb31KDvkzjD2jM76wK89mKhgJXC70=";
|
||||
# }
|
||||
# ];
|
||||
|
||||
userSettings = {
|
||||
|
||||
|
||||
46
modules/home/programs/common/default-apps.nix
Executable file
46
modules/home/programs/common/default-apps.nix
Executable file
@@ -0,0 +1,46 @@
|
||||
# Shared defaultApps submodule options, used by both the hyprland and
|
||||
# nwg-panel modules. Import this file and pass the result as the `options`
|
||||
# argument to types.submodule to avoid duplicating the definition.
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
browser = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.firefox;
|
||||
description = "Default web browser";
|
||||
};
|
||||
editor = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.micro;
|
||||
description = "Default text editor";
|
||||
};
|
||||
fileExplorer = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.nautilus;
|
||||
description = "Default file explorer";
|
||||
};
|
||||
visual = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.vscodium;
|
||||
description = "Default visual/IDE editor";
|
||||
};
|
||||
terminal = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.kitty;
|
||||
description = "Default terminal emulator";
|
||||
};
|
||||
office = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.onlyoffice-desktopeditors;
|
||||
description = "Default office suite";
|
||||
};
|
||||
video = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.vlc;
|
||||
description = "Default video player";
|
||||
};
|
||||
imageViewer = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.nomacs;
|
||||
description = "Default image viewer";
|
||||
};
|
||||
}
|
||||
4
modules/home/programs/git/default.nix
Normal file → Executable file
4
modules/home/programs/git/default.nix
Normal file → Executable file
@@ -1,4 +1,3 @@
|
||||
{ ... }:
|
||||
let
|
||||
gitAliases = {
|
||||
co = "checkout";
|
||||
@@ -21,5 +20,8 @@ in
|
||||
};
|
||||
alias = gitAliases;
|
||||
};
|
||||
# The default value of `programs.git.signing.format` has changed from `"openpgp"` to `null`.
|
||||
# You are currently using the legacy default (`"openpgp"`) because `home.stateVersion` is less than "25.05".
|
||||
signing.format = "openpgp";
|
||||
};
|
||||
}
|
||||
|
||||
0
modules/home/programs/hyprland/avizo.nix
Normal file → Executable file
0
modules/home/programs/hyprland/avizo.nix
Normal file → Executable file
3
modules/home/programs/hyprland/default.nix
Normal file → Executable file
3
modules/home/programs/hyprland/default.nix
Normal file → Executable file
@@ -313,6 +313,7 @@ in
|
||||
secondMonitor = if builtins.length names > 1 then builtins.elemAt names 1 else firstMonitor;
|
||||
in
|
||||
{
|
||||
inherit (cfg) workspace;
|
||||
"$mod" = cfg.modKey;
|
||||
|
||||
# Mouse
|
||||
@@ -513,8 +514,6 @@ in
|
||||
preserve_split = "yes";
|
||||
};
|
||||
|
||||
workspace = cfg.workspace;
|
||||
|
||||
windowrule = [
|
||||
"match:title file_progress, float 1"
|
||||
"match:title .*[Cc]onfirm.*, float 1"
|
||||
|
||||
46
modules/home/programs/hyprland/options.nix
Normal file → Executable file
46
modules/home/programs/hyprland/options.nix
Normal file → Executable file
@@ -1,6 +1,5 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
@@ -158,50 +157,7 @@ with lib;
|
||||
};
|
||||
|
||||
defaultApps = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
browser = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.firefox;
|
||||
description = "Default browser";
|
||||
};
|
||||
editor = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.micro;
|
||||
description = "Default text editor";
|
||||
};
|
||||
fileExplorer = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.nautilus;
|
||||
description = "Default file explorer";
|
||||
};
|
||||
visual = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.vscodium;
|
||||
description = "Default visual editor";
|
||||
};
|
||||
terminal = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.kitty;
|
||||
description = "Default terminal";
|
||||
};
|
||||
office = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.onlyoffice-desktopeditors;
|
||||
description = "Default office suite";
|
||||
};
|
||||
video = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.vlc;
|
||||
description = "Default video player";
|
||||
};
|
||||
imageViewer = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.nomacs;
|
||||
description = "Default image viewer";
|
||||
};
|
||||
};
|
||||
};
|
||||
type = types.submodule (import ../common/default-apps.nix);
|
||||
description = "Default applications used across the system";
|
||||
};
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.programs.kitty;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.kitty = {
|
||||
enable = true;
|
||||
shellIntegration.enableZshIntegration = true;
|
||||
|
||||
settings = {
|
||||
bold_font = "auto";
|
||||
italic_font = "auto";
|
||||
bold_italic_font = "auto";
|
||||
mouse_hide_wait = "2.0";
|
||||
cursor_shape = "block";
|
||||
url_style = "dotted";
|
||||
confirm_os_window_close = "0";
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "kitty";
|
||||
moduleConfig = {
|
||||
programs.kitty = {
|
||||
enable = true;
|
||||
shellIntegration.enableZshIntegration = true;
|
||||
settings = {
|
||||
bold_font = "auto";
|
||||
italic_font = "auto";
|
||||
bold_italic_font = "auto";
|
||||
mouse_hide_wait = "2.0";
|
||||
cursor_shape = "block";
|
||||
url_style = "dotted";
|
||||
confirm_os_window_close = "0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.kitty = {
|
||||
enable = mkEnableOption "enable kitty terminal";
|
||||
};
|
||||
}
|
||||
1
modules/home/programs/librewolf/default.nix
Normal file → Executable file
1
modules/home/programs/librewolf/default.nix
Normal file → Executable file
@@ -1,4 +1,3 @@
|
||||
{ ... }:
|
||||
{
|
||||
programs.librewolf = {
|
||||
enable = false;
|
||||
|
||||
@@ -4,33 +4,37 @@
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.programs.mako;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
config = mkIf cfg.enable {
|
||||
services.mako = {
|
||||
enable = true;
|
||||
settings = {
|
||||
font = mkDefault cfg.fontName;
|
||||
icons = true;
|
||||
ignore-timeout = true;
|
||||
sort = "-time";
|
||||
width = 500;
|
||||
height = 110;
|
||||
layer = "overlay";
|
||||
border-radius = 15;
|
||||
border-size = 1;
|
||||
max-icon-size = 64;
|
||||
default-timeout = 5000;
|
||||
|
||||
# background-color = mkDefault config.lib.stylix.colors.base00;
|
||||
# text-color = mkDefault config.lib.stylix.colors.base06;
|
||||
# border-color = mkDefault config.lib.stylix.colors.base0F;
|
||||
# progress-color = mkDefault "over ${config.lib.stylix.colors.base0C}";
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "mako";
|
||||
options = {
|
||||
fontName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "DejaVu Sans";
|
||||
description = "Font name for mako notifications.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
moduleConfig = {
|
||||
services.mako = {
|
||||
enable = true;
|
||||
settings = {
|
||||
font = lib.mkDefault config.${namespace}.programs.mako.fontName;
|
||||
icons = true;
|
||||
ignore-timeout = true;
|
||||
sort = "-time";
|
||||
width = 500;
|
||||
height = 110;
|
||||
layer = "overlay";
|
||||
border-radius = 15;
|
||||
border-size = 1;
|
||||
max-icon-size = 64;
|
||||
default-timeout = 5000;
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.mako = {
|
||||
enable = mkEnableOption "enable mako";
|
||||
|
||||
fontName = mkOption {
|
||||
type = types.str;
|
||||
default = "DejaVu Sans";
|
||||
};
|
||||
};
|
||||
}
|
||||
225
modules/home/programs/nwg-dock/default.nix
Normal file → Executable file
225
modules/home/programs/nwg-dock/default.nix
Normal file → Executable file
@@ -5,134 +5,131 @@
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.programs.nwg-dock;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "nwg-dock";
|
||||
moduleConfig = {
|
||||
home.packages = with pkgs; [ nwg-dock-hyprland ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = with pkgs; [ nwg-dock-hyprland ];
|
||||
home.file = {
|
||||
".config/nwg-dock-hyprland/config.json".text = ''
|
||||
{
|
||||
"position": "bottom",
|
||||
"anchor": "center",
|
||||
"margin": 12,
|
||||
"icon_size": 48,
|
||||
"icon_size_hover": 64,
|
||||
"spacing": 6,
|
||||
"padding": 8,
|
||||
"autohide": false,
|
||||
"autohide_timeout": 0.3,
|
||||
"exclusive": true,
|
||||
"layer": "top",
|
||||
"height": 72,
|
||||
"background_alpha": 0.55,
|
||||
"rounded_corners": 16,
|
||||
"show_labels": false,
|
||||
"show_running": true,
|
||||
"show_pinned": true,
|
||||
"pinned": [
|
||||
"firefox.desktop",
|
||||
"org.wezfurlong.wezterm.desktop",
|
||||
"codium.desktop",
|
||||
"org.gnome.Nautilus.desktop"
|
||||
]
|
||||
}
|
||||
'';
|
||||
|
||||
home.file = {
|
||||
".config/nwg-dock-hyprland/config.json".text = ''
|
||||
{
|
||||
"position": "bottom",
|
||||
"anchor": "center",
|
||||
"margin": 12,
|
||||
"icon_size": 48,
|
||||
"icon_size_hover": 64,
|
||||
"spacing": 6,
|
||||
"padding": 8,
|
||||
"autohide": false,
|
||||
"autohide_timeout": 0.3,
|
||||
"exclusive": true,
|
||||
"layer": "top",
|
||||
"height": 72,
|
||||
"background_alpha": 0.55,
|
||||
"rounded_corners": 16,
|
||||
"show_labels": false,
|
||||
"show_running": true,
|
||||
"show_pinned": true,
|
||||
"pinned": [
|
||||
"firefox.desktop",
|
||||
"org.wezfurlong.wezterm.desktop",
|
||||
"codium.desktop",
|
||||
"org.gnome.Nautilus.desktop"
|
||||
]
|
||||
}
|
||||
'';
|
||||
".config/nwg-dock-hyprland/style.css".text = ''
|
||||
window {
|
||||
background: #36364f;
|
||||
border-radius: 10px;
|
||||
border-style: none;
|
||||
border-width: 1px;
|
||||
border-color: rgba(156, 142, 122, 0.7)
|
||||
}
|
||||
|
||||
".config/nwg-dock-hyprland/style.css".text = ''
|
||||
window {
|
||||
background: #36364f;
|
||||
border-radius: 10px;
|
||||
border-style: none;
|
||||
border-width: 1px;
|
||||
border-color: rgba(156, 142, 122, 0.7)
|
||||
}
|
||||
#box {
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
#box {
|
||||
/* Define attributes of the box surrounding icons here */
|
||||
padding: 10px
|
||||
}
|
||||
#active {
|
||||
border-bottom: solid 1px;
|
||||
border-color: rgba(255, 255, 255, 0.3)
|
||||
}
|
||||
|
||||
#active {
|
||||
/* This is to underline the button representing the currently active window */
|
||||
border-bottom: solid 1px;
|
||||
border-color: rgba(255, 255, 255, 0.3)
|
||||
}
|
||||
button, image {
|
||||
background: none;
|
||||
border-style: none;
|
||||
box-shadow: none;
|
||||
color: #999
|
||||
}
|
||||
|
||||
button, image {
|
||||
background: none;
|
||||
border-style: none;
|
||||
box-shadow: none;
|
||||
color: #999
|
||||
}
|
||||
button {
|
||||
padding: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
color: #eee;
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
color: #eee;
|
||||
font-size: 12px
|
||||
}
|
||||
button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 2px;
|
||||
}
|
||||
button:focus {
|
||||
box-shadow: none
|
||||
}
|
||||
'';
|
||||
|
||||
button:focus {
|
||||
box-shadow: none
|
||||
}
|
||||
'';
|
||||
".config/nwg-dock-hyprland/drawer.css".text = ''
|
||||
window {
|
||||
background: ${config.lib.stylix.colors.base00};
|
||||
border-radius: 10px;
|
||||
border-style: none;
|
||||
border-width: 1px;
|
||||
border-color: ${config.lib.stylix.colors.base0E}b0
|
||||
}
|
||||
|
||||
".config/nwg-dock-hyprland/drawer.css".text = ''
|
||||
window {
|
||||
background: ${config.lib.stylix.colors.base00};
|
||||
border-radius: 10px;
|
||||
border-style: none;
|
||||
border-width: 1px;
|
||||
border-color: ${config.lib.stylix.colors.base0E}b0
|
||||
}
|
||||
#box {
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
#box {
|
||||
/* Define attributes of the box surrounding icons here */
|
||||
padding: 10px
|
||||
}
|
||||
active {
|
||||
border-bottom: solid 1px;
|
||||
border-color: ${config.lib.stylix.colors.base0B}1a
|
||||
}
|
||||
|
||||
active {
|
||||
/* This is to underline the button representing the currently active window */
|
||||
border-bottom: solid 1px;
|
||||
border-color: ${config.lib.stylix.colors.base0B}1a
|
||||
}
|
||||
button, image {
|
||||
background: none;
|
||||
border-style: none;
|
||||
box-shadow: none;
|
||||
color: ${config.lib.stylix.colors.base0F}
|
||||
}
|
||||
|
||||
button, image {
|
||||
background: none;
|
||||
border-style: none;
|
||||
box-shadow: none;
|
||||
color: ${config.lib.stylix.colors.base0F}
|
||||
}
|
||||
button {
|
||||
padding: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
color: #eee;
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
color: #eee;
|
||||
font-size: 12px
|
||||
}
|
||||
button:hover {
|
||||
background-color: ${config.lib.stylix.colors.base00}1a;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: ${config.lib.stylix.colors.base00}1a;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
box-shadow: none
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
button:focus {
|
||||
box-shadow: none
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.nwg-dock = {
|
||||
enable = mkEnableOption "enable nwg-dock";
|
||||
};
|
||||
}
|
||||
79
modules/home/programs/nwg-drawer/default.nix
Normal file → Executable file
79
modules/home/programs/nwg-drawer/default.nix
Normal file → Executable file
@@ -5,53 +5,50 @@
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.programs.nwg-drawer;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
imports = [
|
||||
(lib.${namespace}.mkHomeModule {
|
||||
inherit config;
|
||||
domain = "programs";
|
||||
name = "nwg-drawer";
|
||||
moduleConfig = {
|
||||
home.packages = with pkgs; [ nwg-drawer ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = with pkgs; [ nwg-drawer ];
|
||||
home.file.".config/nwg-drawer/drawer.css".text = ''
|
||||
window {
|
||||
background-color: ${config.lib.stylix.colors.base00}bf;
|
||||
color: ${config.lib.stylix.colors.base05}00
|
||||
}
|
||||
|
||||
home.file = {
|
||||
".config/nwg-drawer/drawer.css".text = ''
|
||||
window {
|
||||
background-color: ${config.lib.stylix.colors.base00}bf;
|
||||
color: ${config.lib.stylix.colors.base05}00
|
||||
}
|
||||
entry {
|
||||
background-color: ${config.lib.stylix.colors.base01}0f
|
||||
}
|
||||
|
||||
/* search entry */
|
||||
entry {
|
||||
background-color: ${config.lib.stylix.colors.base01}0f
|
||||
}
|
||||
button, image {
|
||||
background: none;
|
||||
border: none
|
||||
}
|
||||
|
||||
button, image {
|
||||
background: none;
|
||||
border: none
|
||||
}
|
||||
button:hover {
|
||||
background-color: ${config.lib.stylix.colors.base0F}1a
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: ${config.lib.stylix.colors.base0F}1a
|
||||
}
|
||||
#category-button {
|
||||
margin: 0 10px 0 10px
|
||||
}
|
||||
|
||||
/* in case you wanted to give category buttons a different look */
|
||||
#category-button {
|
||||
margin: 0 10px 0 10px
|
||||
}
|
||||
#pinned-box {
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px dotted ${config.lib.stylix.colors.base03}
|
||||
}
|
||||
|
||||
#pinned-box {
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px dotted ${config.lib.stylix.colors.base03}
|
||||
}
|
||||
|
||||
#files-box {
|
||||
padding: 5px;
|
||||
border: 1px dotted ${config.lib.stylix.colors.base03};
|
||||
border-radius: 15px
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
#files-box {
|
||||
padding: 5px;
|
||||
border: 1px dotted ${config.lib.stylix.colors.base03};
|
||||
border-radius: 15px
|
||||
}
|
||||
'';
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.nwg-drawer = {
|
||||
enable = mkEnableOption "enable nwg-drawer";
|
||||
};
|
||||
}
|
||||
0
modules/home/programs/nwg-panel/default.nix
Normal file → Executable file
0
modules/home/programs/nwg-panel/default.nix
Normal file → Executable file
43
modules/home/programs/nwg-panel/options.nix
Normal file → Executable file
43
modules/home/programs/nwg-panel/options.nix
Normal file → Executable file
@@ -1,51 +1,14 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.programs.nwg-panel = {
|
||||
enable = mkEnableOption "enable nwg-panel";
|
||||
enable = lib.mkEnableOption "nwg-panel";
|
||||
|
||||
defaultApps = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
browser = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.firefox;
|
||||
};
|
||||
editor = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.micro;
|
||||
};
|
||||
fileExplorer = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.nautilus;
|
||||
};
|
||||
visual = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.vscodium;
|
||||
};
|
||||
terminal = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.kitty;
|
||||
};
|
||||
office = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.onlyoffice-desktopeditors;
|
||||
};
|
||||
video = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.vlc;
|
||||
};
|
||||
imageViewer = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.gnome-photos;
|
||||
};
|
||||
};
|
||||
};
|
||||
defaultApps = lib.mkOption {
|
||||
type = lib.types.submodule (import ../common/default-apps.nix);
|
||||
description = "Default applications used across the system.";
|
||||
};
|
||||
};
|
||||
|
||||
0
modules/home/programs/onlyoffice/default.nix
Normal file → Executable file
0
modules/home/programs/onlyoffice/default.nix
Normal file → Executable file
88
modules/home/programs/opencode/default.nix
Executable file
88
modules/home/programs/opencode/default.nix
Executable file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.programs.opencode;
|
||||
net = lib.${namespace}.network;
|
||||
in
|
||||
{
|
||||
options.${namespace}.programs.opencode = {
|
||||
enable = lib.mkEnableOption "opencode";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
sops.secrets."hass-mcp/token" = { };
|
||||
|
||||
sops.templates."hass-mcp.env" = {
|
||||
mode = "0600";
|
||||
content = ''
|
||||
HA_URL=http://${net.hosts.nuc.lan}:${toString net.ports.nuc.homeAssistant}
|
||||
HA_TOKEN=${config.sops.placeholder."hass-mcp/token"}
|
||||
'';
|
||||
};
|
||||
|
||||
programs.opencode = {
|
||||
enable = true;
|
||||
enableMcpIntegration = true;
|
||||
settings = {
|
||||
provider = {
|
||||
nas = {
|
||||
npm = "@ai-sdk/openai-compatible";
|
||||
name = "llama-server (local)";
|
||||
options = {
|
||||
baseURL = "http://${net.hosts.nas.lan}:${toString net.ports.nas.llamaCpp}/v1";
|
||||
};
|
||||
models = {
|
||||
"gemma-4-26B-A4B-it-UD-Q8_K_XL" = {
|
||||
name = "Gemma 4 26B-A4B (local)";
|
||||
modalities = {
|
||||
input = [
|
||||
"image"
|
||||
"text"
|
||||
];
|
||||
output = [ "text" ];
|
||||
};
|
||||
limit = {
|
||||
context = 32768;
|
||||
output = 8192;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
nixos = {
|
||||
command = "nix";
|
||||
args = [
|
||||
"run"
|
||||
"github:utensils/mcp-nixos"
|
||||
"--"
|
||||
];
|
||||
};
|
||||
hass-mcp = {
|
||||
command = "bash";
|
||||
args = [
|
||||
"-c"
|
||||
"set -a; source ${config.sops.templates."hass-mcp.env".path}; set +a; exec uvx hass-mcp"
|
||||
];
|
||||
};
|
||||
mcp-server-code-runner = {
|
||||
command = "${pkgs.nodejs_24}/bin/npm";
|
||||
args = [
|
||||
"-y"
|
||||
"@iflow-mcp/mcp-server-code-runner"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
9
modules/home/programs/password-store/default.nix
Executable file
9
modules/home/programs/password-store/default.nix
Executable file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
# The default value of `programs.password-store.settings` has changed from `{ PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store"; }` to `{ }`.
|
||||
# You are currently using the legacy default (`{ PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store"; }`) because `home.stateVersion` is less than "25.11".
|
||||
# To silence this warning and keep legacy behavior, set:
|
||||
# programs.password-store.settings = { PASSWORD_STORE_DIR = "$XDG_DATA_HOME/password-store"; };
|
||||
programs.password-store = {
|
||||
settings = { };
|
||||
};
|
||||
}
|
||||
29
modules/home/programs/thunderbird/default.nix
Executable file
29
modules/home/programs/thunderbird/default.nix
Executable file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.programs.thunderbird;
|
||||
in
|
||||
{
|
||||
options.${namespace}.programs.thunderbird = {
|
||||
enable = lib.mkEnableOption "thunderbird";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.thunderbird = {
|
||||
enable = true;
|
||||
profiles = {
|
||||
mjallen = {
|
||||
isDefault = true;
|
||||
accountsOrder = [
|
||||
"gmail"
|
||||
"protonmail"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
3
modules/home/programs/update-checker/default.nix
Normal file → Executable file
3
modules/home/programs/update-checker/default.nix
Normal file → Executable file
@@ -1,6 +1,5 @@
|
||||
{
|
||||
config,
|
||||
namespace,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
@@ -273,7 +272,7 @@ in
|
||||
config = {
|
||||
|
||||
sops = {
|
||||
age.keyFile = "/home/${config.${namespace}.user.name}/.config/sops/age/keys.txt";
|
||||
age.keyFile = "/home/${config.home.username}/.config/sops/age/keys.txt";
|
||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||
validateSopsFiles = false;
|
||||
secrets = {
|
||||
|
||||
51
modules/home/programs/vencord/default.nix
Normal file
51
modules/home/programs/vencord/default.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.${namespace}.programs.vesktop;
|
||||
in
|
||||
{
|
||||
options.${namespace}.programs.vesktop = {
|
||||
enable = lib.mkEnableOption "vesktop";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.vesktop = {
|
||||
enable = true;
|
||||
settings = {
|
||||
appBadge = false;
|
||||
arRPC = true;
|
||||
checkUpdates = false;
|
||||
customTitleBar = false;
|
||||
disableMinSize = true;
|
||||
minimizeToTray = true;
|
||||
tray = true;
|
||||
splashBackground = "#000000";
|
||||
splashColor = "#ffffff";
|
||||
splashTheming = true;
|
||||
staticTitle = true;
|
||||
hardwareAcceleration = true;
|
||||
discordBranch = "stable";
|
||||
};
|
||||
vencord = {
|
||||
settings = {
|
||||
autoUpdate = false;
|
||||
autoUpdateNotification = false;
|
||||
notifyAboutUpdates = false;
|
||||
useQuickCss = true;
|
||||
disableMinSize = true;
|
||||
plugins = {
|
||||
MessageLogger = {
|
||||
enabled = false;
|
||||
ignoreSelf = true;
|
||||
};
|
||||
FakeNitro.enabled = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -294,10 +294,10 @@ in
|
||||
systemd.enable = true;
|
||||
|
||||
settings = {
|
||||
mainBar = (
|
||||
mainBar =
|
||||
(mkMerge [
|
||||
{
|
||||
layer = cfg.layer;
|
||||
inherit (cfg) layer;
|
||||
position = "top";
|
||||
mod = "dock";
|
||||
exclusive = true;
|
||||
@@ -342,7 +342,7 @@ in
|
||||
};
|
||||
|
||||
network = {
|
||||
interface = cfg.network.interface;
|
||||
inherit (cfg.network) interface;
|
||||
on-click = "nm-connection-editor";
|
||||
format = "{icon}";
|
||||
tooltip-format = "{ifname} via {gwaddr} ";
|
||||
@@ -589,8 +589,7 @@ in
|
||||
};
|
||||
})
|
||||
])
|
||||
// cfg.extra.settings
|
||||
);
|
||||
// cfg.extra.settings;
|
||||
}
|
||||
// cfg.extraModules; # keep legacy top-level extra modules for compatibility
|
||||
|
||||
|
||||
0
modules/home/programs/waybar/options.nix
Normal file → Executable file
0
modules/home/programs/waybar/options.nix
Normal file → Executable file
0
modules/home/programs/waybar/scripts/audio-control.nix
Normal file → Executable file
0
modules/home/programs/waybar/scripts/audio-control.nix
Normal file → Executable file
0
modules/home/programs/waybar/scripts/media.nix
Normal file → Executable file
0
modules/home/programs/waybar/scripts/media.nix
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user