Add fresh install script for ISO installer
- Add installer/fresh-install.sh for installing from live ISO - Handles disk partitioning, LUKS encryption, filesystem setup - Generates minimal NixOS config for first boot - Enable flakes in ISO environment - Pass installer script content to ISO build via specialArgs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
452
installer/fresh-install.sh
Executable file
452
installer/fresh-install.sh
Executable file
@@ -0,0 +1,452 @@
|
||||
#!/usr/bin/env bash
|
||||
# Nomarchy Fresh Installation Script
|
||||
# For use from the live ISO to install on a new disk
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Installation target
|
||||
TARGET_DISK=""
|
||||
USE_LUKS=true
|
||||
LUKS_PARTITION=""
|
||||
ROOT_PARTITION=""
|
||||
EFI_PARTITION=""
|
||||
|
||||
print_banner() {
|
||||
echo -e "${CYAN}"
|
||||
cat << 'EOF'
|
||||
_ __ __
|
||||
/ | / /___ ____ ___ ____ _____/ /___ __
|
||||
/ |/ / __ \/ __ `__ \/ __ `/ __/ / __/ / /
|
||||
/ /| / /_/ / / / / / / /_/ / / / / /__ / /
|
||||
/_/ |_/\____/_/ /_/ /_/\__,_/_/ /_/\___//_/
|
||||
|
||||
Fresh Installation
|
||||
EOF
|
||||
echo -e "${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo -e "${RED}Error: This installer must be run as root.${NC}"
|
||||
echo "Run: sudo nomarchy-fresh-install"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_uefi() {
|
||||
if [ ! -d /sys/firmware/efi ]; then
|
||||
echo -e "${YELLOW}Warning: System is not booted in UEFI mode.${NC}"
|
||||
echo "Nomarchy requires UEFI. Please reboot in UEFI mode."
|
||||
read -rp "Continue anyway (legacy BIOS)? [y/N]: " cont
|
||||
if [[ ! "$cont" =~ ^[Yy] ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}UEFI mode detected.${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
list_disks() {
|
||||
echo -e "${BOLD}Available disks:${NC}"
|
||||
echo ""
|
||||
lsblk -d -o NAME,SIZE,MODEL,TYPE | grep -E "disk|NAME"
|
||||
echo ""
|
||||
}
|
||||
|
||||
select_disk() {
|
||||
list_disks
|
||||
|
||||
echo -e "${YELLOW}WARNING: The selected disk will be completely erased!${NC}"
|
||||
echo ""
|
||||
read -rp "Enter disk to install to (e.g., sda, vda, nvme0n1): " disk_input
|
||||
|
||||
if [ -z "$disk_input" ]; then
|
||||
echo -e "${RED}No disk selected. Aborting.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Handle nvme vs sata naming
|
||||
if [[ "$disk_input" == nvme* ]]; then
|
||||
TARGET_DISK="/dev/${disk_input}"
|
||||
EFI_PARTITION="${TARGET_DISK}p1"
|
||||
ROOT_PARTITION="${TARGET_DISK}p2"
|
||||
else
|
||||
TARGET_DISK="/dev/${disk_input}"
|
||||
EFI_PARTITION="${TARGET_DISK}1"
|
||||
ROOT_PARTITION="${TARGET_DISK}2"
|
||||
fi
|
||||
|
||||
if [ ! -b "$TARGET_DISK" ]; then
|
||||
echo -e "${RED}Error: ${TARGET_DISK} is not a valid block device.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${RED}${BOLD}WARNING: ALL DATA ON ${TARGET_DISK} WILL BE DESTROYED!${NC}"
|
||||
echo ""
|
||||
read -rp "Type 'yes' to confirm: " confirm
|
||||
|
||||
if [ "$confirm" != "yes" ]; then
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_encryption() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Disk Encryption${NC}"
|
||||
echo "LUKS encryption protects your data if the device is lost or stolen."
|
||||
read -rp "Enable LUKS encryption? [Y/n]: " luks_choice
|
||||
luks_choice="${luks_choice:-y}"
|
||||
|
||||
if [[ "$luks_choice" =~ ^[Yy] ]]; then
|
||||
USE_LUKS=true
|
||||
echo -e "${GREEN}LUKS encryption enabled.${NC}"
|
||||
else
|
||||
USE_LUKS=false
|
||||
echo -e "${YELLOW}Installing without encryption.${NC}"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
partition_disk() {
|
||||
echo -e "${BLUE}Partitioning ${TARGET_DISK}...${NC}"
|
||||
|
||||
# Wipe existing partition table
|
||||
wipefs -a "$TARGET_DISK"
|
||||
|
||||
# Create GPT partition table with EFI and root partitions
|
||||
parted -s "$TARGET_DISK" mklabel gpt
|
||||
parted -s "$TARGET_DISK" mkpart ESP fat32 1MiB 512MiB
|
||||
parted -s "$TARGET_DISK" set 1 esp on
|
||||
parted -s "$TARGET_DISK" mkpart primary 512MiB 100%
|
||||
|
||||
# Wait for partitions to appear
|
||||
sleep 2
|
||||
partprobe "$TARGET_DISK"
|
||||
sleep 1
|
||||
|
||||
echo -e "${GREEN}Partitioning complete.${NC}"
|
||||
}
|
||||
|
||||
setup_luks() {
|
||||
if [ "$USE_LUKS" = true ]; then
|
||||
echo ""
|
||||
echo -e "${BLUE}Setting up LUKS encryption...${NC}"
|
||||
echo -e "${YELLOW}You will be prompted to enter a passphrase.${NC}"
|
||||
echo ""
|
||||
|
||||
cryptsetup luksFormat --type luks2 "$ROOT_PARTITION"
|
||||
cryptsetup open "$ROOT_PARTITION" cryptroot
|
||||
|
||||
LUKS_PARTITION="$ROOT_PARTITION"
|
||||
ROOT_PARTITION="/dev/mapper/cryptroot"
|
||||
|
||||
echo -e "${GREEN}LUKS encryption configured.${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
format_filesystems() {
|
||||
echo ""
|
||||
echo -e "${BLUE}Formatting filesystems...${NC}"
|
||||
|
||||
# Format EFI partition
|
||||
mkfs.fat -F32 "$EFI_PARTITION"
|
||||
|
||||
# Format root partition with ext4
|
||||
mkfs.ext4 -L nixos "$ROOT_PARTITION"
|
||||
|
||||
echo -e "${GREEN}Filesystems formatted.${NC}"
|
||||
}
|
||||
|
||||
mount_filesystems() {
|
||||
echo ""
|
||||
echo -e "${BLUE}Mounting filesystems...${NC}"
|
||||
|
||||
mount "$ROOT_PARTITION" /mnt
|
||||
mkdir -p /mnt/boot
|
||||
mount "$EFI_PARTITION" /mnt/boot
|
||||
|
||||
echo -e "${GREEN}Filesystems mounted.${NC}"
|
||||
}
|
||||
|
||||
generate_hardware_config() {
|
||||
echo ""
|
||||
echo -e "${BLUE}Generating hardware configuration...${NC}"
|
||||
|
||||
nixos-generate-config --root /mnt
|
||||
|
||||
echo -e "${GREEN}Hardware configuration generated.${NC}"
|
||||
}
|
||||
|
||||
# User configuration prompts (similar to install.sh)
|
||||
prompt_username() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Username${NC}"
|
||||
read -rp "Enter username: " username
|
||||
username="${username:-user}"
|
||||
}
|
||||
|
||||
prompt_hostname() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Hostname${NC}"
|
||||
read -rp "Enter hostname: " hostname_input
|
||||
hostname_input="${hostname_input:-nomarchy}"
|
||||
}
|
||||
|
||||
prompt_timezone() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Timezone${NC}"
|
||||
echo "Examples: America/New_York, Europe/London, Asia/Tokyo"
|
||||
read -rp "Enter timezone [UTC]: " timezone
|
||||
timezone="${timezone:-UTC}"
|
||||
}
|
||||
|
||||
prompt_locale() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Locale${NC}"
|
||||
read -rp "Enter locale [en_US.UTF-8]: " locale
|
||||
locale="${locale:-en_US.UTF-8}"
|
||||
}
|
||||
|
||||
prompt_keyboard() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Keyboard Layout${NC}"
|
||||
read -rp "Enter keyboard layout [us]: " keyboard
|
||||
keyboard="${keyboard:-us}"
|
||||
}
|
||||
|
||||
prompt_bootloader() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Bootloader${NC}"
|
||||
echo "1) systemd-boot - Simple, reliable"
|
||||
echo "2) Limine - Modern, themed to match Nomarchy"
|
||||
read -rp "Choose bootloader [1/2]: " bootloader_choice
|
||||
bootloader_choice="${bootloader_choice:-1}"
|
||||
|
||||
if [[ "$bootloader_choice" == "2" ]]; then
|
||||
bootloader="limine"
|
||||
else
|
||||
bootloader="systemd-boot"
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_features() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Optional Features${NC}"
|
||||
|
||||
read -rp "Enable Plymouth boot splash? [y/N]: " plymouth
|
||||
[[ "$plymouth" =~ ^[Yy] ]] && enable_plymouth="true" || enable_plymouth="false"
|
||||
|
||||
read -rp "Enable Syncthing? [Y/n]: " syncthing
|
||||
syncthing="${syncthing:-y}"
|
||||
[[ "$syncthing" =~ ^[Yy] ]] && enable_syncthing="true" || enable_syncthing="false"
|
||||
|
||||
read -rp "Enable printing support? [Y/n]: " printing
|
||||
printing="${printing:-y}"
|
||||
[[ "$printing" =~ ^[Yy] ]] && enable_printing="true" || enable_printing="false"
|
||||
}
|
||||
|
||||
generate_config() {
|
||||
echo ""
|
||||
echo -e "${BLUE}Generating Nomarchy configuration...${NC}"
|
||||
|
||||
local config_dir="/mnt/etc/nomarchy"
|
||||
mkdir -p "$config_dir"
|
||||
|
||||
# Keyboard layouts as Nix list
|
||||
local kb_layouts_nix
|
||||
kb_layouts_nix=$(echo "$keyboard" | sed 's/,/" "/g' | sed 's/^/"/' | sed 's/$/"/')
|
||||
|
||||
cat > "$config_dir/config.nix" << EOF
|
||||
# Nomarchy Configuration
|
||||
# Generated during installation on $(date)
|
||||
{
|
||||
username = "${username}";
|
||||
hostname = "${hostname_input}";
|
||||
timezone = "${timezone}";
|
||||
locale = "${locale}";
|
||||
keyboardLayouts = [${kb_layouts_nix}];
|
||||
keyboardVariants = [""];
|
||||
|
||||
location = {
|
||||
lat = 0;
|
||||
lon = 0;
|
||||
};
|
||||
|
||||
enableSyncthing = ${enable_syncthing};
|
||||
enableMullvad = false;
|
||||
enablePrinting = ${enable_printing};
|
||||
enableBluetooth = true;
|
||||
|
||||
bootloader = "${bootloader}";
|
||||
enablePlymouth = ${enable_plymouth};
|
||||
|
||||
enableMitigationsOff = false;
|
||||
|
||||
theme = "classical";
|
||||
}
|
||||
EOF
|
||||
|
||||
# Generate flake.nix
|
||||
cat > "$config_dir/flake.nix" << 'FLAKEEOF'
|
||||
{
|
||||
description = "Nomarchy NixOS Configuration";
|
||||
|
||||
inputs = {
|
||||
nomarchy.url = "github:blu/nomarchy";
|
||||
nixpkgs.follows = "nomarchy/nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nomarchy, nixpkgs, ... }@inputs: let
|
||||
userConfig = import ./config.nix;
|
||||
in {
|
||||
nixosConfigurations.${userConfig.hostname} = nomarchy.lib.mkHost {
|
||||
system = "x86_64-linux";
|
||||
config = userConfig;
|
||||
extraModules = [
|
||||
/etc/nixos/hardware-configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
FLAKEEOF
|
||||
|
||||
# Build LUKS config if needed
|
||||
local luks_config=""
|
||||
if [ "$USE_LUKS" = true ]; then
|
||||
local luks_uuid
|
||||
luks_uuid=$(blkid -s UUID -o value "$LUKS_PARTITION")
|
||||
luks_config="
|
||||
# LUKS encryption
|
||||
boot.initrd.luks.devices.\"cryptroot\" = {
|
||||
device = \"/dev/disk/by-uuid/${luks_uuid}\";
|
||||
preLVM = true;
|
||||
};"
|
||||
fi
|
||||
|
||||
# Create configuration.nix with LUKS config included
|
||||
cat > "/mnt/etc/nixos/configuration.nix" << EOF
|
||||
# This file is managed by Nomarchy
|
||||
# Edit /etc/nomarchy/config.nix instead
|
||||
{ ... }: {
|
||||
imports = [ ./hardware-configuration.nix ];
|
||||
|
||||
# Minimal config for initial boot - will be replaced by flake
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
networking.hostName = "${hostname_input}";
|
||||
time.timeZone = "${timezone}";
|
||||
|
||||
users.users.${username} = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" "networkmanager" ];
|
||||
initialPassword = "changeme";
|
||||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
networking.networkmanager.enable = true;
|
||||
${luks_config}
|
||||
system.stateVersion = "24.11";
|
||||
}
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}Configuration generated.${NC}"
|
||||
}
|
||||
|
||||
run_install() {
|
||||
echo ""
|
||||
echo -e "${BLUE}Installing NixOS...${NC}"
|
||||
echo "This may take a while."
|
||||
echo ""
|
||||
|
||||
NIX_CONFIG="experimental-features = nix-command flakes" nixos-install --no-root-passwd
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Installation complete!${NC}"
|
||||
}
|
||||
|
||||
set_user_password() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Set password for ${username}${NC}"
|
||||
nixos-enter --root /mnt -c "passwd ${username}"
|
||||
}
|
||||
|
||||
show_summary() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Installation Summary${NC}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo -e "Disk: ${CYAN}${TARGET_DISK}${NC}"
|
||||
echo -e "Encryption: ${CYAN}${USE_LUKS}${NC}"
|
||||
echo -e "Username: ${CYAN}${username}${NC}"
|
||||
echo -e "Hostname: ${CYAN}${hostname_input}${NC}"
|
||||
echo -e "Timezone: ${CYAN}${timezone}${NC}"
|
||||
echo -e "Bootloader: ${CYAN}${bootloader}${NC}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
}
|
||||
|
||||
finish() {
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}Nomarchy installation complete!${NC}"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Reboot: shutdown -r now"
|
||||
echo " 2. Log in as '${username}' with the password you set"
|
||||
echo " 3. Select 'Hyprland' from the session menu"
|
||||
echo " 4. Press Super+/ for Quick Actions"
|
||||
echo ""
|
||||
echo "To rebuild with flake (after first boot):"
|
||||
echo " cd /etc/nomarchy && sudo nixos-rebuild switch --flake .#${hostname_input}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main() {
|
||||
print_banner
|
||||
check_root
|
||||
check_uefi
|
||||
|
||||
select_disk
|
||||
prompt_encryption
|
||||
partition_disk
|
||||
setup_luks
|
||||
format_filesystems
|
||||
mount_filesystems
|
||||
generate_hardware_config
|
||||
|
||||
# User configuration
|
||||
prompt_username
|
||||
prompt_hostname
|
||||
prompt_timezone
|
||||
prompt_locale
|
||||
prompt_keyboard
|
||||
prompt_bootloader
|
||||
prompt_features
|
||||
|
||||
show_summary
|
||||
|
||||
read -rp "Proceed with installation? [Y/n]: " proceed
|
||||
proceed="${proceed:-y}"
|
||||
if [[ ! "$proceed" =~ ^[Yy] ]]; then
|
||||
echo "Installation cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
generate_config
|
||||
run_install
|
||||
set_user_password
|
||||
finish
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user