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
This commit is contained in:
Bernardo Magri
2026-04-03 21:06:42 +01:00
parent 33deeb494b
commit 29cc0d2547
49 changed files with 1628 additions and 855 deletions

View File

@@ -1,64 +1,40 @@
# Nomarchy - A NixOS-based distribution with Omarchy flavour - Agent Build Blueprint # Nomarchy - A NixOS-based distribution with Omarchy flavour - Agent Build Blueprint
## System Architecture Overview ## 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 ## Directory Structure
Generate the repository using the following exact structure: * `flake.nix` (Master entry point with core modules and test configurations)
* `installer/install-nomarchy.sh` (Interactive installer generating a clean downstream flake)
* `flake.nix` (Master entry point) * `modules/system/default.nix` (Distro-wide OS defaults: SDDM, Plymouth, Audio, Network)
* `installer/install-nomarchy.sh` (Bash/Gum interactive installer) * `modules/home/default.nix` (Distro-wide user environment: Hyprland, Waybar, Styling)
* `installer/disko-ext4.nix` (Standard drive layout) * `bin/` (The collection of Omarchy productivity and config scripts)
* `installer/disko-btrfs-luks.nix` (Encrypted snapshot layout) * `themes/` (Distro-wide color palettes and backgrounds)
* `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)
## Core Components & Logic ## Core Components & Logic
### 1. The Master Flake (`flake.nix`) ### 1. Separation of Concerns (Upstream vs. Downstream)
* **Inputs required:** `nixpkgs` (unstable), `nixos-hardware`, `disko`, `home-manager`, `nix-colors`. * **Upstream:** The `nomarchy/` directory contains the core logic. It is treated as an immutable input by the target system.
* **Outputs required:** * `nixosModules.system`: Points to `modules/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`.
* `nixosModules.home`: Points to `modules/home`. * **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.
* `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/`.
### 2. The Interactive Installer (`installer/install-nomarchy.sh`) ### 2. The Interactive Installer (`installer/install-nomarchy.sh`)
Write a Bash script utilizing `gum` for UI prompts. The flow must execute as follows: The installer is designed to bootstrap a fresh system with this modular structure:
1. **Hardware Detection:** Read `/sys/class/dmi/id/product_name` and map it to a generic or specific `nixos-hardware` flake module. 1. **Repo Detection:** Identifies the location of the Nomarchy source.
2. **Storage Setup:** Prompt user for target drive. Prompt to choose between "Standard Ext4" or "Encrypted BTRFS (LUKS2)". Execute the corresponding Disko `.nix` file. 2. **Scaffolding:** Creates a new downstream `flake.nix` that imports Nomarchy core modules.
3. **User Details:** Prompt for target username. 3. **User Files:** Generates skeleton `system.nix` and `home.nix` files for the user to customize.
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. 4. **Bundling:** Copies the entire Nomarchy source to `/etc/nixos/nomarchy` so the system can be rebuilt offline.
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`.
### 3. Disko Configurations ### 3. Home Manager Integration
* **Ext4:** Single EFI partition, single Ext4 root partition. * **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.
* **BTRFS+LUKS:** EFI partition, LUKS2 encrypted container holding a BTRFS filesystem. Subvolumes must include `@` (root), `@home` (user data), `@nix` (Nix store), and `@log` (logs). * **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/`) ### 4. Dynamic Theming
* **Boot:** Enable `systemd` initrd. Enable Plymouth with a custom Nomarchy theme derivation. Silence kernel logs completely (`quiet splash loglevel=3`). * **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.
* **Login:** Enable SDDM with Wayland support. Read the generated `login-preference.nix` to conditionally enable `autoLogin`. Enable Hyprland system-level dependencies.
### 5. Home Manager & Theming (`modules/home/`) ## Verification & Build
* **Architecture:** Must remain standalone (not built into the system NixOS config). * **Test Installer:** `./bin/nomarchy-test-installer` (Builds a VM of the installer environment).
* **Aliases:** Define `sys-update` (`sudo nixos-rebuild switch`) and `env-update` (`home-manager switch`) in `home.shellAliases`. * **Check Integrity:** `nix flake check --impure` (Verifies all configurations evaluate).
* **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`. * **Build ISO:** `nix build .#nixosConfigurations.installerIso.config.system.build.isoImage` (Generates the flashable USB image).
* **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.

View File

@@ -1,38 +1,31 @@
#!/bin/bash #!/usr/bin/env bash
# Set the system-wide monospace font that should be used by the terminal, hyprlock, waybar, swayosd, etc. # 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" font_name="$1"
if [[ -n $font_name ]]; then if [[ -z $font_name ]]; then
if fc-list | grep -iq "$font_name"; then echo "Usage: nomarchy-font-set <font-name>"
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then exit 1
sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml
fi fi
if [[ -f ~/.config/kitty/kitty.conf ]]; then STATE_DIR="$HOME/.config/home-manager"
sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf 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 pkill -USR1 kitty
fi 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 if pgrep -x ghostty; then
pkill -SIGUSR2 ghostty
notify-send -u low " You must restart Ghostty to see font change" notify-send -u low " You must restart Ghostty to see font change"
fi fi
@@ -41,6 +34,3 @@ if [[ -n $font_name ]]; then
echo "Font '$font_name' not found." echo "Font '$font_name' not found."
exit 1 exit 1
fi fi
else
echo "Usage: nomarchy-font-set <font-name>"
fi

