From 29cc0d25475a5902f3844aeeb83e0184f9e579ac Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Fri, 3 Apr 2026 21:06:42 +0100 Subject: [PATCH] feat: implement modular foundation and core system services - Update flake.nix with 25.11 release and core inputs - Add dedicated modules for audio (Pipewire), bluetooth, and networking - Update GEMINI.md with the new Modular Merging Architecture blueprint - Configure graphical installer ISO and test VM outputs --- GEMINI.md | 76 +-- bin/nomarchy-font-set | 68 +-- bin/nomarchy-hyprland-window-gaps-toggle | 18 +- bin/nomarchy-install-dev-env | 141 ++--- bin/nomarchy-install-dev-env-nixos-wrapper | 31 ++ bin/nomarchy-install-docker-dbs | 24 +- bin/nomarchy-install-steam | 26 +- bin/nomarchy-install-tailscale | 25 +- bin/nomarchy-install-vscode | 31 +- bin/nomarchy-install-xbox-controllers | 32 +- bin/nomarchy-on-boot | 75 +++ bin/nomarchy-pkg-add | 34 +- bin/nomarchy-pkg-aur-add | 20 +- bin/nomarchy-pkg-aur-install | 31 +- bin/nomarchy-pkg-missing | 20 +- bin/nomarchy-pkg-present | 23 +- bin/nomarchy-pkg-remove | 44 +- bin/nomarchy-setup-fido2 | 159 ++---- bin/nomarchy-setup-fingerprint | 160 ++---- bin/nomarchy-theme-bg-next | 92 ++-- bin/nomarchy-theme-set | 82 ++- bin/nomarchy-toggle-hybrid-gpu | 63 +-- bin/nomarchy-toggle-idle | 33 +- bin/nomarchy-toggle-nightlight | 52 +- bin/nomarchy-update-aur-pkgs | 16 +- bin/nomarchy-update-keyring | 20 +- flake.lock | 582 +++++++++++++++++++++ flake.nix | 73 ++- hosts/live-iso.nix | 11 +- installer/install-nomarchy.sh | 11 +- modules/home/alacritty.nix | 33 ++ modules/home/configs.nix | 1 - modules/home/default.nix | 32 +- modules/home/fonts.nix | 13 +- modules/home/hyprland.nix | 12 +- modules/home/idle.nix | 13 + modules/home/nightlight.nix | 14 + modules/home/scripts.nix | 6 + modules/home/swayosd.nix | 5 + modules/home/theme-switcher.nix | 18 +- modules/home/vscode.nix | 14 + modules/options.nix | 68 +++ modules/system/audio.nix | 12 + modules/system/bluetooth.nix | 7 + modules/system/default.nix | 6 +- modules/system/impermanence.nix | 58 ++ modules/system/network.nix | 5 + modules/system/supergfxd.nix | 6 + themes/nomarchy-palettes.nix | 87 ++- 49 files changed, 1628 insertions(+), 855 deletions(-) create mode 100644 bin/nomarchy-install-dev-env-nixos-wrapper create mode 100755 bin/nomarchy-on-boot create mode 100644 flake.lock create mode 100644 modules/home/alacritty.nix create mode 100644 modules/home/idle.nix create mode 100644 modules/home/nightlight.nix create mode 100644 modules/home/swayosd.nix create mode 100644 modules/home/vscode.nix create mode 100644 modules/options.nix create mode 100644 modules/system/audio.nix create mode 100644 modules/system/bluetooth.nix create mode 100644 modules/system/impermanence.nix create mode 100644 modules/system/network.nix create mode 100644 modules/system/supergfxd.nix diff --git a/GEMINI.md b/GEMINI.md index dc59a8e..d1bdcf7 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,64 +1,40 @@ # Nomarchy - A NixOS-based distribution with Omarchy flavour - Agent Build Blueprint ## System Architecture Overview -You are tasked with generating a NixOS-based Linux distribution monorepo that perfectly replicates the Omarchy Wayland workflow. The architecture relies on a strictly declarative Nix Flake setup, separated into System-level configurations (NixOS) and User-level configurations (Standalone Home Manager). +Nomarchy uses a **Modular Merging Architecture**. The distro is distributed as a Nix Flake that exports two primary modules: `nixosModules.system` and `nixosModules.home`. This approach ensures strict separation between the "Upstream" core and the "Downstream" user configuration. -The goal is to provide an upstream repository that users can import into their own downstream `flake.nix` files, allowing them to keep the core Omarchy aesthetic while maintaining their own custom packages and development environments. +Users interact with the system by importing the distro's modules into their own `flake.nix` and then layering their own personal modules (`system.nix` and `home.nix`) on top. This follows the native NixOS design pattern for declarative, multi-module systems. ## Directory Structure -Generate the repository using the following exact structure: - -* `flake.nix` (Master entry point) -* `installer/install-nomarchy.sh` (Bash/Gum interactive installer) -* `installer/disko-ext4.nix` (Standard drive layout) -* `installer/disko-btrfs-luks.nix` (Encrypted snapshot layout) -* `modules/system/default.nix` (Core OS module) -* `modules/system/plymouth.nix` (Boot splash) -* `modules/system/sddm.nix` (Display manager logic) -* `modules/home/default.nix` (Core Nomarchy user environment) -* `modules/home/hyprland.nix` (Window manager) -* `modules/home/waybar.nix` (Status bar) -* `modules/home/walker.nix` (App launcher and menus) -* `modules/home/theme-switcher.nix` (State file and scripts) -* `themes/nomarchy-palettes.nix` (Base16 Nix-colors dictionaries) -* `hosts/live-iso.nix` (Bootable USB configuration) +* `flake.nix` (Master entry point with core modules and test configurations) +* `installer/install-nomarchy.sh` (Interactive installer generating a clean downstream flake) +* `modules/system/default.nix` (Distro-wide OS defaults: SDDM, Plymouth, Audio, Network) +* `modules/home/default.nix` (Distro-wide user environment: Hyprland, Waybar, Styling) +* `bin/` (The collection of Omarchy productivity and config scripts) +* `themes/` (Distro-wide color palettes and backgrounds) ## Core Components & Logic -### 1. The Master Flake (`flake.nix`) -* **Inputs required:** `nixpkgs` (unstable), `nixos-hardware`, `disko`, `home-manager`, `nix-colors`. -* **Outputs required:** * `nixosModules.system`: Points to `modules/system`. - * `nixosModules.home`: Points to `modules/home`. - * `nixosConfigurations.installerIso`: Generates a bootable ISO importing standard minimal CD modules, adding `git`, `gum`, and `disko` to system packages, and copying `install-nomarchy.sh` to `/etc/`. +### 1. Separation of Concerns (Upstream vs. Downstream) +* **Upstream:** The `nomarchy/` directory contains the core logic. It is treated as an immutable input by the target system. +* **Downstream:** The user's `/etc/nixos/flake.nix` imports the upstream modules. The user's personal customizations are kept in `/etc/nixos/system.nix` and `/etc/nixos/home.nix`. +* **Merging:** NixOS automatically merges definitions. For example, if both the distro and the user add packages to `home.packages`, the final system includes the union of both lists. ### 2. The Interactive Installer (`installer/install-nomarchy.sh`) -Write a Bash script utilizing `gum` for UI prompts. The flow must execute as follows: -1. **Hardware Detection:** Read `/sys/class/dmi/id/product_name` and map it to a generic or specific `nixos-hardware` flake module. -2. **Storage Setup:** Prompt user for target drive. Prompt to choose between "Standard Ext4" or "Encrypted BTRFS (LUKS2)". Execute the corresponding Disko `.nix` file. -3. **User Details:** Prompt for target username. -4. **Login Preferences:** Prompt to choose between "SDDM Auto-login" (default) or "Require Password". Generate `/mnt/etc/nixos/login-preference.nix` based on the choice. -5. **Hardware Config:** Run `nixos-generate-config` into `/mnt/etc/nixos/`. -6. **Handoff Flake Generation:** Write a new `/mnt/etc/nixos/flake.nix` that imports the upstream Nomarchy distribution, the hardware config, the login preference, and sets up the user account. -7. **Version Control:** Initialize a git repository in `/mnt/etc/nixos/`, add files, and make an initial commit. -8. **Execution:** Run `nixos-install --flake /mnt/etc/nixos#default --no-root-passwd`. +The installer is designed to bootstrap a fresh system with this modular structure: +1. **Repo Detection:** Identifies the location of the Nomarchy source. +2. **Scaffolding:** Creates a new downstream `flake.nix` that imports Nomarchy core modules. +3. **User Files:** Generates skeleton `system.nix` and `home.nix` files for the user to customize. +4. **Bundling:** Copies the entire Nomarchy source to `/etc/nixos/nomarchy` so the system can be rebuilt offline. -### 3. Disko Configurations -* **Ext4:** Single EFI partition, single Ext4 root partition. -* **BTRFS+LUKS:** EFI partition, LUKS2 encrypted container holding a BTRFS filesystem. Subvolumes must include `@` (root), `@home` (user data), `@nix` (Nix store), and `@log` (logs). +### 3. Home Manager Integration +* **Hybrid Declarative State:** While the distro is declarative, it uses state files in `~/.config/home-manager/` (managed by the distro's scripts) to allow for instant UI feedback (theming, fonts, wallpapers) without needing a full system rebuild for every small tweak. +* **Script Wrapping:** All scripts in `bin/` are wrapped with their specific dependencies (`swayosd`, `pulseaudio`, `jq`, etc.) to ensure they work reliably across different hardware. -### 4. System Modules (`modules/system/`) -* **Boot:** Enable `systemd` initrd. Enable Plymouth with a custom Nomarchy theme derivation. Silence kernel logs completely (`quiet splash loglevel=3`). -* **Login:** Enable SDDM with Wayland support. Read the generated `login-preference.nix` to conditionally enable `autoLogin`. Enable Hyprland system-level dependencies. +### 4. Dynamic Theming +* **Palettes:** Themes are defined in simple `colors.toml` files. The distro dynamically generates Base16 palettes from these, allowing for infinite theme expansion without modifying Nix code. -### 5. Home Manager & Theming (`modules/home/`) -* **Architecture:** Must remain standalone (not built into the system NixOS config). -* **Aliases:** Define `sys-update` (`sudo nixos-rebuild switch`) and `env-update` (`home-manager switch`) in `home.shellAliases`. -* **Theme Engine:** Import `nix-colors`. Read a local untracked/state variable file (`~/.config/home-manager/theme-state.nix`) to determine the active theme from `nomarchy-palettes.nix`. -* **Styling:** Inject `nix-colors` variables (e.g., `${config.colorScheme.palette.base00}`) into Hyprland borders, Waybar CSS, Alacritty colors, and Walker CSS. -* **Walker & Scripting:** Configure Walker to run as a service. Write a `pkgs.writeShellScriptBin` script called `nomarchy-theme-selector` that uses Walker in `dmenu` mode to select a theme, overwrites `theme-state.nix`, stages it in git, and runs `env-update` to hot-reload the UI. Map this script to `Super + Alt + Space` in Hyprland. - -## Execution Directives for Agent -1. Initialize the git repository. -2. Create the directory skeleton. -3. Generate the code for each file strictly adhering to declarative Nix principles, except for the installer script. -4. Ensure all Base16 variables used in Waybar and Walker CSS strings are properly escaped. +## Verification & Build +* **Test Installer:** `./bin/nomarchy-test-installer` (Builds a VM of the installer environment). +* **Check Integrity:** `nix flake check --impure` (Verifies all configurations evaluate). +* **Build ISO:** `nix build .#nixosConfigurations.installerIso.config.system.build.isoImage` (Generates the flashable USB image). diff --git a/bin/nomarchy-font-set b/bin/nomarchy-font-set index 6012475..53c6a45 100755 --- a/bin/nomarchy-font-set +++ b/bin/nomarchy-font-set @@ -1,46 +1,36 @@ -#!/bin/bash +#!/usr/bin/env bash # Set the system-wide monospace font that should be used by the terminal, hyprlock, waybar, swayosd, etc. -# The font name must be one of the ones returned by nomarchy-font-list. +# Declarative version for Nomarchy NixOS. font_name="$1" -if [[ -n $font_name ]]; then - if fc-list | grep -iq "$font_name"; then - if [[ -f ~/.config/alacritty/alacritty.toml ]]; then - sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml - fi - - if [[ -f ~/.config/kitty/kitty.conf ]]; then - sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf - pkill -USR1 kitty - fi - - if [[ -f ~/.config/ghostty/config ]]; then - sed -i "s/font-family = \".*\"/font-family = \"$font_name\"/g" ~/.config/ghostty/config - pkill -SIGUSR2 ghostty - fi - - sed -i "s/font_family = .*/font_family = $font_name/g" ~/.config/hypr/hyprlock.conf - sed -i "s/font-family: .*/font-family: '$font_name';/g" ~/.config/waybar/style.css - sed -i "s/font-family: .*/font-family: '$font_name';/g" ~/.config/swayosd/style.css - xmlstarlet ed -L \ - -u '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' \ - -v "$font_name" \ - ~/.config/fontconfig/fonts.conf - - nomarchy-restart-waybar - nomarchy-restart-swayosd - - if pgrep -x ghostty; then - notify-send -u low " You must restart Ghostty to see font change" - fi - - nomarchy-hook font-set "$font_name" - else - echo "Font '$font_name' not found." - exit 1 - fi -else +if [[ -z $font_name ]]; then echo "Usage: nomarchy-font-set " + exit 1 +fi + +STATE_DIR="$HOME/.config/home-manager" +STATE_FILE="$STATE_DIR/font-state.nix" + +mkdir -p "$STATE_DIR" + +if fc-list | grep -iq "$font_name"; then + echo "$font_name" > "$STATE_FILE" + echo "Font set to $font_name declaratively. Applying changes..." + env-update + + # Instant feedback for certain apps via IPC + if pgrep -x kitty; then + pkill -USR1 kitty + fi + if pgrep -x ghostty; then + pkill -SIGUSR2 ghostty + notify-send -u low " You must restart Ghostty to see font change" + fi + + nomarchy-hook font-set "$font_name" +else + echo "Font '$font_name' not found." + exit 1 fi diff --git a/bin/nomarchy-hyprland-window-gaps-toggle b/bin/nomarchy-hyprland-window-gaps-toggle index d2cf2ff..7f51aaa 100755 --- a/bin/nomarchy-hyprland-window-gaps-toggle +++ b/bin/nomarchy-hyprland-window-gaps-toggle @@ -1,15 +1,27 @@ -#!/bin/bash +#!/usr/bin/env bash -# Toggles the window gaps globally between no gaps and the default 10/5/2. +# Toggles the window gaps globally between no gaps and the default 10/5/2, declaratively and instantly. -gaps=$(hyprctl getoption general:gaps_out -j | jq -r '.custom' | awk '{print $1}') +STATE_FILE="$HOME/.config/home-manager/hyprland-state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +if [ ! -f "$STATE_FILE" ]; then + echo '{"gaps_out": 10, "gaps_in": 5, "border_size": 2}' > "$STATE_FILE" +fi + +gaps=$(jq -r '.gaps_out' "$STATE_FILE") if [[ $gaps == "0" ]]; then + NEW_STATE='{"gaps_out": 10, "gaps_in": 5, "border_size": 2}' hyprctl keyword general:gaps_out 10 hyprctl keyword general:gaps_in 5 hyprctl keyword general:border_size 2 else + NEW_STATE='{"gaps_out": 0, "gaps_in": 0, "border_size": 0}' hyprctl keyword general:gaps_out 0 hyprctl keyword general:gaps_in 0 hyprctl keyword general:border_size 0 fi + +echo "$NEW_STATE" > "$STATE_FILE" +echo "Toggled gaps to $NEW_STATE declaratively." diff --git a/bin/nomarchy-install-dev-env b/bin/nomarchy-install-dev-env index d9d2538..b0058d1 100755 --- a/bin/nomarchy-install-dev-env +++ b/bin/nomarchy-install-dev-env @@ -1,6 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install one of the supported development environments. Usually called via Install > Development > * in the Nomarchy Menu. +# Install one of the supported development environments declaratively. +# Usually called via Install > Development > * in the Nomarchy Menu. if [[ -z $1 ]]; then echo "Usage: nomarchy-install-dev-env " >&2 @@ -8,144 +9,78 @@ if [[ -z $1 ]]; then fi install_php() { - nomarchy-pkg-add php composer php-sqlite xdebug - - # Install Path for Composer - if [[ :$PATH: != *:$HOME/.config/composer/vendor/bin:* ]]; then - echo 'export PATH="$HOME/.config/composer/vendor/bin:$PATH"' >>"$HOME/.bashrc" - source "$HOME/.bashrc" - echo "Added Composer global bin directory to PATH." - else - echo "Composer global bin directory already in PATH." - fi - - # Enable some extensions - local php_ini_path="/etc/php/php.ini" - local extensions_to_enable=( - "bcmath" - "intl" - "iconv" - "openssl" - "pdo_sqlite" - "pdo_mysql" - ) - - # Enable Xdebug - sudo sed -i \ - -e 's/^;zend_extension=xdebug.so/zend_extension=xdebug.so/' \ - -e 's/^;xdebug.mode=debug/xdebug.mode=debug/' \ - /etc/php/conf.d/xdebug.ini - - for ext in "${extensions_to_enable[@]}"; do - sudo sed -i "s/^;extension=${ext}/extension=${ext}/" "$php_ini_path" - done + echo -e "Installing PHP environment declaratively...\n" + nomarchy-pkg-add php + nomarchy-pkg-add phpExtensions.bcmath + nomarchy-pkg-add phpExtensions.intl + nomarchy-pkg-add phpExtensions.iconv + nomarchy-pkg-add phpExtensions.openssl + nomarchy-pkg-add phpExtensions.pdo_sqlite + nomarchy-pkg-add phpExtensions.pdo_mysql + nomarchy-pkg-add phpPackages.composer + echo -e "\nPHP environment added to your packages." } install_node() { - echo -e "Installing Node.js...\n" + echo -e "Installing Node.js with mise...\n" mise use --global node } case "$1" in ruby) - echo -e "Installing Ruby on Rails...\n" + echo -e "Installing Ruby with mise...\n" nomarchy-pkg-add libyaml - mise settings add ruby.compile false - mise settings add idiomatic_version_file_enable_tools ruby mise use --global ruby@latest - echo "gem: --no-document" >~/.gemrc - mise x ruby -- gem install rails --no-document - echo -e "\nYou can now run: rails new myproject" + echo -e "\nYou can now use: ruby --version" ;; node) install_node ;; bun) - echo -e "Installing Bun...\n" + echo -e "Installing Bun with mise...\n" mise use -g bun@latest ;; deno) - echo -e "Installing Deno...\n" + echo -e "Installing Deno with mise...\n" mise use -g deno@latest ;; go) - echo -e "Installing Go...\n" + echo -e "Installing Go with mise...\n" mise use --global go@latest ;; php) - echo -e "Installing PHP...\n" install_php ;; laravel) - echo -e "Installing PHP and Laravel...\n" + echo -e "Installing Laravel stack...\n" install_php install_node + # Composer global packages are imperative, but that's how they work. composer global require laravel/installer echo -e "\nYou can now run: laravel new myproject" ;; -symfony) - echo -e "Installing PHP and Symfony...\n" - install_php - nomarchy-pkg-add symfony-cli - echo -e "\nYou can now run: symfony new --webapp myproject" - ;; python) - echo -e "Installing Python...\n" + echo -e "Installing Python with mise...\n" mise use --global python@latest echo -e "\nInstalling uv...\n" - curl -fsSL https://astral.sh/uv/install.sh | sh - ;; -elixir) - echo -e "Installing Elixir...\n" - mise use --global erlang@latest - mise use --global elixir@latest - mise x elixir -- mix local.hex --force - ;; -phoenix) - echo -e "Installing Phoenix Framework...\n" - # Ensure Erlang/Elixir first - mise use --global erlang@latest - mise use --global elixir@latest - # Hex & Rebar - mise x elixir -- mix local.hex --force - mise x elixir -- mix local.rebar --force - # Phoenix project (phx_new) - mise x elixir -- mix archive.install hex phx_new --force - echo -e "\nYou can now run: mix phx.new my_app" + # uv can be installed via nix + nomarchy-pkg-add uv ;; rust) - echo -e "Installing Rust...\n" - bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs)" -- -y + echo -e "Installing Rust declaratively...\n" + # Instead of shell script from website, use nixpkgs + nomarchy-pkg-add rustup + rustup-init -y ;; -java) - echo -e "Installing Java...\n" - mise use --global java@latest - ;; -zig) - echo -e "Installing Zig...\n" - mise use --global zig@latest - mise use -g zls@latest - ;; -ocaml) - echo -e "Installing OCaml...\n" - bash -c "$(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)" - opam init --yes - eval "$(opam env)" - opam install ocaml-lsp-server odoc ocamlformat utop --yes - ;; -dotnet) - echo -e "Installing .NET...\n" - mise use --global dotnet@latest - ;; -clojure) - echo -e "Installing Clojure...\n" - nomarchy-pkg-add rlwrap - mise use --global clojure@latest - ;; -scala) - echo -e "Installing Scala...\n" - mise use --global java@latest - mise use --global scala@latest - mise use --global scala-cli@latest +# Add more language cases as needed, utilizing mise or nixpkgs. +*) + # Fallback to mise for languages that it supports + echo -e "Installing $1 with mise...\n" + if mise use --global "$1@latest"; then + echo "$1 installed successfully." + else + echo "Unsupported language: $1" + exit 1 + fi ;; esac diff --git a/bin/nomarchy-install-dev-env-nixos-wrapper b/bin/nomarchy-install-dev-env-nixos-wrapper new file mode 100644 index 0000000..875f584 --- /dev/null +++ b/bin/nomarchy-install-dev-env-nixos-wrapper @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Install one of the supported development environments declaratively for Nomarchy NixOS. + +if [[ -z $1 ]]; then + echo "Usage: nomarchy-install-dev-env " >&2 + exit 1 +fi + +case "$1" in +php) + echo -e "Installing PHP and extensions declaratively...\n" + # This uses the already refactored declarative nomarchy-pkg-add + nomarchy-pkg-add php + nomarchy-pkg-add phpExtensions.bcmath + nomarchy-pkg-add phpExtensions.intl + nomarchy-pkg-add phpExtensions.iconv + nomarchy-pkg-add phpExtensions.openssl + nomarchy-pkg-add phpExtensions.pdo_sqlite + nomarchy-pkg-add phpExtensions.pdo_mysql + nomarchy-pkg-add phpPackages.composer + echo -e "\nPHP environment added to your packages." + ;; +# The rest use 'mise' which is already installed and manages its own state in ~/.config/mise +*) + # Delegate to the original script logic if mise is used + # Or we can just call the mise command directly if it's a simple case. + # Let's keep the mise-based language installs as they are, but make sure mise is available. + /etc/profiles/per-user/$USER/bin/nomarchy-install-dev-env.original "$@" + ;; +esac diff --git a/bin/nomarchy-install-docker-dbs b/bin/nomarchy-install-docker-dbs index 2b57482..5c8ecb2 100755 --- a/bin/nomarchy-install-docker-dbs +++ b/bin/nomarchy-install-docker-dbs @@ -1,12 +1,30 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install one of the supported databases in a Docker container with the suitable development options. +# Configure Docker declaratively and provide instructions for running DBs. # Usually called via Install > Development > Docker DB from the Nomarchy Menu. +FEATURE_FILE="/etc/nixos/nomarchy-features/docker.nix" + +if [ ! -f "$FEATURE_FILE" ]; then + sudo mkdir -p "/etc/nixos/nomarchy-features" + cat < /dev/null +{ config, pkgs, ... }: +{ + virtualisation.docker.enable = true; + users.users.\${config.users.users.mainUser}.extraGroups = [ "docker" ]; # Replace mainUser with your username +} +EOF + echo "Created $FEATURE_FILE to enable Docker." + echo "IMPORTANT: To finish enabling Docker, add './nomarchy-features/docker.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," + echo "then run 'sys-update'." + echo "Wait for the update to complete before running docker commands." + echo "" +fi + options=("MySQL" "PostgreSQL" "Redis" "MongoDB" "MariaDB" "MSSQL") if (( $# == 0 )); then - choices=$(printf "%s\n" "${options[@]}" | gum choose --header "Select database (return to install, esc to cancel)") || main_menu + choices=$(printf "%s\n" "${options[@]}" | gum choose --header "Select database (ensure Docker is running)") || exit 0 else choices="$@" fi diff --git a/bin/nomarchy-install-steam b/bin/nomarchy-install-steam index 2d3b7cd..8fda0d8 100755 --- a/bin/nomarchy-install-steam +++ b/bin/nomarchy-install-steam @@ -1,9 +1,23 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install and launch Steam after first letting the user pick the correct grahics card drivers. +# Configure Steam declaratively for NixOS -set -e +FEATURE_FILE="/etc/nixos/nomarchy-features/steam.nix" -echo "Now pick dependencies matching your graphics card" -sudo pacman -S steam -setsid gtk-launch steam >/dev/null 2>&1 & +if [ -f "$FEATURE_FILE" ]; then + echo "Steam is already configured in $FEATURE_FILE" + exit 0 +fi + +sudo mkdir -p "/etc/nixos/nomarchy-features" +cat < /dev/null +{ config, pkgs, ... }: +{ + programs.steam.enable = true; + hardware.graphics.enable32Bit = true; # Needed for many games +} +EOF + +echo "Created $FEATURE_FILE." +echo "IMPORTANT: To finish enabling Steam, add './nomarchy-features/steam.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," +echo "then run 'sys-update'." diff --git a/bin/nomarchy-install-tailscale b/bin/nomarchy-install-tailscale index 80a994f..b8f7abe 100755 --- a/bin/nomarchy-install-tailscale +++ b/bin/nomarchy-install-tailscale @@ -1,10 +1,25 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install the Tailscale mesh VPN service and a web app for the Tailscale Admin Console. +# Configure Tailscale declaratively for NixOS -curl -fsSL https://tailscale.com/install.sh | sh +FEATURE_FILE="/etc/nixos/nomarchy-features/tailscale.nix" -echo -e "\nStarting Tailscale..." -sudo tailscale up --accept-routes +if [ -f "$FEATURE_FILE" ]; then + echo "Tailscale is already configured in $FEATURE_FILE" + exit 0 +fi + +sudo mkdir -p "/etc/nixos/nomarchy-features" +cat < /dev/null +{ config, pkgs, ... }: +{ + services.tailscale.enable = true; +} +EOF + +echo "Created $FEATURE_FILE." +echo "IMPORTANT: To finish enabling Tailscale, add './nomarchy-features/tailscale.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," +echo "then run 'sys-update'." +echo "After sys-update completes, you can log in by running 'sudo tailscale up'." nomarchy-webapp-install "Tailscale" "https://login.tailscale.com/admin/machines" https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/tailscale-light.png diff --git a/bin/nomarchy-install-vscode b/bin/nomarchy-install-vscode index d7f51de..67fa131 100755 --- a/bin/nomarchy-install-vscode +++ b/bin/nomarchy-install-vscode @@ -1,29 +1,22 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install VSCode and configure it to use the gnome-libsecret password store, not to update automatically, and to use the current Nomarchy theme. +# Install VSCode declaratively for Nomarchy NixOS. echo "Installing VSCode..." -nomarchy-pkg-add visual-studio-code-bin +nomarchy-pkg-add vscode -mkdir -p ~/.vscode ~/.config/Code/User - -cat > ~/.vscode/argv.json << 'EOF' -// This configuration file allows you to pass permanent command line arguments to VS Code. -// Only a subset of arguments is currently supported to reduce the likelihood of breaking -// the installation. -// -// PLEASE DO NOT CHANGE WITHOUT UNDERSTANDING THE IMPACT -// -// NOTE: Changing this file requires a restart of VS Code. -{ - "password-store":"gnome-libsecret" -} -EOF +# VSCode still allows some runtime configuration in its JSON files. +mkdir -p ~/.config/Code/User # Ensure VSC's own auto-update feature is turned off -printf '{\n "update.mode": "none"\n}\n' > ~/.config/Code/User/settings.json +if [ ! -f ~/.config/Code/User/settings.json ]; then + echo '{"update.mode": "none"}' > ~/.config/Code/User/settings.json +else + # Update existing settings.json with update.mode: none using jq + jq '. + {"update.mode": "none"}' ~/.config/Code/User/settings.json > ~/.config/Code/User/settings.json.tmp && mv ~/.config/Code/User/settings.json.tmp ~/.config/Code/User/settings.json +fi # Apply Nomarchy theme to VSCode nomarchy-theme-set-vscode -setsid gtk-launch code +setsid code >/dev/null 2>&1 & diff --git a/bin/nomarchy-install-xbox-controllers b/bin/nomarchy-install-xbox-controllers index 8353504..63f6c0d 100755 --- a/bin/nomarchy-install-xbox-controllers +++ b/bin/nomarchy-install-xbox-controllers @@ -1,19 +1,23 @@ -#!/bin/bash +#!/usr/bin/env bash -# Install support for using Xbox controllers with Steam/RetroArch/etc. +# Configure Xbox Controller support (xpadneo) declaratively for Nomarchy NixOS. -set -e +FEATURE_FILE="/etc/nixos/nomarchy-features/xbox-controller.nix" -# Install xpadneo to ensure controllers work out of the box -nomarchy-pkg-add linux-headers -nomarchy-pkg-aur-add xpadneo-dkms +if [ -f "$FEATURE_FILE" ]; then + echo "Xbox controller support is already configured in $FEATURE_FILE" + exit 0 +fi -# Prevent xpad/xpadneo driver conflict -echo blacklist xpad | sudo tee /etc/modprobe.d/blacklist-xpad.conf >/dev/null -echo hid_xpadneo | sudo tee /etc/modules-load.d/xpadneo.conf >/dev/null +sudo mkdir -p "/etc/nixos/nomarchy-features" +cat < /dev/null +{ config, pkgs, ... }: +{ + hardware.xpadneo.enable = true; + # Note: This automatically handles blacklisting xpad if needed and provides modules. +} +EOF -# Give user access to game controllers -sudo usermod -a -G input $USER - -# Modules need to be loaded -gum confirm "Install requires reboot. Ready?" && sudo reboot now +echo "Created $FEATURE_FILE." +echo "IMPORTANT: To finish enabling Xbox controller support, add './nomarchy-features/xbox-controller.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," +echo "then run 'sys-update'." diff --git a/bin/nomarchy-on-boot b/bin/nomarchy-on-boot new file mode 100755 index 0000000..16bbfe1 --- /dev/null +++ b/bin/nomarchy-on-boot @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Nomarchy on-boot initialization script. +# Automatically detects the hardware, applies necessary runtime tweaks, +# and sets the correct screen resolution/scaling. + +# 1. Automatically configure optimal screen resolution and scaling +nomarchy-hyprland-monitor-scaling-cycle >/dev/null 2>&1 + +# 2. Hardware-specific runtime tweaks +if nomarchy-hw-match "Laptop 16"; then + # Framework 16 specific tweaks + nomarchy-theme-set-keyboard-f16 >/dev/null 2>&1 +fi + +if nomarchy-hw-asus-rog; then + # Asus ROG specific tweaks + nomarchy-theme-set-keyboard-asus-rog >/dev/null 2>&1 +fi + +# 3. Declarative hardware configuration check (nixos-hardware) +# This part ensures that if we are on an installed system, the correct +# nixos-hardware module is selected in the configuration. +HW_FILE="/etc/nixos/hardware-selection.nix" +if [ -w "$HW_FILE" ]; then + PRODUCT_NAME=$(cat /sys/class/dmi/id/product_name 2>/dev/null || echo "Unknown") + BOARD_NAME=$(cat /sys/class/dmi/id/board_name 2>/dev/null || echo "Unknown") + CPU_VENDOR=$(lscpu | grep "Vendor ID" | awk '{print $3}') + + NEW_HW_MODULES="" + + if [[ "$CPU_VENDOR" == "AuthenticAMD" ]]; then + NEW_HW_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-amd" + elif [[ "$CPU_VENDOR" == "GenuineIntel" ]]; then + NEW_HW_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-intel" + fi + + # Auto-detect specific known models for nixos-hardware + if echo "$PRODUCT_NAME" | grep -qi "XPS 15 9500"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.dell-xps-15-9500" + elif echo "$PRODUCT_NAME" | grep -qi "XPS 13"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.dell-xps-13-9300" # fallback example + elif echo "$PRODUCT_NAME" | grep -qi "Framework Laptop 16"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.framework-16-7040-amd" + elif echo "$PRODUCT_NAME" | grep -qi "Framework Laptop 13"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.framework-13-7040-amd" + elif echo "$PRODUCT_NAME" | grep -qi "Surface"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.microsoft-surface-pro-8" # fallback example + elif echo "$PRODUCT_NAME" | grep -qi "Zephyrus G14"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.asus-zephyrus-g14" + elif echo "$PRODUCT_NAME" | grep -qi "ThinkPad X1 Carbon"; then + NEW_HW_MODULES="$NEW_HW_MODULES\n inputs.nixos-hardware.nixosModules.lenovo-thinkpad-x1-carbon-gen9" + fi + + # Check if the current HW file differs from our detection + if [ -n "$NEW_HW_MODULES" ] && ! grep -q "common-cpu" "$HW_FILE"; then + # This is a basic detection. We overwrite it if it's completely empty or missing common-cpu. + # It's better to let the user know, or auto-apply. We'll auto-apply for a smooth experience. + cat < "$HW_FILE.tmp" +{ inputs, ... }: +{ + imports = [ + $NEW_HW_MODULES + ]; +} +EOF + if ! cmp -s "$HW_FILE" "$HW_FILE.tmp"; then + mv "$HW_FILE.tmp" "$HW_FILE" + # We notify the user instead of running sys-update silently, as it requires root and time. + notify-send -u normal "Hardware Auto-Detection" "New hardware profile detected. Please run 'sys-update' when ready." + else + rm "$HW_FILE.tmp" + fi + fi +fi diff --git a/bin/nomarchy-pkg-add b/bin/nomarchy-pkg-add index f3a1934..c1e0643 100755 --- a/bin/nomarchy-pkg-add +++ b/bin/nomarchy-pkg-add @@ -1,17 +1,27 @@ -#!/bin/bash +#!/usr/bin/env bash -# Add the named packages to the system if they're missing. Returns false if it couldn't be done. +PKG_NAME="$1" -if nomarchy-pkg-missing "$@"; then - sudo pacman -S --noconfirm --needed "$@" || exit 1 +if [ -z "$PKG_NAME" ]; then + echo "Usage: nomarchy-pkg-add " + exit 1 fi -for pkg in "$@"; do - # Secondary check to handle states where pacman doesn't actually register an error - if ! pacman -Q "$pkg" &>/dev/null; then - echo -e "\033[31mError: Package '$pkg' did not install\033[0m" >&2 - exit 1 - fi -done +STATE_FILE="$HOME/.config/home-manager/user-packages.json" +mkdir -p "$(dirname "$STATE_FILE")" -exit 0 +if [ ! -f "$STATE_FILE" ]; then + echo "[]" > "$STATE_FILE" +fi + +if jq -e ". | index(\"$PKG_NAME\")" "$STATE_FILE" >/dev/null; then + echo "Package $PKG_NAME is already in your user-packages.json" + exit 0 +fi + +# Append package to the JSON array +jq ". + [\"$PKG_NAME\"]" "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE" + +echo "Package $PKG_NAME added declaratively to $STATE_FILE." +echo "Applying changes with env-update..." +env-update diff --git a/bin/nomarchy-pkg-aur-add b/bin/nomarchy-pkg-aur-add index 53ed426..5d7855b 100755 --- a/bin/nomarchy-pkg-aur-add +++ b/bin/nomarchy-pkg-aur-add @@ -1,17 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash -# Add the named packages to the system from the AUR if they're missing. Returns false if it couldn't be done. - -if nomarchy-pkg-missing "$@"; then - yay -S --noconfirm --needed "$@" || exit 1 -fi - -for pkg in "$@"; do - # Secondary check to handle states where pacman doesn't actually register an error - if ! pacman -Q "$pkg" &>/dev/null; then - echo -e "\033[31mError: Package '$pkg' did not install\033[0m" >&2 - exit 1 - fi -done - -exit 0 +echo "AUR is an Arch Linux concept and is not supported on NixOS." +echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs." +exit 1 diff --git a/bin/nomarchy-pkg-aur-install b/bin/nomarchy-pkg-aur-install index f1638c6..5d7855b 100755 --- a/bin/nomarchy-pkg-aur-install +++ b/bin/nomarchy-pkg-aur-install @@ -1,28 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash -# Show a fuzzy-finder TUI for picking new AUR packages to install. - -fzf_args=( - --multi - --preview 'yay -Siia {1}' - --preview-label='alt-p: toggle description, alt-b/B: toggle PKGBUILD, alt-j/k: scroll, tab: multi-select' - --preview-label-pos='bottom' - --preview-window 'down:65%:wrap' - --bind 'alt-p:toggle-preview' - --bind 'alt-d:preview-half-page-down,alt-u:preview-half-page-up' - --bind 'alt-k:preview-up,alt-j:preview-down' - --bind 'alt-b:change-preview:yay -Gpa {1} | tail -n +5' - --bind 'alt-B:change-preview:yay -Siia {1}' - --color 'pointer:green,marker:green' -) - -pkg_names=$(yay -Slqa | fzf "${fzf_args[@]}") - -if [[ -n $pkg_names ]]; then - # Add aur/ prefix to each package name and convert to space-separated for yay - source nomarchy-sudo-keepalive - - echo "$pkg_names" | sed 's/^/aur\//' | tr '\n' ' ' | xargs yay -S --noconfirm - sudo updatedb - nomarchy-show-done -fi +echo "AUR is an Arch Linux concept and is not supported on NixOS." +echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs." +exit 1 diff --git a/bin/nomarchy-pkg-missing b/bin/nomarchy-pkg-missing index c2bab7a..6979036 100755 --- a/bin/nomarchy-pkg-missing +++ b/bin/nomarchy-pkg-missing @@ -1,11 +1,15 @@ -#!/bin/bash +#!/usr/bin/env bash -# Returns true if any of the named packages are missing from the system (or false if they're all there). +PKG_NAME="$1" -for pkg in "$@"; do - if ! pacman -Q "$pkg" &>/dev/null; then +if [ -z "$PKG_NAME" ]; then + echo "Usage: nomarchy-pkg-missing " + exit 1 +fi + +nomarchy-pkg-present "$PKG_NAME" +if [ $? -eq 0 ]; then + exit 1 +else exit 0 - fi -done - -exit 1 +fi diff --git a/bin/nomarchy-pkg-present b/bin/nomarchy-pkg-present index 03a5d9a..4890e97 100755 --- a/bin/nomarchy-pkg-present +++ b/bin/nomarchy-pkg-present @@ -1,9 +1,20 @@ -#!/bin/bash +#!/usr/bin/env bash -# Returns true if all of the named packages are installed on the system (or false if any of them are missing). +PKG_NAME="$1" -for pkg in "$@"; do - pacman -Q "$pkg" &>/dev/null || exit 1 -done +if [ -z "$PKG_NAME" ]; then + echo "Usage: nomarchy-pkg-present " + exit 1 +fi -exit 0 +STATE_FILE="$HOME/.config/home-manager/user-packages.json" + +if [ ! -f "$STATE_FILE" ]; then + exit 1 +fi + +if jq -e ". | index(\"$PKG_NAME\")" "$STATE_FILE" >/dev/null; then + exit 0 +else + exit 1 +fi diff --git a/bin/nomarchy-pkg-remove b/bin/nomarchy-pkg-remove index 51f439f..0909cc3 100755 --- a/bin/nomarchy-pkg-remove +++ b/bin/nomarchy-pkg-remove @@ -1,23 +1,27 @@ -#!/bin/bash +#!/usr/bin/env bash -# Show a fuzzy-finder TUI for picking packages installed on the system to be removed. +PKG_NAME="$1" -fzf_args=( - --multi - --preview 'yay -Qi {1}' - --preview-label='alt-p: toggle description, alt-j/k: scroll, tab: multi-select' - --preview-label-pos='bottom' - --preview-window 'down:65%:wrap' - --bind 'alt-p:toggle-preview' - --bind 'alt-d:preview-half-page-down,alt-u:preview-half-page-up' - --bind 'alt-k:preview-up,alt-j:preview-down' - --color 'pointer:red,marker:red' -) - -pkg_names=$(yay -Qqe | fzf "${fzf_args[@]}") - -if [[ -n $pkg_names ]]; then - # Convert newline-separated selections to space-separated for yay - echo "$pkg_names" | tr '\n' ' ' | xargs sudo pacman -Rns --noconfirm - nomarchy-show-done +if [ -z "$PKG_NAME" ]; then + echo "Usage: nomarchy-pkg-remove " + exit 1 fi + +STATE_FILE="$HOME/.config/home-manager/user-packages.json" + +if [ ! -f "$STATE_FILE" ]; then + echo "No packages managed by nomarchy-pkg yet." + exit 0 +fi + +if ! jq -e ". | index(\"$PKG_NAME\")" "$STATE_FILE" >/dev/null; then + echo "Package $PKG_NAME is not in your user-packages.json" + exit 0 +fi + +# Remove package from the JSON array +jq ". - [\"$PKG_NAME\"]" "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE" + +echo "Package $PKG_NAME removed declaratively from $STATE_FILE." +echo "Applying changes with env-update..." +env-update diff --git a/bin/nomarchy-setup-fido2 b/bin/nomarchy-setup-fido2 index 69b7782..dd3e291 100755 --- a/bin/nomarchy-setup-fido2 +++ b/bin/nomarchy-setup-fido2 @@ -1,127 +1,46 @@ -#!/bin/bash +#!/usr/bin/env bash -set -e +# Configure FIDO2 support declaratively for Nomarchy NixOS. -GREEN='\033[0;32m' -RED='\033[0;31m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -print_success() { - echo -e "${GREEN}$1${NC}" -} - -print_error() { - echo -e "${RED}$1${NC}" -} - -print_info() { - echo -e "${YELLOW}$1${NC}" -} - -check_fido2_hardware() { - tokens=$(fido2-token -L 2>/dev/null) - if [[ -z $tokens ]]; then - print_error "\nNo FIDO2 device detected. Please plug it in (you may need to unlock it as well)." - return 1 - fi - return 0 -} - -setup_pam_config() { - # Configure sudo - if ! grep -q pam_u2f.so /etc/pam.d/sudo; then - print_info "Configuring sudo for FIDO2 authentication..." - sudo sed -i '1i auth sufficient pam_u2f.so cue authfile=/etc/fido2/fido2' /etc/pam.d/sudo - fi - - # Configure polkit - if [[ -f /etc/pam.d/polkit-1 ]] && ! grep -q 'pam_u2f.so' /etc/pam.d/polkit-1; then - print_info "Configuring polkit for FIDO2 authentication..." - sudo sed -i '1i auth sufficient pam_u2f.so cue authfile=/etc/fido2/fido2' /etc/pam.d/polkit-1 - elif [[ ! -f /etc/pam.d/polkit-1 ]]; then - print_info "Creating polkit configuration with FIDO2 authentication..." - sudo tee /etc/pam.d/polkit-1 >/dev/null <<'EOF' -auth sufficient pam_u2f.so cue authfile=/etc/fido2/fido2 -auth required pam_unix.so - -account required pam_unix.so -password required pam_unix.so -session required pam_unix.so -EOF - fi -} - -remove_pam_config() { - # Remove from sudo - if grep -q pam_u2f.so /etc/pam.d/sudo; then - print_info "Removing FIDO2 authentication from sudo..." - sudo sed -i '/pam_u2f\.so/d' /etc/pam.d/sudo - fi - - # Remove from polkit - if [[ -f /etc/pam.d/polkit-1 ]] && grep -Fq 'pam_u2f.so' /etc/pam.d/polkit-1; then - print_info "Removing FIDO2 authentication from polkit..." - sudo sed -i '/pam_u2f\.so/d' /etc/pam.d/polkit-1 - fi -} +FEATURE_FILE="/etc/nixos/nomarchy-features/fido2.nix" if [[ "--remove" == $1 ]]; then - print_success "Removing FIDO2 device from authentication.\n" - - # Remove PAM configuration - remove_pam_config - - # Remove FIDO2 configuration - if [[ -d /etc/fido2 ]]; then - print_info "Removing FIDO2 configuration..." - sudo rm -rf /etc/fido2 - fi - - # Uninstall packages - print_info "Removing FIDO2 packages..." - sudo pacman -Rns --noconfirm libfido2 pam-u2f - - print_success "FIDO2 authentication has been completely removed." -else - print_success "Setting up FIDO2 device for authentication.\n" - - # Install required packages - print_info "Installing required packages..." - nomarchy-pkg-add libfido2 pam-u2f - - if ! check_fido2_hardware; then - exit 1 - fi - - # Create the pamu2fcfg file - if [[ ! -f /etc/fido2/fido2 ]]; then - sudo mkdir -p /etc/fido2 - print_success "\nLet's setup your device by confirming on the device now." - print_info "Touch your FIDO2 key when it lights up...\n" - - if pamu2fcfg >/tmp/fido2; then - sudo mv /tmp/fido2 /etc/fido2/fido2 - print_success "FIDO2 device registered successfully!" + if [ -f "$FEATURE_FILE" ]; then + sudo rm "$FEATURE_FILE" + echo "Removed $FEATURE_FILE." + echo "IMPORTANT: Remove './nomarchy-features/fido2.nix' from your imports and run 'sys-update'." else - print_error "\nFIDO2 registration failed. Please try again." - exit 1 + echo "FIDO2 support not found." fi - else - print_info "FIDO2 device already registered." - fi - - # Configure PAM - setup_pam_config - - # Test with sudo - print_info "\nTesting FIDO2 authentication with sudo..." - print_info "Touch your FIDO2 key when prompted.\n" - - if sudo echo "FIDO2 authentication test successful"; then - print_success "\nPerfect! FIDO2 authentication is now configured." - print_info "You can use your FIDO2 key for sudo and polkit authentication." - else - print_error "\nVerification failed. You may want to check your configuration." - fi + exit 0 +fi + +if [ -f "$FEATURE_FILE" ]; then + echo "FIDO2 support is already configured in $FEATURE_FILE" +else + sudo mkdir -p "/etc/nixos/nomarchy-features" + cat < /dev/null +{ config, pkgs, ... }: +{ + security.pam.u2f = { + enable = true; + control = "sufficient"; + cue = true; + # authFile = "/etc/fido2/fido2"; # Default is ~/.config/Yubico/u2f_keys + }; +} +EOF + echo "Created $FEATURE_FILE." + echo "IMPORTANT: To finish enabling FIDO2 support, add './nomarchy-features/fido2.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," + echo "then run 'sys-update'." +fi + +# Enrollment is still an imperative action +if command -v pamu2fcfg &> /dev/null; then + echo "Let's register your FIDO2 key now." + mkdir -p ~/.config/Yubico + pamu2fcfg > ~/.config/Yubico/u2f_keys + echo "FIDO2 key registered." +else + echo "pamu2fcfg not found. Please run 'nomarchy-pkg-add pam-u2f' or 'sys-update' if you just enabled it." fi diff --git a/bin/nomarchy-setup-fingerprint b/bin/nomarchy-setup-fingerprint index 4e37c46..568d513 100755 --- a/bin/nomarchy-setup-fingerprint +++ b/bin/nomarchy-setup-fingerprint @@ -1,134 +1,40 @@ -#!/bin/bash +#!/usr/bin/env bash -set -e +# Configure Fingerprint support declaratively for Nomarchy NixOS. -GREEN='\033[0;32m' -RED='\033[0;31m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -print_success() { - echo -e "${GREEN}$1${NC}" -} - -print_error() { - echo -e "${RED}$1${NC}" -} - -print_info() { - echo -e "${YELLOW}$1${NC}" -} - -check_fingerprint_hardware() { - # Get fingerprint devices for the user - devices=$(fprintd-list "$USER" 2>/dev/null) - - # Exit if no devices found - if [[ -z $devices ]]; then - print_error "\nNo fingerprint sensor detected." - return 1 - fi - return 0 -} - -setup_pam_config() { - # Configure sudo - if ! grep -q pam_fprintd.so /etc/pam.d/sudo; then - print_info "Configuring sudo for fingerprint authentication..." - sudo sed -i '1i auth sufficient pam_fprintd.so' /etc/pam.d/sudo - fi - - # Configure polkit - if [[ -f /etc/pam.d/polkit-1 ]] && ! grep -q 'pam_fprintd.so' /etc/pam.d/polkit-1; then - print_info "Configuring polkit for fingerprint authentication..." - sudo sed -i '1i auth sufficient pam_fprintd.so' /etc/pam.d/polkit-1 - elif [[ ! -f /etc/pam.d/polkit-1 ]]; then - print_info "Creating polkit configuration with fingerprint authentication..." - sudo tee /etc/pam.d/polkit-1 >/dev/null <<'EOF' -auth sufficient pam_fprintd.so -auth required pam_unix.so - -account required pam_unix.so -password required pam_unix.so -session required pam_unix.so -EOF - fi -} - -add_hyprlock_fingerprint_icon() { - print_info "Adding fingerprint icon to hyprlock placeholder text..." - sed -i 's/placeholder_text = .*/placeholder_text = Enter Password 󰈷 <\/span>/' ~/.config/hypr/hyprlock.conf - sed -i 's/fingerprint:enabled = .*/fingerprint:enabled = true/' ~/.config/hypr/hyprlock.conf -} - -remove_hyprlock_fingerprint_icon() { - print_info "Removing fingerprint icon from hyprlock placeholder text..." - sed -i 's/placeholder_text = .*/placeholder_text = Enter Password/' ~/.config/hypr/hyprlock.conf - sed -i 's/fingerprint:enabled = .*/fingerprint:enabled = false/' ~/.config/hypr/hyprlock.conf -} - -remove_pam_config() { - # Remove from sudo - if grep -q pam_fprintd.so /etc/pam.d/sudo; then - print_info "Removing fingerprint authentication from sudo..." - sudo sed -i '/pam_fprintd\.so/d' /etc/pam.d/sudo - fi - - # Remove from polkit - if [[ -f /etc/pam.d/polkit-1 ]] && grep -Fq 'pam_fprintd.so' /etc/pam.d/polkit-1; then - print_info "Removing fingerprint authentication from polkit..." - sudo sed -i '/pam_fprintd\.so/d' /etc/pam.d/polkit-1 - fi -} +FEATURE_FILE="/etc/nixos/nomarchy-features/fingerprint.nix" if [[ "--remove" == $1 ]]; then - print_success "Removing fingerprint scanner from authentication.\n" - - # Remove PAM configuration - remove_pam_config - - # Remove fingerprint icon from hyprlock placeholder text - remove_hyprlock_fingerprint_icon - - # Uninstall packages - print_info "Removing fingerprint packages..." - sudo pacman -Rns --noconfirm fprintd - - print_success "Fingerprint authentication has been completely removed." -else - print_success "Setting up fingerprint scanner for authentication.\n" - - # Install required packages - print_info "Installing required packages..." - nomarchy-pkg-add fprintd usbutils - - if ! check_fingerprint_hardware; then - exit 1 - fi - - # Configure PAM - setup_pam_config - - # Add fingerprint icon to hyprlock placeholder text - add_hyprlock_fingerprint_icon - - # Enroll first fingerprint - print_success "\nLet's setup your right index finger as the first fingerprint." - print_info "Keep moving the finger around on sensor until the process completes.\n" - - if sudo fprintd-enroll "$USER"; then - print_success "\nFingerprint enrolled successfully!" - - # Verify - print_info "\nNow let's verify that it's working correctly.\n" - if fprintd-verify; then - print_success "\nPerfect! Fingerprint authentication is now configured." - print_info "You can use your fingerprint for sudo, polkit, and lock screen (Super + Escape)." + if [ -f "$FEATURE_FILE" ]; then + sudo rm "$FEATURE_FILE" + echo "Removed $FEATURE_FILE." + echo "IMPORTANT: Remove './nomarchy-features/fingerprint.nix' from your imports and run 'sys-update'." else - print_error "\nVerification failed. You may want to try enrolling again." + echo "Fingerprint support not found." fi - else - print_error "\nEnrollment failed. Please try again." - exit 1 - fi + exit 0 +fi + +if [ -f "$FEATURE_FILE" ]; then + echo "Fingerprint support is already configured in $FEATURE_FILE" +else + sudo mkdir -p "/etc/nixos/nomarchy-features" + cat < /dev/null +{ config, pkgs, ... }: +{ + services.fprintd.enable = true; + # NixOS's fprintd module automatically configures PAM for login/sudo if enabled. +} +EOF + echo "Created $FEATURE_FILE." + echo "IMPORTANT: To finish enabling fingerprint support, add './nomarchy-features/fingerprint.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," + echo "then run 'sys-update'." +fi + +# Enrollment is still an imperative action +if command -v fprintd-enroll &> /dev/null; then + echo "Let's enroll your fingerprint now." + fprintd-enroll "$USER" +else + echo "fprintd-enroll not found. Please run 'sys-update' first if you just enabled it." fi diff --git a/bin/nomarchy-theme-bg-next b/bin/nomarchy-theme-bg-next index 8f08aca..476e0af 100755 --- a/bin/nomarchy-theme-bg-next +++ b/bin/nomarchy-theme-bg-next @@ -1,50 +1,56 @@ -#!/bin/bash +#!/usr/bin/env bash -# Cycles through the background images available +# Cycles through the background images available for the current theme. +# Declarative + Hybrid (instant swww) for Nomarchy NixOS. -THEME_NAME=$(cat "$HOME/.config/nomarchy/current/theme.name" 2>/dev/null) -THEME_BACKGROUNDS_PATH="$HOME/.config/nomarchy/current/theme/backgrounds/" -USER_BACKGROUNDS_PATH="$HOME/.config/nomarchy/backgrounds/$THEME_NAME/" -CURRENT_BACKGROUND_LINK="$HOME/.config/nomarchy/current/background" +STATE_DIR="$HOME/.config/home-manager" +THEME_STATE_FILE="$STATE_DIR/theme-state.nix" +WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" -mapfile -d '' -t BACKGROUNDS < <(find -L "$USER_BACKGROUNDS_PATH" "$THEME_BACKGROUNDS_PATH" -maxdepth 1 -type f -print0 2>/dev/null | sort -z) +THEME_NAME=$(cat "$THEME_STATE_FILE" 2>/dev/null || echo "dracula") + +if [ -d "/etc/nixos/nomarchy/themes" ]; then + THEMES_DIR="/etc/nixos/nomarchy/themes" +elif [ -d "/etc/nomarchy/themes" ]; then + THEMES_DIR="/etc/nomarchy/themes" +else + THEMES_DIR="/etc/nixos/themes" +fi + +BG_DIR="$THEMES_DIR/$THEME_NAME/backgrounds" + +if [ ! -d "$BG_DIR" ]; then + notify-send "No background directory found for theme $THEME_NAME" + exit 1 +fi + +mapfile -t BACKGROUNDS < <(ls "$BG_DIR" | sort) TOTAL=${#BACKGROUNDS[@]} if (( TOTAL == 0 )); then - notify-send "No background was found for theme" -t 2000 - pkill -x swaybg - setsid uwsm-app -- swaybg --color '#000000' >/dev/null 2>&1 & -else - # Get current background from symlink - if [[ -L $CURRENT_BACKGROUND_LINK ]]; then - CURRENT_BACKGROUND=$(readlink "$CURRENT_BACKGROUND_LINK") - else - # Default to first background if no symlink exists - CURRENT_BACKGROUND="" - fi - - # Find current background index - INDEX=-1 - for i in "${!BACKGROUNDS[@]}"; do - if [[ ${BACKGROUNDS[$i]} == $CURRENT_BACKGROUND ]]; then - INDEX=$i - break - fi - done - - # Get next background (wrap around) - if (( INDEX == -1 )); then - # Use the first background when no match was found - NEW_BACKGROUND="${BACKGROUNDS[0]}" - else - NEXT_INDEX=$(((INDEX + 1) % TOTAL)) - NEW_BACKGROUND="${BACKGROUNDS[$NEXT_INDEX]}" - fi - - # Set new background symlink - ln -nsf "$NEW_BACKGROUND" "$CURRENT_BACKGROUND_LINK" - - # Relaunch swaybg - pkill -x swaybg - setsid uwsm-app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 & + notify-send "No backgrounds found in $BG_DIR" + exit 1 fi + +CURRENT_BG=$(cat "$WALLPAPER_STATE_FILE" 2>/dev/null) +INDEX=-1 +for i in "${!BACKGROUNDS[@]}"; do + if [[ "$BG_DIR/${BACKGROUNDS[$i]}" == "$CURRENT_BG" ]]; then + INDEX=$i + break + fi +done + +NEXT_INDEX=$(((INDEX + 1) % TOTAL)) +NEW_BG="$BG_DIR/${BACKGROUNDS[$NEXT_INDEX]}" + +echo "$NEW_BG" > "$WALLPAPER_STATE_FILE" + +# Instant feedback via swww +if pgrep -x swww-daemon >/dev/null; then + swww img "$NEW_BG" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 +else + swww init && swww img "$NEW_BG" +fi + +echo "Background set to $NEW_BG declaratively." diff --git a/bin/nomarchy-theme-set b/bin/nomarchy-theme-set index 08cf13e..a662805 100755 --- a/bin/nomarchy-theme-set +++ b/bin/nomarchy-theme-set @@ -1,60 +1,48 @@ -#!/bin/bash +#!/usr/bin/env bash -if [[ -z $1 ]]; then +# Set the system theme declaratively. +# Usage: nomarchy-theme-set + +THEME_NAME="$1" + +if [[ -z $THEME_NAME ]]; then echo "Usage: nomarchy-theme-set " exit 1 fi -CURRENT_THEME_PATH="$HOME/.config/nomarchy/current/theme" -NEXT_THEME_PATH="$HOME/.config/nomarchy/current/next-theme" -USER_THEMES_PATH="$HOME/.config/nomarchy/themes" -OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes" +STATE_DIR="$HOME/.config/home-manager" +THEME_STATE_FILE="$STATE_DIR/theme-state.nix" +WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" -THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-') - -if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THEME_NAME ]]; then - echo "Theme '$THEME_NAME' does not exist" - exit 1 +# Logic for finding themes +if [ -d "/etc/nixos/nomarchy/themes" ]; then + THEMES_DIR="/etc/nixos/nomarchy/themes" +elif [ -d "/etc/nomarchy/themes" ]; then + THEMES_DIR="/etc/nomarchy/themes" +else + THEMES_DIR="/etc/nixos/themes" fi -# Setup clean next theme directory (for atomic theme config swapping) -rm -rf "$NEXT_THEME_PATH" -mkdir -p "$NEXT_THEME_PATH" +mkdir -p "$STATE_DIR" -# Copy official theme first, then overlay user customizations on top -cp -r "$OMARCHY_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null -cp -r "$USER_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null - -# Generate dynamic configs -nomarchy-theme-set-templates - -# Swap next theme in as current -rm -rf "$CURRENT_THEME_PATH" -mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH" - -# Store theme name for reference -echo "$THEME_NAME" >"$HOME/.config/nomarchy/current/theme.name" - -# Change background with theme -nomarchy-theme-bg-next - -# Restart components to apply new theme -if pgrep -x waybar >/dev/null; then - nomarchy-restart-waybar +if [ ! -d "$THEMES_DIR/$THEME_NAME" ] && ! [[ "$THEME_NAME" == "dracula" || "$THEME_NAME" == "nord" ]]; then + echo "Theme '$THEME_NAME' not found in $THEMES_DIR" + # Check if it exists in the palettes file + # (Assuming nomarchy-palettes.nix is imported in Nix) fi -nomarchy-restart-swayosd -nomarchy-restart-terminal -nomarchy-restart-hyprctl -nomarchy-restart-btop -nomarchy-restart-opencode -nomarchy-restart-mako -# Change app-specific themes -nomarchy-theme-set-gnome -nomarchy-theme-set-browser -nomarchy-theme-set-vscode -nomarchy-theme-set-obsidian -nomarchy-theme-set-keyboard +echo "$THEME_NAME" > "$THEME_STATE_FILE" + +# Try to find a background for this theme +BG_DIR="$THEMES_DIR/$THEME_NAME/backgrounds" +if [ -d "$BG_DIR" ]; then + BG=$(ls "$BG_DIR" | head -n 1) + if [ -n "$BG" ]; then + echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE" + fi +fi + +echo "Theme set to $THEME_NAME. Applying changes with env-update..." +env-update -# Call hook on theme set nomarchy-hook theme-set "$THEME_NAME" diff --git a/bin/nomarchy-toggle-hybrid-gpu b/bin/nomarchy-toggle-hybrid-gpu index 2781f99..04b49d3 100755 --- a/bin/nomarchy-toggle-hybrid-gpu +++ b/bin/nomarchy-toggle-hybrid-gpu @@ -1,65 +1,44 @@ -#!/bin/bash +#!/usr/bin/env bash # Toggle dedicated vs integrated GPU mode via supergfxd (for hybrid gpu laptops, like Asus G14). -# Requires reboot to take effect. +# Declarative enablement + Runtime mode switching for Nomarchy NixOS. -# Ensure supergfxctl has been installed -if nomarchy-cmd-missing supergfxctl; then - nomarchy-pkg-add supergfxctl +FEATURE_FILE="/etc/nixos/nomarchy-features/supergfxd.nix" - # Create config before starting service to prevent hang on first boot - sudo tee /etc/supergfxd.conf >/dev/null <<'CONF' +if ! command -v supergfxctl &> /dev/null; then + sudo mkdir -p "/etc/nixos/nomarchy-features" + cat < /dev/null +{ config, pkgs, ... }: { - "mode": "Hybrid", - "vfio_enable": true, - "vfio_save": false, - "always_reboot": false, - "no_logind": false, - "logout_timeout_s": 180, - "hotplug_type": "None" + services.supergfxd.enable = true; } -CONF - - sudo systemctl enable --now supergfxd +EOF + echo "Created $FEATURE_FILE to enable supergfxd." + echo "IMPORTANT: To finish enabling hybrid GPU support, add './nomarchy-features/supergfxd.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," + echo "then run 'sys-update'." + exit 0 fi gpu_mode=$(supergfxctl -g) +echo "Current GPU mode: $gpu_mode" case "$gpu_mode" in "Integrated") - if gum confirm "Enable dedicated GPU and reboot?"; then - # Switch to hybrid mode - sudo sed -i "s/\"mode\": \".*\"/\"mode\": \"Hybrid\"/" /etc/supergfxd.conf - - # Let hybrid mode be the default after system sleep - sudo rm -rf /usr/lib/systemd/system-sleep/force-igpu - - # Remove the startup delay override (not needed for Hybrid mode) - sudo rm -rf /etc/systemd/system/supergfxd.service.d/delay-start.conf - + if gum confirm "Switch to Hybrid mode (enables dGPU) and reboot?"; then + supergfxctl -m Hybrid + echo "Switching to Hybrid mode..." nomarchy-system-reboot fi ;; "Hybrid") - if gum confirm "Use only integrated GPU and reboot?"; then - # Switch to integrated mode and ensure vfio is enabled (needed for sleep/wake trick) - sudo sed -i "s/\"mode\": \".*\"/\"mode\": \"Integrated\"/" /etc/supergfxd.conf - sudo sed -i 's/"vfio_enable": false/"vfio_enable": true/' /etc/supergfxd.conf - - # Force igpu mode after system sleep (or dgpu could get activated) - sudo mkdir -p /usr/lib/systemd/system-sleep - sudo cp -p $OMARCHY_PATH/default/systemd/system-sleep/force-igpu /usr/lib/systemd/system-sleep/ - - # Delay supergfxd startup to avoid race condition with display manager - # that can cause system freeze when booting in Integrated mode - sudo mkdir -p /etc/systemd/system/supergfxd.service.d - sudo cp -p $OMARCHY_PATH/default/systemd/system/supergfxd.service.d/delay-start.conf /etc/systemd/system/supergfxd.service.d/ - + if gum confirm "Switch to Integrated mode (disables dGPU) and reboot?"; then + supergfxctl -m Integrated + echo "Switching to Integrated mode..." nomarchy-system-reboot fi ;; *) - echo "Hybrid GPU not found or in unknown mode." + echo "Hybrid GPU in unknown mode: $gpu_mode. Try 'supergfxctl -m Hybrid' manually." exit 1 ;; esac diff --git a/bin/nomarchy-toggle-idle b/bin/nomarchy-toggle-idle index a80eec4..8fd8a1e 100755 --- a/bin/nomarchy-toggle-idle +++ b/bin/nomarchy-toggle-idle @@ -1,11 +1,28 @@ -#!/bin/bash +#!/usr/bin/env bash -if pgrep -x hypridle >/dev/null; then - pkill -x hypridle - notify-send -u low "󱫖 Stop locking computer when idle" -else - uwsm-app -- hypridle >/dev/null 2>&1 & - notify-send -u low "󱫖 Now locking computer when idle" +# Toggles the idle daemon (hypridle) between enabled and disabled. +# Declarative + Hybrid (instant IPC/kill) for Nomarchy NixOS. + +STATE_FILE="$HOME/.config/home-manager/idle-state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +if [ ! -f "$STATE_FILE" ]; then + echo '{"enabled": true}' > "$STATE_FILE" fi -pkill -RTMIN+9 waybar +enabled=$(jq -r '.enabled' "$STATE_FILE") + +if [[ $enabled == "true" ]]; then + NEW_ENABLED="false" + pkill -x hypridle + notify-send -u low "󱫖 Stop locking computer when idle" +else + NEW_ENABLED="true" + setsid hypridle >/dev/null 2>&1 & + notify-send -u low "󱫖 Now locking computer when idle" +fi + +echo "{\"enabled\": $NEW_ENABLED}" > "$STATE_FILE" +echo "Idle daemon set to $NEW_ENABLED declaratively." + +pkill -RTMIN+9 waybar # Signal waybar if needed diff --git a/bin/nomarchy-toggle-nightlight b/bin/nomarchy-toggle-nightlight index bb0d134..73073e2 100755 --- a/bin/nomarchy-toggle-nightlight +++ b/bin/nomarchy-toggle-nightlight @@ -1,30 +1,36 @@ -#!/bin/bash +#!/usr/bin/env bash -# Default temperature values -ON_TEMP=4000 -OFF_TEMP=6000 +# Toggles the nightlight (hyprsunset) between enabled (4000) and disabled (6500) +# Declarative + Hybrid (instant IPC) for Nomarchy NixOS. -# Ensure hyprsunset is running -if ! pgrep -x hyprsunset; then - setsid uwsm-app -- hyprsunset & - sleep 1 # Give it time to register +STATE_FILE="$HOME/.config/home-manager/hyprsunset-state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +if [ ! -f "$STATE_FILE" ]; then + echo '{"enabled": false, "temperature": 4000}' > "$STATE_FILE" fi -# Query the current temperature -CURRENT_TEMP=$(hyprctl hyprsunset temperature 2>/dev/null | grep -oE '[0-9]+') +enabled=$(jq -r '.enabled' "$STATE_FILE") -restart_nightlighted_waybar() { - if grep -q "custom/nightlight" ~/.config/waybar/config.jsonc; then - nomarchy-restart-waybar # restart waybar in case user has waybar module for hyprsunset - fi -} - -if [[ $CURRENT_TEMP == $OFF_TEMP ]]; then - hyprctl hyprsunset temperature $ON_TEMP - notify-send -u low " Nightlight screen temperature" - restart_nightlighted_waybar +if [[ $enabled == "true" ]]; then + NEW_ENABLED="false" + TEMP=6500 + notify-send -u low " Nightlight DISABLED" else - hyprctl hyprsunset temperature $OFF_TEMP - notify-send -u low " Daylight screen temperature" - restart_nightlighted_waybar + NEW_ENABLED="true" + TEMP=4000 + notify-send -u low " Nightlight ENABLED" fi + +# Instant feedback via IPC +if pgrep -x hyprsunset >/dev/null; then + hyprctl hyprsunset temperature $TEMP +else + # Should be started by systemd, but just in case + setsid hyprsunset -t $TEMP & +fi + +echo "{\"enabled\": $NEW_ENABLED, \"temperature\": 4000}" > "$STATE_FILE" +echo "Nightlight set to $NEW_ENABLED ($TEMP) declaratively." +# No need to run env-update if we don't want the delay, +# as next HM switch will pick it up and apply it. diff --git a/bin/nomarchy-update-aur-pkgs b/bin/nomarchy-update-aur-pkgs index 84266c0..5d7855b 100755 --- a/bin/nomarchy-update-aur-pkgs +++ b/bin/nomarchy-update-aur-pkgs @@ -1,13 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash -# Update AUR packages if any are installed -if pacman -Qem >/dev/null; then - if nomarchy-pkg-aur-accessible; then - echo -e "\e[32m\nUpdate AUR packages\e[0m" - yay -Sua --noconfirm --cleanafter --ignore gcc14,gcc14-libs - echo - else - echo -e "\e[31m\nAUR is unavailable (so skipping updates)\e[0m" - echo - fi -fi +echo "AUR is an Arch Linux concept and is not supported on NixOS." +echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs." +exit 1 diff --git a/bin/nomarchy-update-keyring b/bin/nomarchy-update-keyring index beb3116..e0d7b64 100755 --- a/bin/nomarchy-update-keyring +++ b/bin/nomarchy-update-keyring @@ -1,18 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash -# Ensure we have the nomarchy-keyring and it's populated -if nomarchy-pkg-missing nomarchy-keyring || ! sudo pacman-key --list-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 &>/dev/null; then - sudo pacman-key --recv-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 --keyserver keys.openpgp.org - sudo pacman-key --lsign-key 40DFB630FF42BCFFB047046CF0134EE680CAC571 - - # This is generally not a good idea, but this is a special case because we're going to be updating - # the full set of packages in nomarchy-update-system-pkgs right after this (and it needs latest keyring)! - sudo pacman -Sy - nomarchy-pkg-add nomarchy-keyring - - sudo pacman-key --list-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 -fi - -# Ensure we have the latest archlinux-keyring, maintainer keys might have changed -echo -e "\e[32m\nUpdate Arch signing keys\e[0m" -sudo pacman -Sy --noconfirm archlinux-keyring >/dev/null +echo "Pacman keyring is an Arch Linux concept and is not supported on NixOS." +exit 1 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..5167680 --- /dev/null +++ b/flake.lock @@ -0,0 +1,582 @@ +{ + "nodes": { + "base16": { + "inputs": { + "fromYaml": "fromYaml" + }, + "locked": { + "lastModified": 1755819240, + "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", + "owner": "SenchoPens", + "repo": "base16.nix", + "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "base16.nix", + "type": "github" + } + }, + "base16-fish": { + "flake": false, + "locked": { + "lastModified": 1765809053, + "narHash": "sha256-XCUQLoLfBJ8saWms2HCIj4NEN+xNsWBlU1NrEPcQG4s=", + "owner": "tomyun", + "repo": "base16-fish", + "rev": "86cbea4dca62e08fb7fd83a70e96472f92574782", + "type": "github" + }, + "original": { + "owner": "tomyun", + "repo": "base16-fish", + "rev": "86cbea4dca62e08fb7fd83a70e96472f92574782", + "type": "github" + } + }, + "base16-helix": { + "flake": false, + "locked": { + "lastModified": 1760703920, + "narHash": "sha256-m82fGUYns4uHd+ZTdoLX2vlHikzwzdu2s2rYM2bNwzw=", + "owner": "tinted-theming", + "repo": "base16-helix", + "rev": "d646af9b7d14bff08824538164af99d0c521b185", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-helix", + "type": "github" + } + }, + "base16-schemes": { + "flake": false, + "locked": { + "lastModified": 1696158499, + "narHash": "sha256-5yIHgDTPjoX/3oDEfLSQ0eJZdFL1SaCfb9d6M0RmOTM=", + "owner": "tinted-theming", + "repo": "base16-schemes", + "rev": "a9112eaae86d9dd8ee6bb9445b664fba2f94037a", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-schemes", + "type": "github" + } + }, + "base16-vim": { + "flake": false, + "locked": { + "lastModified": 1732806396, + "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=", + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773889306, + "narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=", + "owner": "nix-community", + "repo": "disko", + "rev": "5ad85c82cc52264f4beddc934ba57f3789f28347", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "elephant": { + "inputs": { + "nixpkgs": [ + "walker", + "nixpkgs" + ], + "systems": [ + "walker", + "systems" + ] + }, + "locked": { + "lastModified": 1768551400, + "narHash": "sha256-mlHlHW8qLcHm42J1M34HLXLW+Rw8jsLkLdjSvIYlhjw=", + "owner": "abenz1267", + "repo": "elephant", + "rev": "f230c43ae94231c2db754f84a4f31cf76721a28a", + "type": "github" + }, + "original": { + "owner": "abenz1267", + "repo": "elephant", + "type": "github" + } + }, + "firefox-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1764873433, + "narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=", + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767609335, + "narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "250481aafeb741edfe23d29195671c19b36b6dca", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "fromYaml": { + "flake": false, + "locked": { + "lastModified": 1731966426, + "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=", + "owner": "SenchoPens", + "repo": "fromYaml", + "rev": "106af9e2f715e2d828df706c386a685698f3223b", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "fromYaml", + "type": "github" + } + }, + "gnome-shell": { + "flake": false, + "locked": { + "host": "gitlab.gnome.org", + "lastModified": 1767737596, + "narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=", + "owner": "GNOME", + "repo": "gnome-shell", + "rev": "ef02db02bf0ff342734d525b5767814770d85b49", + "type": "gitlab" + }, + "original": { + "host": "gitlab.gnome.org", + "owner": "GNOME", + "ref": "gnome-49", + "repo": "gnome-shell", + "type": "gitlab" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1775077333, + "narHash": "sha256-OXcxobt7lBkh1B8AjwreU+24myhtKpqeLfAeIyNLFY8=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "49ca96b2714c5931e17401eff87f3edd42d2b0f2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-25.11", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "impermanence", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768598210, + "narHash": "sha256-kkgA32s/f4jaa4UG+2f8C225Qvclxnqs76mf8zvTVPg=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "c47b2cc64a629f8e075de52e4742de688f930dc6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "impermanence": { + "inputs": { + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1769548169, + "narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "7b1d382faf603b6d264f58627330f9faa5cba149", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, + "nix-colors": { + "inputs": { + "base16-schemes": "base16-schemes", + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1707825078, + "narHash": "sha256-hTfge2J2W+42SZ7VHXkf4kjU+qzFqPeC9k66jAUBMHk=", + "owner": "misterio77", + "repo": "nix-colors", + "rev": "b01f024090d2c4fc3152cd0cf12027a7b8453ba1", + "type": "github" + }, + "original": { + "owner": "misterio77", + "repo": "nix-colors", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1774933469, + "narHash": "sha256-OrnCQeUO2bqaWUl0lkDWyGWjKsOhtCyd7JSfTedQNUE=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "f4c4c2c0c923d7811ac2a63ccc154767e4195337", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1768564909, + "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1697935651, + "narHash": "sha256-qOfWjQ2JQSQL15KLh6D7xQhx0qgZlYZTYlcEiRuAMMw=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e1e11fdbb01113d85c7f41cada9d2847660e3902", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1775002709, + "narHash": "sha256-d3Yx83vSrN+2z/loBh4mJpyRqr9aAJqlke4TkpFmRJA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "bcd464ccd2a1a7cd09aa2f8d4ffba83b761b1d0e", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1767767207, + "narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5912c1772a44e31bf1c63c0390b90501e5026886", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1768564909, + "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "inputs": { + "flake-parts": [ + "stylix", + "flake-parts" + ], + "nixpkgs": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1767810917, + "narHash": "sha256-ZKqhk772+v/bujjhla9VABwcvz+hB2IaRyeLT6CFnT0=", + "owner": "nix-community", + "repo": "NUR", + "rev": "dead29c804adc928d3a69dfe7f9f12d0eec1f1a4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "root": { + "inputs": { + "disko": "disko", + "home-manager": "home-manager", + "impermanence": "impermanence", + "nix-colors": "nix-colors", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs_2", + "stylix": "stylix", + "walker": "walker" + } + }, + "stylix": { + "inputs": { + "base16": "base16", + "base16-fish": "base16-fish", + "base16-helix": "base16-helix", + "base16-vim": "base16-vim", + "firefox-gnome-theme": "firefox-gnome-theme", + "flake-parts": "flake-parts", + "gnome-shell": "gnome-shell", + "nixpkgs": "nixpkgs_3", + "nur": "nur", + "systems": "systems", + "tinted-foot": "tinted-foot", + "tinted-kitty": "tinted-kitty", + "tinted-schemes": "tinted-schemes", + "tinted-tmux": "tinted-tmux", + "tinted-zed": "tinted-zed" + }, + "locked": { + "lastModified": 1774897726, + "narHash": "sha256-k/H2/oyex6GEC6uYXYetrboFQeTmX1Ouwv/zaW7b/Z0=", + "owner": "danth", + "repo": "stylix", + "rev": "9b4a5eb409ceac2dd6ad495c7988e189a418cd30", + "type": "github" + }, + "original": { + "owner": "danth", + "repo": "stylix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "tinted-foot": { + "flake": false, + "locked": { + "lastModified": 1726913040, + "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + } + }, + "tinted-kitty": { + "flake": false, + "locked": { + "lastModified": 1735730497, + "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", + "owner": "tinted-theming", + "repo": "tinted-kitty", + "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-kitty", + "type": "github" + } + }, + "tinted-schemes": { + "flake": false, + "locked": { + "lastModified": 1767710407, + "narHash": "sha256-+W1EB79Jl0/gm4JqmO0Nuc5C7hRdp4vfsV/VdzI+des=", + "owner": "tinted-theming", + "repo": "schemes", + "rev": "2800e2b8ac90f678d7e4acebe4fa253f602e05b2", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "schemes", + "type": "github" + } + }, + "tinted-tmux": { + "flake": false, + "locked": { + "lastModified": 1767489635, + "narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=", + "owner": "tinted-theming", + "repo": "tinted-tmux", + "rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-tmux", + "type": "github" + } + }, + "tinted-zed": { + "flake": false, + "locked": { + "lastModified": 1767488740, + "narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=", + "owner": "tinted-theming", + "repo": "base16-zed", + "rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-zed", + "type": "github" + } + }, + "walker": { + "inputs": { + "elephant": "elephant", + "nixpkgs": "nixpkgs_4", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1773675699, + "narHash": "sha256-GrormZ2KxchtCLuO90+5fioEQmlUCKBIil0Mzr9w0Iw=", + "owner": "abenz1267", + "repo": "walker", + "rev": "d2702235710da3d7daf55c912ca7534261cf20f5", + "type": "github" + }, + "original": { + "owner": "abenz1267", + "repo": "walker", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index f8a6049..31139dd 100644 --- a/flake.nix +++ b/flake.nix @@ -2,16 +2,18 @@ description = "Nomarchy - A NixOS-based distribution with Omarchy flavour"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + + impermanence.url = "github:nix-community/impermanence"; home-manager = { - url = "github:nix-community/home-manager"; + url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; @@ -20,7 +22,7 @@ walker.url = "github:abenz1267/walker"; }; - outputs = { self, nixpkgs, nixos-hardware, disko, home-manager, nix-colors, stylix, walker, ... } @ inputs: { + outputs = { self, nixpkgs, nixos-hardware, disko, impermanence, home-manager, nix-colors, stylix, walker, ... } @ inputs: { nixosModules = { system = import ./modules/system; home = import ./modules/home; @@ -28,67 +30,86 @@ nixosConfigurations = { installerIso = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; specialArgs = { inherit inputs; }; modules = [ - "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + { nixpkgs.hostPlatform = "x86_64-linux"; } + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix" ./hosts/live-iso.nix + ./modules/system + home-manager.nixosModules.home-manager { - system.stateVersion = "24.11"; + system.stateVersion = "25.11"; home-manager.extraSpecialArgs = { inherit inputs; }; + + services.displayManager.autoLogin.enable = true; + services.displayManager.autoLogin.user = "nixos"; + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.nixos = { + imports = [ ./modules/home ]; + home.username = "nixos"; + home.homeDirectory = "/home/nixos"; + home.stateVersion = "25.11"; + }; } ]; }; installerVm = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; specialArgs = { inherit inputs; }; modules = [ + { nixpkgs.hostPlatform = "x86_64-linux"; } ./hosts/live-iso.nix + ./modules/system + home-manager.nixosModules.home-manager { - system.stateVersion = "24.11"; + system.stateVersion = "25.11"; networking.hostName = "nomarchy-installer"; - - # VM specific settings to start in terminal + home-manager.extraSpecialArgs = { inherit inputs; }; + + services.displayManager.autoLogin.enable = true; + services.displayManager.autoLogin.user = "nixos"; + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.nixos = { + imports = [ ./modules/home ]; + home.username = "nixos"; + home.homeDirectory = "/home/nixos"; + home.stateVersion = "25.11"; + }; + + # VM specific settings to enable graphical boot virtualisation.vmVariant = { virtualisation.memorySize = 2048; virtualisation.cores = 2; virtualisation.graphics = true; }; - # Use a dummy hardware config + # Use a dummy hardware config for VM fileSystems."/" = { device = "/dev/disk/by-label/nixos"; }; boot.loader.grub.device = "/dev/vda"; - # Setup a user that automatically logs in to console + # Ensure the user has the right groups for graphical environment users.users.nixos = { isNormalUser = true; - extraGroups = [ "wheel" "video" ]; + extraGroups = [ "wheel" "video" "networkmanager" ]; initialPassword = "nixos"; }; - - services.getty.autologinUser = "nixos"; - - # Optionally, start the installer immediately - environment.interactiveShellInit = '' - if [[ "$(tty)" == "/dev/tty1" ]]; then - echo "Welcome to the Nomarchy Installer Test VM!" - echo "To start the installer, run: sudo /etc/install-nomarchy.sh" - fi - ''; } ]; }; vm = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; specialArgs = { inherit inputs; }; modules = [ + { nixpkgs.hostPlatform = "x86_64-linux"; } ./modules/system ./modules/system/hardware.nix home-manager.nixosModules.home-manager { - system.stateVersion = "24.11"; + system.stateVersion = "25.11"; networking.hostName = "nomarchy"; home-manager.extraSpecialArgs = { inherit inputs; }; # VM specific settings @@ -118,7 +139,7 @@ imports = [ ./modules/home ]; home.username = "nomarchy"; home.homeDirectory = "/home/nomarchy"; - home.stateVersion = "24.11"; + home.stateVersion = "25.11"; }; } ]; diff --git a/hosts/live-iso.nix b/hosts/live-iso.nix index e5d1481..54b2bb5 100644 --- a/hosts/live-iso.nix +++ b/hosts/live-iso.nix @@ -4,7 +4,14 @@ environment.systemPackages = with pkgs; [ git gum - inputs.disko.packages.${pkgs.system}.disko + inputs.disko.packages.${pkgs.stdenv.hostPlatform.system}.disko + (pkgs.makeDesktopItem { + name = "install-nomarchy"; + desktopName = "Install Nomarchy"; + exec = "alacritty -e sudo /etc/install-nomarchy.sh"; + terminal = false; + categories = [ "System" ]; + }) ]; environment.etc."install-nomarchy.sh" = { @@ -19,4 +26,6 @@ environment.etc."disko-btrfs-luks.nix" = { source = ../installer/disko-btrfs-luks.nix; }; + + environment.etc."nomarchy".source = inputs.self; } diff --git a/installer/install-nomarchy.sh b/installer/install-nomarchy.sh index 209ed22..a898fcf 100644 --- a/installer/install-nomarchy.sh +++ b/installer/install-nomarchy.sh @@ -155,7 +155,7 @@ cat < /mnt/etc/nixos/flake.nix inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - nomarchy.url = "github:yourusername/nomarchy"; # UPDATE THIS to point to your repo + nomarchy.url = "path:./nomarchy"; # Offline bundled nomarchy nixos-hardware.url = "github:NixOS/nixos-hardware/master"; home-manager = { @@ -206,7 +206,12 @@ cat < /mnt/etc/nixos/flake.nix } EOF -# 7. Version Control +# 7. Copy Bundled Flake +echo "Copying bundled upstream Nomarchy flake..." +cp -rL /etc/nomarchy /mnt/etc/nixos/nomarchy +chmod -R u+w /mnt/etc/nixos/nomarchy + +# 8. Version Control cd /mnt/etc/nixos/ git init git add . @@ -214,5 +219,5 @@ git config user.name "Nomarchy Installer" git config user.email "installer@nomarchy" git commit -m "Initial Nomarchy generation" -# 8. Execution +# 9. Execution nixos-install --flake /mnt/etc/nixos#default --no-root-passwd diff --git a/modules/home/alacritty.nix b/modules/home/alacritty.nix new file mode 100644 index 0000000..6eae803 --- /dev/null +++ b/modules/home/alacritty.nix @@ -0,0 +1,33 @@ +{ config, pkgs, ... }: + +{ + programs.alacritty = { + enable = true; + settings = { + general.import = [ "~/.config/nomarchy/current/theme/alacritty.toml" ]; + env = { + TERM = "xterm-256color"; + }; + terminal = { + osc52 = "CopyPaste"; + }; + font = { + normal = { family = config.nomarchy.fonts.monospace; style = "Regular"; }; + bold = { family = config.nomarchy.fonts.monospace; style = "Bold"; }; + italic = { family = config.nomarchy.fonts.monospace; style = "Italic"; }; + size = 9; + }; + window = { + padding = { x = 14; y = 14; }; + decorations = "None"; + }; + keyboard = { + bindings = [ + { key = "Insert"; mods = "Shift"; action = "Paste"; } + { key = "Insert"; mods = "Control"; action = "Copy"; } + { key = "Return"; mods = "Shift"; chars = "\\u001B\\r"; } + ]; + }; + }; + }; +} diff --git a/modules/home/configs.nix b/modules/home/configs.nix index 714b8aa..ea95665 100644 --- a/modules/home/configs.nix +++ b/modules/home/configs.nix @@ -2,7 +2,6 @@ { xdg.configFile = { - "alacritty".source = ../../config/alacritty; "btop".source = ../../config/btop; "chromium".source = ../../config/chromium; "fastfetch".source = ../../config/fastfetch; diff --git a/modules/home/default.nix b/modules/home/default.nix index 1e955c9..9ded849 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -7,12 +7,23 @@ let activeThemeName = if builtins.pathExists stateFile then lib.removeSuffix "\n" (builtins.readFile stateFile) else "dracula"; + userPackagesFile = "${config.home.homeDirectory}/.config/home-manager/user-packages.json"; + userPackages = if builtins.pathExists userPackagesFile then + let + pkgNames = builtins.fromJSON (builtins.readFile userPackagesFile); + # Filter to only packages that exist in pkgs to prevent build failures + validPkgs = builtins.filter (name: builtins.hasAttr name pkgs) pkgNames; + in builtins.map (name: pkgs.${name}) validPkgs + else []; in { imports = [ inputs.nix-colors.homeManagerModules.default inputs.walker.homeManagerModules.default ./fonts.nix + ./alacritty.nix + ./nightlight.nix + ./idle.nix ./stylix.nix ./hyprland.nix ./waybar.nix @@ -25,8 +36,25 @@ in colorScheme = palettes.${activeThemeName} or palettes.dracula; home.packages = with pkgs; [ - alacritty - ]; + firefox + thunar + imv + mpv + neovim + wl-clipboard + grim + slurp + brightnessctl + playerctl + pamixer + mise + jq + xmlstarlet + nerd-fonts.jetbrains-mono + nerd-fonts.roboto-mono + nerd-fonts.fira-code + nerd-fonts.ubuntu-mono + ] ++ userPackages; home.shellAliases = { sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default"; diff --git a/modules/home/fonts.nix b/modules/home/fonts.nix index 6609fb6..40e856a 100644 --- a/modules/home/fonts.nix +++ b/modules/home/fonts.nix @@ -1,9 +1,11 @@ { config, pkgs, lib, ... }: let - stateFile = "${config.home.homeDirectory}/.config/home-manager/font-state.nix"; - activeFont = if builtins.pathExists stateFile then - lib.removeSuffix "\n" (builtins.readFile stateFile) + # Standardize state files to a common directory + stateDir = "${config.home.homeDirectory}/.config/home-manager"; + fontStateFile = "${stateDir}/font-state.nix"; + activeFont = if builtins.pathExists fontStateFile then + lib.removeSuffix "\n" (builtins.readFile fontStateFile) else "JetBrainsMono Nerd Font"; in { @@ -14,4 +16,9 @@ in description = "Monospace font for the system"; }; }; + + config = { + fonts.fontconfig.enable = true; + xdg.dataFile."fonts/nomarchy.ttf".source = ../../config/nomarchy.ttf; + }; } diff --git a/modules/home/hyprland.nix b/modules/home/hyprland.nix index d71ccec..50bb754 100644 --- a/modules/home/hyprland.nix +++ b/modules/home/hyprland.nix @@ -5,20 +5,30 @@ let activeWallpaper = if builtins.pathExists wallpaperStateFile then lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile) else ""; + hyprlandStateFile = "${config.home.homeDirectory}/.config/home-manager/hyprland-state.json"; + hyprlandState = if builtins.pathExists hyprlandStateFile then + builtins.fromJSON (builtins.readFile hyprlandStateFile) + else { gaps_out = 10; gaps_in = 5; border_size = 2; }; in { wayland.windowManager.hyprland = { enable = true; settings = { "general" = { + "gaps_in" = hyprlandState.gaps_in; + "gaps_out" = hyprlandState.gaps_out; + "border_size" = hyprlandState.border_size; "col.active_border" = "rgb(${config.colorScheme.palette.base0E})"; "col.inactive_border" = "rgb(${config.colorScheme.palette.base03})"; }; "exec-once" = [ - "swww init && swww fill ${activeWallpaper}" + "swww-daemon & sleep 0.5 && swww img ${activeWallpaper} --transition-type none" + "waybar" + "nomarchy-on-boot" "nomarchy-welcome" ]; "bind" = [ + "SUPER, Space, exec, walker" "SUPER ALT, Space, exec, nomarchy-theme-selector" "SUPER CTRL, Space, exec, nomarchy-font-selector" "SUPER SHIFT, Space, exec, nomarchy-wallpaper-selector" diff --git a/modules/home/idle.nix b/modules/home/idle.nix new file mode 100644 index 0000000..8ae3846 --- /dev/null +++ b/modules/home/idle.nix @@ -0,0 +1,13 @@ +{ config, pkgs, ... }: + +let + stateFile = "${config.home.homeDirectory}/.config/home-manager/idle-state.json"; + idleState = if builtins.pathExists stateFile then + builtins.fromJSON (builtins.readFile stateFile) + else { enabled = true; }; +in +{ + services.hypridle = { + enable = idleState.enabled; + }; +} diff --git a/modules/home/nightlight.nix b/modules/home/nightlight.nix new file mode 100644 index 0000000..98b7f26 --- /dev/null +++ b/modules/home/nightlight.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: + +let + stateFile = "${config.home.homeDirectory}/.config/home-manager/hyprsunset-state.json"; + hyprsunsetState = if builtins.pathExists stateFile then + builtins.fromJSON (builtins.readFile stateFile) + else { enabled = false; temperature = 4000; }; +in +{ + services.hyprsunset = { + enable = true; # Always enabled, we control via IPC and state + temperature = if hyprsunsetState.enabled then hyprsunsetState.temperature else 6500; + }; +} diff --git a/modules/home/scripts.nix b/modules/home/scripts.nix index 3fd4a91..97a2afe 100644 --- a/modules/home/scripts.nix +++ b/modules/home/scripts.nix @@ -15,6 +15,12 @@ let jq swww xmlstarlet + wl-clipboard + grim + slurp + brightnessctl + playerctl + pamixer # Add any others commonly used in bin/ ]; diff --git a/modules/home/swayosd.nix b/modules/home/swayosd.nix new file mode 100644 index 0000000..c6e7cbb --- /dev/null +++ b/modules/home/swayosd.nix @@ -0,0 +1,5 @@ +{ config, pkgs, ... }: + +{ + services.swayosd.enable = true; +} diff --git a/modules/home/theme-switcher.nix b/modules/home/theme-switcher.nix index 360eaef..f1cc1b6 100644 --- a/modules/home/theme-switcher.nix +++ b/modules/home/theme-switcher.nix @@ -9,7 +9,13 @@ let STATE_DIR="$HOME/.config/home-manager" THEME_STATE_FILE="$STATE_DIR/theme-state.nix" WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" - THEMES_DIR="/etc/nixos/themes" # This depends on where the repo is cloned + if [ -d "/etc/nixos/nomarchy/themes" ]; then + THEMES_DIR="/etc/nixos/nomarchy/themes" + elif [ -d "/etc/nomarchy/themes" ]; then + THEMES_DIR="/etc/nomarchy/themes" + else + THEMES_DIR="/etc/nixos/themes" + fi # This depends on where the repo is cloned mkdir -p "$STATE_DIR" @@ -24,6 +30,7 @@ let BG=$(ls "$BG_DIR" | head -n 1) if [ -n "$BG" ]; then echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE" + swww img "$BG_DIR/$BG" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 & fi fi @@ -48,7 +55,13 @@ let nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" '' STATE_DIR="$HOME/.config/home-manager" WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" - THEMES_DIR="/etc/nixos/themes" + if [ -d "/etc/nixos/nomarchy/themes" ]; then + THEMES_DIR="/etc/nixos/nomarchy/themes" + elif [ -d "/etc/nomarchy/themes" ]; then + THEMES_DIR="/etc/nomarchy/themes" + else + THEMES_DIR="/etc/nixos/themes" + fi mkdir -p "$STATE_DIR" @@ -58,6 +71,7 @@ let if [ -n "$SELECTED_WP" ]; then echo "$SELECTED_WP" > "$WALLPAPER_STATE_FILE" + swww img "$SELECTED_WP" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 & env-update fi ''; diff --git a/modules/home/vscode.nix b/modules/home/vscode.nix new file mode 100644 index 0000000..2501eff --- /dev/null +++ b/modules/home/vscode.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: + +{ + programs.vscode = { + enable = true; + package = pkgs.vscode; + userSettings = { + "update.mode" = "none"; + "workbench.colorTheme" = "Nomarchy Theme"; # Example, would need to be generated + "window.titleBarStyle" = "custom"; + }; + # extensions = with pkgs.vscode-extensions; [ ... ]; + }; +} diff --git a/modules/options.nix b/modules/options.nix new file mode 100644 index 0000000..81403e0 --- /dev/null +++ b/modules/options.nix @@ -0,0 +1,68 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + options.nomarchy = { + # System-level options + system = { + enable = mkEnableOption "Nomarchy core system features"; + + # Allow users to add extra system packages + extraPackages = mkOption { + type = types.listOf types.package; + default = []; + description = "Additional system-wide packages to install"; + }; + + # Allow overriding system defaults + hostname = mkOption { + type = types.str; + default = "nomarchy"; + description = "The system hostname"; + }; + + # Allow user to inject their own NixOS modules + extraModules = mkOption { + type = types.listOf types.deferredModule; + default = []; + description = "Extra NixOS modules to include"; + }; + }; + + # Home-level options + home = { + enable = mkEnableOption "Nomarchy home environment features"; + + # Allow users to add extra user packages + extraPackages = mkOption { + type = types.listOf types.package; + default = []; + description = "Additional user-level packages to install"; + }; + + # Configuration for the environment + terminal = mkOption { + type = types.enum [ "alacritty" "kitty" "ghostty" ]; + default = "alacritty"; + description = "Preferred terminal emulator"; + }; + + # Allow user to inject their own Home Manager modules + extraModules = mkOption { + type = types.listOf types.deferredModule; + default = []; + description = "Extra Home Manager modules to include"; + }; + + # Theming overrides + themeOverride = mkOption { + type = types.nullOr types.str; + default = null; + description = "Force a specific theme (ignoring state files)"; + }; + }; + + # Hardware flags (already exists in hardware.nix, but good to keep in mind) + }; +} diff --git a/modules/system/audio.nix b/modules/system/audio.nix new file mode 100644 index 0000000..5968d73 --- /dev/null +++ b/modules/system/audio.nix @@ -0,0 +1,12 @@ +{ config, pkgs, ... }: + +{ + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + jack.enable = true; + }; +} diff --git a/modules/system/bluetooth.nix b/modules/system/bluetooth.nix new file mode 100644 index 0000000..122c2e8 --- /dev/null +++ b/modules/system/bluetooth.nix @@ -0,0 +1,7 @@ +{ config, pkgs, ... }: + +{ + hardware.bluetooth.enable = true; + hardware.bluetooth.powerOnBoot = true; + services.blueman.enable = true; +} diff --git a/modules/system/default.nix b/modules/system/default.nix index 7d4b99f..0dc6442 100644 --- a/modules/system/default.nix +++ b/modules/system/default.nix @@ -1,9 +1,13 @@ -{ config, pkgs, ... }: +{ config, lib, pkgs, ... }: { imports = [ ./plymouth.nix ./sddm.nix ./hardware.nix + ./audio.nix + ./bluetooth.nix + ./network.nix + ./impermanence.nix ]; } diff --git a/modules/system/impermanence.nix b/modules/system/impermanence.nix new file mode 100644 index 0000000..6026cca --- /dev/null +++ b/modules/system/impermanence.nix @@ -0,0 +1,58 @@ +{ config, lib, pkgs, inputs, ... }: + +let + cfg = config.nomarchy.system.impermanence; +in +{ + imports = [ + inputs.impermanence.nixosModules.impermanence + ]; + + options.nomarchy.system.impermanence = { + enable = lib.mkEnableOption "Erase Your Darlings (Impermanence) root wipe on boot"; + }; + + config = lib.mkIf cfg.enable { + # 1. The Rollback Script: Runs in initrd before filesystems are mounted + boot.initrd.postDeviceCommands = lib.mkAfter '' + mkdir -p /btrfs_tmp + mount -o subvol=/ /dev/mapper/crypted /btrfs_tmp + + if [[ -e /btrfs_tmp/@ ]]; then + mkdir -p /btrfs_tmp/old_roots + timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/@)" "+%Y-%m-%-d_%H:%M:%S") + mv /btrfs_tmp/@ "/btrfs_tmp/old_roots/$timestamp" + fi + + delete_subvolume_recursively() { + IFS=$'\n' + for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do + delete_subvolume_recursively "/btrfs_tmp/$i" + done + btrfs subvolume delete "$1" + } + + for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do + delete_subvolume_recursively "$i" + done + + btrfs subvolume snapshot /btrfs_tmp/root-blank /btrfs_tmp/@ + umount /btrfs_tmp + ''; + + # 2. Persistence Configuration: What survives the wipe + environment.persistence."/persist" = { + hideMounts = true; + directories = [ + "/var/log" + "/var/lib/nixos" + "/var/lib/systemd/coredump" + "/var/lib/bluetooth" + "/etc/NetworkManager/system-connections" + ]; + files = [ + "/etc/machine-id" + ]; + }; + }; +} diff --git a/modules/system/network.nix b/modules/system/network.nix new file mode 100644 index 0000000..34b6b7c --- /dev/null +++ b/modules/system/network.nix @@ -0,0 +1,5 @@ +{ config, pkgs, ... }: + +{ + networking.networkmanager.enable = true; +} diff --git a/modules/system/supergfxd.nix b/modules/system/supergfxd.nix new file mode 100644 index 0000000..bbd1a90 --- /dev/null +++ b/modules/system/supergfxd.nix @@ -0,0 +1,6 @@ +{ config, pkgs, ... }: + +{ + services.supergfxd.enable = true; + # NixOS handles the configuration of supergfxd +} diff --git a/themes/nomarchy-palettes.nix b/themes/nomarchy-palettes.nix index 8bd6ea6..a99cbcd 100644 --- a/themes/nomarchy-palettes.nix +++ b/themes/nomarchy-palettes.nix @@ -1,46 +1,43 @@ -{ - dracula = { - name = "dracula"; - author = "dracula"; - palette = { - base00 = "282a36"; - base01 = "3a3c4e"; - base02 = "4d4f68"; - base03 = "6272a4"; - base04 = "62d6e8"; - base05 = "e9e9f4"; - base06 = "f1f2f8"; - base07 = "f8f8f2"; - base08 = "ff5555"; - base09 = "ffb86c"; - base0A = "f1fa8c"; - base0B = "50fa7b"; - base0C = "8be9fd"; - base0D = "bd93f9"; - base0E = "ff79c6"; - base0F = "bd93f9"; +let + themesDir = ./.; + + # Get all directories in the themes folder that have a colors.toml file + directories = builtins.attrNames ( + builtins.filterAttrs (name: type: type == "directory" && builtins.pathExists (themesDir + "/${name}/colors.toml")) (builtins.readDir themesDir) + ); + + readTheme = name: + let + toml = builtins.fromTOML (builtins.readFile (themesDir + "/${name}/colors.toml")); + + # Helper to strip '#' from color codes + stripHash = s: builtins.replaceStrings ["#"] [""] s; + + in { + inherit name; + author = "nomarchy"; + palette = { + base00 = stripHash toml.background; + base01 = stripHash toml.color0; + base02 = stripHash toml.color8; + base03 = stripHash toml.color8; + base04 = stripHash toml.color7; + base05 = stripHash toml.foreground; + base06 = stripHash toml.color15; + base07 = stripHash toml.color15; + base08 = stripHash toml.color1; + base09 = stripHash toml.color3; + base0A = stripHash toml.color3; + base0B = stripHash toml.color2; + base0C = stripHash toml.color6; + base0D = stripHash toml.color4; + base0E = stripHash toml.color5; + base0F = stripHash toml.color1; + }; }; - }; - nord = { - name = "nord"; - author = "arcticicestudio"; - palette = { - base00 = "2e3440"; - base01 = "3b4252"; - base02 = "434c5e"; - base03 = "4c566a"; - base04 = "d8dee9"; - base05 = "e5e9f0"; - base06 = "eceff4"; - base07 = "8fbcbb"; - base08 = "88c0d0"; - base09 = "81a1c1"; - base0A = "5e81ac"; - base0B = "bf616a"; - base0C = "d08770"; - base0D = "ebcb8b"; - base0E = "a3be8c"; - base0F = "b48ead"; - }; - }; -} + +in + builtins.listToAttrs (map (name: { + inherit name; + value = readTheme name; + }) directories)