feat: make VM and live ISO match an installed Nomarchy

- Migrate VM and graphical ISO to home-manager.nixosModules.home-manager;
  drop the standalone-HM sudo-based activation script (ran HM against
  /root because HOME wasn't reset) in flake.nix, core/system/vm-guest.nix,
  hosts/live-iso.nix.
- Run swaybg as nomarchy-wallpaper.service instead of a silent Hyprland
  exec-once so failures surface in systemctl.
- Skip the battery monitor unit on hosts without /sys/class/power_supply/BAT*
  (VMs, desktops).
- Don't wrap walker --dmenu in uwsm-app; redirect setsid background std-fds
  in nomarchy-launch-walker so $(menu ...) in nomarchy-menu doesn't hang.
- Restart waybar/walker via systemctl --user rather than pkill + uwsm-app
  to stop the post-theme-switch color race.
- Wire nomarchy-restart-walker/-waybar into nomarchy-theme-set so themes
  that only change the imported CSS reload correctly.
- Waybar: pin #custom-nomarchy to the Nomarchy font and use the U+F000
  codepoint so the logo shows across all themes.
- Auto-install the correct icon-theme package per palette via a new
  nomarchyLib.iconThemePackage helper in lib/default.nix; Everforest now
  actually renders for summer-night.
- Pre-cache every theme's HM generation: new packages.allThemeVariants
  flake output and nomarchy-themes-prebuild script so theme switches are
  cache-only (no Stylix rebuild, no downloads).
- Add nomarchy-test-live-iso to boot the graphical ISO in QEMU the same
  way nomarchy-test-vm does, with virtio-gpu support added to live-iso.nix.
- Installer-generated home.nix/system.nix now ship a curated, commented
  app menu (btop/fastfetch/chromium on by default) plus optional system
  services (Docker, libvirtd, Tailscale, Syncthing, Flatpak, Steam).
- nomarchy-test-vm now wipes the stale nomarchy.qcow2 before launch.
- Remove obsolete GEMINI.md and PLAN.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-04-24 18:20:54 +01:00
parent 096124c04a
commit 877da19770
21 changed files with 368 additions and 148 deletions

View File

@@ -1,49 +0,0 @@
The Nomarchy UI/UX Audit Mega-Prompt
System Role: You are a Lead Linux UI/UX Architect and Wayland Desktop Environment QA Engineer. Your task is to perform a rigorous, line-by-line syntax and logic audit of the provided configuration files (dotfiles) for the Nomarchy OS desktop environment.
The Goal: Ensure zero syntax errors, zero deprecated variables, and perfect path resolution across all Wayland compositors, bars, terminals, and launchers.
Execution Directives (STRICT COMPLIANCE REQUIRED):
Your mindset is highly skeptical. Assume these config files contain deprecated syntax, trailing commas, broken script paths, and hardcoded variables. You are forbidden from providing a generic summary until you have completed the Forced UI Audit Protocol for every single file.
The Forced UI Audit Protocol:
For every file provided, you MUST output a block formatted exactly like this:
[UI-AUDIT: filename.extension]
Parser Check: (Identify the language: JSON, TOML, CSS, Hyprland-conf. Explicitly state if you checked for language-specific strictness, like trailing commas in JSON).
Deprecation Check: (Are any variables or syntax structures outdated based on the latest stable releases of the software?)
Path & Dependency Check: (List any shell scripts, fonts, or external commands referenced in this file. Are they valid?)
Status: (Pass / Fail / Warning)
Specific Application Directives (Hunt for these common failures):
Hyprland (hyprland.conf):
Scrutinize shadow and blur variables. (Hyprland recently changed drop_shadow = true to the decoration:shadow { enabled = true } syntax). Check for valid color variable injection (e.g., $base00).
Verify exec-once paths. Do not allow relative paths for critical startup scripts.
Waybar (config & style.css):
JSON Strictness: Waybar uses strict JSON. You MUST check for and flag any trailing commas, missing quotes, or unescaped characters.
CSS Scope: Verify that standard GTK CSS properties are used. Ensure font families have valid fallbacks.
Alacritty (alacritty.toml):
Format Check: Ensure the file is using TOML syntax, NOT the deprecated YAML syntax. Check that font definitions match the correct TOML schema.
Launchers (Walker / Rofi):
Verify that the theme variables match the overarching system color palette. Check that terminal execution commands match the default terminal (Alacritty).
Final Deliverable:
After completing the audit blocks for all files, provide a "UI/UX Incident Report".
For any file that failed, quote the broken line, explain why the target program will reject it (e.g., "Waybar will crash on launch due to a trailing comma on line 42"), and provide the exact corrected code block.
Begin the Forced UI Audit Protocol now.

32
PLAN.md
View File

@@ -1,32 +0,0 @@
# UI/UX Audit Progress
## Core Desktop
- [x] Hyprland Template: `themes/templates/hyprland.conf.tpl`
- [x] Hyprlock Template: `themes/templates/hyprlock.conf.tpl`
- [x] Theme-specific Hyprland configs:
- [x] `features/desktop/hyprland/themes/kanagawa/hyprland.conf`
- [x] `features/desktop/hyprland/themes/lumon/hyprland.conf`
- [x] `features/desktop/hyprland/themes/nord/hyprland.conf`
- [x] `features/desktop/hyprland/themes/retro-82/hyprland.conf`
- [x] `features/desktop/hyprland/themes/summer-night/hyprland.conf`
- [x] Waybar: `features/desktop/waybar/default.nix`
## Launchers & Terminals
- [x] Walker Config: `core/home/config/nomarchy/default/hypr/apps/walker.conf`
- [x] Walker Desktop: `core/home/config/nomarchy/default/walker/walker.desktop`
- [x] Alacritty Template: `themes/templates/alacritty.toml.tpl`
- [x] Alacritty Screensaver: `core/home/config/nomarchy/default/alacritty/screensaver.toml`
- [x] Kitty Template: `themes/templates/kitty.conf.tpl`
- [x] Ghostty Template: `themes/templates/ghostty.conf.tpl`
## Applications & Templates
- [x] Btop Theme: `themes/templates/btop.theme.tpl`
- [x] SwayOSD Style: `themes/templates/swayosd.css.tpl`
- [x] Mako Template: `themes/templates/mako.ini.tpl`
- [x] Chromium Theme: `themes/templates/chromium.theme.tpl`
- [x] Chromium Flags: `core/home/config/chromium-flags.conf`
- [x] Brave Flags: `core/home/config/brave-flags.conf`
- [x] Starship: `core/home/config/starship.toml`
- [x] Obsidian Style: `themes/templates/obsidian.css.tpl`
- [x] Ghostty Config: `themes/templates/ghostty.conf.tpl`
- [x] Keyboard RGB: `themes/templates/keyboard.rgb.tpl`

View File

@@ -2,7 +2,8 @@ exec-once = uwsm-app -- hypridle
exec-once = uwsm-app -- mako exec-once = uwsm-app -- mako
# exec-once = uwsm-app -- waybar # exec-once = uwsm-app -- waybar
exec-once = uwsm-app -- fcitx5 --disable notificationitem exec-once = uwsm-app -- fcitx5 --disable notificationitem
exec-once = uwsm-app -- swaybg -i ~/.config/nomarchy/current/background -m fill # swaybg is started as a systemd user service (nomarchy-wallpaper.service)
# so failures surface in logs and the wallpaper survives Hyprland restarts.
exec-once = uwsm-app -- swayosd-server exec-once = uwsm-app -- swayosd-server
exec-once = nomarchy-on-boot exec-once = nomarchy-on-boot

View File

@@ -1,19 +1,10 @@
{ inputs, lib, pkgs, homeActivationPackage ? null, ... }: { inputs, lib, pkgs, ... }:
{ {
# Pre-activate standalone home-manager if provided # Home Manager activation is provided by the home-manager.nixosModules.home-manager
system.activationScripts.home-manager-activate = lib.mkIf (homeActivationPackage != null) { # module wired up in flake.nix. It runs as a systemd user service per user and
text = '' # deploys ~/.config/hypr, ~/.config/nomarchy, ~/.config/waybar, etc. before the
USER_HOME="/home/nomarchy" # graphical session starts.
if [ ! -d "$USER_HOME" ]; then
mkdir -p "$USER_HOME"
chown nomarchy:users "$USER_HOME"
fi
# Run activation as the nomarchy user
${pkgs.sudo}/bin/sudo -u nomarchy ${homeActivationPackage}/activate
'';
deps = [ "users" ];
};
# Shared VM configuration # Shared VM configuration
virtualisation.vmVariant = { virtualisation.vmVariant = {

View File

@@ -45,8 +45,6 @@ in
colorScheme = lib.mkDefault (nomarchyLib.getColorScheme config.nomarchy.theme); colorScheme = lib.mkDefault (nomarchyLib.getColorScheme config.nomarchy.theme);
nixpkgs.config.allowUnfree = true;
# Enable neovim program module (required for stylix integration) # Enable neovim program module (required for stylix integration)
programs.neovim.enable = lib.mkDefault true; programs.neovim.enable = lib.mkDefault true;
@@ -83,9 +81,9 @@ in
swaybg swaybg
rofi-wayland rofi-wayland
# Theming # Theming — cursor package stays here; icon theme packages are pulled in
yaru-theme # dynamically by themes/engine/stylix.nix via nomarchyLib.iconThemePackage
everforest-gtk-variant # so switching to e.g. summer-night auto-installs everforest-gtk-theme.
bibata-cursors bibata-cursors
]); ]);
} }