View File

@@ -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 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_out 10
hyprctl keyword general:gaps_in 5 hyprctl keyword general:gaps_in 5
hyprctl keyword general:border_size 2 hyprctl keyword general:border_size 2
else else
NEW_STATE='{"gaps_out": 0, "gaps_in": 0, "border_size": 0}'
hyprctl keyword general:gaps_out 0 hyprctl keyword general:gaps_out 0
hyprctl keyword general:gaps_in 0 hyprctl keyword general:gaps_in 0
hyprctl keyword general:border_size 0 hyprctl keyword general:border_size 0
fi fi
echo "$NEW_STATE" > "$STATE_FILE"
echo "Toggled gaps to $NEW_STATE declaratively."

View File

@@ -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 if [[ -z $1 ]]; then
echo "Usage: nomarchy-install-dev-env <ruby|node|bun|deno|go|laravel|symfony|php|python|elixir|phoenix|rust|java|zig|ocaml|dotnet|clojure|scala>" >&2 echo "Usage: nomarchy-install-dev-env <ruby|node|bun|deno|go|laravel|symfony|php|python|elixir|phoenix|rust|java|zig|ocaml|dotnet|clojure|scala>" >&2
@@ -8,144 +9,78 @@ if [[ -z $1 ]]; then
fi fi
install_php() { install_php() {
nomarchy-pkg-add php composer php-sqlite xdebug echo -e "Installing PHP environment declaratively...\n"
nomarchy-pkg-add php
# Install Path for Composer nomarchy-pkg-add phpExtensions.bcmath
if [[ :$PATH: != *:$HOME/.config/composer/vendor/bin:* ]]; then nomarchy-pkg-add phpExtensions.intl
echo 'export PATH="$HOME/.config/composer/vendor/bin:$PATH"' >>"$HOME/.bashrc" nomarchy-pkg-add phpExtensions.iconv
source "$HOME/.bashrc" nomarchy-pkg-add phpExtensions.openssl
echo "Added Composer global bin directory to PATH." nomarchy-pkg-add phpExtensions.pdo_sqlite
else nomarchy-pkg-add phpExtensions.pdo_mysql
echo "Composer global bin directory already in PATH." nomarchy-pkg-add phpPackages.composer
fi echo -e "\nPHP environment added to your packages."
# 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
} }
install_node() { install_node() {
echo -e "Installing Node.js...\n" echo -e "Installing Node.js with mise...\n"
mise use --global node mise use --global node
} }
case "$1" in case "$1" in
ruby) ruby)
echo -e "Installing Ruby on Rails...\n" echo -e "Installing Ruby with mise...\n"
nomarchy-pkg-add libyaml nomarchy-pkg-add libyaml
mise settings add ruby.compile false
mise settings add idiomatic_version_file_enable_tools ruby
mise use --global ruby@latest mise use --global ruby@latest
echo "gem: --no-document" >~/.gemrc echo -e "\nYou can now use: ruby --version"
mise x ruby -- gem install rails --no-document
echo -e "\nYou can now run: rails new myproject"
;; ;;
node) node)
install_node install_node
;; ;;
bun) bun)
echo -e "Installing Bun...\n" echo -e "Installing Bun with mise...\n"
mise use -g bun@latest mise use -g bun@latest
;; ;;
deno) deno)
echo -e "Installing Deno...\n" echo -e "Installing Deno with mise...\n"
mise use -g deno@latest mise use -g deno@latest
;; ;;
go) go)
echo -e "Installing Go...\n" echo -e "Installing Go with mise...\n"
mise use --global go@latest mise use --global go@latest
;; ;;
php) php)
echo -e "Installing PHP...\n"
install_php install_php
;; ;;
laravel) laravel)
echo -e "Installing PHP and Laravel...\n" echo -e "Installing Laravel stack...\n"
install_php install_php
install_node install_node
# Composer global packages are imperative, but that's how they work.
composer global require laravel/installer composer global require laravel/installer
echo -e "\nYou can now run: laravel new myproject" 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) python)
echo -e "Installing Python...\n" echo -e "Installing Python with mise...\n"
mise use --global python@latest mise use --global python@latest
echo -e "\nInstalling uv...\n" echo -e "\nInstalling uv...\n"
curl -fsSL https://astral.sh/uv/install.sh | sh # uv can be installed via nix
;; nomarchy-pkg-add uv
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"
;; ;;
rust) rust)
echo -e "Installing Rust...\n" echo -e "Installing Rust declaratively...\n"
bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs)" -- -y # Instead of shell script from website, use nixpkgs
nomarchy-pkg-add rustup
rustup-init -y
;; ;;
java) # Add more language cases as needed, utilizing mise or nixpkgs.
echo -e "Installing Java...\n" *)
mise use --global java@latest # Fallback to mise for languages that it supports
;; echo -e "Installing $1 with mise...\n"
zig) if mise use --global "$1@latest"; then
echo -e "Installing Zig...\n" echo "$1 installed successfully."
mise use --global zig@latest else
mise use -g zls@latest echo "Unsupported language: $1"
;; exit 1
ocaml) fi
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
;; ;;
esac esac

