Upgrade to Nix 25.11 and migrate configs
All checks were successful
Ansible Lint Check / check-ansible (push) Successful in 7s
Nix Format Check / check-format (push) Successful in 43s
Python Lint Check / check-python (push) Successful in 7s

Update flake inputs and flake.lock to Nix/nixpkgs and home-manager
release 25.11; bump home.stateVersion and setup script NIXOS_RELEASE.

Migrate git config to new Home Manager layout (programs.git.settings,
aliases under settings.alias), adjust delta config path, and reorganize
SSH into matchBlocks with enableDefaultConfig=false to avoid global
leaks. Simplify snapd session variable handling to avoid recursion.

Misc: tweak Dashy title, replace du-dust->dust and plex-media-player ->
plex-desktop, remove unused hostname arg, and add GitHub Copilot
instructions document.
This commit is contained in:
2025-12-11 16:28:22 +01:00
parent cc359274bc
commit 2947ea8060
11 changed files with 181 additions and 111 deletions

71
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,71 @@
# GitHub Copilot Instructions
## Project Overview
This repository manages system configurations (dotfiles) using a hybrid approach:
- **Nix (Home Manager):** Manages user environment, CLI tools, and dotfile symlinks.
- **Ansible:** Manages system-level configurations, services (Docker containers), and secrets.
- **Python (`dotf`):** A custom CLI wrapper to orchestrate updates and maintenance.
## Architecture
### Nix & Home Manager
- **Entry Point:** `flake.nix` defines `homeConfigurations` for each host (e.g., `mennos-desktop`, `mennos-server`).
- **Configuration:** `home.nix` is the main module, conditionally importing from `packages/` and `server/` or `workstation/` based on the `isServer` flag.
- **Packages:** Defined in `packages/{common,server,workstation}/packages.nix`.
### Ansible
- **Playbook:** `ansible/playbook.yml` is the main entry point.
- **Inventory:** `ansible/inventory.ini` defines host groups (`workstations`, `servers`). All connections are `local`.
- **Tasks:** Organized in `ansible/tasks/`:
- `global/`: Applied to all hosts.
- `servers/`: Applied to server hosts.
- `workstations/`: Applied to workstation hosts.
- **Services:** Docker services are defined in `ansible/tasks/servers/services/`.
### CLI Tool (`dotf`)
- **Location:** `bin/dotf` (entry point) and `bin/actions/` (logic).
- **Purpose:** Abstracts complex `home-manager` and `ansible-playbook` commands.
## Critical Workflows
### Applying Changes
Do not run `home-manager` or `ansible-playbook` directly unless debugging. Use the `dotf` CLI:
- **Update everything:** `dotf update`
- **Update only Home Manager:** `dotf update --ha`
- **Update only Ansible:** `dotf update --ansible`
- **Run specific Ansible tags:** `dotf update --tags <tag_name>` (e.g., `dotf update --tags caddy`)
### Adding Packages
1. Identify if the package is for `common`, `server`, or `workstation`.
2. Edit the corresponding `packages/<type>/packages.nix`.
3. Add the package name to the `home.packages` list.
### Adding Services (Servers)
1. Create a new YAML file in `ansible/tasks/servers/services/<service_name>/`.
2. Define the Docker container and related configuration.
3. Ensure the task is imported in `ansible/tasks/servers/server.yml` (or the relevant parent file).
## Conventions & Patterns
- **Secrets:** Use 1Password integration. Secrets are fetched via the custom lookup plugin or `op` CLI.
- **Host-Specific Logic:**
- **Nix:** Use the `isServer` argument or check `hostname` in modules.
- **Ansible:** Use `when: inventory_hostname in [...]` or group-based imports in `playbook.yml`.
- **Path References:** Use `{{ playbook_dir }}` in Ansible and relative paths in Nix.
- **Python Scripts:** Located in `bin/`, use `helpers.functions` for common output formatting (`printfe`).
## Key Files
- `flake.nix`: Host definitions.
- `home.nix`: Main Home Manager config.
- `ansible/playbook.yml`: Main Ansible playbook.
- `bin/actions/update.py`: The update logic implementation.

View File

@@ -30,8 +30,7 @@ sections:
url: https://drive.mvl.sh
id: 3_1035_nxtcld
statusCheck: true
- title: ComfyUI
icon: http://mennos-server:8188/assets/favicon.ico
- title: SD.Next / ComfyUI
url: http://mennos-server:8188
statusCheckUrl: http://host.docker.internal:8188/api/system_stats
id: 3_1035_comfyui

View File

