From 925dd4114a40a0641f4ffeee6998369be16bc490 Mon Sep 17 00:00:00 2001 From: Alex Maldonado Date: Sun, 2 Aug 2026 00:29:15 -0400 Subject: [PATCH] feat: initial macos setup --- .gitignore | 2 ++ .ignore | 2 ++ flake.lock | 22 +++++++++++++ flake.nix | 62 +++++++++++++++++++++++++----------- home/alex/default.nix | 36 +++++++++++++-------- home/modules/ghostty.nix | 11 ++++--- home/modules/vscode.nix | 10 ++++-- home/modules/zed.nix | 2 +- home/modules/zsh.nix | 11 +++++-- hosts/seasoned/default.nix | 21 +++++++++++++ justfile | 14 ++++++--- modules/darwin.nix | 64 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 210 insertions(+), 47 deletions(-) create mode 100644 .ignore create mode 100644 hosts/seasoned/default.nix create mode 100644 modules/darwin.nix diff --git a/.gitignore b/.gitignore index ca66999..6937f43 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ result result-* secrets.d/ + +.DS_Store diff --git a/.ignore b/.ignore new file mode 100644 index 0000000..5ca0973 --- /dev/null +++ b/.ignore @@ -0,0 +1,2 @@ +.DS_Store + diff --git a/flake.lock b/flake.lock index d636a24..e178de5 100644 --- a/flake.lock +++ b/flake.lock @@ -102,6 +102,27 @@ "type": "github" } }, + "nix-darwin": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1783744694, + "narHash": "sha256-2cp6N3rrwnGYLTx9l6N+NI+kwrCWxvJUbj5WJhvB29A=", + "owner": "nix-darwin", + "repo": "nix-darwin", + "rev": "c3e90c89649b07d1a96e4b9dd6cd0d6e44b91a74", + "type": "github" + }, + "original": { + "owner": "nix-darwin", + "ref": "nix-darwin-26.05", + "repo": "nix-darwin", + "type": "github" + } + }, "nix4vscode": { "inputs": { "nixpkgs": [ @@ -230,6 +251,7 @@ "inputs": { "globalprotect-openconnect": "globalprotect-openconnect", "home-manager": "home-manager", + "nix-darwin": "nix-darwin", "nix4vscode": "nix4vscode", "nixpkgs": "nixpkgs_4", "onedark-yazi": "onedark-yazi", diff --git a/flake.nix b/flake.nix index 88f1a47..92a25b0 100644 --- a/flake.nix +++ b/flake.nix @@ -9,6 +9,12 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + # macOS system management (paired with nixpkgs 26.05). + nix-darwin = { + url = "github:nix-darwin/nix-darwin/nix-darwin-26.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + globalprotect-openconnect.url = "github:yuezk/GlobalProtect-openconnect"; plasma-manager = { @@ -28,44 +34,62 @@ }; }; - outputs = { self, nixpkgs, home-manager, globalprotect-openconnect, ... }@inputs: + outputs = { self, nixpkgs, home-manager, nix-darwin, globalprotect-openconnect, ... }@inputs: let - system = "x86_64-linux"; + linuxSystem = "x86_64-linux"; + + # Home Manager wiring shared by the NixOS (Linux) hosts. + # plasma-manager is Linux-only, so it lives here rather than in the + # darwin block below. + nixosHome = { + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + backupFileExtension = "backup"; + users.alex = import ./home/alex; + extraSpecialArgs = { inherit inputs; isDarwin = false; }; + sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ]; + }; + }; in { nixosConfigurations = { - - # To add a new machine, duplicate this block and change the name + + # To add a new Linux machine, duplicate this block and change the name. whitegrizzly = nixpkgs.lib.nixosSystem { - inherit system; - specialArgs = { inherit inputs; }; + system = linuxSystem; + specialArgs = { inherit inputs; }; modules = [ ./hosts/whitegrizzly home-manager.nixosModules.home-manager - { - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - users.alex = import ./home/alex; - extraSpecialArgs = { inherit inputs; }; - sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ]; - }; - } + nixosHome ]; }; oreo = nixpkgs.lib.nixosSystem { - inherit system; - specialArgs = { inherit inputs; }; + system = linuxSystem; + specialArgs = { inherit inputs; }; modules = [ ./hosts/oreo home-manager.nixosModules.home-manager + nixosHome + ]; + }; + }; + + darwinConfigurations = { + + seasoned = nix-darwin.lib.darwinSystem { + specialArgs = { inherit inputs; }; + modules = [ + ./hosts/seasoned + home-manager.darwinModules.home-manager { home-manager = { useGlobalPkgs = true; useUserPackages = true; + backupFileExtension = "backup"; users.alex = import ./home/alex; - extraSpecialArgs = { inherit inputs; }; - sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ]; + extraSpecialArgs = { inherit inputs; isDarwin = true; }; }; } ]; diff --git a/home/alex/default.nix b/home/alex/default.nix index 70c28b6..bbb2ef6 100644 --- a/home/alex/default.nix +++ b/home/alex/default.nix @@ -1,24 +1,34 @@ -{ pkgs, ... }: { +{ pkgs, lib, isDarwin, ... }: + +let + # Modules that only make sense on Linux, either because they use systemd, + # KDE/Plasma, or a package that nixpkgs only builds for Linux. On macOS the + # equivalents are installed as Homebrew casks (see modules/darwin.nix). + linuxOnly = lib.optionals (!isDarwin) [ + ../modules/plasma.nix + ../modules/dropbox.nix + ../modules/globalprotect.nix + ../modules/gimp.nix + ../modules/libreoffice.nix + ../modules/masterpdfeditor.nix + ../modules/pymol.nix + ../modules/zoom.nix + ]; +in +{ home.username = "alex"; - home.homeDirectory = "/home/alex"; + home.homeDirectory = if isDarwin then "/Users/alex" else "/home/alex"; home.stateVersion = "25.11"; home.sessionPath = [ "$HOME/.local/bin" ]; imports = [ ../modules/datalad.nix ../modules/docker.nix - ../modules/dropbox.nix ../modules/fonts.nix ../modules/ghostty.nix - ../modules/gimp.nix - ../modules/globalprotect.nix ../modules/helix.nix ../modules/hyperfine.nix - ../modules/libreoffice.nix - ../modules/masterpdfeditor.nix ../modules/pixi.nix - ../modules/plasma.nix - ../modules/pymol.nix ../modules/python.nix ../modules/rust.nix ../modules/ssh.nix @@ -28,21 +38,21 @@ ../modules/yazi.nix ../modules/zellij.nix ../modules/zig.nix - ../modules/zoom.nix ../modules/zsh.nix ./git.nix ./gh.nix - ]; + ] ++ linuxOnly; home.packages = with pkgs; [ atool httpie just - spotify - brave git-lfs typst unzip glow + ] ++ lib.optionals (!isDarwin) [ + spotify + brave ]; } diff --git a/home/modules/ghostty.nix b/home/modules/ghostty.nix index 460645f..85a0e47 100644 --- a/home/modules/ghostty.nix +++ b/home/modules/ghostty.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, ... }: +{ pkgs, lib, isDarwin, ... }: let baseKeybinds = [ "ctrl+t=new_tab" @@ -16,7 +16,10 @@ in { programs.ghostty = { enable = true; - + # nixpkgs `ghostty` is the Linux/GTK build (Linux-only meta.platforms). + # On macOS use `ghostty-bin`, the repackaged official .dmg. + package = if isDarwin then pkgs.ghostty-bin else pkgs.ghostty; + settings = { # Font Settings "font-family" = "Roboto Mono"; @@ -93,8 +96,8 @@ in # Keybindings (Tabs & Splits) "keybind" = baseKeybinds - ++ lib.optionals pkgs.stdenv.isDarwin [ "super+d=unbind" ]; - } // lib.optionalAttrs pkgs.stdenv.isDarwin { + ++ lib.optionals isDarwin [ "super+d=unbind" ]; + } // lib.optionalAttrs isDarwin { "macos-titlebar-style" = "transparent"; "macos-icon" = "official"; }; diff --git a/home/modules/vscode.nix b/home/modules/vscode.nix index 5a1f999..d08a06f 100644 --- a/home/modules/vscode.nix +++ b/home/modules/vscode.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: { +{ pkgs, lib, isDarwin, ... }: { programs.vscodium = { enable = true; package = pkgs.vscodium; @@ -18,12 +18,16 @@ rust-lang.rust-analyzer timonwong.shellcheck unifiedjs.vscode-mdx - yzane.markdown-pdf ]) ++ pkgs.nix4vscode.forOpenVsx [ "akamud.vscode-theme-onedark" "astral-sh.ty" "modular-mojotools.vscode-mojo" - ]; + ] ++ lib.optionals (!isDarwin) (with pkgs.vscode-extensions; [ + # markdown-pdf pins ungoogled-chromium (Linux-only) as its PDF + # renderer. On macOS, install it from the marketplace by hand and set + # markdown-pdf.executablePath to Chrome/Brave, or render via typst. + yzane.markdown-pdf + ]); userSettings = { "editor.fontFamily" = "'JetBrains Mono', monospace"; diff --git a/home/modules/zed.nix b/home/modules/zed.nix index be6ee8f..ef1ef64 100644 --- a/home/modules/zed.nix +++ b/home/modules/zed.nix @@ -2,7 +2,7 @@ { programs.zed-editor = { enable = true; - package = pkgs.zed-editor-fhs; + package = pkgs.zed-editor; mutableUserSettings = true; userSettings = { diff --git a/home/modules/zsh.nix b/home/modules/zsh.nix index 99b043c..dd61bed 100644 --- a/home/modules/zsh.nix +++ b/home/modules/zsh.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, lib, isDarwin, ... }: { programs.zsh = { @@ -12,7 +12,7 @@ la = "ls -A"; l = "ls -CF"; tp = "tree -I '__init__*' -I '__pycache__'"; - clear = "/run/current-system/sw/bin/clear"; + clear = "${pkgs.ncurses}/bin/clear"; zide = "zellij --layout ide"; }; @@ -45,6 +45,11 @@ ''; }; home.sessionVariables = { - TERMINFO_DIRS = "${pkgs.ghostty}/share/terminfo:${pkgs.ncurses}/share/terminfo"; + # ghostty (GTK) ships terminfo under $out/share on Linux. The macOS + # ghostty-bin bundles its own, so only add ncurses there. + TERMINFO_DIRS = lib.concatStringsSep ":" ( + lib.optional (!isDarwin) "${pkgs.ghostty}/share/terminfo" + ++ [ "${pkgs.ncurses}/share/terminfo" ] + ); }; } diff --git a/hosts/seasoned/default.nix b/hosts/seasoned/default.nix new file mode 100644 index 0000000..10d7bfb --- /dev/null +++ b/hosts/seasoned/default.nix @@ -0,0 +1,21 @@ +{ ... }: +{ + imports = [ + ../../modules/darwin.nix + ]; + + # Apple Silicon. For an Intel Mac use "x86_64-darwin". + nixpkgs.hostPlatform = "aarch64-darwin"; + + networking.hostName = "seasoned"; + networking.localHostName = "seasoned"; + networking.computerName = "seasoned"; + + system.primaryUser = "alex"; + users.users.alex = { + name = "alex"; + home = "/Users/alex"; + }; + + system.stateVersion = 6; +} diff --git a/justfile b/justfile index 78cf050..dc3869c 100644 --- a/justfile +++ b/justfile @@ -1,14 +1,20 @@ set positional-arguments -host := `hostname` +# Flake host key. On macOS the LocalHostName is what matches the flake key +# (after the first rebuild); on Linux it's the plain hostname. +# Override: just host=myname rebuild +host := if os() == "macos" { `scutil --get LocalHostName` } else { `hostname` } + +# Pick the rebuild tool for the current OS. +rebuild-cmd := if os() == "macos" { "darwin-rebuild" } else { "nixos-rebuild" } # Default: list available recipes. default: @just --list -# Rebuild the system and switch immediately +# Rebuild the system and switch immediately. Works on NixOS and macOS. rebuild: - sudo nixos-rebuild switch --flake .#{{host}} + sudo {{rebuild-cmd}} switch --flake .#{{host}} # Update flake.lock update: @@ -18,7 +24,7 @@ update: clean: sudo nix-collect-garbage --delete-older-than 7d sudo nix-store --optimise - sudo nixos-rebuild boot --flake .#{{host}} + sudo {{ if os() == "macos" { "darwin-rebuild switch" } else { "nixos-rebuild boot" } }} --flake .#{{host}} # Generate Ed25519 SSH keys for each named service (default: github gradescope). # Override: just gen-keys gitlab bitbucket diff --git a/modules/darwin.nix b/modules/darwin.nix new file mode 100644 index 0000000..1512c0c --- /dev/null +++ b/modules/darwin.nix @@ -0,0 +1,64 @@ +{ inputs, pkgs, ... }: +{ + # We installed Nix via the *Determinate* package (the installer + # asks on macOS Tahoe), Determinate manages /etc/nix/nix.conf itself and + # nix-darwin must NOT. Thus, we have to set `nix.enable = false;`. + nix.enable = false; + + nixpkgs.config.allowUnfree = true; + + nixpkgs.overlays = [ inputs.nix4vscode.overlays.default ]; + + environment.systemPackages = with pkgs; [ + wget + curl + git + tree + coreutils + ]; + + programs.zsh.enable = true; + + homebrew = { + enable = true; + onActivation = { + autoUpdate = false; + upgrade = false; + cleanup = "zap"; + }; + + casks = [ + "1password" + "1password-cli" + "dropbox" + "zoom" + "spotify" + "brave-browser" + "gimp" + "orbstack" + ]; + }; + + # macOS preferences, declaratively. Tweak to taste. + # Full option list: https://nix-darwin.github.io/nix-darwin/manual/ + system.defaults = { + NSGlobalDomain = { + KeyRepeat = 2; + InitialKeyRepeat = 15; + AppleShowAllExtensions = true; + ApplePressAndHoldEnabled = false; + }; + dock = { + autohide = true; + show-recents = false; + mru-spaces = false; + }; + finder = { + AppleShowAllFiles = true; + FXPreferredViewStyle = "Nlsv"; + ShowPathbar = true; + }; + trackpad.Clicking = false; + }; +} +