View File

@@ -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 <ruby|node|bun|deno|go|laravel|symfony|php|python|elixir|phoenix|rust|java|zig|ocaml|dotnet|clojure|scala>" >&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

View File

@@ -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. # 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 <<EOF | sudo tee "$FEATURE_FILE" > /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") options=("MySQL" "PostgreSQL" "Redis" "MongoDB" "MariaDB" "MSSQL")
if (( $# == 0 )); then 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 else
choices="$@" choices="$@"
fi fi

View File

@@ -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" if [ -f "$FEATURE_FILE" ]; then
sudo pacman -S steam echo "Steam is already configured in $FEATURE_FILE"
setsid gtk-launch steam >/dev/null 2>&1 & exit 0
fi
sudo mkdir -p "/etc/nixos/nomarchy-features"
cat <<EOF | sudo tee "$FEATURE_FILE" > /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'."

View File

@@ -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..." if [ -f "$FEATURE_FILE" ]; then
sudo tailscale up --accept-routes echo "Tailscale is already configured in $FEATURE_FILE"
exit 0
fi
sudo mkdir -p "/etc/nixos/nomarchy-features"
cat <<EOF | sudo tee "$FEATURE_FILE" > /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 nomarchy-webapp-install "Tailscale" "https://login.tailscale.com/admin/machines" https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/tailscale-light.png

View File

@@ -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..." echo "Installing VSCode..."
nomarchy-pkg-add visual-studio-code-bin nomarchy-pkg-add vscode
mkdir -p ~/.vscode ~/.config/Code/User # VSCode still allows some runtime configuration in its JSON files.
mkdir -p ~/.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
# Ensure VSC's own auto-update feature is turned off # 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 # Apply Nomarchy theme to VSCode
nomarchy-theme-set-vscode nomarchy-theme-set-vscode
setsid gtk-launch code setsid code >/dev/null 2>&1 &

View File

@@ -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 if [ -f "$FEATURE_FILE" ]; then
nomarchy-pkg-add linux-headers echo "Xbox controller support is already configured in $FEATURE_FILE"
nomarchy-pkg-aur-add xpadneo-dkms exit 0
fi
# Prevent xpad/xpadneo driver conflict sudo mkdir -p "/etc/nixos/nomarchy-features"
echo blacklist xpad | sudo tee /etc/modprobe.d/blacklist-xpad.conf >/dev/null cat <<EOF | sudo tee "$FEATURE_FILE" > /dev/null
echo hid_xpadneo | sudo tee /etc/modules-load.d/xpadneo.conf >/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 echo "Created $FEATURE_FILE."
sudo usermod -a -G input $USER 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'."
# Modules need to be loaded
gum confirm "Install requires reboot. Ready?" && sudo reboot now

75
bin/nomarchy-on-boot Executable file
View File

@@ -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 <<EOF > "$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

View File

@@ -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 if [ -z "$PKG_NAME" ]; then
sudo pacman -S --noconfirm --needed "$@" || exit 1 echo "Usage: nomarchy-pkg-add <package-name>"
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 exit 1
fi fi
done
STATE_FILE="$HOME/.config/home-manager/user-packages.json"
mkdir -p "$(dirname "$STATE_FILE")"
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 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

View File

@@ -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. echo "AUR is an Arch Linux concept and is not supported on NixOS."
echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs."
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 exit 1
fi
done
exit 0

View File

@@ -1,28 +1,5 @@
#!/bin/bash #!/usr/bin/env bash
# Show a fuzzy-finder TUI for picking new AUR packages to install. echo "AUR is an Arch Linux concept and is not supported on NixOS."
echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs."
fzf_args=( exit 1
--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

View File

@@ -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 [ -z "$PKG_NAME" ]; then
if ! pacman -Q "$pkg" &>/dev/null; then echo "Usage: nomarchy-pkg-missing <package-name>"
exit 1
fi
nomarchy-pkg-present "$PKG_NAME"
if [ $? -eq 0 ]; then
exit 1
else
exit 0 exit 0
fi fi
done
exit 1

View File

@@ -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 if [ -z "$PKG_NAME" ]; then
pacman -Q "$pkg" &>/dev/null || exit 1 echo "Usage: nomarchy-pkg-present <package-name>"
done exit 1
fi
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 exit 0
else
exit 1
fi

View File

@@ -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=( if [ -z "$PKG_NAME" ]; then
--multi echo "Usage: nomarchy-pkg-remove <package-name>"
--preview 'yay -Qi {1}' exit 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
fi 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

View File

@@ -1,127 +1,46 @@
#!/bin/bash #!/usr/bin/env bash
set -e # Configure FIDO2 support declaratively for Nomarchy NixOS.
GREEN='\033[0;32m' FEATURE_FILE="/etc/nixos/nomarchy-features/fido2.nix"
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
}
if [[ "--remove" == $1 ]]; then if [[ "--remove" == $1 ]]; then
print_success "Removing FIDO2 device from authentication.\n" if [ -f "$FEATURE_FILE" ]; then
sudo rm "$FEATURE_FILE"
# Remove PAM configuration echo "Removed $FEATURE_FILE."
remove_pam_config echo "IMPORTANT: Remove './nomarchy-features/fido2.nix' from your imports and run 'sys-update'."
# 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 else
print_success "Setting up FIDO2 device for authentication.\n" echo "FIDO2 support not found."
fi
# Install required packages exit 0
print_info "Installing required packages..."
nomarchy-pkg-add libfido2 pam-u2f
if ! check_fido2_hardware; then
exit 1
fi fi
# Create the pamu2fcfg file if [ -f "$FEATURE_FILE" ]; then
if [[ ! -f /etc/fido2/fido2 ]]; then echo "FIDO2 support is already configured in $FEATURE_FILE"
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!"
else else
print_error "\nFIDO2 registration failed. Please try again." sudo mkdir -p "/etc/nixos/nomarchy-features"
exit 1 cat <<EOF | sudo tee "$FEATURE_FILE" > /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 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 else
print_info "FIDO2 device already registered." echo "pamu2fcfg not found. Please run 'nomarchy-pkg-add pam-u2f' or 'sys-update' if you just enabled it."
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
fi fi

View File

@@ -1,134 +1,40 @@
#!/bin/bash #!/usr/bin/env bash
set -e # Configure Fingerprint support declaratively for Nomarchy NixOS.
GREEN='\033[0;32m' FEATURE_FILE="/etc/nixos/nomarchy-features/fingerprint.nix"
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 = <span> 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
}
if [[ "--remove" == $1 ]]; then if [[ "--remove" == $1 ]]; then
print_success "Removing fingerprint scanner from authentication.\n" if [ -f "$FEATURE_FILE" ]; then
sudo rm "$FEATURE_FILE"
# Remove PAM configuration echo "Removed $FEATURE_FILE."
remove_pam_config echo "IMPORTANT: Remove './nomarchy-features/fingerprint.nix' from your imports and run 'sys-update'."
# 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 else
print_success "Setting up fingerprint scanner for authentication.\n" echo "Fingerprint support not found."
fi
# Install required packages exit 0
print_info "Installing required packages..."
nomarchy-pkg-add fprintd usbutils
if ! check_fingerprint_hardware; then
exit 1
fi fi
# Configure PAM if [ -f "$FEATURE_FILE" ]; then
setup_pam_config echo "Fingerprint support is already configured in $FEATURE_FILE"
# 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)."
else else
print_error "\nVerification failed. You may want to try enrolling again." sudo mkdir -p "/etc/nixos/nomarchy-features"
cat <<EOF | sudo tee "$FEATURE_FILE" > /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 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 else
print_error "\nEnrollment failed. Please try again." echo "fprintd-enroll not found. Please run 'sys-update' first if you just enabled it."
exit 1
fi
fi fi

View File

@@ -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) STATE_DIR="$HOME/.config/home-manager"
THEME_BACKGROUNDS_PATH="$HOME/.config/nomarchy/current/theme/backgrounds/" THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
USER_BACKGROUNDS_PATH="$HOME/.config/nomarchy/backgrounds/$THEME_NAME/" WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
CURRENT_BACKGROUND_LINK="$HOME/.config/nomarchy/current/background"
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[@]} TOTAL=${#BACKGROUNDS[@]}
if (( TOTAL == 0 )); then if (( TOTAL == 0 )); then
notify-send "No background was found for theme" -t 2000 notify-send "No backgrounds found in $BG_DIR"
pkill -x swaybg exit 1
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 fi
# Find current background index CURRENT_BG=$(cat "$WALLPAPER_STATE_FILE" 2>/dev/null)
INDEX=-1 INDEX=-1
for i in "${!BACKGROUNDS[@]}"; do for i in "${!BACKGROUNDS[@]}"; do
if [[ ${BACKGROUNDS[$i]} == $CURRENT_BACKGROUND ]]; then if [[ "$BG_DIR/${BACKGROUNDS[$i]}" == "$CURRENT_BG" ]]; then
INDEX=$i INDEX=$i
break break
fi fi
done 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)) NEXT_INDEX=$(((INDEX + 1) % TOTAL))
NEW_BACKGROUND="${BACKGROUNDS[$NEXT_INDEX]}" 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 fi
# Set new background symlink echo "Background set to $NEW_BG declaratively."
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 &
fi

