{ pkgs , lib , ... }: let # Managed block in /etc/hosts. Same markers the ansible blockinfile uses, so # an existing block is rewritten in place rather than duplicated. cleoHosts = [ "dev.wellthy.com" "www.dev.wellthy.com" "app.dev.wellthy.com" "www.app.dev.wellthy.com" "auth.dev.wellthy.com" "internal-api.dev.wellthy.com" "local-api.hicleo.com" "local-identity.hicleo.com" "local-file-ingestion.hicleo.com" "local-eligibility.hicleo.com" ]; cleoHostsBlock = pkgs.writeText "cleo-local-dev-hosts" ( lib.concatMapStrings (h: "127.0.0.1 ${h}\n") cleoHosts ); ansibleRequired = { taps = [ "fwdcloudsec/granted" # aws sso utility "felipeelias/tap" # claude-statusline "oven-sh/bun" # bun "schpet/tap" ## Excluded intentionally # "sst/tap" # opencode ]; brews = [ "allure" "aws-sso-util" "awscli" "ccusage" "doppler" "fd" "felipeelias/tap/claude-statusline" "oven-sh/bun/bun" "fwdcloudsec/granted/granted" "schpet/tap/linear" "gh" "jq" "maven" "snyk-cli" "ldcli" ## Excluded intentionally # "rg" # "gdal" # "sst/tap/opencode" # "libpq@17" # "node@22" ]; casks = [ "1password-cli" "aws-vpn-client" "chromedriver" "copilot-cli" "docker-desktop" "expo-orbit" "zulu@17" "ngrok" ## Excluded intentionally # "visual-studio-code" # app installed by brew; home-manager owns settings + extensions # "jetbrains-toolbox" ]; }; in { ids.gids.nixbld = 350; security.pam.services.sudo_local.touchIdAuth = true; # Set vim as default editor environment.variables.EDITOR = "vim"; environment.variables.VISUAL = "vim"; environment.variables.GIT_EDITOR = "vim"; environment.variables.HOMEBREW_NO_ANALYTICS = "1"; # GUI apps (Android Studio, Dock-launched tools) don't see home-manager session # vars, so mirror the XDG-relocated ones here with absolute paths. launchd.user.envVariables = { CLAUDE_CONFIG_DIR = "/Users/matthew.bessette/.config/claude"; GRADLE_USER_HOME = "/Users/matthew.bessette/.local/share/gradle"; ANDROID_USER_HOME = "/Users/matthew.bessette/.local/share/android"; CP_HOME_DIR = "/Users/matthew.bessette/.local/share/cocoapods"; }; environment.systemPackages = with pkgs; [ vim git wget curl python3 postgresql_17 # valkey-cli for the ~/Projects/redis-proxy ElastiCache proxy valkey # wellthy.com: psycopg2 builds from source (needs pg_config + libpq headers) postgresql_17.pg_config postgresql_17.dev # wellthy.com: python-magic loads libmagic; gettext for compilemessages file gettext openssl openssl.dev # default outputs are bin+man only; the shared libs live in `out` openssl.out home-manager ttyd xcodes xz # node 24.x from unstable (cached); the pinnedNode 24.19.0 rev had no cache.nixos.org binaries unstable.nodejs_24 unstable.yarn # iOS simulator UI driving (tap/scroll/type) for screenshots and e2e flows unstable.maestro unstable.idb-companion act ]; # Link lib/ and include/ into /run/current-system/sw so native builds (psycopg2) # and runtime lookups (python-magic -> libmagic) have a stable path. environment.pathsToLink = [ "/lib" "/include" ]; # python-magic only searches /opt/local/lib, /usr/local/lib and /opt/homebrew/lib # (DYLD_* variables don't survive macOS system binaries). Point the last one at the # nix libmagic through the stable system profile path. Only touches the path when # it is free or already our own link, so a Homebrew libmagic is never overwritten. system.activationScripts.postActivation.text = '' dest=/opt/homebrew/lib/libmagic.dylib ours=/run/current-system/sw/lib/libmagic.dylib if [ -d /opt/homebrew/lib ] && { { [ ! -e "$dest" ] && [ ! -L "$dest" ]; } || [ "$(readlink "$dest")" = "$ours" ]; }; then ln -sfn "$ours" "$dest" fi # /etc/hosts is owned by macOS (and holds hand-written entries), so manage only # the CLEO LOCAL DEV HOSTS block: replace it in place, or append it if missing. hosts=/etc/hosts begin="# BEGIN CLEO LOCAL DEV HOSTS" end="# END CLEO LOCAL DEV HOSTS" tmp=$(mktemp) if grep -qxF "$begin" "$hosts"; then awk -v begin="$begin" -v end="$end" -v blk="${cleoHostsBlock}" ' $0 == begin { print; while ((getline l < blk) > 0) print l; skip = 1; next } $0 == end { skip = 0 } !skip { print } ' "$hosts" > "$tmp" else { cat "$hosts"; printf '\n%s\n' "$begin"; cat ${cleoHostsBlock}; printf '%s\n' "$end"; } > "$tmp" fi if ! cmp -s "$tmp" "$hosts"; then cat "$tmp" > "$hosts" fi rm -f "$tmp" ''; # Add Homebrew to PATH environment.systemPath = [ "/opt/homebrew/bin" "/opt/homebrew/sbin" "/Users/matthew.bessette/.local/bin" ]; system.primaryUser = "matthew.bessette"; users.users."matthew.bessette" = { name = "matthew.bessette"; home = "/Users/matthew.bessette"; }; services.openssh = { enable = true; extraConfig = '' StrictModes no # Deny everyone by default unless they match the subnet rule Match Address !192.168.0.0/16 DenyUsers * ''; }; # Homebrew for Casks and specific binaries # In a nix-darwin setup, Homebrew packages are not actually stored inside the Nix store. # Instead, nix-darwin acts as a manager that triggers the standard Homebrew installation # process on your macOS system. homebrew = { enable = true; onActivation.cleanup = "uninstall"; onActivation.autoUpdate = true; onActivation.upgrade = true; # global.autoUpdate = true; # Each list is (ansible-managed set) ++ (nix-only extras), deduped. With # cleanup = "uninstall" above, anything NOT listed here gets removed on # activation — so ansibleRequired must be merged in or nix would clobber it. taps = lib.unique ( ansibleRequired.taps ++ [ # nix-only taps go here ] ); brews = lib.unique ( ansibleRequired.brews ++ [ "biome" "jira-cli" ] ); # visual-studio-code is installed by Homebrew (in ansibleRequired.casks) so # Homebrew owns the .app; home-manager (cleo.home.nix) owns settings + # extensions only (programs.vscode with package = null) — no second copy. casks = lib.unique ( ansibleRequired.casks ++ [ "android-commandlinetools" "android-platform-tools" "bruno" "figma" "kopiaui" "libreoffice" "obsidian" "postico" "sublime-text" "spotify" "yubico-yubikey-manager" "zoom" ] ); }; nix = { settings = { experimental-features = "nix-command flakes"; auto-optimise-store = true; }; gc = { automatic = true; interval = { Weekday = 0; Hour = 2; Minute = 0; }; # Sunday at 2:00 AM options = "--delete-older-than 7d"; }; }; system.stateVersion = 4; }