View File

@@ -50,4 +50,24 @@ in
xdg.configFile."hypr/bindings.conf".source = lib.mkDefault ./config/bindings.conf; xdg.configFile."hypr/bindings.conf".source = lib.mkDefault ./config/bindings.conf;
xdg.configFile."hypr/looknfeel.conf".source = lib.mkDefault ./config/looknfeel.conf; xdg.configFile."hypr/looknfeel.conf".source = lib.mkDefault ./config/looknfeel.conf;
xdg.configFile."hypr/autostart.conf".source = lib.mkDefault ./config/autostart.conf; xdg.configFile."hypr/autostart.conf".source = lib.mkDefault ./config/autostart.conf;
# Run swaybg as a proper systemd user service rather than a Hyprland exec-once.
# exec-once fails silently (black screen with no visible error) when timing
# against uwsm's graphical-session target is off; a service surfaces failures
# via `systemctl --user status nomarchy-wallpaper` and auto-restarts.
systemd.user.services.nomarchy-wallpaper = {
Unit = {
Description = "Nomarchy desktop wallpaper (swaybg)";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${pkgs.swaybg}/bin/swaybg -i %h/.config/nomarchy/current/background -m fill";
Restart = "on-failure";
RestartSec = "2";
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
} }

View File

@@ -1,11 +1,18 @@
#!/bin/bash #!/bin/bash
# Walker (with runAsService = true) and elephant are Home Manager user
# services. Restart via systemd so the new process inherits the full graphical
# session environment — the pkill/uwsm-app dance left a window where the
# launcher would come back up with stale theming.
restart_services() { restart_services() {
if systemctl --user is-enabled elephant.service &>/dev/null; then if systemctl --user list-unit-files elephant.service >/dev/null 2>&1; then
systemctl --user restart elephant.service systemctl --user restart elephant.service
fi fi
if systemctl --user is-enabled app-walker@autostart.service &>/dev/null; then if systemctl --user list-unit-files walker.service >/dev/null 2>&1; then
systemctl --user restart walker.service
elif systemctl --user is-enabled app-walker@autostart.service &>/dev/null; then
systemctl --user restart app-walker@autostart.service systemctl --user restart app-walker@autostart.service
else else
echo -e "\e[31mUnable to restart Walker -- RESTART MANUALLY\e[0m" echo -e "\e[31mUnable to restart Walker -- RESTART MANUALLY\e[0m"

View File

@@ -1,3 +1,14 @@
#!/bin/bash #!/bin/bash
# Waybar is provided as a Home Manager user service
# (programs.waybar.systemd.enable = true), so the right way to restart it is
# via systemd. `pkill + uwsm-app` races with HM's sd-switch on theme changes
# and sometimes lands the new waybar without a full environment, producing
# the "wrong colors after theme switch" symptom.
if systemctl --user list-unit-files waybar.service >/dev/null 2>&1; then
exec systemctl --user restart waybar.service
fi
# Fallback for systems where waybar isn't managed by systemd.
nomarchy-restart-app waybar nomarchy-restart-app waybar

View File

@@ -40,7 +40,7 @@
} }
}, },
"custom/nomarchy": { "custom/nomarchy": {
"format": "<span font='nomarchy'>a</span>", "format": "",
"on-click": "nomarchy-menu", "on-click": "nomarchy-menu",
"on-click-right": "xdg-terminal-exec", "on-click-right": "xdg-terminal-exec",
"tooltip-format": "Nomarchy Menu\n\nSuper + Alt + Space" "tooltip-format": "Nomarchy Menu\n\nSuper + Alt + Space"

View File

@@ -39,6 +39,14 @@
margin: 0 7.5px; margin: 0 7.5px;
} }
/* The Nomarchy glyph lives at U+F000 in the dedicated "Nomarchy" font.
Nerd Fonts (used by default) also have U+F000 but render it as a glass
icon, so we have to pin the family for this module. */
#custom-nomarchy {
font-family: Nomarchy;
font-size: 20px;
}
#tray { #tray {
margin-right: 16px; margin-right: 16px;
} }