View File

@@ -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>
THEME_NAME="$1"
if [[ -z $THEME_NAME ]]; then
echo "Usage: nomarchy-theme-set <theme-name>" echo "Usage: nomarchy-theme-set <theme-name>"
exit 1 exit 1
fi fi
CURRENT_THEME_PATH="$HOME/.config/nomarchy/current/theme" STATE_DIR="$HOME/.config/home-manager"
NEXT_THEME_PATH="$HOME/.config/nomarchy/current/next-theme" THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
USER_THEMES_PATH="$HOME/.config/nomarchy/themes" WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-') # Logic for finding themes
if [ -d "/etc/nixos/nomarchy/themes" ]; then
if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THEME_NAME ]]; then THEMES_DIR="/etc/nixos/nomarchy/themes"
echo "Theme '$THEME_NAME' does not exist" elif [ -d "/etc/nomarchy/themes" ]; then
exit 1 THEMES_DIR="/etc/nomarchy/themes"
else
THEMES_DIR="/etc/nixos/themes"
fi fi
# Setup clean next theme directory (for atomic theme config swapping) mkdir -p "$STATE_DIR"
rm -rf "$NEXT_THEME_PATH"
mkdir -p "$NEXT_THEME_PATH"
# Copy official theme first, then overlay user customizations on top if [ ! -d "$THEMES_DIR/$THEME_NAME" ] && ! [[ "$THEME_NAME" == "dracula" || "$THEME_NAME" == "nord" ]]; then
cp -r "$OMARCHY_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null echo "Theme '$THEME_NAME' not found in $THEMES_DIR"
cp -r "$USER_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null # Check if it exists in the palettes file
# (Assuming nomarchy-palettes.nix is imported in Nix)
# 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
fi fi
nomarchy-restart-swayosd
nomarchy-restart-terminal
nomarchy-restart-hyprctl
nomarchy-restart-btop
nomarchy-restart-opencode
nomarchy-restart-mako
# Change app-specific themes echo "$THEME_NAME" > "$THEME_STATE_FILE"
nomarchy-theme-set-gnome
nomarchy-theme-set-browser # Try to find a background for this theme
nomarchy-theme-set-vscode BG_DIR="$THEMES_DIR/$THEME_NAME/backgrounds"
nomarchy-theme-set-obsidian if [ -d "$BG_DIR" ]; then
nomarchy-theme-set-keyboard 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" nomarchy-hook theme-set "$THEME_NAME"