@@ -1,6 +1,5 @@
{
config,
pkgs,
lib,
...
}:
@@ -10,14 +9,17 @@
enable = true;
# Basic configuration
userName = "Menno van Leeuwen";
userEmail = "menno@vleeuwen.me";
signing = lib.mkIf (!config.isServer) {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM+sKpcREOUjwMMSzEWAso6830wbOi8kUxqpuXWw5gHr";
};
# Git settings
extraConfig = {
# Git settings (migrated to `programs.git.settings` for Nix 25.11+)
settings = {
user = {
name = "Menno van Leeuwen";
email = "menno@vleeuwen.me";
};
init = {
defaultBranch = "main";
};
@@ -108,93 +110,93 @@
protocol = {
version = 2;
};
};
# Git aliases
aliases = {
# Status and info
st = "status -sb";
s = "status";
stat = "status";
# Git aliases moved under `settings.alias` per Nix 25.11
alias = {
# Status and info
st = "status -sb";
s = "status";
stat = "status";
# Logging
l = "log --oneline --graph --decorate";
ll = "log --graph --pretty=format:'%C(yellow)%h%Creset -%C(red)%d%Creset %s %C(green)(%cr) %C(blue)<%an>%Creset' --abbrev-commit --date=relative";
lol = "log --graph --decorate --pretty=oneline --abbrev-commit";
lola = "log --graph --decorate --pretty=oneline --abbrev-commit --all";
hist = "log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short";
# Logging
l = "log --oneline --graph --decorate";
ll = "log --graph --pretty=format:'%C(yellow)%h%Creset -%C(red)%d%Creset %s %C(green)(%cr) %C(blue)<%an>%Creset' --abbrev-commit --date=relative";
lol = "log --graph --decorate --pretty=oneline --abbrev-commit";
lola = "log --graph --decorate --pretty=oneline --abbrev-commit --all";
hist = "log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short";
# Diff
d = "diff";
dc = "diff --cached";
ds = "diff --staged";
dt = "difftool";
# Diff
d = "diff";
dc = "diff --cached";
ds = "diff --staged";
dt = "difftool";
# Add and commit
a = "add";
aa = "add -A";
ap = "add -p";
c = "commit";
cm = "commit -m";
ca = "commit -am";
amend = "commit --amend";
# Add and commit
a = "add";
aa = "add -A";
ap = "add -p";
c = "commit";
cm = "commit -m";
ca = "commit -am";
amend = "commit --amend";
# Checkout and branch
co = "checkout";
cb = "checkout -b";
br = "branch";
bra = "branch -a";
bd = "branch -d";
bdd = "branch -D";
# Checkout and branch
co = "checkout";
cb = "checkout -b";
br = "branch";
bra = "branch -a";
bd = "branch -d";
bdd = "branch -D";
# Remote
r = "remote";
rv = "remote -v";
# Remote
r = "remote";
rv = "remote -v";
# Push and pull
p = "push";
pf = "push --force-with-lease";
pu = "push -u origin";
pl = "pull";
pom = "push origin main";
plom = "pull origin main";
# Push and pull
p = "push";
pf = "push --force-with-lease";
pu = "push -u origin";
pl = "pull";
pom = "push origin main";
plom = "pull origin main";
# Reset and clean
unstage = "reset HEAD --";
undo = "reset --soft HEAD~1";
undohard = "reset --hard HEAD~1";
clean-branches = "!git branch --merged | grep -v '\\*\\|master\\|main\\|develop' | xargs -n 1 git branch -d";
# Reset and clean
unstage = "reset HEAD --";
undo = "reset --soft HEAD~1";
undohard = "reset --hard HEAD~1";
clean-branches = "!git branch --merged | grep -v '\\*\\|master\\|main\\|develop' | xargs -n 1 git branch -d";
# Stash
ss = "stash save";
sp = "stash pop";
sl = "stash list";
sd = "stash drop";
# Stash
ss = "stash save";
sp = "stash pop";
sl = "stash list";
sd = "stash drop";
# Tags
tags = "tag -l";
# Tags
tags = "tag -l";
# Show
show-files = "show --pretty=\"\" --name-only";
# Show
show-files = "show --pretty=\"\" --name-only";
# Worktree
wt = "worktree";
# Worktree
wt = "worktree";
# Maintenance
cleanup = "!git remote prune origin && git gc && git clean -df && git stash clear";
# Maintenance
cleanup = "!git remote prune origin && git gc && git clean -df && git stash clear";
# Find
find = "!git ls-files | grep -i";
grep = "grep -Ii";
# Find
find = "!git ls-files | grep -i";
grep = "grep -Ii";
# Contributors
contributors = "shortlog --summary --numbered --email";
# Contributors
contributors = "shortlog --summary --numbered --email";
# Current branch
current = "rev-parse --abbrev-ref HEAD";
# Current branch
current = "rev-parse --abbrev-ref HEAD";
# Ignore
ignore = "!gi() { curl -sL https://www.toptal.com/developers/gitignore/api/$@ ;}; gi";
# Ignore
ignore = "!gi() { curl -sL https://www.toptal.com/developers/gitignore/api/$@ ;}; gi";
};
};
# Global gitignore
@@ -246,7 +248,7 @@
};
# Delta for better git diffs
programs.git.delta = {
programs.delta = {
enable = true;
options = {
features = "decorations";

View File

@@ -3,14 +3,20 @@
{
programs.ssh = {
enable = true;
compression = true;
serverAliveInterval = 60;
serverAliveCountMax = 3;
enableDefaultConfig = false;
# SSH Multiplexing - reuses existing SSH connections for multiple sessions, reducing authentication overhead and improving speed for subsequent logins.
controlPath = "~/.ssh/master-%r@%n:%p";
controlMaster = "auto";
controlPersist = "600";
matchBlocks = {
"*" = {
compression = true;
serverAliveInterval = 60;
serverAliveCountMax = 3;
# SSH Multiplexing - reuses existing SSH connections for multiple sessions, reducing authentication overhead and improving speed for subsequent logins.
controlPath = "~/.ssh/master-%r@%n:%p";
controlMaster = "auto";
controlPersist = "600";
};
};
# Include custom configs from 1Password (See packages/common/secrets.nix)
includes = [

16
flake.lock generated
View File

@@ -25,32 +25,32 @@
]
},
"locked": {
"lastModified": 1763992789,
"narHash": "sha256-WHkdBlw6oyxXIra/vQPYLtqY+3G8dUVZM8bEXk0t8x4=",
"lastModified": 1765384171,
"narHash": "sha256-FuFtkJrW1Z7u+3lhzPRau69E0CNjADku1mLQQflUORo=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "44831a7eaba4360fb81f2acc5ea6de5fde90aaa3",
"rev": "44777152652bc9eacf8876976fa72cc77ca8b9d8",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-25.05",
"ref": "release-25.11",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1765363881,
"narHash": "sha256-3C3xWn8/2Zzr7sxVBmpc1H1QfxjNfta5IMFe3O9ZEPw=",
"lastModified": 1765311797,
"narHash": "sha256-mSD5Ob7a+T2RNjvPvOA1dkJHGVrNVl8ZOrAwBjKBDQo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d2b1213bf5ec5e62d96b003ab4b5cbc42abfc0d0",
"rev": "09eb77e94fa25202af8f3e81ddc7353d9970ac1b",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.05",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}

View File

@@ -2,9 +2,9 @@
description = "menno's dotfiles";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
home-manager = {
url = "github:nix-community/home-manager/release-25.05";
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
opnix.url = "github:brizzbuzz/opnix";

View File

@@ -45,7 +45,7 @@
home = {
username = "menno";
homeDirectory = "/home/menno";
stateVersion = "25.05";
stateVersion = "25.11";
sessionVariables = {
PATH = "${config.home.homeDirectory}/go/bin:$PATH";
DOTFILES_PATH = "${config.home.homeDirectory}/.dotfiles";

View File

@@ -1,6 +1,5 @@
{
pkgs,
hostname,
...
}:
{
@@ -31,7 +30,7 @@
eza # Modern ls
bat # Modern cat
broot # Interactive directory navigator
du-dust # Modern du
dust # Modern du
duf # Modern df
zip
unzip

View File

@@ -26,7 +26,7 @@ in
scrcpy
## Multimedia
plex-media-player
plex-desktop
vlc
## Astronomy

View File

@@ -4,7 +4,7 @@ set -euo pipefail
IFS=$'\n\t'
# Constants
readonly NIXOS_RELEASE="25.05" # Home Manager release version (Must match NixOS version)
readonly NIXOS_RELEASE="25.11" # Home Manager release version (Must match NixOS version)
readonly GIT_REPO="https://git.mvl.sh/vleeuwenmenno/dotfiles.git" # Dotfiles repository URL
readonly DOTFILES_PATH="${HOME}/.dotfiles" # Dotfiles directory
readonly SETUP_MARKER="${HOME}/.dotfiles-setup" # Setup marker file indicates setup has been run

View File

@@ -1,17 +1,10 @@
{ config, lib, ... }:
let
# Merge our session variable into any existing ones, if present.
existingSessionVars = config.home.sessionVariables or {};
sessionVars = existingSessionVars // {
# Prepend snap desktop dir so snap-provided .desktop files are discovered by desktop environments.
# We include `$XDG_DATA_DIRS` to preserve any previously-set value at runtime.
XDG_DATA_DIRS = "/var/lib/snapd/desktop:$XDG_DATA_DIRS";
};
in
{
config = {
# Use mkForce to ensure this module's value takes precedence when modules are merged.
home.sessionVariables = lib.mkForce sessionVars;
# Prepend snap desktop dir so snap-provided .desktop files are discovered by desktop environments.
# We include `$XDG_DATA_DIRS` to preserve any previously-set value at runtime.
# Avoid reading `config.home.sessionVariables` here to prevent evaluation recursion.
home.sessionVariables.XDG_DATA_DIRS = "/var/lib/snapd/desktop:$XDG_DATA_DIRS";
};
}