diff --git a/flake.lock b/flake.lock index fb9b627..9d72b1b 100644 --- a/flake.lock +++ b/flake.lock @@ -337,6 +337,42 @@ "type": "github" } }, + "manifest": { + "locked": { + "lastModified": 1752588656, + "narHash": "sha256-clKPzQ43eDpukeiGHzXmd1hGb2s4N+MWXAzQ5u5+pHQ=", + "owner": "rrvsh", + "repo": "manifest", + "rev": "365902fba994f30469298dee0c98a5fc0f41ec38", + "type": "github" + }, + "original": { + "owner": "rrvsh", + "repo": "manifest", + "type": "github" + } + }, + "nix-darwin": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1751313918, + "narHash": "sha256-HsJM3XLa43WpG+665aGEh8iS8AfEwOIQWk3Mke3e7nk=", + "owner": "nix-darwin", + "repo": "nix-darwin", + "rev": "e04a388232d9a6ba56967ce5b53a8a6f713cdfcf", + "type": "github" + }, + "original": { + "owner": "nix-darwin", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, "nix-index-database": { "inputs": { "nixpkgs": [ @@ -467,6 +503,8 @@ "impermanence": "impermanence", "import-tree": "import-tree", "make-shell": "make-shell", + "manifest": "manifest", + "nix-darwin": "nix-darwin", "nix-index-database": "nix-index-database", "nixpkgs": "nixpkgs", "nur": "nur", diff --git a/flake.nix b/flake.nix index 86b2997..dcb6882 100644 --- a/flake.nix +++ b/flake.nix @@ -1,11 +1,14 @@ { outputs = - inputs: + { self, ... }@inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ( (inputs.import-tree ./nix) // { systems = import inputs.systems; - flake.paths.root = ./.; + flake = { + inherit self; + paths.root = ./.; + }; } ); inputs = { @@ -22,6 +25,11 @@ url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; + # nix darwin provides declarative mac configuration + nix-darwin = { + url = "github:nix-darwin/nix-darwin/master"; + inputs.nixpkgs.follows = "nixpkgs"; + }; # the nix user repository for mainly firefox extensions nur = { url = "github:nix-community/NUR"; @@ -63,6 +71,8 @@ files.url = "github:mightyiam/files"; # text.nix lets us easily define markdown text to pass to files text.url = "github:rrvsh/text.nix"; + # manifest lets us define all hosts in one file + manifest.url = "github:rrvsh/manifest"; # make-shells. creates devShells and checks make-shell = { url = "github:nicknovitski/make-shell"; diff --git a/nix/configurations.nix b/nix/configurations.nix index 1d27ceb..3cae4bd 100644 --- a/nix/configurations.nix +++ b/nix/configurations.nix @@ -6,28 +6,30 @@ }: let inherit (lib) nixosSystem; + inherit (inputs.nix-darwin.lib) darwinSystem; inherit (lib.lists) optional; inherit (lib.attrsets) mapAttrs; inherit (cfg.lib.modules) forAllUsers'; + inherit (config.manifest) hosts; cfg = config.flake; - globalCfg = name: hostConfig: { + globalCfg = hostName: hostConfig: { useGlobalPkgs = true; useUserPackages = true; - extraSpecialArgs = { - inherit hostConfig; - hostName = name; - }; + extraSpecialArgs = { inherit hostName hostConfig; }; sharedModules = [ cfg.modules.homeManager.default ]; users = forAllUsers' (name: _: cfg.modules.homeManager.${name}); }; - hosts = cfg.manifest.hosts or { }; mkConfigurations = class: hosts: mapAttrs ( name: value: if class == "nixos" then nixosSystem { - specialArgs.hostName = name; + specialArgs = { + inherit (config.flake) self; + hostName = name; + hostConfig = value; + }; modules = [ cfg.modules.nixos.default inputs.home-manager.nixosModules.home-manager @@ -35,6 +37,20 @@ let (value.extraCfg or { }) ] ++ optional value.graphical cfg.modules.nixos.graphical; } + else if class == "darwin" then + darwinSystem { + specialArgs = { + inherit (config.flake) self; + hostName = name; + hostConfig = value; + }; + modules = [ + cfg.modules.darwin.default + inputs.home-manager.darwinModules.home-manager + { home-manager = globalCfg name value; } + (value.extraCfg or { }) + ] ++ optional value.graphical cfg.modules.darwin.graphical; + } else { } ) hosts; @@ -42,4 +58,5 @@ in { imports = [ inputs.home-manager.flakeModules.home-manager ]; flake.nixosConfigurations = mkConfigurations "nixos" hosts.nixos; + flake.darwinConfigurations = mkConfigurations "darwin" hosts.darwin; } diff --git a/nix/files/readme.nix b/nix/files/readme.nix index a8eccbf..6209325 100644 --- a/nix/files/readme.nix +++ b/nix/files/readme.nix @@ -24,8 +24,8 @@ parts."Structure" = # markdown '' The system configurations are defined in [`flake.manifest`](nix/manifest.nix). - `flake.manifest.owner` provides the attributes for the administrator user, including username and pubkey. - `flake.manifest.hosts` provides the specifications for the system configurations that should be exposed by the flake as nixosConfigurations. + `manifest.owner` provides the attributes for the administrator user, including username and pubkey. + `manifest.hosts` provides the specifications for the system configurations that should be exposed by the flake as nixosConfigurations. `flake.modules.nixos.*` provide NixOS options and configurations. The attribute `flake.modules.nixos.default` provides options that will be applied to every system of that class. You can use it as seen [here](nix/modules/flake/home-manager.nix): diff --git a/nix/flake-parts/debug.nix b/nix/flake-parts/debug.nix deleted file mode 100644 index 38e2cb3..0000000 --- a/nix/flake-parts/debug.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - debug = true; -} diff --git a/nix/flake-parts/flake-parts.nix b/nix/flake-parts/flake-parts.nix new file mode 100644 index 0000000..4f0d093 --- /dev/null +++ b/nix/flake-parts/flake-parts.nix @@ -0,0 +1,10 @@ +{ inputs, ... }: +{ + debug = true; + imports = [ + inputs.make-shell.flakeModules.default + inputs.manifest.flakeModules.default + inputs.flake-parts.flakeModules.modules + inputs.text.flakeModules.default + ]; +} diff --git a/nix/flake-parts/make-shell.nix b/nix/flake-parts/make-shell.nix deleted file mode 100644 index 66ca600..0000000 --- a/nix/flake-parts/make-shell.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ inputs, ... }: -{ - #TODO: add to readme - imports = [ inputs.make-shell.flakeModules.default ]; -} diff --git a/nix/flake-parts/modules.nix b/nix/flake-parts/modules.nix deleted file mode 100644 index 1c75663..0000000 --- a/nix/flake-parts/modules.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ inputs, ... }: -{ - imports = [ inputs.flake-parts.flakeModules.modules ]; -} diff --git a/nix/flake-parts/text.nix b/nix/flake-parts/text.nix deleted file mode 100644 index 81b2f51..0000000 --- a/nix/flake-parts/text.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ inputs, ... }: -{ - imports = [ inputs.text.flakeModules.default ]; -} diff --git a/nix/homes/rafiq/_nvf/languages.nix b/nix/homes/rafiq/_nvf/languages.nix index cc3dd8c..fbeaf85 100644 --- a/nix/homes/rafiq/_nvf/languages.nix +++ b/nix/homes/rafiq/_nvf/languages.nix @@ -4,7 +4,8 @@ enableTreesitter = true; bash.enable = true; clang.enable = true; - csharp.enable = true; + # broken on macos + # csharp.enable = true; css.enable = true; go.enable = true; html.enable = true; @@ -26,6 +27,7 @@ }; rust.enable = true; rust.crates.enable = true; + tailwind.enable = true; ts.enable = true; ts.extensions.ts-error-translator.enable = true; typst.enable = true; diff --git a/nix/homes/rafiq/darwin.nix b/nix/homes/rafiq/darwin.nix new file mode 100644 index 0000000..873dbcd --- /dev/null +++ b/nix/homes/rafiq/darwin.nix @@ -0,0 +1,21 @@ +{ lib, ... }: +let + inherit (lib.modules) mkIf; +in +{ + flake.modules.homeManager.rafiq = + { + pkgs, + config, + hostName, + hostConfig, + ... + }: + mkIf (pkgs.system == "aarch64-darwin" || pkgs.system == "x86_64-darwin") { + home.file."Library/Application Support/aichat/config.yaml".text = '' + model: gemini:gemini-2.0-flash + clients: + - type: gemini + ''; + }; +} diff --git a/nix/homes/rafiq/default.nix b/nix/homes/rafiq/default.nix index ed01690..86b4733 100644 --- a/nix/homes/rafiq/default.nix +++ b/nix/homes/rafiq/default.nix @@ -45,6 +45,7 @@ in ]; }; programs = { + mise.enable = true; nvf.enable = true; nvf.settings.vim = { syntaxHighlighting = true; diff --git a/nix/homes/rafiq/desktop/darwin.nix b/nix/homes/rafiq/desktop/darwin.nix new file mode 100644 index 0000000..892031c --- /dev/null +++ b/nix/homes/rafiq/desktop/darwin.nix @@ -0,0 +1,31 @@ +{ + flake.modules.darwin.graphical.homebrew = { + brews = [ + "mise" + "docker" + ]; + casks = [ + "ghostty" + "slack" + "gitify" + "telegram" + "vial" + "linear-linear" + "chatgpt" + "spotify" + ]; + }; + flake.modules.homeManager.rafiq = { + # make sure brew is on the path for M1 + programs.zsh.initContent = '' + if [[ $(uname -m) == 'arm64' ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + fi + ''; + programs.fish.shellInit = '' + if test (uname -m) = "arm64" + eval (/opt/homebrew/bin/brew shellenv) + end + ''; + }; +} diff --git a/nix/homes/rafiq/desktop/default.nix b/nix/homes/rafiq/desktop/default.nix index 9eb1fc4..277d445 100644 --- a/nix/homes/rafiq/desktop/default.nix +++ b/nix/homes/rafiq/desktop/default.nix @@ -1,75 +1,9 @@ +{ lib, inputs, ... }: { - lib, - inputs, - config, - ... -}: -let - cfg = config.flake; -in -{ - allowedUnfreePackages = [ - "stremio-shell" - "stremio-server" - "steam" - "steam-unwrapped" - ]; - flake.modules.nixos.graphical = - { config, pkgs, ... }: - { - fonts.packages = [ pkgs.font-awesome ]; - services.getty.autologinUser = cfg.admin.username; - # Start Hyprland at boot only if not connecting through SSH - environment.loginShellInit = # sh - '' - if [[ -z "$SSH_CLIENT" && -z "$SSH_CONNECTION" ]]; then - if uwsm check may-start; then - exec uwsm start hyprland-uwsm.desktop - fi - fi - ''; - environment.variables = { - # Get Electron apps to use Wayland - ELECTRON_OZONE_PLATFORM_HINT = "auto"; - NIXOS_OZONE_WL = "1"; - }; - programs = { - hyprland = { - enable = true; - # Use UWSM to have each process controlled by systemd init - withUWSM = true; - }; - steam = { - enable = true; - gamescopeSession.enable = true; - }; - }; - security.pam.services.hyprlock = { }; - services.sunshine = { - enable = true; - capSysAdmin = true; - openFirewall = true; - settings = { - sunshine_name = config.networking.hostName; - origin_pin_allowed = "wan"; - origin_web_ui_allowed = "wan"; - }; - applications = { }; - }; - # spotifyd - networking.firewall.allowedTCPPorts = [ 5353 ]; - networking.firewall.allowedUDPPorts = [ 5353 ]; - }; flake.modules.homeManager.rafiq = - { - pkgs, - config, - hostName, - hostConfig, - ... - }: + { pkgs, config, ... }: let - inherit (lib.modules) mkMerge mkIf; + inherit (lib.modules) mkIf; inherit (builtins) map listToAttrs; inherit (lib.lists) findFirstIndex; inherit (inputs.nur.legacyPackages.${pkgs.stdenv.hostPlatform.system}.repos.rycee) firefox-addons; @@ -104,185 +38,24 @@ in targets = { firefox.colorTheme.enable = true; firefox.profileNames = syncedProfiles; - waybar.addCss = false; }; }; - persistDirs = [ - "docs" - "repos" - "vids" - "tmp" - ".cache/Smart Code ltd/Stremio" - ".local/share/Smart Code ltd/Stremio" - ".mozilla/firefox" - ".tor project" - ".local/share/Steam" - ".local/share/PrismLauncher" - ".config/sunshine" - ]; home = { - packages = with pkgs; [ - prismlauncher - stremio - tor-browser - vlc - wl-clipboard-rs - ]; sessionVariables = { BROWSER = "firefox"; - LAUNCHER = "fuzzel"; - LOCKSCREEN = "hyprlock"; - NOTIFICATION_DAEMON = "mako"; TERMINAL = "ghostty"; - STATUS_BAR = "waybar"; }; }; programs = { - fuzzel.enable = true; - obs-studio.enable = true; vesktop.enable = true; thunderbird.enable = true; thunderbird.profiles.rafiq.isDefault = true; + # ghostty is broken on nix-darwin + ghostty.settings.confirm-close-surface = false; firefox = { enable = true; inherit profiles; }; - hyprlock = { - enable = true; - settings = { - general.hide_cursor = true; - general.ignore_empty_input = true; - background.blur_passes = 5; - background.blur_size = 5; - label = { - text = ''hi, $USER.''; - font_size = 32; - position = "0, 0"; - halign = "center"; - valign = "center"; - zindex = 1; - shadow_passes = 5; - shadow_size = 5; - }; - input-field = { - placeholder_text = ""; - fade_on_empty = true; - size = "200, 45"; - position = "0, -5%"; - halign = "center"; - valign = "center"; - zindex = 1; - shadow_passes = 5; - shadow_size = 5; - }; - }; - }; - ghostty = { - enable = true; - settings = { - confirm-close-surface = false; - }; - }; - waybar = { - enable = true; - settings = [ - { - layer = "top"; - modules-left = [ - "pulseaudio" - ]; - modules-right = [ - "battery" - "clock" - ]; - "pulseaudio" = { - format = "{icon} {volume}%"; - format-muted = ""; - format-icons.default = [ - "" - "" - ]; - on-click = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle"; - }; - "clock" = { - interval = 1; - format = "{:%F %T}"; - }; - "battery" = { - interval = 1; - bat-compatibility = true; - }; - } - ]; - style = # css - '' - window#waybar { - background-color: rgba(0, 0, 0, 0); - } - - #pulseaudio, - #battery, - #clock { - padding-top: 5px; - padding-bottom: 5px; - padding-right: 5px; - color: #ffffff; - } - ''; - }; - }; - services = { - spotifyd.enable = true; - spotifyd.settings.global = { - device_name = "${hostName}"; - device_type = "computer"; - zeroconf_port = 5353; - }; - - mako.enable = true; - mako.settings.default-timeout = 10000; - - }; - wayland.windowManager.hyprland = { - enable = true; - # This is needed for UWSM - systemd.enable = false; - # Null the packages since we use them system wide - package = null; - portalPackage = null; - settings = mkMerge [ - (import ./_hyprland/decoration.nix) - (import ./_hyprland/keybinds.nix { inherit pkgs; }) - { - ecosystem.no_update_news = true; - xwayland.force_zero_scaling = true; - monitor = - let - mainMonitor = hostConfig.machine.monitors.main; - in - [ - "${mainMonitor.id}, ${mainMonitor.resolution}@${mainMonitor.refresh-rate}, auto, ${mainMonitor.scale}" - ", preferred, auto, 1" - ]; - exec-once = [ - "uwsm app -- $LOCKSCREEN" - "uwsm app -- $NOTIFICATION_DAEMON" - "uwsm app -- $STATUS_BAR" - ]; - } - ]; - }; - # xdg.configFile."uwsm/env".text = # sh - # '' - # # Force apps to scale right with Wayland - # export GDK_SCALE=${mainMonitor.scale} - # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} - # ''; - # xdg.configFile."uwsm/env-hyprland".text = # sh - # '' - # export GDK_SCALE=${mainMonitor.scale} - # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} - # ''; }; } diff --git a/nix/homes/rafiq/desktop/nixos.nix b/nix/homes/rafiq/desktop/nixos.nix new file mode 100644 index 0000000..e7d66b4 --- /dev/null +++ b/nix/homes/rafiq/desktop/nixos.nix @@ -0,0 +1,232 @@ +{ lib, config, ... }: +let + inherit (config.manifest) admin; +in +{ + allowedUnfreePackages = [ + "stremio-shell" + "stremio-server" + "steam" + "steam-unwrapped" + ]; + flake.modules.nixos.graphical = + { config, pkgs, ... }: + { + fonts.packages = [ pkgs.font-awesome ]; + services.getty.autologinUser = admin.username; + # Start Hyprland at boot only if not connecting through SSH + environment.loginShellInit = # sh + '' + if [[ -z "$SSH_CLIENT" && -z "$SSH_CONNECTION" ]]; then + if uwsm check may-start; then + exec uwsm start hyprland-uwsm.desktop + fi + fi + ''; + environment.variables = { + # Get Electron apps to use Wayland + ELECTRON_OZONE_PLATFORM_HINT = "auto"; + NIXOS_OZONE_WL = "1"; + }; + programs = { + hyprland = { + enable = true; + # Use UWSM to have each process controlled by systemd init + withUWSM = true; + }; + steam = { + enable = true; + gamescopeSession.enable = true; + }; + }; + security.pam.services.hyprlock = { }; + services.sunshine = { + enable = true; + capSysAdmin = true; + openFirewall = true; + settings = { + sunshine_name = config.networking.hostName; + origin_pin_allowed = "wan"; + origin_web_ui_allowed = "wan"; + }; + applications = { }; + }; + # spotifyd + networking.firewall.allowedTCPPorts = [ 5353 ]; + networking.firewall.allowedUDPPorts = [ 5353 ]; + }; + flake.modules.homeManager.rafiq = + { + pkgs, + config, + hostName, + hostConfig, + ... + }: + let + inherit (lib.modules) mkMerge mkIf; + in + mkIf (config.graphical && pkgs.system == "x86_64-linux") { + stylix.targets.waybar.addCss = false; + persistDirs = [ + "docs" + "repos" + "vids" + "tmp" + ".cache/Smart Code ltd/Stremio" + ".local/share/Smart Code ltd/Stremio" + ".mozilla/firefox" + ".tor project" + ".local/share/Steam" + ".local/share/PrismLauncher" + ".config/sunshine" + ]; + home = { + packages = with pkgs; [ + wl-clipboard-rs + stremio + tor-browser + vlc + prismlauncher + ]; + sessionVariables = { + LAUNCHER = "fuzzel"; + LOCKSCREEN = "hyprlock"; + NOTIFICATION_DAEMON = "mako"; + STATUS_BAR = "waybar"; + }; + }; + # xdg.configFile."uwsm/env".text = # sh + # '' + # # Force apps to scale right with Wayland + # export GDK_SCALE=${mainMonitor.scale} + # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} + # ''; + # xdg.configFile."uwsm/env-hyprland".text = # sh + # '' + # export GDK_SCALE=${mainMonitor.scale} + # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} + # ''; + wayland.windowManager.hyprland = { + enable = true; + # This is needed for UWSM + systemd.enable = false; + # Null the packages since we use them system wide + package = null; + portalPackage = null; + settings = mkMerge [ + (import ./_hyprland/decoration.nix) + (import ./_hyprland/keybinds.nix { inherit pkgs; }) + { + ecosystem.no_update_news = true; + xwayland.force_zero_scaling = true; + monitor = + let + mainMonitor = hostConfig.machine.monitors.main; + in + [ + "${mainMonitor.id}, ${mainMonitor.resolution}@${mainMonitor.refresh-rate}, auto, ${mainMonitor.scale}" + ", preferred, auto, 1" + ]; + exec-once = [ + "uwsm app -- $LOCKSCREEN" + "uwsm app -- $NOTIFICATION_DAEMON" + "uwsm app -- $STATUS_BAR" + ]; + } + ]; + }; + services = { + spotifyd.enable = true; + spotifyd.settings.global = { + device_name = "${hostName}"; + device_type = "computer"; + zeroconf_port = 5353; + }; + mako.enable = true; + mako.settings.default-timeout = 10000; + }; + programs = { + obs-studio.enable = true; + fuzzel.enable = true; + ghostty.enable = true; + waybar = { + enable = true; + settings = [ + { + layer = "top"; + modules-left = [ + "pulseaudio" + ]; + modules-right = [ + "battery" + "clock" + ]; + "pulseaudio" = { + format = "{icon} {volume}%"; + format-muted = ""; + format-icons.default = [ + "" + "" + ]; + on-click = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle"; + }; + "clock" = { + interval = 1; + format = "{:%F %T}"; + }; + "battery" = { + interval = 1; + bat-compatibility = true; + }; + } + ]; + style = # css + '' + window#waybar { + background-color: rgba(0, 0, 0, 0); + } + + #pulseaudio, + #battery, + #clock { + padding-top: 5px; + padding-bottom: 5px; + padding-right: 5px; + color: #ffffff; + } + ''; + }; + hyprlock = { + enable = true; + settings = { + general.hide_cursor = true; + general.ignore_empty_input = true; + background.blur_passes = 5; + background.blur_size = 5; + label = { + text = ''hi, $USER.''; + font_size = 32; + position = "0, 0"; + halign = "center"; + valign = "center"; + zindex = 1; + shadow_passes = 5; + shadow_size = 5; + }; + input-field = { + placeholder_text = ""; + fade_on_empty = true; + size = "200, 45"; + position = "0, -5%"; + halign = "center"; + valign = "center"; + zindex = 1; + shadow_passes = 5; + shadow_size = 5; + }; + }; + }; + }; + }; +} diff --git a/nix/lib/modules.nix b/nix/lib/modules.nix index 0d5b50b..ba27bfd 100644 --- a/nix/lib/modules.nix +++ b/nix/lib/modules.nix @@ -1,6 +1,5 @@ { lib, config, ... }: let - cfg = config.flake; inherit (builtins) foldl' attrNames; inherit (lib.attrsets) mapAttrs; in @@ -35,7 +34,7 @@ in ::: */ - userListToAttrs = f: foldl' (acc: elem: acc // (f elem)) { } (attrNames cfg.manifest.users); + userListToAttrs = f: foldl' (acc: elem: acc // (f elem)) { } (attrNames config.manifest.users); /** Return an attribute set for use with a option that needs to be used for all users. @@ -65,7 +64,7 @@ in ::: */ - forAllUsers = attrset: mapAttrs (_: _: attrset) cfg.manifest.users; + forAllUsers = attrset: mapAttrs (_: _: attrset) config.manifest.users; /** Like forAllUsers, but passes in the name and value from the manifest. @@ -96,6 +95,6 @@ in ::: */ - forAllUsers' = f: mapAttrs f cfg.manifest.users; + forAllUsers' = f: mapAttrs f config.manifest.users; }; } diff --git a/nix/manifest.nix b/nix/manifest.nix index 0643eb8..4f4f42f 100644 --- a/nix/manifest.nix +++ b/nix/manifest.nix @@ -1,5 +1,5 @@ { - flake.manifest = { + manifest = { users.rafiq = { primary = true; name = "Mohammad Rafiq"; @@ -7,83 +7,95 @@ shell = "fish"; pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdsZyY3gu8IGB8MzMnLdh+ClDxQQ2RYG9rkeetIKq8n rafiq"; }; - hosts.nixos = { - nemesis = { - graphical = true; - machine = { - platform = "amd"; - gpu = "nvidia"; - root.drive = "/dev/disk/by-id/nvme-CT2000P3SSD8_2325E6E77434"; - monitors.main = { - id = "desc:OOO AN-270W04K"; - resolution = "3840x2160"; - refresh-rate = "60"; - scale = "2"; - }; + hosts = { + darwin = { + venus = { + graphical = true; + machine.platform = "intel"; }; - extraCfg = { - services.fwupd.enable = true; # FIXME: remove - machine = { - bluetooth.enable = true; - usb.automount = true; - virtualisation = { - podman.enable = true; - podman.distrobox.enable = true; - }; - }; - server.web-apps = { - comfy-ui.enable = true; - sd-webui-forge.enable = true; - }; + hephaestus = { + graphical = true; + machine.platform = "apple-silicon"; }; }; - apollo = { - graphical = false; - machine = { - platform = "intel"; - root.drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; - }; - extraCfg.server = { - ddns = { - enable = true; - domains = [ - "aenyrathia.wiki" - "slayment.com" - ]; + nixos = { + nemesis = { + graphical = true; + machine = { + platform = "amd"; + gpu = "nvidia"; + root.drive = "/dev/disk/by-id/nvme-CT2000P3SSD8_2325E6E77434"; + monitors.main = { + id = "desc:OOO AN-270W04K"; + resolution = "3840x2160"; + refresh-rate = "60"; + scale = "2"; + }; }; - web-servers = { - enableSSL = true; - nginx = { + extraCfg = { + machine = { + bluetooth.enable = true; + usb.automount = true; + usb.qmk.enable = true; + virtualisation = { + podman.enable = true; + podman.distrobox.enable = true; + }; + }; + server.web-apps = { + comfy-ui.enable = true; + sd-webui-forge.enable = true; + }; + }; + }; + apollo = { + graphical = false; + machine = { + platform = "intel"; + root.drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; + }; + extraCfg.server = { + ddns = { enable = true; - proxies = [ - { - source = "aenyrathia.wiki"; - target = "http://helios:5896"; - } - { - source = "il.bwfiq.com"; - target = "http://helios:2283"; - } + domains = [ + "aenyrathia.wiki" + "slayment.com" ]; }; - }; - databases = { - mongodb.enable = true; - mysql.enable = true; - postgresql.enable = true; - }; - web-apps = { - librechat = { - enable = true; - domain = "chat.bwfiq.com"; + web-servers = { + enableSSL = true; + nginx = { + enable = true; + proxies = [ + { + source = "aenyrathia.wiki"; + target = "http://helios:5896"; + } + { + source = "il.bwfiq.com"; + target = "http://helios:2283"; + } + ]; + }; }; - forgejo = { - enable = true; - domain = "git.rrv.sh"; - openFirewall = true; + databases = { + mongodb.enable = true; + mysql.enable = true; + postgresql.enable = true; + }; + web-apps = { + librechat = { + enable = true; + domain = "chat.bwfiq.com"; + }; + forgejo = { + enable = true; + domain = "git.rrv.sh"; + openFirewall = true; + }; + rrv-sh.enable = true; + rrv-sh.domain = "rrv.sh"; }; - rrv-sh.enable = true; - rrv-sh.domain = "rrv.sh"; }; }; }; diff --git a/nix/meta.nix b/nix/meta.nix index 0d95bd7..9b93c47 100644 --- a/nix/meta.nix +++ b/nix/meta.nix @@ -5,57 +5,14 @@ ... }: let - inherit (lib.options) mkOption mkEnableOption; - inherit (cfg.lib.options) mkStrOption; - inherit (lib.types) - path - lazyAttrsOf - raw - deferredModule - submodule - ; + inherit (lib.options) mkOption; + inherit (lib.types) path lazyAttrsOf raw; inherit (inputs.flake-parts.lib) mkSubmoduleOptions; - inherit (cfg.lib.attrsets) firstAttrNameMatching; cfg = config.flake; - monitorOpts = submodule { - options = { - id = mkStrOption ""; - resolution = mkStrOption ""; - refresh-rate = mkStrOption ""; - scale = mkStrOption ""; - }; - }; - userOpts = submodule { - options = { - username = mkStrOption ""; - primary = mkEnableOption ""; - name = mkStrOption ""; - email = mkStrOption ""; - shell = mkStrOption ""; - pubkey = mkStrOption ""; - }; - }; - hostOpts = submodule { - options = { - graphical = mkEnableOption ""; - machine = { - platform = mkStrOption ""; - gpu = mkStrOption ""; - root.drive = mkStrOption ""; - monitors = mkOption { - type = lazyAttrsOf monitorOpts; - default = { }; - }; - }; - extraCfg = mkOption { - type = deferredModule; - default = { }; - }; - }; - }; in { options.flake = mkSubmoduleOptions { + self = mkOption { type = raw; }; lib = mkOption { type = lazyAttrsOf raw; default = { }; @@ -67,35 +24,8 @@ in readOnly = true; }; }; - manifest = mkOption { - type = submodule { - options = { - users = mkOption { - type = lazyAttrsOf userOpts; - default = { }; - }; - hosts = mkOption { - # hosts.nixos, hosts.darwin, etc. - type = lazyAttrsOf (lazyAttrsOf hostOpts); - default = { }; - }; - }; - }; - }; - # Helper Option - admin = mkOption { - type = userOpts; - default = { }; - }; }; - config.flake = - let - username = firstAttrNameMatching (_: v: v.primary or false) cfg.manifest.users; - in - { - paths.secrets = cfg.paths.root + "/secrets"; - admin = cfg.manifest.users.${username} // { - inherit username; - }; - }; + config.flake = { + paths.secrets = cfg.paths.root + "/secrets"; + }; } diff --git a/nix/modules/cli/git.nix b/nix/modules/cli/git.nix index c609a1a..0571ca3 100644 --- a/nix/modules/cli/git.nix +++ b/nix/modules/cli/git.nix @@ -1,6 +1,6 @@ { config, ... }: let - inherit (config.flake) manifest; + inherit (config.manifest) users; in { flake.modules.homeManager.default = @@ -9,8 +9,8 @@ in home.sessionVariables.GIT_CONFIG_GLOBAL = "$HOME/.config/git/config"; programs.git = { enable = true; - userName = manifest.users.${config.home.username}.name; - userEmail = manifest.users.${config.home.username}.email; + userName = users.${config.home.username}.name; + userEmail = users.${config.home.username}.email; signing.key = "~/.ssh/id_ed25519.pub"; }; }; diff --git a/nix/modules/cli/nix.nix b/nix/modules/cli/nix.nix index ad97ee5..a69b1d6 100644 --- a/nix/modules/cli/nix.nix +++ b/nix/modules/cli/nix.nix @@ -3,4 +3,11 @@ "nix-command" "flakes" ]; + flake.modules.darwin.default = { + nix.enable = false; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + }; } diff --git a/nix/modules/cli/shell.nix b/nix/modules/cli/shell.nix index c28f00b..ac1617d 100644 --- a/nix/modules/cli/shell.nix +++ b/nix/modules/cli/shell.nix @@ -1,23 +1,36 @@ { config, lib, ... }: let cfg = config.flake; + inherit (config.manifest) users; inherit (cfg.lib.modules) forAllUsers'; inherit (lib.attrsets) mapAttrs'; in { - flake.modules.nixos.default = - { pkgs, ... }: - { - programs = mapAttrs' (name: value: { - name = value.shell; - value.enable = true; - }) cfg.manifest.users; - users.users = forAllUsers' (_: value: { shell = pkgs.${value.shell}; }); - }; - flake.modules.homeManager.default = - { config, ... }: - { - programs.${cfg.manifest.users.${config.home.username}.shell}.enable = true; - home.shell.enableShellIntegration = true; - }; + flake.modules = { + nixos.default = + { pkgs, ... }: + { + programs = mapAttrs' (name: value: { + name = value.shell; + value.enable = true; + }) users; + users.users = forAllUsers' (_: value: { shell = pkgs.${value.shell}; }); + }; + darwin.default = + { pkgs, ... }: + { + programs = mapAttrs' (name: value: { + name = value.shell; + value.enable = true; + }) users; + users.users = forAllUsers' (_: value: { shell = pkgs.${value.shell}; }); + environment.shells = [ pkgs.fish ]; + }; + homeManager.default = + { config, ... }: + { + programs.${users.${config.home.username}.shell}.enable = true; + home.shell.enableShellIntegration = true; + }; + }; } diff --git a/nix/modules/graphical/default.nix b/nix/modules/graphical/default.nix index c714a2d..0ba55ca 100644 --- a/nix/modules/graphical/default.nix +++ b/nix/modules/graphical/default.nix @@ -3,12 +3,15 @@ let inherit (lib.options) mkEnableOption; in { - flake.modules.nixos.graphical = { - home-manager.sharedModules = [ { graphical = true; } ]; - services.pipewire = { - enable = true; - pulse.enable = true; + flake.modules = { + nixos.graphical = { + home-manager.sharedModules = [ { graphical = true; } ]; + services.pipewire = { + enable = true; + pulse.enable = true; + }; }; + homeManager.default.options.graphical = mkEnableOption ""; + darwin.graphical.home-manager.sharedModules = [ { graphical = true; } ]; }; - flake.modules.homeManager.default.options.graphical = mkEnableOption ""; } diff --git a/nix/modules/graphical/stylix.nix b/nix/modules/graphical/stylix.nix index c4b3c65..c347b6a 100644 --- a/nix/modules/graphical/stylix.nix +++ b/nix/modules/graphical/stylix.nix @@ -9,4 +9,12 @@ stylix.enable = true; stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml"; }; + flake.modules.darwin.default = + { pkgs, ... }: + { + imports = [ inputs.stylix.darwinModules.stylix ]; + stylix.enable = true; + #TODO: move into manifest + stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml"; + }; } diff --git a/nix/modules/machine/default.nix b/nix/modules/machine/default.nix index 8ad3f7a..ce8c615 100644 --- a/nix/modules/machine/default.nix +++ b/nix/modules/machine/default.nix @@ -5,7 +5,12 @@ let in { flake.modules.nixos.default = - { config, modulesPath, ... }: + { + config, + modulesPath, + pkgs, + ... + }: let cfg = config.machine; in @@ -14,6 +19,7 @@ in options.machine = { bluetooth.enable = mkEnableOption ""; usb.automount = mkEnableOption ""; + usb.qmk.enable = mkEnableOption ""; }; config = mkMerge [ (mkIf cfg.usb.automount { @@ -28,6 +34,18 @@ in } ]; }) + (mkIf cfg.usb.qmk.enable { + hardware.keyboard.qmk.enable = true; + services.udev = { + packages = with pkgs; [ + vial + qmk + qmk-udev-rules + qmk_hid + ]; + }; + + }) (mkIf cfg.bluetooth.enable { persistDirs = [ "/var/lib/bluetooth" ]; hardware.bluetooth = { diff --git a/nix/modules/machine/gpu.nix b/nix/modules/machine/gpu.nix index 00c56cd..8517036 100644 --- a/nix/modules/machine/gpu.nix +++ b/nix/modules/machine/gpu.nix @@ -1,7 +1,3 @@ -{ config, ... }: -let - cfg = config.flake; -in { allowedUnfreePackages = [ "nvidia-x11" @@ -11,11 +7,11 @@ in { config, pkgs, - hostName, + hostConfig, ... }: let - gpu = cfg.manifest.hosts.nixos.${hostName}.machine.gpu or ""; + inherit (hostConfig.machine) gpu; in if gpu == "nvidia" then { diff --git a/nix/modules/machine/platform.nix b/nix/modules/machine/platform.nix index ae8ab61..62943b4 100644 --- a/nix/modules/machine/platform.nix +++ b/nix/modules/machine/platform.nix @@ -1,9 +1,8 @@ -{ config, ... }: { flake.modules.nixos.default = - { hostName, ... }: + { hostConfig, ... }: let - inherit (config.flake.manifest.hosts.nixos.${hostName}.machine) platform; + inherit (hostConfig.machine) platform; arch = if platform == "amd" || platform == "intel" then "x86_64" else "aarch64"; in { @@ -11,4 +10,14 @@ boot.kernelModules = [ "kvm-${platform}" ]; nixpkgs.hostPlatform = "${arch}-linux"; }; + + flake.modules.darwin.default = + { hostConfig, ... }: + let + inherit (hostConfig.machine) platform; + arch = if platform == "intel" then "x86_64" else "aarch64"; + in + { + nixpkgs.hostPlatform = "${arch}-darwin"; + }; } diff --git a/nix/modules/machine/root.nix b/nix/modules/machine/root.nix index 98c1120..9c7d4ea 100644 --- a/nix/modules/machine/root.nix +++ b/nix/modules/machine/root.nix @@ -1,17 +1,12 @@ -{ - config, - lib, - inputs, - ... -}: +{ lib, inputs, ... }: let inherit (lib.modules) mkMerge mkIf mkAfter; in { flake.modules.nixos.default = - { hostName, ... }: + { hostConfig, ... }: let - inherit (config.flake.manifest.hosts.nixos.${hostName}.machine) root; + inherit (hostConfig.machine) root; in { imports = [ inputs.disko.nixosModules.disko ]; @@ -85,7 +80,7 @@ in }; } # Ephemeral by default - assumes btrfs - (mkIf (config.flake.manifest.hosts.nixos.${hostName}.machine.root.ephemeral or true) { + (mkIf root.ephemeral { boot.initrd.postDeviceCommands = mkAfter '' mkdir /btrfs_tmp mount /dev/root_vg/root /btrfs_tmp diff --git a/nix/modules/networking/ssh.nix b/nix/modules/networking/ssh.nix index d721746..2238b7e 100644 --- a/nix/modules/networking/ssh.nix +++ b/nix/modules/networking/ssh.nix @@ -1,6 +1,7 @@ { config, lib, ... }: let cfg = config.flake; + inherit (config.manifest) admin; inherit (lib.modules) mkMerge; inherit (cfg.lib.modules) forAllUsers'; in @@ -16,7 +17,7 @@ in "/etc/ssh/ssh_host_rsa_key.pub" ]; } - { users.users.root.openssh.authorizedKeys.keys = [ cfg.admin.pubkey ]; } + { users.users.root.openssh.authorizedKeys.keys = [ admin.pubkey ]; } ]; flake.modules.homeManager.default = { persistDirs = [ ".ssh" ]; diff --git a/nix/modules/networking/tailscale.nix b/nix/modules/networking/tailscale.nix index ddf1b9a..e1ad04c 100644 --- a/nix/modules/networking/tailscale.nix +++ b/nix/modules/networking/tailscale.nix @@ -14,4 +14,12 @@ in persistDirs = [ "/var/lib/tailscale" ]; sops.secrets."tailscale/client-secret".sopsFile = secrets + "/tailscale.yaml"; }; + flake.modules.darwin.default = + { pkgs, ... }: + { + services.tailscale = { + enable = true; + package = pkgs.tailscale.overrideAttrs { doCheck = false; }; + }; + }; } diff --git a/nix/modules/server/web-servers.nix b/nix/modules/server/web-servers.nix index 1967268..9b0cf75 100644 --- a/nix/modules/server/web-servers.nix +++ b/nix/modules/server/web-servers.nix @@ -4,7 +4,7 @@ let inherit (config.flake.lib.options) mkStrOption mkPathOption; inherit (config.flake.lib.services) mkRootDomain; inherit (config.flake.paths) secrets; - inherit (config.flake.admin) email; + inherit (config.manifest.admin) email; inherit (lib.types) listOf submodule attrs; inherit (lib.options) mkOption mkEnableOption; inherit (lib.modules) mkMerge mkIf; diff --git a/nix/modules/system/homebrew.nix b/nix/modules/system/homebrew.nix new file mode 100644 index 0000000..312a26b --- /dev/null +++ b/nix/modules/system/homebrew.nix @@ -0,0 +1,11 @@ +{ config, ... }: +let + inherit (config.manifest) admin; +in +{ + flake.modules.darwin.graphical.homebrew = { + enable = true; + user = admin.username; + onActivation.cleanup = "uninstall"; + }; +} diff --git a/nix/modules/system/persist.nix b/nix/modules/system/persist.nix index 4e298c0..917440b 100644 --- a/nix/modules/system/persist.nix +++ b/nix/modules/system/persist.nix @@ -5,6 +5,7 @@ ... }: let + inherit (lib.modules) mkIf; inherit (lib.options) mkOption; inherit (config.flake.lib.options) mkStrOption; inherit (lib.types) @@ -49,15 +50,17 @@ in }; }; flake.modules.homeManager.default = - { config, ... }: + { config, pkgs, ... }: { imports = [ inputs.impermanence.homeManagerModules.impermanence ]; options.persistDirs = mkOpts "directory" { }; options.persistFiles = mkOpts "file" { }; - config.home.persistence."/persist${config.home.homeDirectory}" = { - allowOther = true; - directories = config.persistDirs; - files = config.persistFiles; + config = mkIf (pkgs.system == "x86_64-linux") { + home.persistence."/persist${config.home.homeDirectory}" = { + allowOther = true; + directories = config.persistDirs; + files = config.persistFiles; + }; }; }; } diff --git a/nix/modules/system/secrets.nix b/nix/modules/system/secrets.nix index ff90532..e71989d 100644 --- a/nix/modules/system/secrets.nix +++ b/nix/modules/system/secrets.nix @@ -6,21 +6,48 @@ }: let cfg = config.flake; + inherit (cfg.paths) secrets; inherit (builtins) readFile; inherit (lib.meta) getExe; inherit (lib.strings) trim; - inherit (cfg.admin) username pubkey; + inherit (config.manifest.admin) username pubkey; in { - flake.modules.nixos.default = - { config, ... }: - { - imports = [ inputs.sops-nix.nixosModules.sops ]; - config.sops.age.sshKeyPaths = [ - "/persist${config.users.defaultUserHome}/${username}/.ssh/id_ed25519" - ]; - }; - flake.modules.homeManager.default.persistDirs = [ ".config/sops/age" ]; + flake.modules = { + nixos.default = + { config, ... }: + { + imports = [ inputs.sops-nix.nixosModules.sops ]; + config = { + sops = { + age.sshKeyPaths = [ + "/persist${config.users.defaultUserHome}/${username}/.ssh/id_ed25519" + ]; + secrets."keys/gemini".sopsFile = secrets + "/keys.yaml"; + }; + environment.shellInit = # sh + '' + export GEMINI_API_KEY=$(sudo cat ${config.sops.secrets."keys/gemini".path}) + ''; + }; + }; + darwin.default = + { config, ... }: + { + imports = [ inputs.sops-nix.darwinModules.sops ]; + config = { + sops = { + age.sshKeyPaths = [ "${config.users.users.${username}.home}/.ssh/id_ed25519" ]; + secrets."keys/gemini".sopsFile = secrets + "/keys.yaml"; + }; + environment.shellInit = # sh + '' + export GEMINI_API_KEY=$(sudo cat ${config.sops.secrets."keys/gemini".path}) + ''; + }; + }; + homeManager.default.persistDirs = [ ".config/sops/age" ]; + }; perSystem = { pkgs, ... }: { diff --git a/nix/modules/system/sudo.nix b/nix/modules/system/sudo.nix index 1c9b560..fa7724c 100644 --- a/nix/modules/system/sudo.nix +++ b/nix/modules/system/sudo.nix @@ -1,11 +1,19 @@ { config, ... }: let - cfg = config.flake; + inherit (config.manifest) admin; in { flake.modules.nixos.default = { security.sudo.wheelNeedsPassword = false; nix.settings.trusted-users = [ "@wheel" ]; - users.users.${cfg.admin.username}.extraGroups = [ "wheel" ]; + users.users.${admin.username}.extraGroups = [ "wheel" ]; + }; + flake.modules.darwin.default.security = { + sudo.extraConfig = "%admin ALL = (ALL) NOPASSWD: ALL"; + pam.services.sudo_local = { + enable = true; + reattach = true; + touchIdAuth = true; + }; }; } diff --git a/nix/modules/system/system.nix b/nix/modules/system/system.nix index 15342b1..cee1df3 100644 --- a/nix/modules/system/system.nix +++ b/nix/modules/system/system.nix @@ -1,14 +1,18 @@ { - flake.modules.nixos.default = { - persistFiles = [ "/etc/machine-id" ]; - persistDirs = [ "/var/lib/systemd" ]; - time.timeZone = "Asia/Singapore"; - i18n.defaultLocale = "en_US.UTF-8"; - system.stateVersion = "25.11"; - }; - flake.modules.homeManager.default = - { osConfig, ... }: - { - home.stateVersion = osConfig.system.stateVersion; + flake.modules = { + nixos.default = { + persistFiles = [ "/etc/machine-id" ]; + persistDirs = [ "/var/lib/systemd" ]; + time.timeZone = "Asia/Singapore"; + i18n.defaultLocale = "en_US.UTF-8"; + system.stateVersion = "25.11"; }; + homeManager.default.home.stateVersion = "25.11"; + darwin.default = + { self, ... }: + { + system.configurationRevision = self.rev or self.dirtyRev or null; + system.stateVersion = 6; + }; + }; } diff --git a/nix/modules/system/users.nix b/nix/modules/system/users.nix index 5815089..dc80b0b 100644 --- a/nix/modules/system/users.nix +++ b/nix/modules/system/users.nix @@ -1,7 +1,10 @@ -{ config, ... }: +{ config, lib, ... }: let cfg = config.flake; + inherit (config.manifest) users admin; inherit (cfg.lib.modules) userListToAttrs forAllUsers'; + inherit (lib.lists) findFirstIndex; + inherit (builtins) attrNames; in { flake.modules.nixos.default = @@ -31,4 +34,22 @@ in } ); }; + flake.modules.darwin.default = + { config, ... }: + { + system.primaryUser = admin.username; + users.knownUsers = attrNames users; + users.users = forAllUsers' ( + name: _: { + home = "/Users/${name}"; + uid = 501 + (findFirstIndex (x: x == name) null (attrNames users)); + } + ); + home-manager.users = forAllUsers' ( + name: _: { + home.username = name; + home.homeDirectory = config.users.users.${name}.home; + } + ); + }; } diff --git a/nix/modules/unfree-packages.nix b/nix/modules/unfree-packages.nix index b74984e..d444024 100644 --- a/nix/modules/unfree-packages.nix +++ b/nix/modules/unfree-packages.nix @@ -11,7 +11,8 @@ in type = listOf str; default = [ ]; }; - config.flake.modules.nixos.default = { - nixpkgs.config.allowUnfreePredicate = predicate; + config.flake.modules = { + nixos.default.nixpkgs.config.allowUnfreePredicate = predicate; + darwin.default.nixpkgs.config.allowUnfreePredicate = predicate; }; }