View File

@@ -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). # 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 FEATURE_FILE="/etc/nixos/nomarchy-features/supergfxd.nix"
if nomarchy-cmd-missing supergfxctl; then
nomarchy-pkg-add supergfxctl
# Create config before starting service to prevent hang on first boot if ! command -v supergfxctl &> /dev/null; then
sudo tee /etc/supergfxd.conf >/dev/null <<'CONF' sudo mkdir -p "/etc/nixos/nomarchy-features"
cat <<EOF | sudo tee "$FEATURE_FILE" > /dev/null
{ config, pkgs, ... }:
{ {
"mode": "Hybrid", services.supergfxd.enable = true;
"vfio_enable": true,
"vfio_save": false,
"always_reboot": false,
"no_logind": false,
"logout_timeout_s": 180,
"hotplug_type": "None"
} }
CONF EOF
echo "Created $FEATURE_FILE to enable supergfxd."
sudo systemctl enable --now 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 fi
gpu_mode=$(supergfxctl -g) gpu_mode=$(supergfxctl -g)
echo "Current GPU mode: $gpu_mode"
case "$gpu_mode" in case "$gpu_mode" in
"Integrated") "Integrated")
if gum confirm "Enable dedicated GPU and reboot?"; then if gum confirm "Switch to Hybrid mode (enables dGPU) and reboot?"; then
# Switch to hybrid mode supergfxctl -m Hybrid
sudo sed -i "s/\"mode\": \".*\"/\"mode\": \"Hybrid\"/" /etc/supergfxd.conf echo "Switching to Hybrid mode..."
# 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
nomarchy-system-reboot nomarchy-system-reboot
fi fi
;; ;;
"Hybrid") "Hybrid")
if gum confirm "Use only integrated GPU and reboot?"; then if gum confirm "Switch to Integrated mode (disables dGPU) and reboot?"; then
# Switch to integrated mode and ensure vfio is enabled (needed for sleep/wake trick) supergfxctl -m Integrated
sudo sed -i "s/\"mode\": \".*\"/\"mode\": \"Integrated\"/" /etc/supergfxd.conf echo "Switching to Integrated mode..."
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/
nomarchy-system-reboot nomarchy-system-reboot
fi 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 exit 1
;; ;;
esac esac

View File

@@ -1,11 +1,28 @@
#!/bin/bash #!/usr/bin/env bash
if pgrep -x hypridle >/dev/null; then # 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
enabled=$(jq -r '.enabled' "$STATE_FILE")
if [[ $enabled == "true" ]]; then
NEW_ENABLED="false"
pkill -x hypridle pkill -x hypridle
notify-send -u low "󱫖 Stop locking computer when idle" notify-send -u low "󱫖 Stop locking computer when idle"
else else
uwsm-app -- hypridle >/dev/null 2>&1 & NEW_ENABLED="true"
setsid hypridle >/dev/null 2>&1 &
notify-send -u low "󱫖 Now locking computer when idle" notify-send -u low "󱫖 Now locking computer when idle"
fi fi
pkill -RTMIN+9 waybar echo "{\"enabled\": $NEW_ENABLED}" > "$STATE_FILE"
echo "Idle daemon set to $NEW_ENABLED declaratively."
pkill -RTMIN+9 waybar # Signal waybar if needed

View File

