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

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