diff --git a/nix-darwin/flake.lock b/nix-darwin/flake.lock index 8728737f..967da4e0 100644 --- a/nix-darwin/flake.lock +++ b/nix-darwin/flake.lock @@ -48,6 +48,23 @@ } }, "brew-src": { + "flake": false, + "locked": { + "lastModified": 1777253336, + "narHash": "sha256-IYVi28jebMUfQ3MDPG9IkSrLsf09Y7ShsNo+n4cmURU=", + "owner": "Homebrew", + "repo": "brew", + "rev": "b9763ee5280dc1acb3036383b3608084eebac6b7", + "type": "github" + }, + "original": { + "owner": "Homebrew", + "ref": "5.1.8", + "repo": "brew", + "type": "github" + } + }, + "brew-src_2": { "flake": false, "locked": { "lastModified": 1776478798, @@ -64,23 +81,6 @@ "type": "github" } }, - "brew-src_2": { - "flake": false, - "locked": { - "lastModified": 1774235677, - "narHash": "sha256-0ryNYmzDAeRlrzPTAgmzGH/Cgc8iv/LBN6jWGUANvIk=", - "owner": "Homebrew", - "repo": "brew", - "rev": "894a3d23ac0c8aaf561b9874b528b9cb2e839201", - "type": "github" - }, - "original": { - "owner": "Homebrew", - "ref": "5.1.1", - "repo": "brew", - "type": "github" - } - }, "claude-code-nix": { "inputs": { "flake-utils": "flake-utils", @@ -89,11 +89,11 @@ ] }, "locked": { - "lastModified": 1777126457, - "narHash": "sha256-jE5KMGZc9p2H86gCi38o2H3loV/OwICJVa8YbDmpDyg=", + "lastModified": 1777604373, + "narHash": "sha256-cQ+Z/fx5o43bD3PFZaz9yeEOVbAH1jqzdOiEP0ytW4M=", "owner": "sadjow", "repo": "claude-code-nix", - "rev": "002de6e1b2d10f4646c68af360d9dc92b89a6be9", + "rev": "8bd0a84bcfbd7e76eaa1c3421fc59861eb8a8f24", "type": "github" }, "original": { @@ -377,11 +377,11 @@ ] }, "locked": { - "lastModified": 1777151655, - "narHash": "sha256-Th3a5OZyEy4kCoyLfefnt+2dwRIrFQqYgMsayF9qzFw=", + "lastModified": 1777659959, + "narHash": "sha256-ax3229dUvNuwTQwo2o68kOQ24dvOlJ/BrVYY4miD1bI=", "owner": "nix-community", "repo": "home-manager", - "rev": "6f59831b23d03bbf4fbd13ad167ae25da294cc14", + "rev": "5c1b74905c7261e8280dcda3623dbe677a1bc158", "type": "github" }, "original": { @@ -415,11 +415,11 @@ "homebrew-cask": { "flake": false, "locked": { - "lastModified": 1777159046, - "narHash": "sha256-/3NNjeudK+0vc4ZyCIyIf80gbhDyXWjJzLUuMaPilMI=", + "lastModified": 1777656023, + "narHash": "sha256-h2aRm8tXWVRA9DN2JTwPwoZ4RZdJM4kYa6HnHamZqdo=", "owner": "homebrew", "repo": "homebrew-cask", - "rev": "191adc33f03f399c8d97c438c8a1a9acea173f0b", + "rev": "bdf39e6ffff60aa5a5b752f242094b25b96d232e", "type": "github" }, "original": { @@ -431,11 +431,11 @@ "homebrew-core": { "flake": false, "locked": { - "lastModified": 1777157463, - "narHash": "sha256-SM5CtkgezWUgd2zmIQVBcRtWpSE3VVgj5dP6nnQ5sBo=", + "lastModified": 1777660361, + "narHash": "sha256-QWdFILBUcdvYHM3pcU7h4HgwSiX8zf8vOesUz48NAFQ=", "owner": "homebrew", "repo": "homebrew-core", - "rev": "8a0c7637b90ce943cd9f4520c8a1d13df81ee276", + "rev": "bbc26e4e60ac052340242afc4a4712f2bad35704", "type": "github" }, "original": { @@ -455,11 +455,11 @@ ] }, "locked": { - "lastModified": 1777109987, - "narHash": "sha256-8obD0vLqaPIhu5q6guZ3XN70+9OGzA2GWKQC4/PNcVo=", + "lastModified": 1777434099, + "narHash": "sha256-GutKXyfGI7o89Dge4bP0yt0CQn1rqA6LyYDOH4GemdE=", "owner": "colonelpanic8", "repo": "keepbook", - "rev": "a130c6592f215e8e5727e9fd6eafd234f09f9341", + "rev": "240fe454c26e7dbdd25a2fa4f0b436bf1c4f937b", "type": "github" }, "original": { @@ -493,11 +493,11 @@ "brew-src": "brew-src_2" }, "locked": { - "lastModified": 1774720267, - "narHash": "sha256-YYftFe8jyfpQI649yfr0E+dqEXE2jznZNcYvy/lKV1U=", + "lastModified": 1777250621, + "narHash": "sha256-WynkkG0hdZ5niYPJUbVg7oMfu8MVwGGzKZ6lKmfa+O8=", "owner": "zhaofengli-wip", "repo": "nix-homebrew", - "rev": "a7760a3a83f7609f742861afb5732210fdc437ed", + "rev": "aeb2069920742d0d6570089e8b3b8620050bacf2", "type": "github" }, "original": { @@ -524,11 +524,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1776949667, - "narHash": "sha256-GMSVw35Q+294GlrTUKlx087E31z7KurReQ1YHSKp5iw=", + "lastModified": 1777425547, + "narHash": "sha256-d57AbflkNfZNoFaZDzssEq1RfPoM9dLtOGI2O+N/68Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "01fbdeef22b76df85ea168fbfe1bfd9e63681b30", + "rev": "ebc08544afa77957cc348ba72dc490ec73b87f68", "type": "github" }, "original": { diff --git a/nix-darwin/flake.nix b/nix-darwin/flake.nix index 3841485e..b031495a 100644 --- a/nix-darwin/flake.nix +++ b/nix-darwin/flake.nix @@ -15,7 +15,7 @@ }; nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew"; brew-src = { - url = "github:Homebrew/brew/5.1.7"; + url = "github:Homebrew/brew/5.1.8"; flake = false; }; @@ -71,27 +71,26 @@ ... }: let libDir = ../dotfiles/lib; - # Keep this on the currently-existing macOS account until the target user - # exists locally and its home directory has been migrated. activePrimaryUser = "kat"; targetPrimaryUser = "imalison"; - primaryUser = activePrimaryUser; personalUsers = [ activePrimaryUser targetPrimaryUser ]; - # Home Manager activation should only target accounts that exist today. - # Add targetPrimaryUser here when the macOS account is ready. - enabledHomeUsers = [ - activePrimaryUser - ]; sharedHomeModules = [ ./home/common.nix ./home/git-sync.nix ./home/syncthing.nix ]; homeForUser = user: "/Users/${user}"; - configuration = { + mkUserDescription = user: + if user == targetPrimaryUser + then "Ivan Malison" + else null; + mkConfiguration = { + primaryUser, + enabledHomeUsers ? [primaryUser], + }: { pkgs, lib, config, @@ -229,8 +228,13 @@ system.activationScripts.postActivation.text = '' echo >&2 "current-host screensaver defaults..." - launchctl asuser "$(id -u -- ${primaryUser})" sudo --user=${primaryUser} -- defaults -currentHost write com.apple.screensaver askForPassword -bool false - launchctl asuser "$(id -u -- ${primaryUser})" sudo --user=${primaryUser} -- defaults -currentHost write com.apple.screensaver askForPasswordDelay -int 0 + primary_uid="$(id -u -- ${primaryUser})" + if launchctl print "gui/$primary_uid" >/dev/null 2>&1; then + launchctl asuser "$primary_uid" sudo --user=${primaryUser} -- defaults -currentHost write com.apple.screensaver askForPassword -bool false + launchctl asuser "$primary_uid" sudo --user=${primaryUser} -- defaults -currentHost write com.apple.screensaver askForPasswordDelay -int 0 + else + echo >&2 "skipping current-host screensaver defaults; ${primaryUser} has no GUI launchd session" + fi ''; power.sleep = { @@ -287,7 +291,6 @@ essentialPkgs ++ [ pkgs.gnupg - pkgs.spotify ]; nixpkgs.config.allowUnfree = true; @@ -310,19 +313,25 @@ "ghostty" "hammerspoon" "raycast" + "spotify" "vlc" ]; masApps = { Xcode = 497799835; }; - onActivation.cleanup = "zap"; + greedyCasks = true; + onActivation = { + cleanup = "zap"; + }; }; # Auto upgrade nix package and the daemon service. - launchd.user.envVariables.PATH = config.environment.systemPath; - launchd.user.agents.hammerspoon.serviceConfig = { - ProgramArguments = ["/usr/bin/open" "-gja" "Hammerspoon"]; - RunAtLoad = true; + launchd.user = lib.mkIf (primaryUser == activePrimaryUser) { + envVariables.PATH = config.environment.systemPath; + agents.hammerspoon.serviceConfig = { + ProgramArguments = ["/usr/bin/open" "-gja" "Hammerspoon"]; + RunAtLoad = true; + }; }; programs.direnv.enable = true; @@ -354,6 +363,7 @@ lib.genAttrs personalUsers (user: { name = user; home = homeForUser user; + description = mkUserDescription user; openssh.authorizedKeys.keys = inputs.railbird-secrets.keys.kanivanKeys; }) // { @@ -380,31 +390,47 @@ users = lib.genAttrs enabledHomeUsers (_: {}); }; }; - in { - darwinConfigurations."mac-demarco-mini" = nix-darwin.lib.darwinSystem { - modules = [ - agenix.darwinModules.default - home-manager.darwinModules.home-manager - nix-homebrew.darwinModules.nix-homebrew - { - nix-homebrew = { - enable = true; - user = primaryUser; - autoMigrate = true; - package = - inputs.brew-src - // { - name = "brew-5.1.7"; - version = "5.1.7"; + mkDarwinSystem = { + primaryUser, + enabledHomeUsers ? [primaryUser], + }: + nix-darwin.lib.darwinSystem { + modules = [ + agenix.darwinModules.default + home-manager.darwinModules.home-manager + nix-homebrew.darwinModules.nix-homebrew + { + nix-homebrew = { + enable = true; + user = primaryUser; + autoMigrate = true; + package = + inputs.brew-src + // { + name = "brew-5.1.8"; + version = "5.1.8"; + }; + taps = { + "homebrew/homebrew-core" = inputs.homebrew-core; + "homebrew/homebrew-cask" = inputs.homebrew-cask; }; - taps = { - "homebrew/homebrew-core" = inputs.homebrew-core; - "homebrew/homebrew-cask" = inputs.homebrew-cask; }; - }; - } - configuration - ]; + } + (mkConfiguration {inherit primaryUser enabledHomeUsers;}) + ]; + }; + in { + # The default remains on the currently existing macOS account. Switch to + # mac-demarco-mini-imalison after the target login account and home are in + # place. + darwinConfigurations."mac-demarco-mini" = mkDarwinSystem { + primaryUser = activePrimaryUser; + enabledHomeUsers = [activePrimaryUser]; + }; + + darwinConfigurations."mac-demarco-mini-imalison" = mkDarwinSystem { + primaryUser = targetPrimaryUser; + enabledHomeUsers = [targetPrimaryUser]; }; # Expose the package set, including overlays, for convenience. diff --git a/nix-darwin/home/common.nix b/nix-darwin/home/common.nix index 73c346e4..4e0db4c4 100644 --- a/nix-darwin/home/common.nix +++ b/nix-darwin/home/common.nix @@ -153,7 +153,11 @@ in { done < "$password_store_gpg_id" if [ "$needs_import" -eq 1 ]; then - ${importGpgKeyScript} + if [ -n "''${XDG_RUNTIME_DIR:-}" ] && [ -r "${gpgKeyPath}" ] && [ -r "${gpgPassphrasePath}" ]; then + ${importGpgKeyScript} + else + echo "Skipping GPG key import; agenix runtime secrets are not available yet" >&2 + fi fi fi ''; diff --git a/nix-darwin/justfile b/nix-darwin/justfile index a835cb2a..10cda535 100644 --- a/nix-darwin/justfile +++ b/nix-darwin/justfile @@ -1,8 +1,21 @@ hostname := "mac-demarco-mini" +target-hostname := "mac-demarco-mini-imalison" + +build: + sudo -H /run/current-system/sw/bin/nix run nix-darwin -- build --flake .#{{hostname}} + +build-imalison: + sudo -H /run/current-system/sw/bin/nix run nix-darwin -- build --flake .#{{target-hostname}} + +check-imalison: + ./scripts/check-imalison-ready.sh switch: sudo -H /run/current-system/sw/bin/nix run nix-darwin -- switch --flake .#{{hostname}} +switch-imalison: check-imalison + sudo -H /run/current-system/sw/bin/nix run nix-darwin -- switch --flake .#{{target-hostname}} + update: /run/current-system/sw/bin/nix flake update just switch diff --git a/nix-darwin/scripts/check-imalison-ready.sh b/nix-darwin/scripts/check-imalison-ready.sh new file mode 100755 index 00000000..914fc688 --- /dev/null +++ b/nix-darwin/scripts/check-imalison-ready.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +target_user="${TARGET_USER:-imalison}" +target_home="${TARGET_HOME:-/Users/${target_user}}" +dotfiles_checkout="${DOTFILES_CHECKOUT:-${target_home}/dotfiles}" + +failures=0 + +check() { + local description="$1" + shift + + if "$@" >/dev/null 2>&1; then + printf 'ok: %s\n' "$description" + else + printf 'missing: %s\n' "$description" >&2 + failures=$((failures + 1)) + fi +} + +check "macOS user ${target_user} exists" id -u "$target_user" +check "home directory ${target_home} exists" sudo test -d "$target_home" +check "home directory is owned by ${target_user}" sudo sh -c '[ "$(stat -f "%Su" "$1")" = "$2" ]' sh "$target_home" "$target_user" +check "dotfiles checkout exists at ${dotfiles_checkout}" sudo test -d "$dotfiles_checkout/.git" +check "nix-darwin checkout exists under target home" sudo test -d "$dotfiles_checkout/nix-darwin" +check "SSH identity exists for agenix and git" sudo test -r "$target_home/.ssh/id_ed25519" +check "password store exists for pass/git-sync" sudo test -d "$target_home/.password-store" +check "org checkout exists for git-sync" sudo test -d "$target_home/org" + +if [ "$failures" -ne 0 ]; then + cat >&2 <