Files
Nomarchy/installer/install.sh
Bernardo Magri 5f0834f30c refactor: consolidate app configurations and utility scripts
- Move 32+ app-specific scripts from features/apps/scripts/ to features/scripts/utils/ for centralized packaging.
- Create individual Nix modules for orphaned app configurations (btop, kitty, tmux, etc.) in features/apps/ using xdg.configFile.
- Fix broken paths in core/system/makima.nix and features/apps/vscode.nix.
- Update VSCode configuration to use the modern 'profiles.default.userSettings' API, resolving deprecation warnings.
- Merge duplicate 'nomarchy-launch-walker' scripts into a single robust utility.
- Remove stale root 'config/' directory.
- Update README.md and docs/creating-themes.md to reflect the new architecture and keybindings.
- Ensure all modules are correctly imported and verified via nix flake check.
2026-04-12 22:32:44 +01:00

524 lines
15 KiB
Bash
Executable File

#!/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=""
LUKS_PASSWORD=""
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
LUKS_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 disko_file tmp_disko
disko_file="$NOMARCHY_REPO/installer/disko-golden.nix"
tmp_disko=$(mktemp --suffix=.nix)
sed "s|@TARGET_DRIVE@|${TARGET_DRIVE}|g" "$disko_file" > "$tmp_disko"
# Provide the LUKS passphrase via stdin for disk encryption
echo -n "$LUKS_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 "$@"