diff --git a/.gitignore b/.gitignore index 367423f14..7628531f3 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,7 @@ tags result result-* ref +*.iso .direnv/ .env diff --git a/Makefile b/Makefile index 7b79bab24..329cb9f32 100644 --- a/Makefile +++ b/Makefile @@ -638,6 +638,57 @@ nix-setup-offline: ## Set up offline environment. ##@ Named Hosts Specific Targets +.PHONY: build-vm +build-vm: ## Build a named host VM launcher (set HOST=, e.g. make build-vm HOST=viper). + @host="$(HOST)"; \ + if [ -z "$$host" ]; then \ + host="$(DETECTED_HOST)"; \ + fi; \ + if [ -z "$$host" ]; then \ + echo "❌ No HOST specified and no named host auto-detected"; \ + exit 1; \ + fi; \ + echo "🏗️ Building VM for $$host"; \ + $(NIX_ALLOW_UNFREE) $(NIX_EXEC) build .#nixosConfigurations.$$host.config.system.build.vm $(NIX_FLAGS) --impure --show-trace + +.PHONY: run-vm +run-vm: ## Run a named host VM launcher (set HOST=, e.g. make run-vm HOST=viper). + @host="$(HOST)"; \ + if [ -z "$$host" ]; then \ + host="$(DETECTED_HOST)"; \ + fi; \ + if [ -z "$$host" ]; then \ + echo "❌ No HOST specified and no named host auto-detected"; \ + exit 1; \ + fi; \ + $(MAKE) build-vm HOST="$$host"; \ + script=$$(find ./result/bin -maxdepth 1 -type f \( -name 'run-*-vm' -o -name 'run-nixos-vm' \) | head -n 1); \ + if [ -z "$$script" ]; then \ + echo "❌ Could not find a VM launcher under ./result/bin"; \ + exit 1; \ + fi; \ + "$$script" + +.PHONY: build-iso +build-iso: ## Build a named host live/install ISO and copy it to ./.iso (set HOST=, e.g. make build-iso HOST=viper). + @host="$(HOST)"; \ + if [ -z "$$host" ]; then \ + host="$(DETECTED_HOST)"; \ + fi; \ + if [ -z "$$host" ]; then \ + echo "❌ No HOST specified and no named host auto-detected"; \ + exit 1; \ + fi; \ + echo "💿 Building ISO for $$host"; \ + $(NIX_ALLOW_UNFREE) $(NIX_EXEC) build .#nixosConfigurations.$$host"Iso".config.system.build.isoImage $(NIX_FLAGS) --impure --show-trace; \ + iso_path=$$(find ./result -type f -name '*.iso' | head -n 1); \ + if [ -z "$$iso_path" ]; then \ + echo "❌ Could not find a built ISO under ./result"; \ + exit 1; \ + fi; \ + cp -f "$$iso_path" "./$$host.iso"; \ + echo "✅ Copied $$iso_path to ./$$host.iso" + .PHONY: switch-% switch-%: ## Switch to a named host configuration (e.g., make switch-galactica). @$(MAKE) nix-switch HOST=$* @@ -1151,4 +1202,3 @@ gt-status: ## Show Gas Town health and Dolt server status. .PHONY: gt-dolt-status gt-dolt-status: ## Show Dolt server status and latency. @gt dolt status - diff --git a/flake.nix b/flake.nix index 519d78f60..4320abbd9 100644 --- a/flake.nix +++ b/flake.nix @@ -134,6 +134,18 @@ inherit inputs; username = "skakinoki"; }; + maticIso = import ./named-hosts/matic/iso.nix { + inherit inputs; + username = "skakinoki"; + }; + viper = import ./named-hosts/viper { + inherit inputs; + username = "shunkakinoki"; + }; + viperIso = import ./named-hosts/viper/iso.nix { + inherit inputs; + username = "shunkakinoki"; + }; }; homeConfigurations = { "ubuntu@x86_64-linux" = import ./hosts/linux { diff --git a/home-manager/modules/local-scripts/clipboard-copy.sh b/home-manager/modules/local-scripts/clipboard-copy.sh index bf230b52a..0d41529d5 100755 --- a/home-manager/modules/local-scripts/clipboard-copy.sh +++ b/home-manager/modules/local-scripts/clipboard-copy.sh @@ -2,14 +2,14 @@ set -euo pipefail -if command -v pbcopy >/dev/null 2>&1; then - exec pbcopy -fi - if [[ -n ${WAYLAND_DISPLAY:-} ]] && command -v wl-copy >/dev/null 2>&1; then exec wl-copy fi +if command -v pbcopy >/dev/null 2>&1; then + exec pbcopy +fi + if command -v xclip >/dev/null 2>&1; then exec xclip -selection clipboard fi diff --git a/home-manager/modules/local-scripts/pushover-notify.sh b/home-manager/modules/local-scripts/pushover-notify.sh index 4d73fc872..fb90ce6b7 100644 --- a/home-manager/modules/local-scripts/pushover-notify.sh +++ b/home-manager/modules/local-scripts/pushover-notify.sh @@ -12,8 +12,9 @@ priority="${3:-0}" [[ -z $message ]] && exit 0 -# Source credentials if not already set -if [[ -z ${PUSHOVER_API_TOKEN:-} ]] || [[ -z ${PUSHOVER_USER_KEY:-} ]]; then +# Source credentials only when the vars are unset. Explicitly blank values +# should disable notifications instead of falling back to ~/.env. +if [[ -z ${PUSHOVER_API_TOKEN+x} ]] || [[ -z ${PUSHOVER_USER_KEY+x} ]]; then if [[ -f "$HOME/dotfiles/.env" ]]; then set -a # shellcheck source=/dev/null @@ -35,4 +36,4 @@ curl -s \ --form-string "message=${message}" \ --form-string "priority=${priority}" \ --form-string "title=${title}" \ - https://api.pushover.net/1/messages.json >/dev/null 2>&1 + https://api.pushover.net/1/messages.json >/dev/null 2>&1 || exit 0 diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index f6e4e2de9..5549d7fea 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -37,6 +37,19 @@ inputs.nixpkgs.lib.nixosSystem { ( { config, lib, ... }: { + imports = [ + (import ../shared/linux-base.nix { + inherit inputs pkgs username; + hostname = "matic"; + userExtraGroups = [ + "input" + "video" + "audio" + "docker" + ]; + }) + ]; + # Boot loader (EFI/systemd-boot) boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.configurationLimit = 10; @@ -70,34 +83,11 @@ inputs.nixpkgs.lib.nixosSystem { ]; # Networking - networking.hostName = "matic"; - networking.networkmanager.enable = true; networking.networkmanager.wifi.powersave = true; - # Enable fish shell - programs.fish.enable = true; - - # User configuration - users.users.${username} = { - isNormalUser = true; - extraGroups = [ - "wheel" - "networkmanager" - "input" - "video" - "audio" - "docker" - ]; - home = "/home/${username}"; - shell = pkgs.fish; - initialPassword = "changemeow"; # Change this after first login with: passwd - }; - # Docker virtualisation.docker.enable = true; - security.sudo.wheelNeedsPassword = false; - # Home Manager activation can take a long time (npm globals, cargo installs, etc.) systemd.services."home-manager-${username}".serviceConfig.TimeoutStartSec = lib.mkForce "30m"; @@ -344,21 +334,6 @@ inputs.nixpkgs.lib.nixosSystem { zlib ]; - # NixOS-level nix settings (complements home-manager nix/) - nix = { - channel.enable = false; - settings = { - nix-path = lib.mkForce "nixpkgs=/etc/nix/inputs/nixpkgs"; - trusted-users = [ - username - "@wheel" - "root" - ]; - }; - }; - environment.etc."nix/inputs/nixpkgs".source = "${inputs.nixpkgs}"; - - system.stateVersion = "24.11"; } ) diff --git a/named-hosts/matic/iso.nix b/named-hosts/matic/iso.nix new file mode 100644 index 000000000..93223fa2f --- /dev/null +++ b/named-hosts/matic/iso.nix @@ -0,0 +1,29 @@ +{ + inputs, + username, + ... +}: +let + system = "x86_64-linux"; + nixpkgsConfig = import ../../lib/nixpkgs-config.nix { + nixpkgsLib = inputs.nixpkgs.lib; + }; + overlays = import ../../overlays { inherit inputs; }; + pkgs = import inputs.nixpkgs { + inherit system overlays; + config = nixpkgsConfig; + }; +in +inputs.nixpkgs.lib.nixosSystem { + inherit system; + specialArgs = { + inherit inputs username; + }; + modules = [ + (import ../shared/live-iso.nix { + inherit inputs pkgs username; + hostname = "matic"; + userInitialPassword = "changemeow"; + }) + ]; +} diff --git a/named-hosts/shared/linux-base.nix b/named-hosts/shared/linux-base.nix new file mode 100644 index 000000000..5daa9da0b --- /dev/null +++ b/named-hosts/shared/linux-base.nix @@ -0,0 +1,46 @@ +{ + inputs, + pkgs, + username, + hostname, + userExtraGroups ? [ ], + userInitialPassword ? "changemeow", + stateVersion ? "24.11", +}: +{ lib, ... }: +{ + networking.hostName = hostname; + networking.networkmanager.enable = true; + + programs.fish.enable = true; + + users.users.${username} = { + isNormalUser = true; + extraGroups = [ + "wheel" + "networkmanager" + ] + ++ userExtraGroups; + home = "/home/${username}"; + shell = pkgs.fish; + initialPassword = userInitialPassword; + }; + + security.sudo.wheelNeedsPassword = false; + + nix = { + channel.enable = false; + settings = { + nix-path = lib.mkForce "nixpkgs=/etc/nix/inputs/nixpkgs"; + trusted-users = [ + username + "@wheel" + "root" + ]; + }; + }; + + environment.etc."nix/inputs/nixpkgs".source = "${inputs.nixpkgs}"; + + system.stateVersion = stateVersion; +} diff --git a/named-hosts/shared/live-iso.nix b/named-hosts/shared/live-iso.nix new file mode 100644 index 000000000..eeca7f6a4 --- /dev/null +++ b/named-hosts/shared/live-iso.nix @@ -0,0 +1,33 @@ +{ + inputs, + pkgs, + username, + hostname, + userInitialPassword, + isoName ? "${hostname}.iso", +}: +{ lib, ... }: +{ + imports = [ + "${inputs.nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + "${inputs.nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix" + (import ./linux-base.nix { + inherit + inputs + pkgs + username + hostname + userInitialPassword + ; + }) + ]; + + environment.systemPackages = with pkgs; [ + curl + git + vim + ]; + + image.fileName = isoName; + services.getty.helpLine = lib.mkForce ""; +} diff --git a/named-hosts/viper/default.nix b/named-hosts/viper/default.nix new file mode 100644 index 000000000..81b77456d --- /dev/null +++ b/named-hosts/viper/default.nix @@ -0,0 +1,65 @@ +{ + inputs, + username, + ... +}: +let + system = "x86_64-linux"; + nixpkgsConfig = import ../../lib/nixpkgs-config.nix { + nixpkgsLib = inputs.nixpkgs.lib; + }; + overlays = import ../../overlays { inherit inputs; }; + pkgs = import inputs.nixpkgs { + inherit system overlays; + config = nixpkgsConfig; + }; +in +inputs.nixpkgs.lib.nixosSystem { + inherit system; + specialArgs = { + inherit inputs username; + }; + modules = [ + (import ../shared/linux-base.nix { + inherit inputs pkgs username; + hostname = "viper"; + userInitialPassword = "test"; + }) + ( + { + lib, + modulesPath, + ... + }: + { + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/vda"; + boot.loader.timeout = 3; + + fileSystems."/" = { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + }; + + environment.systemPackages = with pkgs; [ + curl + git + vim + ]; + + services.openssh.enable = true; + + virtualisation.vmVariant = { + virtualisation = { + graphics = false; + memorySize = 4096; + cores = 4; + }; + users.users.${username}.initialPassword = lib.mkForce "test"; + }; + } + ) + ]; +} diff --git a/named-hosts/viper/iso.nix b/named-hosts/viper/iso.nix new file mode 100644 index 000000000..5cd4d9626 --- /dev/null +++ b/named-hosts/viper/iso.nix @@ -0,0 +1,29 @@ +{ + inputs, + username, + ... +}: +let + system = "x86_64-linux"; + nixpkgsConfig = import ../../lib/nixpkgs-config.nix { + nixpkgsLib = inputs.nixpkgs.lib; + }; + overlays = import ../../overlays { inherit inputs; }; + pkgs = import inputs.nixpkgs { + inherit system overlays; + config = nixpkgsConfig; + }; +in +inputs.nixpkgs.lib.nixosSystem { + inherit system; + specialArgs = { + inherit inputs username; + }; + modules = [ + (import ../shared/live-iso.nix { + inherit inputs pkgs username; + hostname = "viper"; + userInitialPassword = "test"; + }) + ]; +} diff --git a/tests/eval.nix b/tests/eval.nix index 428459e8e..189c04d77 100644 --- a/tests/eval.nix +++ b/tests/eval.nix @@ -73,6 +73,27 @@ let inherit inputs; username = "shunkakinoki"; }).config.system.build.toplevel; + + eval-nixos-matic-iso = + mkEvalCheck "nixos-matic-iso" + (import ../named-hosts/matic/iso.nix { + inherit inputs; + username = "shunkakinoki"; + }).config.system.build.isoImage; + + eval-nixos-viper = + mkEvalCheck "nixos-viper" + (import ../named-hosts/viper { + inherit inputs; + username = "shunkakinoki"; + }).config.system.build.toplevel; + + eval-nixos-viper-iso = + mkEvalCheck "nixos-viper-iso" + (import ../named-hosts/viper/iso.nix { + inherit inputs; + username = "shunkakinoki"; + }).config.system.build.isoImage; }; # --- Home-manager configurations (filtered by matching system) ---