aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-13 13:43:24 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-13 13:43:24 +0100
commitebad39adab212ab4e26f9a98befa0048c7eea710 (patch)
tree92fae17be7a264595bbbaf7a52dec1249f043f08
parent415d55a7b5f87dec2d5ecfe3cd109c0530e4cbd7 (diff)
downloaddotfiles-ebad39adab212ab4e26f9a98befa0048c7eea710.tar.gz
dotfiles-ebad39adab212ab4e26f9a98befa0048c7eea710.tar.bz2
dotfiles-ebad39adab212ab4e26f9a98befa0048c7eea710.zip
feat(nix): hybrid setup with flakes + direnv for per-project dev shells
Install Nix (multi-user daemon) on Arch and wire up direnv so any project can declare its toolchain in a flake.nix and get a hermetic dev shell on cd. No NixOS, no home-manager, no migration off paru/chezmoi — just one new package manager scoped to project dev shells. - meta/nix.txt: nix from extra repo - meta/dev.txt: direnv (general-purpose, not nix-specific) - systemd-units/system/nix.txt: nix-daemon.socket (socket-activated) - etc/nix/nix.conf: enable flakes + nix-command, trusted-users=@wheel, auto-optimise-store, keep-outputs/derivations so direnv envs survive GC - dot_config/direnv/direnvrc: load nix-direnv 3.1.1 via source_url with pinned sha256 (not packaged for Arch; refusing -git AUR) - dot_config/nix/templates/{flake.nix,dev/}: flake template usable via 'nix flake init -t ~/.config/nix/templates' - dot_config/zsh/dot_zshrc: 'eval "$(direnv hook zsh)"'
-rw-r--r--dot_config/direnv/direnvrc14
-rw-r--r--dot_config/nix/templates/dev/dot_envrc1
-rw-r--r--dot_config/nix/templates/dev/flake.nix29
-rw-r--r--dot_config/nix/templates/flake.nix13
-rw-r--r--dot_config/zsh/dot_zshrc3
-rw-r--r--etc/nix/nix.conf21
-rw-r--r--meta/dev.txt1
-rw-r--r--meta/nix.txt16
-rw-r--r--systemd-units/system/nix.txt3
9 files changed, 101 insertions, 0 deletions
diff --git a/dot_config/direnv/direnvrc b/dot_config/direnv/direnvrc
new file mode 100644
index 0000000..40bfc86
--- /dev/null
+++ b/dot_config/direnv/direnvrc
@@ -0,0 +1,14 @@
+# Global direnv runtime config.
+#
+# Loads nix-direnv on demand. nix-direnv is NOT packaged for Arch and we
+# refuse to depend on -git AUR packages, so we fetch the loader from
+# upstream pinned by version + content hash. direnv caches it under
+# $XDG_CACHE_HOME/direnv/, so the network fetch happens exactly once
+# per pin bump.
+#
+# To upgrade: bump the version in the URL and replace the sha256 with
+# the new one. direnv prints the expected hash on mismatch.
+if ! has nix_direnv_version || ! nix_direnv_version 3.1.1; then
+ source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.1/direnvrc" \
+ "sha256-p+fzQdrms/hDa7g+soShAybJNo4bN4SIAeSfqNKgD5I="
+fi
diff --git a/dot_config/nix/templates/dev/dot_envrc b/dot_config/nix/templates/dev/dot_envrc
new file mode 100644
index 0000000..3550a30
--- /dev/null
+++ b/dot_config/nix/templates/dev/dot_envrc
@@ -0,0 +1 @@
+use flake
diff --git a/dot_config/nix/templates/dev/flake.nix b/dot_config/nix/templates/dev/flake.nix
new file mode 100644
index 0000000..84b3179
--- /dev/null
+++ b/dot_config/nix/templates/dev/flake.nix
@@ -0,0 +1,29 @@
+{
+ description = "Project dev shell";
+
+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+
+ outputs = { self, nixpkgs }:
+ let
+ systems = [ "x86_64-linux" "aarch64-linux" ];
+ forAllSystems = nixpkgs.lib.genAttrs systems;
+ in
+ {
+ devShells = forAllSystems (system:
+ let
+ pkgs = nixpkgs.legacyPackages.${system};
+ in
+ {
+ default = pkgs.mkShell {
+ packages = with pkgs; [
+ # Add per-project tools here.
+ # Example: nodejs_22 python313 cargo gcc
+ ];
+
+ shellHook = ''
+ # Per-project env setup (printed once on shell entry).
+ '';
+ };
+ });
+ };
+}
diff --git a/dot_config/nix/templates/flake.nix b/dot_config/nix/templates/flake.nix
new file mode 100644
index 0000000..dc4cf2d
--- /dev/null
+++ b/dot_config/nix/templates/flake.nix
@@ -0,0 +1,13 @@
+{
+ description = "Personal flake templates. Use: nix flake init -t ~/.config/nix/templates#<name>";
+
+ outputs = { self }: {
+ templates = {
+ dev = {
+ path = ./dev;
+ description = "Generic per-project dev shell with direnv .envrc";
+ };
+ default = self.templates.dev;
+ };
+ };
+}
diff --git a/dot_config/zsh/dot_zshrc b/dot_config/zsh/dot_zshrc
index f516495..e8fca42 100644
--- a/dot_config/zsh/dot_zshrc
+++ b/dot_config/zsh/dot_zshrc
@@ -353,6 +353,9 @@ compdef l=lsd la=lsd lt=lsd
export GPG_TTY=$TTY
gpg-connect-agent updatestartuptty /bye &>/dev/null
+# ── direnv (per-project env via .envrc; nix-direnv loaded from direnvrc) ─────
+eval "$(direnv hook zsh)"
+
# ── Zoxide (smart directory jumping) ──────────────────────────────────────────
# z foo → jump to frecency-ranked dir matching "foo"
# zi → interactive picker with fzf
diff --git a/etc/nix/nix.conf b/etc/nix/nix.conf
new file mode 100644
index 0000000..eb24511
--- /dev/null
+++ b/etc/nix/nix.conf
@@ -0,0 +1,21 @@
+# /etc/nix/nix.conf — daemon-wide Nix config.
+# Managed by chezmoi (etc/nix/nix.conf in dotfiles).
+
+# Enable `nix` CLI (vs legacy nix-* commands) and flakes.
+experimental-features = nix-command flakes
+
+# Wheel users may configure extra substituters / import paths without
+# the daemon prompting. Safe on a single-user laptop.
+trusted-users = root @wheel
+
+# Hard-link identical store paths to save disk after large builds.
+auto-optimise-store = true
+
+# Keep build outputs and derivations alive even when only referenced
+# from GC roots like direnv envs. Without these, `nix store gc` would
+# drop dev-shell deps and force a re-download next `cd` into a project.
+keep-outputs = true
+keep-derivations = true
+
+# Lift the default 64 MiB download buffer; reduces stalls on big closures.
+download-buffer-size = 524288000
diff --git a/meta/dev.txt b/meta/dev.txt
index bca1348..5f26ad7 100644
--- a/meta/dev.txt
+++ b/meta/dev.txt
@@ -1,6 +1,7 @@
android-tools
curl
difftastic
+direnv
git-absorb
git-delta
github-cli
diff --git a/meta/nix.txt b/meta/nix.txt
new file mode 100644
index 0000000..e5c4bb4
--- /dev/null
+++ b/meta/nix.txt
@@ -0,0 +1,16 @@
+# Nix package manager (multi-user daemon mode).
+#
+# Used purely for hermetic per-project dev shells via `nix develop` +
+# direnv `use flake`. Not a replacement for paru/pacman, not home-manager,
+# not NixOS — just a sandboxed second package manager that gives every
+# project a reproducible toolchain pinned in its own flake.lock.
+#
+# Pairs with:
+# - systemd-units/system/nix.txt (enables nix-daemon.socket)
+# - etc/nix/nix.conf (flakes, trusted-users=@wheel, GC roots)
+# - dot_config/direnv/direnvrc (loads nix-direnv; pinned via source_url)
+# - dot_config/nix/templates/ (flake templates: nix flake init -t ~/.config/nix/templates)
+#
+# nix-direnv itself is not packaged for Arch — it's loaded at runtime via
+# direnv's source_url with a content hash, so no extra package needed.
+nix
diff --git a/systemd-units/system/nix.txt b/systemd-units/system/nix.txt
new file mode 100644
index 0000000..de99aaa
--- /dev/null
+++ b/systemd-units/system/nix.txt
@@ -0,0 +1,3 @@
+# Nix builder daemon — socket-activated, idle-friendly.
+# The .service spawns on first client connect; the .socket is what gets enabled.
+nix-daemon.socket