diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..be214fb --- /dev/null +++ b/.github/copilot-instructions.md @@ -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 ` (e.g., `dotf update --tags caddy`) + +### Adding Packages + +1. Identify if the package is for `common`, `server`, or `workstation`. +2. Edit the corresponding `packages//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//`. +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. diff --git a/ansible/tasks/servers/services/dashy/conf.yml.j2 b/ansible/tasks/servers/services/dashy/conf.yml.j2 index c4c9bc2..4cb6929 100644 --- a/ansible/tasks/servers/services/dashy/conf.yml.j2 +++ b/ansible/tasks/servers/services/dashy/conf.yml.j2 @@ -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 diff --git a/config/git.nix b/config/git.nix index 47a9467..eff0df1 100644 --- a/config/git.nix +++ b/config/git.nix @@ -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"; diff --git a/config/ssh.nix b/config/ssh.nix index 92a7d81..28ab7a0 100644 --- a/config/ssh.nix +++ b/config/ssh.nix @@ -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 = [ diff --git a/flake.lock b/flake.lock index d52beee..f51eb20 100644 --- a/flake.lock +++ b/flake.lock @@ -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" } diff --git a/flake.nix b/flake.nix index 040f361..0082d90 100644 --- a/flake.nix +++ b/flake.nix @@ -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"; diff --git a/home.nix b/home.nix index d4d93ef..4f4896f 100644 --- a/home.nix +++ b/home.nix @@ -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"; diff --git a/packages/common/packages.nix b/packages/common/packages.nix index 73bbb2b..69a8116 100644 --- a/packages/common/packages.nix +++ b/packages/common/packages.nix @@ -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 diff --git a/packages/workstation/packages.nix b/packages/workstation/packages.nix index 34c863d..e544be6 100644 --- a/packages/workstation/packages.nix +++ b/packages/workstation/packages.nix @@ -26,7 +26,7 @@ in scrcpy ## Multimedia - plex-media-player + plex-desktop vlc ## Astronomy diff --git a/setup.sh b/setup.sh index 44d9cf2..c8bfbc1 100755 --- a/setup.sh +++ b/setup.sh @@ -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 diff --git a/workstation/snapd.nix b/workstation/snapd.nix index e7b888b..9dbb362 100644 --- a/workstation/snapd.nix +++ b/workstation/snapd.nix @@ -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"; }; }