@@ -1,30 +1,36 @@
#!/bin/bash #!/usr/bin/env bash
# Default temperature values # Toggles the nightlight (hyprsunset) between enabled (4000) and disabled (6500)
ON_TEMP=4000 # Declarative + Hybrid (instant IPC) for Nomarchy NixOS.
OFF_TEMP=6000
# Ensure hyprsunset is running STATE_FILE="$HOME/.config/home-manager/hyprsunset-state.json"
if ! pgrep -x hyprsunset; then mkdir -p "$(dirname "$STATE_FILE")"
setsid uwsm-app -- hyprsunset &
sleep 1 # Give it time to register if [ ! -f "$STATE_FILE" ]; then
echo '{"enabled": false, "temperature": 4000}' > "$STATE_FILE"
fi fi
# Query the current temperature enabled=$(jq -r '.enabled' "$STATE_FILE")
CURRENT_TEMP=$(hyprctl hyprsunset temperature 2>/dev/null | grep -oE '[0-9]+')
restart_nightlighted_waybar() { if [[ $enabled == "true" ]]; then
if grep -q "custom/nightlight" ~/.config/waybar/config.jsonc; then NEW_ENABLED="false"
nomarchy-restart-waybar # restart waybar in case user has waybar module for hyprsunset TEMP=6500
fi notify-send -u low " Nightlight DISABLED"
}
if [[ $CURRENT_TEMP == $OFF_TEMP ]]; then
hyprctl hyprsunset temperature $ON_TEMP
notify-send -u low " Nightlight screen temperature"
restart_nightlighted_waybar
else else
hyprctl hyprsunset temperature $OFF_TEMP NEW_ENABLED="true"
notify-send -u low " Daylight screen temperature" TEMP=4000
restart_nightlighted_waybar notify-send -u low " Nightlight ENABLED"
fi 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.

View File

@@ -1,13 +1,5 @@
#!/bin/bash #!/usr/bin/env bash
# Update AUR packages if any are installed echo "AUR is an Arch Linux concept and is not supported on NixOS."
if pacman -Qem >/dev/null; then echo "Please use 'nomarchy-pkg-add' to install packages from nixpkgs."
if nomarchy-pkg-aur-accessible; then exit 1
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

View File

@@ -1,18 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
# Ensure we have the nomarchy-keyring and it's populated echo "Pacman keyring is an Arch Linux concept and is not supported on NixOS."
if nomarchy-pkg-missing nomarchy-keyring || ! sudo pacman-key --list-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 &>/dev/null; then exit 1
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

582
flake.lock generated Normal file
View File

@@ -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
}

View File

