refactor: major architectural restructure for theme-centric organization

Theme System:
- Move all theme app configs to apps/ subdirectory (20 themes)
- Add theme-loader.nix for dynamic theme config deployment
- Simplify stylix.nix to focus on base theming only

Override System:
- Add overrides.nix for file-based config overrides
- Add behavior-configs.nix for non-visual configuration
- Split hypr/nomarchy.conf into behavior vs visual sections

Module Improvements:
- Add lib.mkDefault to all customizable settings
- Add modules/lib/ with shared utilities and state schema
- Update all home and system modules for downstream overridability

Installer:
- New minimal TTY installer (installer/install.sh)
- Golden path: BTRFS + LUKS2 (disko-golden.nix)
- New installer-iso.nix for TTY-only installation
- Keep graphical installer as installerIsoGraphical option

Cleanup:
- Remove obsolete install.sh, disko-ext4.nix, install-nomarchy.sh
- Update live-iso.nix references
- Add .claude/ to .gitignore for local IDE settings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-04-11 19:38:27 +01:00
parent 769fd88f25
commit b27fc5aee8
141 changed files with 2014 additions and 943 deletions

View File

@@ -1,36 +0,0 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "@TARGET_DRIVE@";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,95 @@
# Nomarchy Golden Path Disk Configuration
#
# BTRFS + LUKS2 encryption with subvolumes optimized for:
# - Compression (zstd)
# - SSD optimization (noatime)
# - Impermanence support (root-blank snapshot)
# - Separate subvolumes for home, nix store, logs
#
# Replace @TARGET_DRIVE@ with the target device (e.g., /dev/nvme0n1)
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "@TARGET_DRIVE@";
content = {
type = "gpt";
partitions = {
# EFI System Partition
ESP = {
priority = 1;
name = "ESP";
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
# LUKS-encrypted root partition
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
# Password will be provided interactively or via stdin
settings = {
allowDiscards = true; # Enable TRIM for SSDs
};
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Force creation
subvolumes = {
# Root filesystem
"@" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
# Persistent storage (for impermanence)
"@persist" = {
mountpoint = "/persist";
mountOptions = [ "compress=zstd" "noatime" ];
};
# User home directories
"@home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" "noatime" ];
};
# Nix store (separate for better deduplication)
"@nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
# System logs
"@log" = {
mountpoint = "/var/log";
mountOptions = [ "compress=zstd" "noatime" ];
};
};
# Create a read-only snapshot of root for impermanence rollback
postCreateHook = ''
MNTPOINT=$(mktemp -d)
mount -t btrfs /dev/mapper/crypted $MNTPOINT
btrfs subvolume snapshot -r $MNTPOINT/@ $MNTPOINT/root-blank
umount $MNTPOINT
'';
};
};
};
};
};
};
};
};
}

View File