View File

@@ -5,6 +5,9 @@
Unit = { Unit = {
Description = "Nomarchy Battery Monitor Check"; Description = "Nomarchy Battery Monitor Check";
After = [ "graphical-session.target" ]; After = [ "graphical-session.target" ];
# Skip on hosts with no battery (VMs, desktops) — otherwise the
# monitor script fails and degrades the user session.
ConditionPathExistsGlob = "/sys/class/power_supply/BAT*";
}; };
Service = { Service = {
@@ -19,6 +22,7 @@
systemd.user.timers.nomarchy-battery-monitor = { systemd.user.timers.nomarchy-battery-monitor = {
Unit = { Unit = {
Description = "Nomarchy Battery Monitor Timer"; Description = "Nomarchy Battery Monitor Timer";
ConditionPathExistsGlob = "/sys/class/power_supply/BAT*";
}; };
Timer = { Timer = {

View File

@@ -3,14 +3,27 @@
# Wrapper to launch walker with elephant provider, or fallback to rofi if walker is missing. # Wrapper to launch walker with elephant provider, or fallback to rofi if walker is missing.
if command -v walker >/dev/null 2>&1; then if command -v walker >/dev/null 2>&1; then
# Ensure elephant is running before launching walker # The setsid backgrounded commands below MUST redirect all std fds to
# /dev/null. If they inherit stdout from a $(...) caller (e.g. nomarchy-menu
# doing `$(menu ...)`), bash waits for those fds to close on every return,
# which hangs the terminal after each menu selection.
if ! pgrep -x elephant > /dev/null; then if ! pgrep -x elephant > /dev/null; then
setsid uwsm-app -- elephant & setsid uwsm-app -- elephant </dev/null >/dev/null 2>&1 &
disown
fi fi
# Ensure walker service is running
if ! pgrep -f "walker --gapplication-service" > /dev/null; then if ! pgrep -f "walker --gapplication-service" > /dev/null; then
setsid uwsm-app -- walker --gapplication-service & setsid uwsm-app -- walker --gapplication-service </dev/null >/dev/null 2>&1 &
disown
fi
# dmenu mode reads stdin and is invoked many times in quick succession
# by nomarchy-menu. Wrapping each call in uwsm-app (systemd-run --scope)
# creates a fresh transient scope per invocation, which breaks chained
# submenus — subsequent walker calls don't see a usable stdin and exit
# without showing anything. Invoke walker directly for dmenu.
if [[ "$*" == *"--dmenu"* ]]; then
exec walker "$@"
fi fi
exec uwsm-app -- walker --width 644 --maxheight 300 --minheight 300 "$@" exec uwsm-app -- walker --width 644 --maxheight 300 --minheight 300 "$@"

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Build the Nomarchy graphical live ISO and boot it in QEMU for a
# try-before-install experience. The ISO is the `installerIsoGraphical`
# NixOS configuration — same Nomarchy system + Home Manager stack as
# `nomarchy-test-vm`, just wrapped in an installable live medium.
set -e
echo "Building Nomarchy Live ISO..."
nix build .#nixosConfigurations.installerIsoGraphical.config.system.build.isoImage
ISO=$(ls -1 result/iso/*.iso 2>/dev/null | head -n 1)
if [ -z "$ISO" ]; then
echo "Error: ISO build succeeded but no .iso file found in result/iso/"
exit 1
fi
# Prefer UEFI with OVMF so the ISO boots the same way a modern install does.
# Fall back to BIOS if OVMF isn't available on this host.
OVMF_CANDIDATES=(
"/run/current-system/sw/share/OVMF/OVMF_CODE.fd"
"/run/current-system/sw/share/qemu/edk2-x86_64-code.fd"
"/nix/var/nix/profiles/system/sw/share/OVMF/OVMF_CODE.fd"
)
BIOS_ARG=()
for c in "${OVMF_CANDIDATES[@]}"; do
if [ -f "$c" ]; then
BIOS_ARG=(-bios "$c")
break
fi
done
# KVM if the host supports it; software emulation otherwise.
ACCEL_ARG=()
if [ -r /dev/kvm ]; then
ACCEL_ARG=(-enable-kvm -cpu host)
fi
echo "Launching ISO: $ISO"
exec qemu-system-x86_64 \
"${ACCEL_ARG[@]}" \
-m 4096 -smp 2 \
"${BIOS_ARG[@]}" \
-device virtio-vga-gl -display gtk,gl=on \
-device virtio-net-pci,netdev=n0 -netdev user,id=n0 \
-cdrom "$ISO" -boot d

View File

@@ -7,6 +7,10 @@ echo "Note: To test the INSTALLER, run 'nomarchy-test-installer' instead."
nix build .#nixosConfigurations.default.config.system.build.vm nix build .#nixosConfigurations.default.config.system.build.vm
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# Drop any persisted VM disk so activation runs against fresh state.
# Without this, broken symlinks from a prior activation survive rebuilds
# and mask fixes on the next launch.
rm -f ./nomarchy.qcow2
echo "Success! Launching VM..." echo "Success! Launching VM..."
./result/bin/run-nomarchy-vm ./result/bin/run-nomarchy-vm
else else

View File

@@ -35,6 +35,9 @@
}; };
outputs = { self, nixpkgs, nixos-hardware, disko, impermanence, home-manager, nix-colors, stylix, walker, ... } @ inputs: let outputs = { self, nixpkgs, nixos-hardware, disko, impermanence, home-manager, nix-colors, stylix, walker, ... } @ inputs: let
system = "x86_64-linux";
lib = nixpkgs.lib;
# Overlays # Overlays
overlays = [ overlays = [
(final: prev: { (final: prev: {
@@ -43,13 +46,14 @@
}) })
]; ];
# Helper to create standalone home configurations
mkHome = { username, modules ? [] }: home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs { pkgs = import nixpkgs {
inherit (nixpkgs.legacyPackages.x86_64-linux) system; inherit system overlays;
inherit overlays;
config.allowUnfree = true; config.allowUnfree = true;
}; };
# Helper to create standalone home configurations
mkHome = { username, modules ? [] }: home-manager.lib.homeManagerConfiguration {
inherit pkgs;
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = { inherit inputs; };
modules = [ modules = [
./features ./features
@@ -65,6 +69,23 @@
"nixos" = mkHome { username = "nixos"; }; "nixos" = mkHome { username = "nixos"; };
"nomarchy" = mkHome { username = "nomarchy"; }; "nomarchy" = mkHome { username = "nomarchy"; };
}; };
# Realise the full HM generation for every palette so theme switches hit
# the Nix cache instead of rebuilding Stylix outputs per swap. Each entry
# pins `nomarchy.theme` (and clears the wallpaper override so the theme's
# own default background is used) and exposes the generation's activation
# package under its theme name.
palettes = import ./themes/palettes;
themeNames = builtins.attrNames palettes;
themeVariantFor = themeName: (mkHome {
username = "nomarchy";
modules = [{
nomarchy.theme = lib.mkForce themeName;
nomarchy.wallpaper = lib.mkForce "";
}];
}).activationPackage;
allThemeVariants = pkgs.linkFarm "nomarchy-all-theme-variants"
(map (name: { inherit name; path = themeVariantFor name; }) themeNames);
in { in {
# Expose inputs for downstream use # Expose inputs for downstream use
inherit inputs; inherit inputs;
@@ -94,37 +115,42 @@
# Graphical installer ISO (legacy, for users who prefer GUI) # Graphical installer ISO (legacy, for users who prefer GUI)
installerIsoGraphical = nixpkgs.lib.nixosSystem { installerIsoGraphical = nixpkgs.lib.nixosSystem {
specialArgs = { specialArgs = { inherit inputs; };
inherit inputs;
homeActivationPackage = homeConfigs."nixos".activationPackage;
};
modules = [ modules = [
{ {
nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.hostPlatform = "x86_64-linux";
nixpkgs.overlays = overlays; nixpkgs.overlays = overlays;
} }
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix" "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix"
home-manager.nixosModules.home-manager
./hosts/live-iso.nix ./hosts/live-iso.nix
./core ./core
{ {
system.stateVersion = "25.11"; system.stateVersion = "25.11";
services.displayManager.autoLogin.enable = true; services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = "nixos"; services.displayManager.autoLogin.user = "nixos";
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "hm-bak";
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.nixos = {
imports = [ ./features ];
home.stateVersion = "25.11";
};
} }
]; ];
}; };
# Default configuration (VM and testing) # Default configuration (VM and testing)
default = nixpkgs.lib.nixosSystem { default = nixpkgs.lib.nixosSystem {
specialArgs = { specialArgs = { inherit inputs; };
inherit inputs;
homeActivationPackage = homeConfigs."nomarchy".activationPackage;
};
modules = [ modules = [
{ {
nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.hostPlatform = "x86_64-linux";
nixpkgs.overlays = overlays; nixpkgs.overlays = overlays;
} }
home-manager.nixosModules.home-manager
./core/default.nix ./core/default.nix
./core/system/vm-guest.nix ./core/system/vm-guest.nix
{ {
@@ -143,11 +169,29 @@
services.displayManager.autoLogin.enable = true; services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = "nomarchy"; services.displayManager.autoLogin.user = "nomarchy";
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "hm-bak";
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.nomarchy = {
imports = [ ./features ];
home.stateVersion = "25.11";
};
} }
]; ];
}; };
}; };
homeConfigurations = homeConfigs; homeConfigurations = homeConfigs;
packages.${system} = {
# Pre-cache every theme's Home Manager generation so subsequent
# `nomarchy-theme-set` swaps are cache hits (no Stylix rebuild, no
# downloads). Run once after install:
# nix build /etc/nomarchy#allThemeVariants --no-link
inherit allThemeVariants;
default = allThemeVariants;
};
}; };
} }

View File

@@ -1,19 +1,8 @@
{ config, pkgs, inputs, lib, homeActivationPackage, ... }: { config, pkgs, inputs, lib, ... }:
{ {
# Pre-activate standalone home-manager for the live environment # Home Manager activation for the nixos live user is provided by the
system.activationScripts.home-manager-activate = { # home-manager.nixosModules.home-manager module wired up in flake.nix.
text = ''
USER_HOME="/home/nixos"
if [ ! -d "$USER_HOME" ]; then
mkdir -p "$USER_HOME"
chown nixos:users "$USER_HOME"
fi
# Run activation as the nixos user
${pkgs.sudo}/bin/sudo -u nixos ${homeActivationPackage}/activate
'';
deps = [ "users" ];
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
@@ -35,9 +24,11 @@
# Ensure the live environment user has the necessary groups for graphical acceleration and audio # Ensure the live environment user has the necessary groups for graphical acceleration and audio
users.users.nixos.extraGroups = [ "wheel" "video" "render" "audio" "networkmanager" ]; users.users.nixos.extraGroups = [ "wheel" "video" "render" "audio" "networkmanager" ];
# Graphics support for live environment # Graphics support for live environment.
boot.initrd.kernelModules = [ "amdgpu" "radeon" "nouveau" "i915" ]; # `virtio` is a no-op on real hardware (no virtio-gpu PCI device) but lets
services.xserver.videoDrivers = [ "amdgpu" "radeon" "nouveau" "modesetting" "fbdev" ]; # the ISO render correctly when booted in QEMU via nomarchy-test-live-iso.
boot.initrd.kernelModules = [ "amdgpu" "radeon" "nouveau" "i915" "virtio_gpu" ];
services.xserver.videoDrivers = [ "amdgpu" "radeon" "nouveau" "modesetting" "fbdev" "virtio" ];
environment.etc."install.sh" = { environment.etc."install.sh" = {
source = ../installer/install.sh; source = ../installer/install.sh;

View File

@@ -454,7 +454,8 @@ FLAKE_EOF
} }
EOF EOF
# system.nix # system.nix — curated system-level options. Uncomment what you want and
# run \`sudo nixos-rebuild switch --flake /etc/nixos#default\` to apply.
cat > /mnt/etc/nixos/system.nix << EOF cat > /mnt/etc/nixos/system.nix << EOF
{ pkgs, ... }: { pkgs, ... }:
{ {
@@ -462,8 +463,18 @@ EOF
$impermanence_opt $impermanence_opt
# System-wide packages. Most tools belong in home.nix instead — only put
# things here that need to be available to all users or to root (e.g. CLI
# tools used by sudo, system admin utilities).
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
home-manager home-manager
# --- CLI tools useful as root ---
# wget
# curl
# rsync
# htop
# tree
# tmux
]; ];
services.displayManager.autoLogin.enable = true; services.displayManager.autoLogin.enable = true;
@@ -475,20 +486,111 @@ EOF
extraGroups = [ "networkmanager" "wheel" "video" "audio" "render" ]; extraGroups = [ "networkmanager" "wheel" "video" "audio" "render" ];
}; };
# --- Optional system services ---
# Uncomment to enable. Some require extra groups on your user (see below).
# Containers / virtualization
# virtualisation.docker.enable = true; # adds "docker" group
# virtualisation.libvirtd.enable = true; # adds "libvirtd" group — needed for virt-manager
# Networking / sync
# services.tailscale.enable = true;
# services.syncthing = {
# enable = true;
# user = "$USERNAME";
# dataDir = "/home/$USERNAME";
# };
# Printing
# services.printing.enable = true;
# Flatpak (alternative app delivery)
# services.flatpak.enable = true;
# xdg.portal.enable = true;
# Gaming (system-level — pairs with home.packages.steam)
# programs.steam.enable = true;
# programs.gamemode.enable = true;
system.stateVersion = "25.11"; system.stateVersion = "25.11";
} }
EOF EOF
# home.nix (empty for user customization) # home.nix — curated app menu. Uncomment what you want and run
# `nomarchy-env-update` to apply.
cat > /mnt/etc/nixos/home.nix << 'EOF' cat > /mnt/etc/nixos/home.nix << 'EOF'
{ pkgs, ... }: { pkgs, ... }:
{ {
# Add your personal packages here # User-level packages (Home Manager).
#
# Nomarchy already ships a minimal desktop (firefox, thunar, mpv, imv, mako,
# hyprlock, swww, wl-clipboard, grim, slurp, rofi-wayland, etc.). The list
# below is a menu of extras — uncomment what you want and run
# `nomarchy-env-update`.
home.packages = with pkgs; [ home.packages = with pkgs; [
# example: firefox thunderbird libreoffice # --- Enabled by default ---
btop # Resource monitor (TUI)
fastfetch # System info at login
chromium # Secondary browser
# --- Editors & dev ---
# vscode
# jetbrains.idea-community
# neovide
# zed-editor
# lazygit
# gh # GitHub CLI
# docker-compose
# postman
# dbeaver-bin
# --- Productivity ---
# obsidian
# libreoffice
# thunderbird
# zathura # PDF viewer
# zotero
# xournalpp
# --- Media ---
# vlc
# obs-studio
# gimp
# inkscape
# kdenlive
# spotify
# audacity
# yt-dlp
# --- Comms ---
# discord
# telegram-desktop
# signal-desktop
# slack
# zoom-us
# --- Security ---
# keepassxc
# bitwarden-desktop
# _1password-gui
# --- Gaming ---
# steam
# lutris
# heroic
# --- CLI / utilities ---
# ripgrep
# fd
# bat
# eza
# zoxide
# fzf
# httpie
# tldr
]; ];
# Add your personal home-manager configuration here # Extra Home Manager modules go here (program configs, services, etc.).
} }
EOF EOF
} }
@@ -510,6 +612,9 @@ finish() {
echo " 3. Log in with username: $USERNAME" echo " 3. Log in with username: $USERNAME"
echo " 4. Your configuration is at /etc/nixos/" echo " 4. Your configuration is at /etc/nixos/"
echo "" echo ""
echo "Tip: run 'nomarchy-themes-prebuild' once to pre-cache every theme"
echo " variant. Theme switches after that are instant (no rebuild)."
echo ""
if nrun gum confirm "Reboot now?"; then if nrun gum confirm "Reboot now?"; then
reboot reboot

View File

@@ -78,6 +78,20 @@ let
else else
default; default;
# Map an icon-theme name (as declared in a palette's icons.theme file) to
# the nixpkgs attribute that ships it. Anything unknown falls back to
# yaru-theme so GTK still has a working default.
#
# When adding a palette that uses a new icon family, extend this mapping
# so `nomarchy-theme-set <name>` auto-installs the matching package.
iconThemePackage = { iconsTheme, pkgs }:
if lib.hasPrefix "Yaru" iconsTheme then pkgs.yaru-theme
else if lib.hasPrefix "Everforest" iconsTheme then pkgs.everforest-gtk-theme
else if lib.hasPrefix "Papirus" iconsTheme then pkgs.papirus-icon-theme
else if lib.hasPrefix "Adwaita" iconsTheme then pkgs.adwaita-icon-theme
else if lib.hasPrefix "breeze" iconsTheme || lib.hasPrefix "Breeze" iconsTheme then pkgs.kdePackages.breeze-icons
else pkgs.yaru-theme;
# Get list of available theme names # Get list of available theme names
themeNames = builtins.attrNames palettes; themeNames = builtins.attrNames palettes;
@@ -92,5 +106,6 @@ in {
getColorScheme getColorScheme
isThemeLightMode isThemeLightMode
getIconsTheme getIconsTheme
iconThemePackage
themeNames; themeNames;
} }

View File

@@ -51,4 +51,15 @@ nomarchy-env-update
nomarchy-theme-set-templates nomarchy-theme-set-templates
# Walker reads its CSS via @import of ~/.config/nomarchy/current/theme/apps/walker/style.css,
# and waybar's shared fallback style does the same with waybar.css. HM's sd-switch
# only restarts services whose unit *definition* changed, so when only the imported
# file's contents change, neither gets reloaded. Restart them explicitly.
command -v nomarchy-restart-walker >/dev/null 2>&1 && nomarchy-restart-walker || true
command -v nomarchy-restart-waybar >/dev/null 2>&1 && nomarchy-restart-waybar || true
# Reload the wallpaper — its ExecStart path is stable (~/.config/nomarchy/current/background)
# so sd-switch does not detect a unit change when only the symlink target moves.
systemctl --user restart nomarchy-wallpaper.service 2>/dev/null || true
nomarchy-hook theme-set "$THEME_NAME" nomarchy-hook theme-set "$THEME_NAME"

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Pre-realise every theme's Home Manager generation into the Nix store so
# future `nomarchy-theme-set` swaps are cache hits — no Stylix rebuild, no
# downloads. Run once after install (the installer wires this up) and again
# after adding or updating palettes.
set -e
if [ -f "/etc/nixos/flake.nix" ]; then
REPO_DIR="/etc/nixos"
elif [ -f "/etc/nomarchy/flake.nix" ]; then
REPO_DIR="/etc/nomarchy"
else
echo "Error: Nomarchy flake repository not found in /etc/nixos or /etc/nomarchy." >&2
exit 1
fi
echo "Pre-building every theme variant from $REPO_DIR#allThemeVariants..."
echo "This is a one-time cache warm-up. Subsequent theme switches will be instant."
nix build --no-link --print-out-paths \
--extra-experimental-features "nix-command flakes" \
"$REPO_DIR#allThemeVariants"
echo "Theme variants cached. Theme switches now avoid rebuilds."

View File

@@ -92,11 +92,17 @@ in
}; };
}; };
# GTK Icon Theme configuration # GTK Icon Theme configuration. The package is derived from the theme's
# declared icon family (palettes/<theme>/icons.theme), so switching to a
# palette that needs e.g. Everforest icons automatically installs
# `everforest-gtk-variant` instead of sticking with `yaru-theme`.
gtk = { gtk = {
enable = lib.mkDefault true; enable = lib.mkDefault true;
iconTheme = lib.mkDefault { iconTheme = lib.mkDefault {
package = pkgs.yaru-theme; package = nomarchyLib.iconThemePackage {
iconsTheme = config.nomarchy.iconsTheme;
inherit pkgs;
};
name = config.nomarchy.iconsTheme; name = config.nomarchy.iconsTheme;
}; };
}; };