@@ -2,7 +2,7 @@
description = "Nomarchy - A NixOS-based distribution with Omarchy flavour"; description = "Nomarchy - A NixOS-based distribution with Omarchy flavour";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nixos-hardware.url = "github:NixOS/nixos-hardware/master";
disko = { disko = {
@@ -10,8 +10,10 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
impermanence.url = "github:nix-community/impermanence";
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
@@ -20,7 +22,7 @@
walker.url = "github:abenz1267/walker"; 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 = { nixosModules = {
system = import ./modules/system; system = import ./modules/system;
home = import ./modules/home; home = import ./modules/home;
@@ -28,67 +30,86 @@
nixosConfigurations = { nixosConfigurations = {
installerIso = nixpkgs.lib.nixosSystem { installerIso = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ 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 ./hosts/live-iso.nix
./modules/system
home-manager.nixosModules.home-manager
{ {
system.stateVersion = "24.11"; system.stateVersion = "25.11";
home-manager.extraSpecialArgs = { inherit inputs; }; 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 { installerVm = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ modules = [
{ nixpkgs.hostPlatform = "x86_64-linux"; }
./hosts/live-iso.nix ./hosts/live-iso.nix
./modules/system
home-manager.nixosModules.home-manager
{ {
system.stateVersion = "24.11"; system.stateVersion = "25.11";
networking.hostName = "nomarchy-installer"; networking.hostName = "nomarchy-installer";
home-manager.extraSpecialArgs = { inherit inputs; };
# VM specific settings to start in terminal 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.vmVariant = {
virtualisation.memorySize = 2048; virtualisation.memorySize = 2048;
virtualisation.cores = 2; virtualisation.cores = 2;
virtualisation.graphics = true; virtualisation.graphics = true;
}; };
# Use a dummy hardware config # Use a dummy hardware config for VM
fileSystems."/" = { device = "/dev/disk/by-label/nixos"; }; fileSystems."/" = { device = "/dev/disk/by-label/nixos"; };
boot.loader.grub.device = "/dev/vda"; 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 = { users.users.nixos = {
isNormalUser = true; isNormalUser = true;
extraGroups = [ "wheel" "video" ]; extraGroups = [ "wheel" "video" "networkmanager" ];
initialPassword = "nixos"; 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 { vm = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ modules = [
{ nixpkgs.hostPlatform = "x86_64-linux"; }
./modules/system ./modules/system
./modules/system/hardware.nix ./modules/system/hardware.nix
home-manager.nixosModules.home-manager home-manager.nixosModules.home-manager
{ {
system.stateVersion = "24.11"; system.stateVersion = "25.11";
networking.hostName = "nomarchy"; networking.hostName = "nomarchy";
home-manager.extraSpecialArgs = { inherit inputs; }; home-manager.extraSpecialArgs = { inherit inputs; };
# VM specific settings # VM specific settings
@@ -118,7 +139,7 @@
imports = [ ./modules/home ]; imports = [ ./modules/home ];
home.username = "nomarchy"; home.username = "nomarchy";
home.homeDirectory = "/home/nomarchy"; home.homeDirectory = "/home/nomarchy";
home.stateVersion = "24.11"; home.stateVersion = "25.11";
}; };
} }
]; ];

View File

@@ -4,7 +4,14 @@
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
gum 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" = { environment.etc."install-nomarchy.sh" = {
@@ -19,4 +26,6 @@
environment.etc."disko-btrfs-luks.nix" = { environment.etc."disko-btrfs-luks.nix" = {
source = ../installer/disko-btrfs-luks.nix; source = ../installer/disko-btrfs-luks.nix;
}; };
environment.etc."nomarchy".source = inputs.self;
} }

View File

@@ -155,7 +155,7 @@ cat <<EOF > /mnt/etc/nixos/flake.nix
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 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"; nixos-hardware.url = "github:NixOS/nixos-hardware/master";
home-manager = { home-manager = {
@@ -206,7 +206,12 @@ cat <<EOF > /mnt/etc/nixos/flake.nix
} }
EOF 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/ cd /mnt/etc/nixos/
git init git init
git add . git add .
@@ -214,5 +219,5 @@ git config user.name "Nomarchy Installer"
git config user.email "installer@nomarchy" git config user.email "installer@nomarchy"
git commit -m "Initial Nomarchy generation" git commit -m "Initial Nomarchy generation"
# 8. Execution # 9. Execution
nixos-install --flake /mnt/etc/nixos#default --no-root-passwd nixos-install --flake /mnt/etc/nixos#default --no-root-passwd

View File

@@ -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"; }
];
};
};
};
}

View File

@@ -2,7 +2,6 @@
{ {
xdg.configFile = { xdg.configFile = {
"alacritty".source = ../../config/alacritty;
"btop".source = ../../config/btop; "btop".source = ../../config/btop;
"chromium".source = ../../config/chromium; "chromium".source = ../../config/chromium;
"fastfetch".source = ../../config/fastfetch; "fastfetch".source = ../../config/fastfetch;

View File

@@ -7,12 +7,23 @@ let
activeThemeName = if builtins.pathExists stateFile then activeThemeName = if builtins.pathExists stateFile then
lib.removeSuffix "\n" (builtins.readFile stateFile) lib.removeSuffix "\n" (builtins.readFile stateFile)
else "dracula"; 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 in
{ {
imports = [ imports = [
inputs.nix-colors.homeManagerModules.default inputs.nix-colors.homeManagerModules.default
inputs.walker.homeManagerModules.default inputs.walker.homeManagerModules.default
./fonts.nix ./fonts.nix
./alacritty.nix
./nightlight.nix
./idle.nix
./stylix.nix ./stylix.nix
./hyprland.nix ./hyprland.nix
./waybar.nix ./waybar.nix
@@ -25,8 +36,25 @@ in
colorScheme = palettes.${activeThemeName} or palettes.dracula; colorScheme = palettes.${activeThemeName} or palettes.dracula;
home.packages = with pkgs; [ 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 = { home.shellAliases = {
sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default"; sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default";

View File

@@ -1,9 +1,11 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
let let
stateFile = "${config.home.homeDirectory}/.config/home-manager/font-state.nix"; # Standardize state files to a common directory
activeFont = if builtins.pathExists stateFile then stateDir = "${config.home.homeDirectory}/.config/home-manager";
lib.removeSuffix "\n" (builtins.readFile stateFile) fontStateFile = "${stateDir}/font-state.nix";
activeFont = if builtins.pathExists fontStateFile then
lib.removeSuffix "\n" (builtins.readFile fontStateFile)
else "JetBrainsMono Nerd Font"; else "JetBrainsMono Nerd Font";
in in
{ {
@@ -14,4 +16,9 @@ in
description = "Monospace font for the system"; description = "Monospace font for the system";
}; };
}; };
config = {
fonts.fontconfig.enable = true;
xdg.dataFile."fonts/nomarchy.ttf".source = ../../config/nomarchy.ttf;
};
} }

View File

@@ -5,20 +5,30 @@ let
activeWallpaper = if builtins.pathExists wallpaperStateFile then activeWallpaper = if builtins.pathExists wallpaperStateFile then
lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile) lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile)
else ""; 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 in
{ {
wayland.windowManager.hyprland = { wayland.windowManager.hyprland = {
enable = true; enable = true;
settings = { settings = {
"general" = { "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.active_border" = "rgb(${config.colorScheme.palette.base0E})";
"col.inactive_border" = "rgb(${config.colorScheme.palette.base03})"; "col.inactive_border" = "rgb(${config.colorScheme.palette.base03})";
}; };
"exec-once" = [ "exec-once" = [
"swww init && swww fill ${activeWallpaper}" "swww-daemon & sleep 0.5 && swww img ${activeWallpaper} --transition-type none"
"waybar"
"nomarchy-on-boot"
"nomarchy-welcome" "nomarchy-welcome"
]; ];
"bind" = [ "bind" = [
"SUPER, Space, exec, walker"
"SUPER ALT, Space, exec, nomarchy-theme-selector" "SUPER ALT, Space, exec, nomarchy-theme-selector"
"SUPER CTRL, Space, exec, nomarchy-font-selector" "SUPER CTRL, Space, exec, nomarchy-font-selector"
"SUPER SHIFT, Space, exec, nomarchy-wallpaper-selector" "SUPER SHIFT, Space, exec, nomarchy-wallpaper-selector"

13
modules/home/idle.nix Normal file
View File

@@ -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;
};
}

View File

@@ -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;
};
}

View File

@@ -15,6 +15,12 @@ let
jq jq
swww swww
xmlstarlet xmlstarlet
wl-clipboard
grim
slurp
brightnessctl
playerctl
pamixer
# Add any others commonly used in bin/ # Add any others commonly used in bin/
]; ];

5
modules/home/swayosd.nix Normal file
View File

@@ -0,0 +1,5 @@
{ config, pkgs, ... }:
{
services.swayosd.enable = true;
}

View File

@@ -9,7 +9,13 @@ let
STATE_DIR="$HOME/.config/home-manager" STATE_DIR="$HOME/.config/home-manager"
THEME_STATE_FILE="$STATE_DIR/theme-state.nix" THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-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" mkdir -p "$STATE_DIR"
@@ -24,6 +30,7 @@ let
BG=$(ls "$BG_DIR" | head -n 1) BG=$(ls "$BG_DIR" | head -n 1)
if [ -n "$BG" ]; then if [ -n "$BG" ]; then
echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE" 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
fi fi
@@ -48,7 +55,13 @@ let
nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" '' nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" ''
STATE_DIR="$HOME/.config/home-manager" STATE_DIR="$HOME/.config/home-manager"
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
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" THEMES_DIR="/etc/nixos/themes"
fi
mkdir -p "$STATE_DIR" mkdir -p "$STATE_DIR"
@@ -58,6 +71,7 @@ let
if [ -n "$SELECTED_WP" ]; then if [ -n "$SELECTED_WP" ]; then
echo "$SELECTED_WP" > "$WALLPAPER_STATE_FILE" echo "$SELECTED_WP" > "$WALLPAPER_STATE_FILE"
swww img "$SELECTED_WP" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 &
env-update env-update
fi fi
''; '';

14
modules/home/vscode.nix Normal file
View File

@@ -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; [ ... ];
};
}

68
modules/options.nix Normal file
View File

@@ -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)
};
}

12
modules/system/audio.nix Normal file
View File

@@ -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;
};
}

View File

@@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
hardware.bluetooth.enable = true;
hardware.bluetooth.powerOnBoot = true;
services.blueman.enable = true;
}

View File

@@ -1,9 +1,13 @@
{ config, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
./plymouth.nix ./plymouth.nix
./sddm.nix ./sddm.nix
./hardware.nix ./hardware.nix
./audio.nix
./bluetooth.nix
./network.nix
./impermanence.nix
]; ];
} }

