aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/nix/common.nix
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-20 13:56:09 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-20 13:56:09 +0100
commitde5146c7976e1fb38e8d1f82c30544462d881100 (patch)
tree2de6f2358d6b83b2f64b68fe105ed11d4ff0feea /nix/common.nix
parent52e53ad7956f637af3bb87de79934bfda4b74a2e (diff)
downloaddotfiles-de5146c7976e1fb38e8d1f82c30544462d881100.tar.gz
dotfiles-de5146c7976e1fb38e8d1f82c30544462d881100.tar.bz2
dotfiles-de5146c7976e1fb38e8d1f82c30544462d881100.zip
refactor(nix): promote remote-dev/ to nix/ with common/vm/host split
Restructures the Home-Manager profile to support both the Arch host and the Ubuntu remote-dev VM from the same flake. - remote-dev/ → nix/ (hard rename; .chezmoiignore updated) - home.nix split into common.nix (shared), vm.nix (Mason runtime carve-outs + podman stack), host.nix (gpg scdaemon delegation to system pcscd) - flake.nix exposes homeConfigurations.{vm,host} via a mkProfile helper - rj alias in dot_zshrc updated to ~/.local/share/dotfiles/nix - bootstrap.sh / justfile updated to use #vm against the new path The split is behaviour-preserving for the VM: vm.nix + common.nix together carry the same package set as the previous home.nix. host.nix is provisioned but not yet wired into bootstrap (phase p8). Phase 1 of the nix-on-host migration plan.
Diffstat (limited to 'nix/common.nix')
-rw-r--r--nix/common.nix160
1 files changed, 160 insertions, 0 deletions
diff --git a/nix/common.nix b/nix/common.nix
new file mode 100644
index 0000000..b6a8493
--- /dev/null
+++ b/nix/common.nix
@@ -0,0 +1,160 @@
+{ config, pkgs, lib, dotfilesRoot, ... }:
+
+# Shared Home-Manager module: the leaf-CLI subset, editor/AI-agent
+# runtimes, and the shared dotfiles symlinks used by **both** the Arch
+# host and the Ubuntu remote-dev VM. Profile-specific extras live in
+# `host.nix` and `vm.nix`.
+#
+# Policy: this profile carries leaf CLI tools plus editor/AI-agent
+# runtimes (node, uv). It must NEVER carry anything the project build
+# might invoke. Forbidden on PATH (would shadow the system's and break
+# builds against the system sysroot/libc): cc, c++, gcc, g++, clang,
+# clang++, ld, ld.lld, ar, nm, objcopy, make, cmake, ninja, meson,
+# pkg-config, autoconf, automake, libtool, python, python3, pip,
+# cargo, rustc, go. If a project needs a newer toolchain, put it in a
+# project-local flake.nix + direnv `.envrc`, NOT here.
+#
+# Allowed runtimes (used only by editor/AI agents): node, npm, npx
+# (via `nodejs`), uv, uvx (via `uv` — does NOT install a python3,
+# manages its own interpreters under XDG). `clang-tools` is allowed
+# because it ships only formatters/linters/clangd, no compiler driver.
+
+let
+ dotfiles = "${config.home.homeDirectory}/.local/share/dotfiles";
+ link = path: config.lib.file.mkOutOfStoreSymlink "${dotfiles}/${path}";
+in
+{
+ home.stateVersion = "25.05";
+
+ # ── Packages ────────────────────────────────────────────────────────────────
+ home.packages = with pkgs; [
+ # Editor + multiplexer
+ neovim
+ zellij
+ tree-sitter
+
+ # Search / move
+ ripgrep
+ fd
+ fzf
+ sd
+ choose
+ zoxide
+ just
+
+ # Viewers
+ bat
+ lsd
+ glow
+
+ # Git stack
+ git
+ gh
+ delta
+ mergiraf
+
+ # JSON / YAML
+ jq
+ yq-go
+
+ # System
+ htop
+ fastfetch
+
+ # Net
+ curl
+ curlie
+ wget
+ dog
+ rsync
+ openssh
+
+ # Docs
+ tldr
+ man-db
+ man-pages
+
+ # Secrets
+ gnupg
+ pass
+
+ # C/C++ source tooling (no compiler driver in PATH)
+ clang-tools
+
+ # Editor/AI agent runtimes — NOT for project builds (see policy above)
+ nodejs_24 # copilot-language-server requires Node 24 (see ai.lua)
+ uv # for project tooling that asks for `uv`/`uvx`; brings no python
+
+ # AI coding agents
+ claude-code
+ github-copilot-cli # NB: pkgs.copilot-cli is AWS Copilot, NOT this
+
+ # Zsh and plugins (loaded from $HOME/.nix-profile/share/... by the
+ # shared zshrc; nix-profile path is preferred, system path is the
+ # fallback for un-bootstrapped states).
+ zsh
+ zsh-syntax-highlighting
+ zsh-autosuggestions
+ zsh-history-substring-search
+ ];
+
+ # ── direnv + nix-direnv ─────────────────────────────────────────────────────
+ programs.direnv = {
+ enable = true;
+ nix-direnv.enable = true;
+ enableZshIntegration = false; # zshrc already calls `eval "$(direnv hook zsh)"`
+ };
+
+ # ── Shared config symlinks ──────────────────────────────────────────────────
+ # Live symlinks back into the cloned working tree so `git pull` is enough
+ # to update configs — no `home-manager switch` required after every edit.
+ xdg.configFile = {
+ "nvim".source = link "dot_config/nvim";
+ "zellij".source = link "dot_config/zellij";
+ "zsh/.zshrc".source = link "dot_config/zsh/dot_zshrc";
+ "zsh/.zprofile".source = link "dot_config/zsh/dot_zprofile";
+ "ghostty".source = link "dot_config/ghostty"; # for terminfo refs only
+ "direnv/direnvrc".source = link "dot_config/direnv/direnvrc";
+ "git/config".source = link "dot_config/git/config";
+ "git/attributes".source = link "dot_config/git/attributes";
+ "git/ignore".source = link "dot_config/git/ignore";
+ # Git hooks: source filenames carry the chezmoi `executable_` attribute
+ # prefix which only chezmoi strips. In nix-managed setups we use raw
+ # symlinks, so map each hook to its stripped name explicitly. The
+ # executable bit comes from the working-tree file mode (git resolves
+ # the symlink).
+ "git/hooks/pre-push".source = link "dot_config/git/hooks/executable_pre-push";
+ "git/hooks/pre-commit".source = link "dot_config/git/hooks/executable_pre-commit";
+ "git/hooks/commit-msg".source = link "dot_config/git/hooks/executable_commit-msg";
+ "git/hooks/post-commit".source = link "dot_config/git/hooks/executable_post-commit";
+ "git/hooks/_dispatch.sh".source = link "dot_config/git/hooks/_dispatch.sh";
+ };
+
+ # ~/.ssh/config from the dotfiles tree (read-only); keys + known_hosts
+ # stay machine-local. We can't symlink via home.file because
+ # mkOutOfStoreSymlink exposes the working-tree perms (0664 under a
+ # default umask 002) and OpenSSH refuses any group-writable ssh_config.
+ # Materialize a real 0600 file via activation instead.
+ home.activation.sshConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
+ run install -D -m 600 \
+ "${dotfiles}/private_dot_ssh/config" "$HOME/.ssh/config"
+ '';
+
+ # ZDOTDIR redirect so login shells find ~/.config/zsh/.zprofile etc.
+ # Also source HM's session-vars — HM normally drops these into
+ # ~/.profile, but zsh login shells don't read .profile, and we don't
+ # use programs.zsh.enable.
+ home.file.".zshenv".text = ''
+ if [ -r "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" ]; then
+ . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
+ fi
+ export ZDOTDIR="$HOME/.config/zsh"
+ [[ -r "$ZDOTDIR/.zshenv" ]] && source "$ZDOTDIR/.zshenv"
+ '';
+
+ # ── XDG base dirs ──────────────────────────────────────────────────────────
+ xdg.enable = true;
+
+ # ── Enable HM-managed activation messages ──────────────────────────────────
+ programs.home-manager.enable = true;
+}