@@ -1,316 +0,0 @@
#!/usr/bin/env bash
set -e
# Nomarchy Installer
# Professionalized with Gum
# Function to display stylized headers
header() {
clear
gum style \
--foreground 212 --border-foreground 212 --border double \
--align center --width 50 --margin "1 2" --padding "2 4" \
"NOMARCHY" "The Omarchy-flavored NixOS"
}
# Function to show a section header
section() {
echo
gum style --foreground 10 --bold "» $1"
}
header
section "Environment Check"
gum spin --spinner dot --title "Verifying internet connection..." -- sleep 1
while ! ping -c 1 8.8.8.8 &> /dev/null; do
gum style --foreground 9 "Error: No internet connection detected."
CHOICE=$(gum choose "Open Network Manager (nmtui)" "Retry Connection" "Exit Installer")
if [ "$CHOICE" = "Open Network Manager (nmtui)" ]; then
nmtui
elif [ "$CHOICE" = "Exit Installer" ]; then
echo "Exiting installer."
exit 1
fi
done
echo "✓ Internet connection verified."
# 0. Environment Setup
NOMARCHY_REPO=""
if [ -d "/etc/nomarchy" ]; then
NOMARCHY_REPO="/etc/nomarchy"
elif [ -d "$(dirname "$0")/.." ] && [ -f "$(dirname "$0")/../flake.nix" ]; then
NOMARCHY_REPO="$(realpath "$(dirname "$0")/..")"
fi
if [ -z "$NOMARCHY_REPO" ]; then
gum style --foreground 9 "Error: Nomarchy repository not found."
exit 1
fi
# 1. Hardware Detection
section "Hardware Detection"
PRODUCT_NAME=$(cat /sys/class/dmi/id/product_name 2>/dev/null || echo "Unknown")
CPU_VENDOR=$(lscpu | grep "Vendor ID" | awk '{print $3}')
echo "Detected Device: $PRODUCT_NAME"
echo "Detected CPU: $CPU_VENDOR"
HARDWARE_MODULES=""
NOMARCHY_HW_OPTS=""
if [[ "$CPU_VENDOR" == "AuthenticAMD" ]]; then
HARDWARE_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-amd"
elif [[ "$CPU_VENDOR" == "GenuineIntel" ]]; then
HARDWARE_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-intel"
fi
echo "Select your hardware vendor for optimized profiles:"
VENDOR=$(gum choose --header "Hardware Vendor" \
"acer" "apple" "asus" "dell" "framework" "google" "hp" "lenovo" "microsoft" "msi" "purism" "samsung" "starlabs" "system76" "toshiba" "None/Generic")
if [ "$VENDOR" != "None/Generic" ]; then
case $VENDOR in
dell)
MODEL=$(gum choose "xps-13-9300" "xps-13-9310" "xps-13-9343" "xps-13-9360" "xps-13-9370" "xps-13-9380" "xps-15-7590" "xps-15-9500" "xps-15-9510" "xps-15-9550" "precision-5510" "precision-5530")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.dell-$MODEL"
[[ "$MODEL" == *"xps"* ]] && NOMARCHY_HW_OPTS="nomarchy.hardware.isXPS = true;"
;;
lenovo)
MODEL=$(gum choose "thinkpad-x1-carbon-gen7" "thinkpad-x1-carbon-gen8" "thinkpad-x1-carbon-gen9" "thinkpad-x1-carbon-gen10" "thinkpad-x1-extreme" "thinkpad-t480" "thinkpad-t490" "thinkpad-t14-amd" "thinkpad-t14-intel" "thinkpad-p1-gen3")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.lenovo-$MODEL"
;;
framework)
MODEL=$(gum choose "13-7040-amd" "13-intel-12th-gen" "13-intel-13th-gen" "16-7040-amd")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.framework-$MODEL"
NOMARCHY_HW_OPTS="nomarchy.hardware.isFramework = true;"
;;
microsoft)
MODEL=$(gum choose "surface-pro-7" "surface-pro-8" "surface-pro-9" "surface-laptop-3" "surface-laptop-4")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.microsoft-$MODEL"
;;
apple)
MODEL=$(gum choose "macbook-pro-12-1" "macbook-air-6-2" "t2")
if [ "$MODEL" == "t2" ]; then
NOMARCHY_HW_OPTS="nomarchy.hardware.isT2Mac = true;"
else
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.apple-$MODEL"
fi
;;
*)
INPUT_MOD=$(gum input --placeholder "Enter nixos-hardware module path")
HARDWARE_MODULES="$HARDWARE_MODULES\n $INPUT_MOD"
;;
esac
fi
# 2. Storage Setup
section "Storage & Partitioning"
DRIVES=$(lsblk -d -n -p -o NAME,SIZE | grep -v loop)
TARGET_DRIVE=$(echo "$DRIVES" | gum choose --header "Select target drive" | awk '{print $1}')
if [ -z "$TARGET_DRIVE" ]; then exit 1; fi
LAYOUT=$(gum choose "Standard Ext4" "Encrypted BTRFS (LUKS2)")
IMPERMANENCE="No"
if [ "$LAYOUT" = "Standard Ext4" ]; then
DISKO_FILE="installer/disko-ext4.nix"
else
DISKO_FILE="installer/disko-btrfs-luks.nix"
echo "Enable Impermanence? (Erase root on every boot)"
IMPERMANENCE=$(gum choose "No" "Yes")
fi
# 3. User & Localization
section "User & Localization"
USERNAME=$(gum input --placeholder "Enter target username (no spaces)")
if [ -z "$USERNAME" ]; then exit 1; fi
USER_PASSWORD=$(gum input --password --placeholder "Enter password for $USERNAME")
USER_PASSWORD_CONFIRM=$(gum input --password --placeholder "Confirm password")
if [ "$USER_PASSWORD" != "$USER_PASSWORD_CONFIRM" ]; then
gum style --foreground 9 "Error: Passwords do not match."
exit 1
fi
echo "Select Timezone:"
TIMEZONES=$(timedatectl list-timezones || echo "UTC")
TIMEZONE=$(echo "$TIMEZONES" | gum filter --placeholder "Type to search...")
[ -z "$TIMEZONE" ] && TIMEZONE="UTC"
echo "Select Keyboard Layout:"
KEYBOARD_LAYOUT=$(gum choose "us" "uk" "de" "fr" "es" "it" "br-abnt2" "latam" "Other...")
if [ "$KEYBOARD_LAYOUT" = "Other..." ]; then
KEYBOARD_LAYOUT=$(gum input --placeholder "Enter layout (e.g. jp)")
fi
# 4. Software Profiles
section "Software Profiles"
echo "Select additional profiles (Space to toggle):"
PROFILES=$(gum choose --no-limit "Development (VSCode, Docker, DBs)" "Gaming (Steam, Lutris)" "Media Production (OBS, Kdenlive)")
PROFILE_HOME_PKGS=""
PROFILE_SYSTEM_CONFIG=""
[[ $PROFILES == *"Development"* ]] && PROFILE_HOME_PKGS="$PROFILE_HOME_PKGS\n vscode\n docker-compose\n dbeaver-bin" && PROFILE_SYSTEM_CONFIG="$PROFILE_SYSTEM_CONFIG\n virtualisation.docker.enable = true;"
[[ $PROFILES == *"Gaming"* ]] && PROFILE_HOME_PKGS="$PROFILE_HOME_PKGS\n lutris\n protonup-qt\n mangohud" && PROFILE_SYSTEM_CONFIG="$PROFILE_SYSTEM_CONFIG\n programs.steam.enable = true;"
[[ $PROFILES == *"Media Production"* ]] && PROFILE_HOME_PKGS="$PROFILE_HOME_PKGS\n obs-studio\n kdenlive\n gimp\n audacity"
[[ "$IMPERMANENCE" == "Yes" ]] && PROFILE_SYSTEM_CONFIG="$PROFILE_SYSTEM_CONFIG\n nomarchy.system.impermanence.enable = true;"
# 5. Review
section "Review Configuration"
echo "Target Drive: $TARGET_DRIVE"
echo "Layout: $LAYOUT (Impermanence: $IMPERMANENCE)"
echo "User: $USERNAME"
echo "Timezone: $TIMEZONE"
echo "Profiles: $PROFILES"
if ! gum confirm "Ready to begin installation?"; then
echo "Aborted."
exit 0
fi
# 6. Execution
section "Executing Installation"
# 6.1. Partitioning
gum spin --spinner pulse --title "Partitioning $TARGET_DRIVE..." -- bash -c "
DISKO_NIX=\"$NOMARCHY_REPO/$DISKO_FILE\"
TMP_DISKO=\$(mktemp --suffix=.nix)
sed \"s|@TARGET_DRIVE@|$TARGET_DRIVE|g\" \"\$DISKO_NIX\" > \"\$TMP_DISKO\"
sudo env PATH=\"\$PATH\" disko --mode disko \"\$TMP_DISKO\"
"
# 6.2. Scaffold Config
gum spin --spinner pulse --title "Generating NixOS configuration..." -- bash -c "
mkdir -p /mnt/etc/nixos/
cat <<EOF > /mnt/etc/nixos/login-preference.nix
{
services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = \"$USERNAME\";
}
EOF
cat <<EOF > /mnt/etc/nixos/localization.nix
{
time.timeZone = \"$TIMEZONE\";
services.xserver.xkb.layout = \"$KEYBOARD_LAYOUT\";
console.keyMap = \"$KEYBOARD_LAYOUT\";
}
EOF
cat <<EOF > /mnt/etc/nixos/hardware-selection.nix
{ inputs, ... }:
{
imports = [
\$(echo -e \"$HARDWARE_MODULES\")
];
$NOMARCHY_HW_OPTS
}
EOF
nixos-generate-config --root /mnt
cat <<EOF > /mnt/etc/nixos/system.nix
{ pkgs, ... }:
{
\$(echo -e \"$PROFILE_SYSTEM_CONFIG\")
users.users.\"$USERNAME\" = {
isNormalUser = true;
initialPassword = \"$USER_PASSWORD\";
extraGroups = [ \"networkmanager\" \"wheel\" \"video\" \"audio\" ];
};
system.stateVersion = \"25.11\";
environment.systemPackages = with pkgs; [];
}
EOF
cat <<EOF > /mnt/etc/nixos/home.nix
{ pkgs, ... }:
{
home.packages = with pkgs; [
\$(echo -e \"$PROFILE_HOME_PKGS\")
];
}
EOF
cat <<EOF > /mnt/etc/nixos/flake.nix
{
description = \"My Nomarchy - Downstream Configuration\";
inputs = {
nixpkgs.url = \"github:nixos/nixpkgs/nixos-25.11\";
nomarchy.url = \"git+https://git.bemagri.xyz/bernardo/Nomarchy.git\";
nixos-hardware.url = \"github:NixOS/nixos-hardware/master\";
home-manager = {
url = \"github:nix-community/home-manager/release-25.11\";
inputs.nixpkgs.follows = \"nixpkgs\";
};
};
outputs = { self, nixpkgs, nomarchy, home-manager, ... }@inputs: {
nixosConfigurations.default = nixpkgs.lib.nixosSystem {
specialArgs = { inputs = nomarchy.inputs // inputs; };
modules = [
{ nixpkgs.hostPlatform = \"x86_64-linux\"; }
./hardware-configuration.nix
./hardware-selection.nix
./login-preference.nix
./localization.nix
nomarchy.nixosModules.system
./system.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.$USERNAME = {
imports = [ nomarchy.nixosModules.home ./home.nix ];
home.username = \"$USERNAME\";
home.homeDirectory = \"/home/$USERNAME\";
home.stateVersion = \"25.11\";
};
}
];
};
};
}
EOF
"
# 6.3. Git Init
cd /mnt/etc/nixos/
git init
git add .
git config user.name "Nomarchy Installer"
git config user.email "installer@nomarchy"
git commit -m "Initial Nomarchy generation"
# 6.4. Impermanence logic
if [[ "$IMPERMANENCE" == "Yes" ]]; then
echo "Redirecting to persistent storage..."
mkdir -p /mnt/persist/etc
mv /mnt/etc/nixos /mnt/persist/etc/
mkdir -p /mnt/etc
ln -s /persist/etc/nixos /mnt/etc/nixos
fi
# 6.5. Install
section "Installing System"
echo "Starting nixos-install. This will take some time..."
sudo nixos-install --flake /mnt/etc/nixos#default --no-root-passwd
# 7. Finished
header
gum style --foreground 10 --bold "INSTALLATION COMPLETE!"
echo "Nomarchy has been successfully installed on $TARGET_DRIVE."
echo
echo "What's next?"
echo "1. Remove the installation media."
echo "2. Reboot your computer."
echo "3. Log in and run 'nomarchy-update' to finish setup."
echo
if gum confirm "Reboot now?"; then
reboot
fi

523
installer/install.sh Executable file
View File

@@ -0,0 +1,523 @@
#!/usr/bin/env bash
set -e
# Nomarchy TTY Installer
# Golden path: BTRFS + LUKS2 encryption
#
# This is a minimal, single-path installer designed for TTY-only environments.
# For a customized installation, manually set up your disk and use the generated
# flake configuration as a starting point.
# Colors and styling
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
BOLD='\033[1m'
# Installer state
NOMARCHY_REPO=""
TARGET_DRIVE=""
USERNAME=""
USER_PASSWORD=""
TIMEZONE="UTC"
HARDWARE_MODULES=""
NOMARCHY_HW_OPTS=""
ENABLE_IMPERMANENCE="false"
# ============================================================================
# UTILITY FUNCTIONS
# ============================================================================
header() {
clear
gum style \
--foreground 212 --border-foreground 212 --border double \
--align center --width 60 --margin "1 2" --padding "2 4" \
"NOMARCHY INSTALLER" "NixOS with Omarchy flavor"
echo ""
}
section() {
echo ""
gum style --foreground 14 --bold "━━━ $1 ━━━"
echo ""
}
success() {
gum style --foreground 10 "$1"
}
error() {
gum style --foreground 9 "$1"
}
info() {
gum style --foreground 12 "$1"
}
# ============================================================================
# STEP 1: ENVIRONMENT CHECK
# ============================================================================
check_environment() {
section "Environment Check"
# Check for root
if [[ $EUID -ne 0 ]]; then
error "This installer must be run as root (use sudo)"
exit 1
fi
success "Running as root"
# Find Nomarchy repo
if [[ -d "/etc/nomarchy" ]]; then
NOMARCHY_REPO="/etc/nomarchy"
elif [[ -d "$(dirname "$0")/.." ]] && [[ -f "$(dirname "$0")/../flake.nix" ]]; then
NOMARCHY_REPO="$(realpath "$(dirname "$0")/..")"
fi
if [[ -z "$NOMARCHY_REPO" ]]; then
error "Nomarchy repository not found"
exit 1
fi
success "Found Nomarchy at $NOMARCHY_REPO"
# Check internet
gum spin --spinner dot --title "Checking internet connection..." -- sleep 1
while ! ping -c 1 -W 2 1.1.1.1 &>/dev/null; do
error "No internet connection"
local choice
choice=$(gum choose "Open Network Manager (nmtui)" "Retry" "Exit")
case "$choice" in
*nmtui*) nmtui ;;
*Exit*) exit 1 ;;
esac
done
success "Internet connection verified"
}
# ============================================================================
# STEP 2: DISK SELECTION
# ============================================================================
select_disk() {
section "Disk Selection"
info "Available drives:"
echo ""
lsblk -d -n -p -o NAME,SIZE,MODEL | grep -v loop
echo ""
local drives
drives=$(lsblk -d -n -p -o NAME,SIZE | grep -v loop)
TARGET_DRIVE=$(echo "$drives" | gum choose --header "Select target drive" | awk '{print $1}')
if [[ -z "$TARGET_DRIVE" ]]; then
error "No drive selected"
exit 1
fi
echo ""
gum style --foreground 9 --bold "⚠ WARNING: All data on $TARGET_DRIVE will be DESTROYED!"
echo ""
if ! gum confirm "Are you sure you want to use $TARGET_DRIVE?"; then
error "Aborted"
exit 1
fi
success "Selected: $TARGET_DRIVE"
}
# ============================================================================
# STEP 3: LUKS PASSPHRASE
# ============================================================================
get_luks_passphrase() {
section "Disk Encryption"
info "Your disk will be encrypted with LUKS2."
info "Enter a strong passphrase (you'll need this at every boot)."
echo ""
local pass1 pass2
while true; do
pass1=$(gum input --password --placeholder "Enter LUKS passphrase")
[[ -z "$pass1" ]] && continue
pass2=$(gum input --password --placeholder "Confirm passphrase")
if [[ "$pass1" == "$pass2" ]]; then
USER_PASSWORD="$pass1"
break
else
error "Passphrases do not match. Try again."
fi
done
success "Encryption passphrase set"
}
# ============================================================================
# STEP 4: USER CONFIGURATION
# ============================================================================
configure_user() {
section "User Configuration"
USERNAME=$(gum input --placeholder "Enter username (lowercase, no spaces)")
if [[ -z "$USERNAME" ]] || [[ ! "$USERNAME" =~ ^[a-z][a-z0-9_-]*$ ]]; then
error "Invalid username"
exit 1
fi
success "Username: $USERNAME"
# User password (can be same as LUKS or different)
info "Set a password for your user account"
local pass1 pass2
while true; do
pass1=$(gum input --password --placeholder "Enter user password")
[[ -z "$pass1" ]] && continue
pass2=$(gum input --password --placeholder "Confirm user password")
if [[ "$pass1" == "$pass2" ]]; then
USER_PASSWORD="$pass1"
break
else
error "Passwords do not match. Try again."
fi
done
success "User password set"
}
# ============================================================================
# STEP 5: TIMEZONE
# ============================================================================
select_timezone() {
section "Timezone"
local timezones
timezones=$(timedatectl list-timezones 2>/dev/null || echo "UTC")
TIMEZONE=$(echo "$timezones" | gum filter --placeholder "Search timezone...")
[[ -z "$TIMEZONE" ]] && TIMEZONE="UTC"
success "Timezone: $TIMEZONE"
}
# ============================================================================
# STEP 6: HARDWARE VENDOR
# ============================================================================
select_hardware() {
section "Hardware Configuration"
local product_name cpu_vendor
product_name=$(cat /sys/class/dmi/id/product_name 2>/dev/null || echo "Unknown")
cpu_vendor=$(lscpu 2>/dev/null | grep "Vendor ID" | awk '{print $3}' || echo "Unknown")
info "Detected: $product_name"
info "CPU: $cpu_vendor"
echo ""
# Set CPU-specific module
if [[ "$cpu_vendor" == "AuthenticAMD" ]]; then
HARDWARE_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-amd"
elif [[ "$cpu_vendor" == "GenuineIntel" ]]; then
HARDWARE_MODULES="inputs.nixos-hardware.nixosModules.common-cpu-intel"
fi
local vendor
vendor=$(gum choose --header "Select hardware vendor" \
"Generic (Auto-detect)" \
"Framework" \
"Dell" \
"Lenovo" \
"Apple (T2 Mac)" \
"Microsoft Surface" \
"Other...")
case "$vendor" in
*Framework*)
local model
model=$(gum choose "16-7040-amd" "13-7040-amd" "13-intel-13th-gen" "13-intel-12th-gen")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.framework-$model"
NOMARCHY_HW_OPTS="nomarchy.hardware.isFramework = true;"
;;
*Dell*)
local model
model=$(gum choose "xps-15-9500" "xps-15-9510" "xps-13-9310" "xps-13-9380" "precision-5530")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.dell-$model"
[[ "$model" == *"xps"* ]] && NOMARCHY_HW_OPTS="nomarchy.hardware.isXPS = true;"
;;
*Lenovo*)
local model
model=$(gum choose "thinkpad-x1-carbon-gen10" "thinkpad-t14-amd" "thinkpad-t480" "thinkpad-x1-extreme")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.lenovo-$model"
;;
*Apple*)
NOMARCHY_HW_OPTS="nomarchy.hardware.isT2Mac = true;"
;;
*Surface*)
local model
model=$(gum choose "surface-pro-9" "surface-pro-8" "surface-laptop-4")
HARDWARE_MODULES="$HARDWARE_MODULES\n inputs.nixos-hardware.nixosModules.microsoft-$model"
;;
*Other*)
info "Enter nixos-hardware module path (or leave empty):"
local custom_mod
custom_mod=$(gum input --placeholder "e.g., inputs.nixos-hardware.nixosModules.asus-zephyrus-ga401")
[[ -n "$custom_mod" ]] && HARDWARE_MODULES="$HARDWARE_MODULES\n $custom_mod"
;;
esac
success "Hardware configuration set"
}
# ============================================================================
# STEP 7: IMPERMANENCE (OPTIONAL)
# ============================================================================
configure_impermanence() {
section "Impermanence (Optional)"
info "Impermanence erases your root filesystem on every boot."
info "Only explicitly persisted files survive reboots."
info "This provides a clean, reproducible system."
echo ""
if gum confirm "Enable Impermanence?"; then
ENABLE_IMPERMANENCE="true"
success "Impermanence enabled"
else
info "Impermanence disabled (traditional persistent root)"
fi
}
# ============================================================================
# STEP 8: REVIEW & CONFIRM
# ============================================================================
review_configuration() {
section "Review Configuration"
echo " Drive: $TARGET_DRIVE (BTRFS + LUKS2)"
echo " Username: $USERNAME"
echo " Timezone: $TIMEZONE"
echo " Impermanence: $ENABLE_IMPERMANENCE"
echo ""
gum style --foreground 9 "This will DESTROY all data on $TARGET_DRIVE"
echo ""
if ! gum confirm "Proceed with installation?"; then
error "Aborted"
exit 1
fi
}
# ============================================================================
# STEP 9: EXECUTION
# ============================================================================
execute_installation() {
section "Installing Nomarchy"
# 9.1 Partition with disko
info "Partitioning disk..."
local escaped_drive disko_file tmp_disko
escaped_drive=$(printf '%s\n' "$TARGET_DRIVE" | sed 's/[[\.*^$()+?{|]/\\&/g')
disko_file="$NOMARCHY_REPO/installer/disko-golden.nix"
tmp_disko=$(mktemp --suffix=.nix)
sed "s|@TARGET_DRIVE@|$escaped_drive|g" "$disko_file" > "$tmp_disko"
# For LUKS, we need to provide the passphrase
echo -n "$USER_PASSWORD" | disko --mode disko "$tmp_disko"
success "Disk partitioned"
# 9.2 Generate hardware config
info "Generating hardware configuration..."
mkdir -p /mnt/etc/nixos
nixos-generate-config --root /mnt
success "Hardware configuration generated"
# 9.3 Generate flake configuration
info "Creating system configuration..."
generate_flake_config
success "Configuration generated"
# 9.4 Initialize git repo
info "Initializing git repository..."
(
cd /mnt/etc/nixos
git init -q
git add .
git config user.name "Nomarchy Installer"
git config user.email "installer@nomarchy"
git commit -qm "Initial Nomarchy configuration"
)
success "Git repository initialized"
# 9.5 Handle impermanence
if [[ "$ENABLE_IMPERMANENCE" == "true" ]]; then
info "Setting up impermanence..."
mkdir -p /mnt/persist/etc
mv /mnt/etc/nixos /mnt/persist/etc/
mkdir -p /mnt/etc
ln -s /persist/etc/nixos /mnt/etc/nixos
success "Impermanence configured"
fi
# 9.6 Install
info "Running nixos-install (this will take a while)..."
nixos-install --flake /mnt/etc/nixos#default --no-root-passwd
success "Installation complete!"
}
# ============================================================================
# GENERATE FLAKE CONFIGURATION
# ============================================================================
generate_flake_config() {
local impermanence_opt=""
[[ "$ENABLE_IMPERMANENCE" == "true" ]] && impermanence_opt="nomarchy.system.impermanence.enable = true;"
# flake.nix
cat > /mnt/etc/nixos/flake.nix << 'FLAKE_EOF'
{
description = "My Nomarchy Configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
nomarchy.url = "github:bemagri/nomarchy";
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
home-manager = {
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, nomarchy, home-manager, nixos-hardware, ... }@inputs: {
nixosConfigurations.default = nixpkgs.lib.nixosSystem {
specialArgs = { inputs = nomarchy.inputs // inputs; };
modules = [
{ nixpkgs.hostPlatform = "x86_64-linux"; }
./hardware-configuration.nix
./hardware-selection.nix
nomarchy.nixosModules.system
./system.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.@USERNAME@ = {
imports = [ nomarchy.nixosModules.home ./home.nix ];
home.username = "@USERNAME@";
home.homeDirectory = "/home/@USERNAME@";
home.stateVersion = "25.11";
};
}
];
};
};
}
FLAKE_EOF
sed -i "s/@USERNAME@/$USERNAME/g" /mnt/etc/nixos/flake.nix
# hardware-selection.nix
cat > /mnt/etc/nixos/hardware-selection.nix << EOF
{ inputs, ... }:
{
imports = [
$(echo -e "$HARDWARE_MODULES")
];
$NOMARCHY_HW_OPTS
}
EOF
# system.nix
cat > /mnt/etc/nixos/system.nix << EOF
{ pkgs, ... }:
{
time.timeZone = "$TIMEZONE";
$impermanence_opt
services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = "$USERNAME";
users.users."$USERNAME" = {
isNormalUser = true;
initialPassword = "$USER_PASSWORD";
extraGroups = [ "networkmanager" "wheel" "video" "audio" "render" ];
};
system.stateVersion = "25.11";
}
EOF
# home.nix (empty for user customization)
cat > /mnt/etc/nixos/home.nix << 'EOF'
{ pkgs, ... }:
{
# Add your personal packages here
home.packages = with pkgs; [
# example: firefox thunderbird libreoffice
];
# Add your personal home-manager configuration here
}
EOF
}
# ============================================================================
# FINISH
# ============================================================================
finish() {
header
gum style --foreground 10 --bold --align center "INSTALLATION COMPLETE!"
echo ""
echo "Nomarchy has been successfully installed."
echo ""
echo "Next steps:"
echo " 1. Remove the installation media"
echo " 2. Reboot your computer"
echo " 3. Log in with username: $USERNAME"
echo " 4. Your configuration is at /etc/nixos/"
echo ""
if gum confirm "Reboot now?"; then
reboot
fi
}
# ============================================================================
# MAIN
# ============================================================================
main() {
header
check_environment
select_disk
get_luks_passphrase
configure_user
select_timezone
select_hardware
configure_impermanence
review_configuration
execute_installation
finish
}
main "$@"