View File

@@ -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"
];
};
};
}

View File

@@ -0,0 +1,5 @@
{ config, pkgs, ... }:
{
networking.networkmanager.enable = true;
}

View File

@@ -0,0 +1,6 @@
{ config, pkgs, ... }:
{
services.supergfxd.enable = true;
# NixOS handles the configuration of supergfxd
}

View File

@@ -1,46 +1,43 @@
{ let
dracula = { themesDir = ./.;
name = "dracula";
author = "dracula"; # 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 = { palette = {
base00 = "282a36"; base00 = stripHash toml.background;
base01 = "3a3c4e"; base01 = stripHash toml.color0;
base02 = "4d4f68"; base02 = stripHash toml.color8;
base03 = "6272a4"; base03 = stripHash toml.color8;
base04 = "62d6e8"; base04 = stripHash toml.color7;
base05 = "e9e9f4"; base05 = stripHash toml.foreground;
base06 = "f1f2f8"; base06 = stripHash toml.color15;
base07 = "f8f8f2"; base07 = stripHash toml.color15;
base08 = "ff5555"; base08 = stripHash toml.color1;
base09 = "ffb86c"; base09 = stripHash toml.color3;
base0A = "f1fa8c"; base0A = stripHash toml.color3;
base0B = "50fa7b"; base0B = stripHash toml.color2;
base0C = "8be9fd"; base0C = stripHash toml.color6;
base0D = "bd93f9"; base0D = stripHash toml.color4;
base0E = "ff79c6"; base0E = stripHash toml.color5;
base0F = "bd93f9"; base0F = stripHash toml.color1;
}; };
}; };
nord = {
name = "nord"; in
author = "arcticicestudio"; builtins.listToAttrs (map (name: {
palette = { inherit name;
base00 = "2e3440"; value = readTheme name;
base01 = "3b4252"; }) directories)
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";
};
};
}