summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.envrc6
-rw-r--r--.gitignore1
-rw-r--r--REUSE.toml5
l---------bin/darwin-rebuild1
-rwxr-xr-xbin/home-manager160
l---------bin/nixos-rebuild1
-rw-r--r--flake.lock638
-rw-r--r--flake.nix204
-rw-r--r--lib/default.nix25
-rw-r--r--npins/default.nix80
-rw-r--r--npins/sources.json107
-rw-r--r--overlays/emacs.nix1
-rw-r--r--overlays/nur.nix3
-rw-r--r--overlays/personal.nix13
-rw-r--r--shell.nix21
-rw-r--r--sources.nix20
-rw-r--r--system/linde.nix10
-rw-r--r--system/marvin.nix9
-rw-r--r--system/prefect.nix5
-rw-r--r--system/settings/configuration/nix.nix12
-rw-r--r--system/settings/pin.nix14
-rw-r--r--user/marvin.nix3
-rw-r--r--user/prefect.nix2
-rw-r--r--user/server.nix2
-rw-r--r--user/settings/base.nix5
-rw-r--r--user/settings/darwin.nix2
-rw-r--r--user/settings/nix.nix5
-rw-r--r--user/settings/nixos.nix4
-rw-r--r--user/settings/shell.nix6
29 files changed, 497 insertions, 868 deletions
diff --git a/.envrc b/.envrc
index ed8f9482..b5fda8db 100644
--- a/.envrc
+++ b/.envrc
@@ -1,9 +1,7 @@
 if type -P lorri &>/dev/null; then
-  if test -n "$TMPDIR"; then
-    export TMPDIR="$(readlink -f $TMPDIR)"
-  fi
-  eval "$(lorri direnv --flake .)"
+  eval "$(lorri direnv)"
 else
   echo 'while direnv evaluated .envrc, could not find the command "lorri" [https://github.com/nix-community/lorri]'
   use nix
 fi
+PATH_add bin
diff --git a/.gitignore b/.gitignore
index 06dad061..6a2720eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 /result
 /secrets/key.txt
+/system/configuration.nix
diff --git a/REUSE.toml b/REUSE.toml
index 90f300c0..a044e623 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -10,6 +10,11 @@ SPDX-FileCopyrightText = "2024 Alan Pearce <alan@alanpearce.eu>"
 SPDX-License-Identifier = "MIT"
 
 [[annotations]]
+path = ["npins/*"]
+SPDX-FileCopyrightText = "NONE"
+SPDX-License-Identifier = "CC0-1.0"
+
+[[annotations]]
 path = "**/*.el"
 SPDX-FileCopyrightText = "2024 Alan Pearce <alan@alanpearce.eu>"
 SPDX-License-Identifier = "GPL-3.0-or-later"
diff --git a/bin/darwin-rebuild b/bin/darwin-rebuild
new file mode 120000
index 00000000..2eaccdef
--- /dev/null
+++ b/bin/darwin-rebuild
@@ -0,0 +1 @@
+home-manager
\ No newline at end of file
diff --git a/bin/home-manager b/bin/home-manager
new file mode 100755
index 00000000..e19e2885
--- /dev/null
+++ b/bin/home-manager
@@ -0,0 +1,160 @@
+#!/usr/bin/env fish
+
+if not set --query HOME
+    echo "error: no HOME"
+    exit 1
+end
+
+set --query XDG_STATE_HOME || set --function XDG_STATE_HOME $HOME/.local/state
+set --function nix_state_home $XDG_STATE_HOME/nix
+set --function channel_root $nix_state_home/profiles/channels
+set --function user_nixpkgs $HOME/.config/nixpkgs
+set --function darwin_config /etc/nix-darwin/
+set --function nixfiles (path resolve (status dirname)/..)
+
+if set --query XDG_CONFIG_HOME
+    set --function hm_config_dir $XDG_CONFIG_HOME/home-manager
+else
+    set --function hm_config_dir $HOME/.config/home-manager
+end
+
+set --function current_script_name (status basename)
+for i in 1
+    if test ! -d $darwin_config
+        if test ! -e $darwin_config && test -L $darwin_config
+            echo "$darwin_config is a broken symlink, deleting it [sudo]"
+            sudo rm $darwin_config
+        end
+        echo "darwin configuration folder $darwin_config does not exist, creating it [sudo]"
+        sudo mkdir -p $darwin_config
+    end
+    if test ! -d $user_nixpkgs
+        if test ! -e $user_nixpkgs && test -L $user_nixpkgs
+            echo "~/.config/nixpkgs is a broken symlink, deleting it"
+            rm $user_nixpkgs
+        end
+        echo "user nixpkgs folder $user_nixpkgs does not exist, creating it"
+        mkdir -p $user_nixpkgs
+    end
+    if test -L $hm_config_dir -a (path resolve $hm_config_dir) = (path resolve (status basename))
+        if test y = (read --nchars=1 --prompt-str="$hm_config_dir already exists as a symlink to the current directory. Remove it [yN]? ")
+            unlink $hm_config_dir
+        end
+    end
+    if test ! -d $hm_config_dir
+        echo "user home-manager configuration folder $hm_config_dir does not exist, creating it"
+        mkdir -p $hm_config_dir
+    end
+    if test ! -e $channel_root
+        if test -L $channel_root
+            # broken symlink
+            rm $channel_root
+        end
+        echo "channel root $channel_root does not exist, creating it"
+        mkdir -p $channel_root
+    else
+        if test ! -d $channel_root
+            echo "error: $channel_root is not a directory"
+        else if test -L $channel_root
+            echo "error: $channel_root is a symlink, please remove it"
+        else if path is --invert --perm write $channel_root
+            echo "error: $channel_root is not writable; might be a symlink"
+        else if path is --invert --type link $channel_root/*
+            for p in (path filter --invert --type link $channel_root/*)
+                # might be a broken symlink
+                if test -L $p -a ! -e $p
+                    rm $p
+                else
+                    echo "error: channel $p is not a broken symlink, don't know what to do with it"
+                end
+            end
+            # check again and fail if there are still unknown files
+            if path is --invert --type link $channel_root/*
+                echo "error: non-link(s) in $channel_root"
+                path filter --invert --type link $channel_root/*
+            else
+                continue
+            end
+        else
+            continue # with script
+        end
+        exit 1
+    end
+end
+
+set --function current_script_name (status basename)
+switch $current_script_name
+    case darwin-rebuild
+        set --local darwin_config_source $nixfiles/system/$hostname.nix
+        set --local darwin_config_target $darwin_config/configuration.nix
+        if test ! -e $darwin_config_target
+            echo "Need to link $darwin_config_target"
+            sudo ln -s $darwin_config_source $darwin_config_target
+        end
+        set --append argv -I darwin-config=$darwin_config_target
+    case nixos-rebuild
+        set --local nixos_config_source $nixfiles/system/$hostname.nix
+        set --local nixos_config_target $user_nixpkgs/configuration.nix
+        if test ! -e $nixos_config_target
+            ln -s $nixos_config_source $nixos_config_target
+        end
+        if ! fish_is_root_user
+            set --append argv --use-remote-sudo
+        end
+        set --append argv -I nixos-config=$nixos_config_source
+    case home-manager
+        set --local hm_config_source $nixfiles/user/$hostname.nix
+        set --local hm_config_target $hm_config_dir/home.nix
+        if test ! -e $hm_config_target
+            ln -s $hm_config_source $hm_config_target
+        end
+        set --export HOME_MANAGER_CONFIG $hm_config_source
+end
+
+set --function old_channels (path basename $channel_root/*)
+
+function update_link --argument-names new_src target
+    set --function current_src (path resolve $target)
+    if test -e $current_src
+        if test $current_src = $new_src
+            # no need to re-link it
+            return
+        else
+            unlink $target
+        end
+    end
+    ln -s $new_src $target
+end
+
+for np in $NIX_PATH
+    if string match --quiet --entire "=" $np
+        echo $np | read --function --delimiter "=" channel new_src_rel
+        set --local new_src (path resolve $new_src_rel)
+
+        if set --local i (contains --index $channel $old_channels)
+            set --erase old_channels[$i]
+        end
+
+        update_link $new_src $channel_root/$channel
+    end
+end
+
+for old in $channel_root/$old_channels
+    rm $old
+end
+
+if set --function i (contains --index (status dirname) $PATH) && test -n $i
+    set --erase PATH[$i]
+end
+
+set --function cmd $current_script_name $argv
+
+if contains -- -n $argv
+    set --prepend cmd echo
+end
+
+if set --query IN_NIX_SHELL
+    eval $cmd
+else
+    nix-shell --run "$cmd"
+end
diff --git a/bin/nixos-rebuild b/bin/nixos-rebuild
new file mode 120000
index 00000000..2eaccdef
--- /dev/null
+++ b/bin/nixos-rebuild
@@ -0,0 +1 @@
+home-manager
\ No newline at end of file
diff --git a/flake.lock b/flake.lock
deleted file mode 100644
index 81d820da..00000000
--- a/flake.lock
+++ /dev/null
@@ -1,638 +0,0 @@
-{
-  "nodes": {
-    "agenix": {
-      "inputs": {
-        "darwin": "darwin",
-        "home-manager": "home-manager",
-        "nixpkgs": [
-          "nixpkgs"
-        ],
-        "systems": "systems"
-      },
-      "locked": {
-        "lastModified": 1736955230,
-        "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
-        "owner": "ryantm",
-        "repo": "agenix",
-        "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
-        "type": "github"
-      },
-      "original": {
-        "owner": "ryantm",
-        "repo": "agenix",
-        "type": "github"
-      }
-    },
-    "darwin": {
-      "inputs": {
-        "nixpkgs": [
-          "agenix",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1700795494,
-        "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
-        "owner": "lnl7",
-        "repo": "nix-darwin",
-        "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
-        "type": "github"
-      },
-      "original": {
-        "owner": "lnl7",
-        "ref": "master",
-        "repo": "nix-darwin",
-        "type": "github"
-      }
-    },
-    "darwin_2": {
-      "inputs": {
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1739933872,
-        "narHash": "sha256-UhuvTR4OrWR+WBaRCZm4YMkvjJhZ1KZo/jRjE41m+Ek=",
-        "owner": "lnl7",
-        "repo": "nix-darwin",
-        "rev": "6ab392f626a19f1122d1955c401286e1b7cf6b53",
-        "type": "github"
-      },
-      "original": {
-        "owner": "lnl7",
-        "ref": "master",
-        "repo": "nix-darwin",
-        "type": "github"
-      }
-    },
-    "deploy-rs": {
-      "inputs": {
-        "flake-compat": "flake-compat",
-        "nixpkgs": "nixpkgs",
-        "utils": "utils"
-      },
-      "locked": {
-        "lastModified": 1727447169,
-        "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
-        "owner": "serokell",
-        "repo": "deploy-rs",
-        "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
-        "type": "github"
-      },
-      "original": {
-        "owner": "serokell",
-        "repo": "deploy-rs",
-        "type": "github"
-      }
-    },
-    "emacs-overlay": {
-      "inputs": {
-        "nixpkgs": "nixpkgs_2",
-        "nixpkgs-stable": "nixpkgs-stable"
-      },
-      "locked": {
-        "lastModified": 1740333969,
-        "narHash": "sha256-zkLwCGw1PylyV0cGywnYF/duox1gC45BcV5XtkXD6zM=",
-        "owner": "nix-community",
-        "repo": "emacs-overlay",
-        "rev": "84420d1963cada13bc63be2e118082586690728a",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "emacs-overlay",
-        "type": "github"
-      }
-    },
-    "flake-compat": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-compat_2": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1696426674,
-        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
-    "flake-utils": {
-      "inputs": {
-        "systems": "systems_3"
-      },
-      "locked": {
-        "lastModified": 1731533236,
-        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "flake-utils_2": {
-      "inputs": {
-        "systems": "systems_4"
-      },
-      "locked": {
-        "lastModified": 1731533236,
-        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "gitignore": {
-      "inputs": {
-        "nixpkgs": [
-          "searchix",
-          "pre-commit-hooks",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1709087332,
-        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
-        "type": "github"
-      },
-      "original": {
-        "owner": "hercules-ci",
-        "repo": "gitignore.nix",
-        "type": "github"
-      }
-    },
-    "golink": {
-      "inputs": {
-        "flake-utils": "flake-utils",
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1736547866,
-        "narHash": "sha256-Zmcuo1lab4V1nMcEU0vZ49XwvIhGJyZUybW4m5hLfJg=",
-        "owner": "tailscale",
-        "repo": "golink",
-        "rev": "c21529a06d80c16b6da1a0dab98dff3d84ad86fc",
-        "type": "github"
-      },
-      "original": {
-        "owner": "tailscale",
-        "repo": "golink",
-        "type": "github"
-      }
-    },
-    "gomod2nix": {
-      "inputs": {
-        "flake-utils": [
-          "searchix",
-          "flake-utils"
-        ],
-        "nixpkgs": [
-          "searchix",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1733668782,
-        "narHash": "sha256-tPsqU00FhgdFr0JiQUiBMgPVbl1jbPCY5gbFiJycL3I=",
-        "owner": "nix-community",
-        "repo": "gomod2nix",
-        "rev": "514283ec89c39ad0079ff2f3b1437404e4cba608",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "gomod2nix",
-        "type": "github"
-      }
-    },
-    "home-manager": {
-      "inputs": {
-        "nixpkgs": [
-          "agenix",
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1703113217,
-        "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
-        "owner": "nix-community",
-        "repo": "home-manager",
-        "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "home-manager",
-        "type": "github"
-      }
-    },
-    "home-manager_2": {
-      "inputs": {
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1740318342,
-        "narHash": "sha256-fjr9+3Iru6O5qE+2oERQkabqAUXx4awm0+i2MBcta1U=",
-        "owner": "nix-community",
-        "repo": "home-manager",
-        "rev": "b5ab2c7fdaa807cf425066ab7cd34b073946b1ca",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "home-manager",
-        "type": "github"
-      }
-    },
-    "nix-index-database": {
-      "inputs": {
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1740281615,
-        "narHash": "sha256-dZWcbAQ1sF8oVv+zjSKkPVY0ebwENQEkz5vc6muXbKY=",
-        "owner": "Mic92",
-        "repo": "nix-index-database",
-        "rev": "465792533d03e6bb9dc849d58ab9d5e31fac9023",
-        "type": "github"
-      },
-      "original": {
-        "owner": "Mic92",
-        "repo": "nix-index-database",
-        "type": "github"
-      }
-    },
-    "nixos-hardware": {
-      "locked": {
-        "lastModified": 1740089251,
-        "narHash": "sha256-Y78mDBWoO8CLLTjQfPfII+KXFb6lAmF9GrLbyVBsIMM=",
-        "owner": "NixOS",
-        "repo": "nixos-hardware",
-        "rev": "18e9f9753e9ae261bcc7d3abe15745686991fd30",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "repo": "nixos-hardware",
-        "type": "github"
-      }
-    },
-    "nixpkgs": {
-      "locked": {
-        "lastModified": 1702272962,
-        "narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-stable": {
-      "locked": {
-        "lastModified": 1740162160,
-        "narHash": "sha256-SSYxFhqCOb3aiPb6MmN68yEzBIltfom8IgRz7phHscM=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "11415c7ae8539d6292f2928317ee7a8410b28bb9",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-24.11",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs-stable_2": {
-      "locked": {
-        "lastModified": 1730741070,
-        "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-24.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1740126099,
-        "narHash": "sha256-ozoOtE2hGsqh4XkTJFsrTkNxkRgShxpQxDynaPZUGxk=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "32fb99ba93fea2798be0e997ea331dd78167f814",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_3": {
-      "locked": {
-        "lastModified": 1734424634,
-        "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_4": {
-      "locked": {
-        "lastModified": 1730768919,
-        "narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_5": {
-      "locked": {
-        "lastModified": 1739928959,
-        "narHash": "sha256-ZroNoSIYC1trtuUpWlWGRCrvYt9QBEiut7DC1GHKmT4=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "9228994eca7cc0e00f8318e015d4dfbbf7ad41e2",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-unstable-small",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-compat": "flake-compat_2",
-        "gitignore": "gitignore",
-        "nixpkgs": "nixpkgs_4",
-        "nixpkgs-stable": "nixpkgs-stable_2"
-      },
-      "locked": {
-        "lastModified": 1734425854,
-        "narHash": "sha256-nzE5UbJ41aPEKf8R2ZFYtLkqPmF7EIUbNEdHMBLg0Ig=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "0ddd26d0925f618c3a5d85a4fa5eb1e23a09491d",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
-    "root": {
-      "inputs": {
-        "agenix": "agenix",
-        "darwin": "darwin_2",
-        "deploy-rs": "deploy-rs",
-        "emacs-overlay": "emacs-overlay",
-        "golink": "golink",
-        "home-manager": "home-manager_2",
-        "nix-index-database": "nix-index-database",
-        "nixos-hardware": "nixos-hardware",
-        "nixpkgs": [
-          "srvos",
-          "nixpkgs"
-        ],
-        "searchix": "searchix",
-        "srvos": "srvos",
-        "utils": "utils_2"
-      }
-    },
-    "searchix": {
-      "inputs": {
-        "flake-utils": "flake-utils_2",
-        "gomod2nix": "gomod2nix",
-        "nixpkgs": "nixpkgs_3",
-        "pre-commit-hooks": "pre-commit-hooks",
-        "simple-css": "simple-css"
-      },
-      "locked": {
-        "lastModified": 1739493400,
-        "narHash": "sha256-pdKTt5M13n9dgg5S6+ZsQd52aAxFayHbVUoqhzR0puA=",
-        "ref": "refs/heads/main",
-        "rev": "ea8c3053006e67210e16ed55febbcb0c6a374b54",
-        "revCount": 321,
-        "type": "git",
-        "url": "https://git.alanpearce.eu/searchix"
-      },
-      "original": {
-        "type": "git",
-        "url": "https://git.alanpearce.eu/searchix"
-      }
-    },
-    "simple-css": {
-      "flake": false,
-      "locked": {
-        "narHash": "sha256-aZTz1/XT7LZX9VfOclIumJzlUDLOlQLaZ89v6Ys26VU=",
-        "type": "file",
-        "url": "https://raw.githubusercontent.com/kevquirk/simple.css/v2.3.1/simple.css"
-      },
-      "original": {
-        "type": "file",
-        "url": "https://raw.githubusercontent.com/kevquirk/simple.css/v2.3.1/simple.css"
-      }
-    },
-    "srvos": {
-      "inputs": {
-        "nixpkgs": "nixpkgs_5"
-      },
-      "locked": {
-        "lastModified": 1740012831,
-        "narHash": "sha256-u6Y5ttXBuQ+tyyCei07QnbNL6Gydv55OpoGh4fXzTqg=",
-        "owner": "nix-community",
-        "repo": "srvos",
-        "rev": "f6ddf92bc61e021ea05c971a055624509ffac429",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-community",
-        "repo": "srvos",
-        "type": "github"
-      }
-    },
-    "systems": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_3": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_4": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "systems_5": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "utils": {
-      "inputs": {
-        "systems": "systems_2"
-      },
-      "locked": {
-        "lastModified": 1701680307,
-        "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    },
-    "utils_2": {
-      "inputs": {
-        "systems": "systems_5"
-      },
-      "locked": {
-        "lastModified": 1731533236,
-        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
-    }
-  },
-  "root": "root",
-  "version": 7
-}
diff --git a/flake.nix b/flake.nix
deleted file mode 100644
index 46e55e3b..00000000
--- a/flake.nix
+++ /dev/null
@@ -1,204 +0,0 @@
-{
-  inputs = {
-    srvos.url = "github:nix-community/srvos";
-    nixpkgs.follows = "srvos/nixpkgs";
-    nixos-hardware.url = "github:NixOS/nixos-hardware";
-    nix-index-database.url = "github:Mic92/nix-index-database";
-    nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
-    darwin.url = "github:lnl7/nix-darwin/master";
-    darwin.inputs.nixpkgs.follows = "nixpkgs";
-    emacs-overlay.url = "github:nix-community/emacs-overlay";
-    home-manager.url = "github:nix-community/home-manager";
-    home-manager.inputs.nixpkgs.follows = "nixpkgs";
-    utils.url = "github:numtide/flake-utils";
-    agenix.url = "github:ryantm/agenix";
-    agenix.inputs.nixpkgs.follows = "nixpkgs";
-    deploy-rs.url = "github:serokell/deploy-rs";
-    searchix.url = "git+https://git.alanpearce.eu/searchix";
-    golink = {
-      url = "github:tailscale/golink";
-      inputs.nixpkgs.follows = "nixpkgs";
-    };
-  };
-
-  outputs =
-    inputs@
-    { self
-    , utils
-    , srvos
-    , nixpkgs
-    , nixos-hardware
-    , emacs-overlay
-    , home-manager
-    , darwin
-    , nix-index-database
-    , agenix
-    , deploy-rs
-    , searchix
-    , golink
-    , ...
-    }:
-    let
-      readOverlays = path:
-        let content = builtins.readDir path; in
-        map (n: import (path + ("/" + n)))
-          (builtins.filter
-            (n:
-              (builtins.match ".*\\.nix" n != null &&
-              # ignore Emacs lock files (.#foo.nix)
-              builtins.match "\\.#.*" n == null) ||
-              builtins.pathExists (path + ("/" + n + "/default.nix")))
-            (builtins.attrNames content));
-
-      mkHomeConfiguration = { modules, system }: home-manager.lib.homeManagerConfiguration {
-        pkgs = import nixpkgs {
-          inherit system;
-          overlays = readOverlays (toString ./overlays) ++ [
-            agenix.overlays.default
-            emacs-overlay.overlays.default
-            (self: super: {
-              personal = import ./packages/overlay.nix self super;
-              enchant = super.enchant.override {
-                withHspell = false;
-                withAspell = false;
-              };
-            })
-          ];
-        };
-
-        inherit modules;
-        extraSpecialArgs = {
-          inherit inputs system;
-        };
-      };
-    in
-    {
-      nixosConfigurations.prefect = nixpkgs.lib.nixosSystem {
-        system = utils.lib.system.x86_64-linux;
-        specialArgs = { inherit inputs; };
-        modules = [
-          ./system/prefect.nix
-        ] ++ (with nixos-hardware.nixosModules; [
-          common-cpu-amd
-          common-cpu-amd-pstate
-          common-pc-ssd
-          common-pc
-          common-gpu-nvidia-nonprime
-        ]);
-      };
-      nixosConfigurations.nano = nixpkgs.lib.nixosSystem {
-        system = utils.lib.system.aarch64-linux;
-        specialArgs = { inherit inputs; };
-        modules = [
-          agenix.nixosModules.default
-          srvos.nixosModules.server
-          srvos.nixosModules.mixins-systemd-boot
-          ./system/nano.nix
-          ./system/nano-hardware.nix
-        ];
-      };
-      nixosConfigurations.linde = nixpkgs.lib.nixosSystem {
-        system = utils.lib.system.aarch64-linux;
-        specialArgs = { inherit inputs; };
-        modules = [
-          srvos.nixosModules.server
-          srvos.nixosModules.hardware-hetzner-cloud-arm
-          agenix.nixosModules.default
-          searchix.nixosModules.web
-          golink.nixosModules.default
-          ./packages/modules/nixos/laminar.nix
-          ./system/linde.nix
-        ];
-      };
-      darwinConfigurations.marvin = darwin.lib.darwinSystem {
-        system = utils.lib.system.aarch64-darwin;
-        specialArgs = { inherit inputs; };
-        modules = [
-          srvos.darwinModules.desktop
-          ./system/marvin.nix
-          ./packages/modules/darwin/caddy
-        ];
-      };
-      homeConfigurations."alan@marvin" = mkHomeConfiguration {
-        system = utils.lib.system.aarch64-darwin;
-        modules = [
-          ./user/marvin.nix
-          ./private/default.nix
-          ./private/tabnine.nix
-          ./private/ssh.nix
-          nix-index-database.hmModules.nix-index
-        ];
-      };
-      homeConfigurations."alan@prefect" = mkHomeConfiguration {
-        system = utils.lib.system.x86_64-linux;
-        modules = [
-          ./user/prefect.nix
-          ./private/default.nix
-          ./private/tabnine.nix
-          ./private/ssh.nix
-          nix-index-database.hmModules.nix-index
-        ];
-      };
-      homeConfigurations."alan@nano" = mkHomeConfiguration {
-        system = utils.lib.system.aarch64-linux;
-        modules = [
-          ./user/nano.nix
-          ./private/default.nix
-          nix-index-database.hmModules.nix-index
-        ];
-      };
-      homeConfigurations."alan@linde" = mkHomeConfiguration {
-        system = utils.lib.system.aarch64-linux;
-        modules = [
-          ./user/server.nix
-          ./private/default.nix
-          nix-index-database.hmModules.nix-index
-        ];
-      };
-
-      deploy = {
-        nodes.linde = {
-          hostname = "linde";
-          profiles.system = {
-            user = "root";
-            sshUser = "root";
-            path = deploy-rs.lib.${utils.lib.system.aarch64-linux}.activate.nixos
-              self.nixosConfigurations.linde;
-          };
-          profiles.alan = {
-            user = "alan";
-            path = deploy-rs.lib.${utils.lib.system.aarch64-linux}.activate.home-manager
-              self.homeConfigurations."alan@linde";
-          };
-        };
-        nodes.nano = {
-          hostname = "nano";
-          profiles.system = {
-            user = "root";
-            sshUser = "root";
-            path = deploy-rs.lib.${utils.lib.system.aarch64-linux}.activate.nixos
-              self.nixosConfigurations.nano;
-          };
-          profiles.alan = {
-            user = "alan";
-            sshUser = "alan";
-            path = deploy-rs.lib.${utils.lib.system.aarch64-linux}.activate.home-manager
-              self.homeConfigurations."alan@nano";
-          };
-        };
-      };
-    } // utils.lib.eachDefaultSystem (system:
-    let
-      pkgs = import nixpkgs { inherit system; };
-    in
-    {
-      devShells = {
-        default = pkgs.mkShell {
-          packages = [
-            deploy-rs.packages.${system}.default
-            agenix.packages.${system}.default
-          ];
-        };
-      };
-    });
-}
diff --git a/lib/default.nix b/lib/default.nix
new file mode 100644
index 00000000..2cbaf55c
--- /dev/null
+++ b/lib/default.nix
@@ -0,0 +1,25 @@
+{ pkgs }:
+with builtins;
+let
+  inherit (pkgs) lib;
+in
+rec {
+  importPathStore = p: "${append ../. "/${p}"}";
+
+  mkPathable = s: toString (
+    if lib.path.subpath.isValid s
+    then (lib.path.append ../. s)
+    else s
+  );
+
+  kvPath = k: v: "${k}=${v}";
+
+  fromSources = sources:
+    lib.attrsets.mapAttrs
+      (k: v: v.outPath)
+      sources;
+
+  mkNixPath = sources: lib.attrsets.mapAttrsToList
+    (k: v: kvPath k (mkPathable v))
+    sources;
+}
diff --git a/npins/default.nix b/npins/default.nix
new file mode 100644
index 00000000..5e7d086e
--- /dev/null
+++ b/npins/default.nix
@@ -0,0 +1,80 @@
+# Generated by npins. Do not modify; will be overwritten regularly
+let
+  data = builtins.fromJSON (builtins.readFile ./sources.json);
+  version = data.version;
+
+  mkSource =
+    spec:
+    assert spec ? type;
+    let
+      path =
+        if spec.type == "Git" then
+          mkGitSource spec
+        else if spec.type == "GitRelease" then
+          mkGitSource spec
+        else if spec.type == "PyPi" then
+          mkPyPiSource spec
+        else if spec.type == "Channel" then
+          mkChannelSource spec
+        else
+          builtins.throw "Unknown source type ${spec.type}";
+    in
+    spec // { outPath = path; };
+
+  mkGitSource =
+    {
+      repository,
+      revision,
+      url ? null,
+      hash,
+      branch ? null,
+      ...
+    }:
+    assert repository ? type;
+    # At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
+    # In the latter case, there we will always be an url to the tarball
+    if url != null then
+      (builtins.fetchTarball {
+        inherit url;
+        sha256 = hash; # FIXME: check nix version & use SRI hashes
+      })
+    else
+      assert repository.type == "Git";
+      let
+        urlToName =
+          url: rev:
+          let
+            matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url;
+
+            short = builtins.substring 0 7 rev;
+
+            appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
+          in
+          "${if matched == null then "source" else builtins.head matched}${appendShort}";
+        name = urlToName repository.url revision;
+      in
+      builtins.fetchGit {
+        url = repository.url;
+        rev = revision;
+        inherit name;
+        # hash = hash;
+      };
+
+  mkPyPiSource =
+    { url, hash, ... }:
+    builtins.fetchurl {
+      inherit url;
+      sha256 = hash;
+    };
+
+  mkChannelSource =
+    { url, hash, ... }:
+    builtins.fetchTarball {
+      inherit url;
+      sha256 = hash;
+    };
+in
+if version == 3 then
+  builtins.mapAttrs (_: mkSource) data.pins
+else
+  throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"
diff --git a/npins/sources.json b/npins/sources.json
new file mode 100644
index 00000000..f785a2d4
--- /dev/null
+++ b/npins/sources.json
@@ -0,0 +1,107 @@
+{
+  "pins": {
+    "agenix": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "ryantm",
+        "repo": "agenix"
+      },
+      "branch": "main",
+      "revision": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
+      "url": "https://github.com/ryantm/agenix/archive/e600439ec4c273cf11e06fe4d9d906fb98fa097c.tar.gz",
+      "hash": "006ngydiykjgqs85cl19h9klq8kaqm5zs0ng51dnwy7nzgqxzsdr"
+    },
+    "darwin": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "lnl7",
+        "repo": "nix-darwin"
+      },
+      "branch": "master",
+      "revision": "5d6e0851b60508cffd66b4a6982440a40720338d",
+      "url": "https://github.com/lnl7/nix-darwin/archive/5d6e0851b60508cffd66b4a6982440a40720338d.tar.gz",
+      "hash": "0hfj4jib2dd7alyp4m74p0spfc2x0cqgk4q6p8lz07rqzyl5nrka"
+    },
+    "emacs-overlay": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "nix-community",
+        "repo": "emacs-overlay"
+      },
+      "branch": "master",
+      "revision": "d9492638daa77fca7bf84e5b218cd95598ac3f72",
+      "url": "https://github.com/nix-community/emacs-overlay/archive/d9492638daa77fca7bf84e5b218cd95598ac3f72.tar.gz",
+      "hash": "0wr8y84g8q45y0vahvwx5px7728i88qskj3657g2i8j08skndlw6"
+    },
+    "home-manager": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "nix-community",
+        "repo": "home-manager"
+      },
+      "branch": "master",
+      "revision": "fcac3d6d88302a5e64f6cb8014ac785e08874c8d",
+      "url": "https://github.com/nix-community/home-manager/archive/fcac3d6d88302a5e64f6cb8014ac785e08874c8d.tar.gz",
+      "hash": "172sb8wdqm5fcx85gwzbf0b3l846s4b3ldfrpdhq5lf27lb20w81"
+    },
+    "nix-index-database": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "Mic92",
+        "repo": "nix-index-database"
+      },
+      "branch": "main",
+      "revision": "26a0f969549cf4d56f6e9046b9e0418b3f3b94a5",
+      "url": "https://github.com/Mic92/nix-index-database/archive/26a0f969549cf4d56f6e9046b9e0418b3f3b94a5.tar.gz",
+      "hash": "0ag1ma5qy7h3zxsvg24qzqlfnfvdkrkj36rp1lakbsj1ilks9plc"
+    },
+    "nixos-hardware": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "NixOS",
+        "repo": "nixos-hardware"
+      },
+      "branch": "master",
+      "revision": "009b764ac98a3602d41fc68072eeec5d24fc0e49",
+      "url": "https://github.com/NixOS/nixos-hardware/archive/009b764ac98a3602d41fc68072eeec5d24fc0e49.tar.gz",
+      "hash": "1cg4qrzwkd3xdmp70rniync25kgm123400i5l8m7jjqv186mxi3l"
+    },
+    "nixpkgs": {
+      "type": "Channel",
+      "name": "nixos-unstable",
+      "url": "https://releases.nixos.org/nixos/unstable/nixos-25.05beta761040.303bd8071377/nixexprs.tar.xz",
+      "hash": "15xz52bchv05cd4yxi4qhym9l7z0qr7hnw34pl098rjikp6yqbvw"
+    },
+    "nur": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "nix-community",
+        "repo": "NUR"
+      },
+      "branch": "main",
+      "revision": "eb2e9317b9e301ed5cbe2b07cb57b33558b79670",
+      "url": "https://github.com/nix-community/NUR/archive/eb2e9317b9e301ed5cbe2b07cb57b33558b79670.tar.gz",
+      "hash": "0gg453khpw5255rc6jgndid8qh2l9nh0jnrc1mlp24zjjqn567g8"
+    },
+    "srvos": {
+      "type": "Git",
+      "repository": {
+        "type": "GitHub",
+        "owner": "nix-community",
+        "repo": "srvos"
+      },
+      "branch": "main",
+      "revision": "b3065811ae1c822b856af8a254e07703172a0e76",
+      "url": "https://github.com/nix-community/srvos/archive/b3065811ae1c822b856af8a254e07703172a0e76.tar.gz",
+      "hash": "1lirn8klqj1vx0c42hmh7p6bn1s8rwxd6m1r27z93w333q7knbss"
+    }
+  },
+  "version": 3
+}
\ No newline at end of file
diff --git a/overlays/emacs.nix b/overlays/emacs.nix
new file mode 100644
index 00000000..ded36707
--- /dev/null
+++ b/overlays/emacs.nix
@@ -0,0 +1 @@
+import <emacs-overlay>
diff --git a/overlays/nur.nix b/overlays/nur.nix
new file mode 100644
index 00000000..6f34f2aa
--- /dev/null
+++ b/overlays/nur.nix
@@ -0,0 +1,3 @@
+self: super: {
+  nur = import <nur> { pkgs = self; };
+}
diff --git a/overlays/personal.nix b/overlays/personal.nix
new file mode 100644
index 00000000..eadb7851
--- /dev/null
+++ b/overlays/personal.nix
@@ -0,0 +1,13 @@
+self: super:
+let
+  personal = import <personal> {
+    pkgs = self;
+  };
+in
+{
+  inherit personal;
+  enchant = super.enchant.override {
+    withHspell = false;
+    withAspell = false;
+  };
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 00000000..2fa4ecf4
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,21 @@
+let
+  inherit (import ./sources.nix) nixPath sources;
+
+  pkgs = import sources.nixpkgs { };
+in
+pkgs.mkShell
+{
+
+  name = "nixfiles-shell";
+
+  buildInputs = with pkgs; [
+    npins
+    fish
+    (pkgs.callPackage "${sources.agenix}/pkgs/agenix.nix" { })
+    (import sources.home-manager { inherit pkgs; }).home-manager
+  ];
+
+  shellHook = ''
+    export NIX_PATH="${builtins.concatStringsSep ":" nixPath}";
+  '';
+}
diff --git a/sources.nix b/sources.nix
new file mode 100644
index 00000000..624ddfc7
--- /dev/null
+++ b/sources.nix
@@ -0,0 +1,20 @@
+let
+  sources = import ./npins;
+  pkgs = import sources.nixpkgs { };
+  config =
+    if pkgs.stdenv.isDarwin
+    then "darwin-config"
+    else "nixos-config";
+  inherit (import ./lib { inherit pkgs; }) mkNixPath fromSources;
+
+  allSources = {
+    personal = ./packages;
+    nixpkgs-overlays = ./overlays;
+    private = ./private;
+    ${config} = ./system/configuration.nix;
+  } // (fromSources sources);
+in
+{
+  sources = allSources;
+  nixPath = mkNixPath allSources;
+}
diff --git a/system/linde.nix b/system/linde.nix
index 5bf67cda..596cac19 100644
--- a/system/linde.nix
+++ b/system/linde.nix
@@ -17,14 +17,21 @@ let
   net-gw6 = "fe80::1";
   domain = "alanpearce.eu";
   ts-domain = "hydra-pinecone.ts.net";
+  golink = (builtins.getFlake (toString <golink>)).nixosModules.default;
 in
 {
   imports =
     [
+      <personal/modules/nixos/laminar.nix>
+      <home-manager/nixos>
+      <agenix/modules/age.nix>
+      <searchix/nix/modules>
+      golink
       # Include the results of the hardware scan.
       ./linde-hardware.nix
 
       ./settings/configuration/nix-linux.nix
+      ./settings/pin.nix
       ./settings/services/git-server.nix
     ];
   age.secrets = {
@@ -290,6 +297,9 @@ in
       "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJVREjPey2TOIPzfYJoG9yIR4Rui7tNJK2QIKa+pbgsyXg31hhPIw37LRRIic+l53mW8eahHxX3Y1IeTjcMw8IU= alan@secretive.marvin"
     ];
   };
+  home-manager = {
+    users.alan = import ../user/server.nix;
+  };
 
   users.users.nixremote = {
     shell = "/bin/sh";
diff --git a/system/marvin.nix b/system/marvin.nix
index 44c1e9a5..2e88e0d2 100644
--- a/system/marvin.nix
+++ b/system/marvin.nix
@@ -1,8 +1,14 @@
-{ pkgs, ... }: {
+{ pkgs, ... }:
+let
+  srvos = import <srvos>;
+in
+{
   imports = [
     ./settings/darwin.nix
     ./settings/dev.nix
     ./settings/programs/shell.nix
+    <personal/modules/darwin/caddy>
+    srvos.modules.darwin.desktop
   ];
 
   services.caddy = {
@@ -24,6 +30,7 @@
     "/Users/alan/.local/state/nix/profile/bin/fish"
   ];
 
+  environment.darwinConfig = "/etc/nix-darwin/configuration.nix";
   environment.variables.LANG = "en_GB.UTF-8";
 
   launchd.user.envVariables = {
diff --git a/system/prefect.nix b/system/prefect.nix
index 662c0144..e145c304 100644
--- a/system/prefect.nix
+++ b/system/prefect.nix
@@ -25,6 +25,11 @@
     ./settings/programs/docker.nix
     ./settings/dev.nix
     ./settings/gaming.nix
+    <nixos-hardware/common/cpu/amd>
+    <nixos-hardware/common/cpu/amd/pstate.nix>
+    <nixos-hardware/common/pc/ssd>
+    <nixos-hardware/common/pc>
+    <nixos-hardware/common/gpu/nvidia>
   ];
 
   virtualisation.vmVariant = {
diff --git a/system/settings/configuration/nix.nix b/system/settings/configuration/nix.nix
index 5a9b4996..48c6b4ef 100644
--- a/system/settings/configuration/nix.nix
+++ b/system/settings/configuration/nix.nix
@@ -3,6 +3,7 @@
 , lib
 , ...
 }: {
+  imports = [ ../pin.nix ];
   nix = {
     package = pkgs.lix;
     settings = {
@@ -30,16 +31,5 @@
       automatic = lib.mkDefault true;
       options = lib.mkDefault "--delete-older-than 14d";
     };
-
-    registry =
-      if pkgs.stdenv.isDarwin
-      then {
-        nixpkgs.flake = inputs.nixpkgs;
-      } else {
-        nixpkgs.to = {
-          type = "path";
-          path = pkgs.path;
-        };
-      };
   };
 }
diff --git a/system/settings/pin.nix b/system/settings/pin.nix
new file mode 100644
index 00000000..2ff2e773
--- /dev/null
+++ b/system/settings/pin.nix
@@ -0,0 +1,14 @@
+let
+  inherit (import ../../sources.nix) sources;
+in
+{
+  nix = {
+    nixPath = [
+      "nixpkgs=flake:nixpkgs"
+    ];
+    registry.nixpkgs.to = {
+      type = "path";
+      path = sources.nixpkgs;
+    };
+  };
+}
diff --git a/user/marvin.nix b/user/marvin.nix
index c74e621c..58ee2dc3 100644
--- a/user/marvin.nix
+++ b/user/marvin.nix
@@ -15,6 +15,9 @@
     ./settings/tabnine.nix
     ./settings/user-interface.nix
     ./settings/nix.nix
+    ../private
+    ../private/ssh.nix
+    ../private/tabnine.nix
   ];
 
   home.username = "alan";
diff --git a/user/prefect.nix b/user/prefect.nix
index dc074b19..6cf31cbc 100644
--- a/user/prefect.nix
+++ b/user/prefect.nix
@@ -20,6 +20,8 @@
     ./settings/tabnine.nix
     ./settings/user-interface.nix
     ./settings/xresources.nix
+    <private>
+    <private/ssh.nix>
   ];
 
   home.username = "alan";
diff --git a/user/server.nix b/user/server.nix
index e1946206..ed25bf5c 100644
--- a/user/server.nix
+++ b/user/server.nix
@@ -7,6 +7,8 @@
     ./settings/git.nix
     ./settings/fish.nix
     ./settings/nixos.nix
+    ./settings/development/base.nix
+    <private>
   ];
   home = {
     username = "alan";
diff --git a/user/settings/base.nix b/user/settings/base.nix
index edfe692b..aa131ad3 100644
--- a/user/settings/base.nix
+++ b/user/settings/base.nix
@@ -1,4 +1,4 @@
-{ config
+args@{ config
 , lib
 , pkgs
 , ...
@@ -6,7 +6,10 @@
   imports = [
     ./neovim.nix
     ./shell.nix
+    (import <nix-index-database/home-manager-module.nix>
+      (args // { databases = import <nix-index-database/packages.nix>; }))
   ];
+
   # Let Home Manager install and manage itself.
   programs.home-manager.enable = true;
   manual = {
diff --git a/user/settings/darwin.nix b/user/settings/darwin.nix
index f65cfaa2..b4da1cd3 100644
--- a/user/settings/darwin.nix
+++ b/user/settings/darwin.nix
@@ -87,7 +87,7 @@
 
   home.shellAliases = {
     rb = "darwin-rebuild";
-    rbs = "darwin-rebuild switch --flake '.?submodules=1'";
+    rbs = "darwin-rebuild switch";
 
     dig = "dig +noall +answer";
 
diff --git a/user/settings/nix.nix b/user/settings/nix.nix
index 85f4c65d..5c8543fa 100644
--- a/user/settings/nix.nix
+++ b/user/settings/nix.nix
@@ -15,11 +15,10 @@ in
   };
 
   home.packages = with pkgs; [
-    age
-    agenix
     cached-nix-shell
     nixd
     nil
+    npins
     nix-prefetch-scripts
     nix-init
     nix-update
@@ -32,7 +31,7 @@ in
   ];
   xdg.configFile."nix-init/config.toml".source = toml.generate "config.toml" {
     maintainers = [ "alanpearce" ];
-    nixpkgs = "builtins.getFlake \"nixpkgs\"";
+    nixpkgs = "<nixpkgs>";
   };
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     nix-mode
diff --git a/user/settings/nixos.nix b/user/settings/nixos.nix
index 862ccdf5..0745b010 100644
--- a/user/settings/nixos.nix
+++ b/user/settings/nixos.nix
@@ -5,8 +5,8 @@
   ];
 
   home.shellAliases = {
-    rbs = "nixos-rebuild switch --flake '.?submodules=1'";
-    rbb = "nixos-rebuild boot --flake '.?submodules=1'";
+    rbs = "nixos-rebuild switch";
+    rbb = "nixos-rebuild boot";
     rbr = "nixos-rebuild switch --rollback";
   };
 }
diff --git a/user/settings/shell.nix b/user/settings/shell.nix
index 446c9fd4..e35564ef 100644
--- a/user/settings/shell.nix
+++ b/user/settings/shell.nix
@@ -112,8 +112,8 @@ in
 
       ho = "home-manager";
       hob = "home-manager build";
-      hos = "home-manager switch --flake '.?submodules=1' -b hm_bak_$(date +%Y%m%d%H%M)";
-      hon = "home-manager news --flake '.?submodules=1'";
+      hos = "home-manager switch";
+      hon = "home-manager news";
       hoh = "home-manager help";
       hop = "home-manager packages";
       hol = "home-manager generations";
@@ -122,7 +122,7 @@ in
       lw = "lorri watch";
       lwo = "lorri watch --once";
 
-      nsh = "nix shell";
+      nsh = "nix-shell";
       nb = "nix build";
       nd = "nix develop";
       nl = "nix log"; # shadows `coreutils.nl`, but I've never used that yet