diff --git a/configuration.nix b/configuration.nix index d90b42c..2b01d9a 100644 --- a/configuration.nix +++ b/configuration.nix @@ -3,6 +3,8 @@ { imports = [ ./modules/modules.nix + ./custom.nix + ./iso/branding.nix ]; # ── Boot ──────────────────────────────────────────────────── diff --git a/flake.nix b/flake.nix index 9f48648..eacf571 100755 --- a/flake.nix +++ b/flake.nix @@ -27,13 +27,21 @@ ]; }; - nixosConfigurations.sovran-iso = nixpkgs.lib.nixosSystem { + nixosConfigurations.sovran-iso-desktop = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ - ({ config, pkgs, ... }: { - nixpkgs.overlays = [ overlay-stable ]; - }) - ./iso.nix + ({ config, pkgs, ... }: { nixpkgs.overlays = [ overlay-stable ]; }) + ./iso/desktop.nix + nix-bitcoin.nixosModules.default + nixvim.nixosModules.nixvim + ]; + }; + + nixosConfigurations.sovran-iso-server = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ({ config, pkgs, ... }: { nixpkgs.overlays = [ overlay-stable ]; }) + ./iso/server.nix nix-bitcoin.nixosModules.default nixvim.nixosModules.nixvim ]; diff --git a/iso.nix b/iso.nix deleted file mode 100644 index 8bf6fe0..0000000 --- a/iso.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ config, pkgs, lib, ... }: - -{ - imports = [ - # Base ISO profile - "${pkgs.path}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" - - # Your full system config + modules - ./configuration.nix - ]; - - # ISO tweaks - isoImage.isoName = "Sovran_SystemsOS.iso"; - - # Convenience: enable SSH in live ISO - services.openssh.enable = true; - services.openssh.settings.PermitRootLogin = "yes"; - services.openssh.settings.PasswordAuthentication = true; - - # Optional: default password for ISO login only - users.users.nixos.password = "nixos"; -} \ No newline at end of file diff --git a/iso/g42.png b/iso/g42.png new file mode 100755 index 0000000..788d6d0 Binary files /dev/null and b/iso/g42.png differ diff --git a/iso/iso_branding.nix b/iso/iso_branding.nix new file mode 100644 index 0000000..1028bdf --- /dev/null +++ b/iso/iso_branding.nix @@ -0,0 +1,11 @@ +{ config, pkgs, lib, ... }: + +let + theme = pkgs.callPackage ./plymouth-theme.nix {}; +in +{ + boot.plymouth.enable = true; + boot.plymouth.theme = "sovran"; + boot.plymouth.themePackages = [ theme ]; + boot.kernelParams = [ "quiet" "splash" ]; +} \ No newline at end of file diff --git a/iso/iso_common.nix b/iso/iso_common.nix new file mode 100644 index 0000000..835b41d --- /dev/null +++ b/iso/iso_common.nix @@ -0,0 +1,48 @@ +{ config, pkgs, lib, ... }: + +let + sovranSource = builtins.path { path = ../.; name = "sovran-systemsos"; }; + installer = pkgs.writeShellScriptBin "sovran-install" (builtins.readFile ./installer.sh); +in +{ + imports = [ + "${pkgs.path}/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix" + ./branding.nix + ]; + + isoImage.isoName = "Sovran_SystemsOS.iso"; + + users.users.free = { + isNormalUser = true; + description = "free"; + extraGroups = [ "wheel" "networkmanager" ]; + initialPassword = "free"; + }; + + services.displayManager.autoLogin.enable = true; + services.displayManager.autoLogin.user = "free"; + + environment.systemPackages = with pkgs; [ + installer + zenity + util-linux + parted + dosfstools + e2fsprogs + gptfdisk + nixos-install-tools + git + curl + ]; + + environment.etc."sovran/flake".source = sovranSource; + + environment.etc."xdg/autostart/sovran-installer.desktop".text = '' + [Desktop Entry] + Type=Application + Name=Sovran Guided Installer + Exec=${installer}/bin/sovran-install + Terminal=false + X-GNOME-Autostart-enabled=true + ''; +} \ No newline at end of file diff --git a/iso/iso_desktop.nix b/iso/iso_desktop.nix new file mode 100644 index 0000000..b604b4c --- /dev/null +++ b/iso/iso_desktop.nix @@ -0,0 +1,5 @@ +{ config, pkgs, lib, ... }: + +{ + imports = [ ./common.nix ]; +} \ No newline at end of file diff --git a/iso/iso_installer.sh b/iso/iso_installer.sh new file mode 100644 index 0000000..9653a59 --- /dev/null +++ b/iso/iso_installer.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash +set -euo pipefail + +LOG=/tmp/sovran-install.log +exec > >(tee -a "$LOG") 2>&1 + +export PATH=/run/current-system/sw/bin:$PATH + +BYTES_4TB=$((4 * 1024 * 1024 * 1024 * 1024)) + +human_size() { + numfmt --to=iec --suffix=B "$1" +} + +zenity --info --width=500 --text="Sovran SystemsOS Installer\n\nWARNING:\nThis installer will ERASE ALL DATA on selected disks.\n\nPress OK to continue." + +mapfile -t DISKS < <(lsblk -b -dno NAME,SIZE,TYPE | awk '$3=="disk"{print $1":"$2}') +if [ "${#DISKS[@]}" -eq 0 ]; then + zenity --error --text="No disks found." + exit 1 +fi + +IFS=$'\n' DISKS_SORTED=($(printf "%s\n" "${DISKS[@]}" | sort -t: -k2,2n)) +unset IFS + +BOOT_DISK="${DISKS_SORTED[0]%%:*}" +BOOT_SIZE="${DISKS_SORTED[0]##*:}" + +DATA_DISK="" +DATA_SIZE="" + +if [ "${#DISKS_SORTED[@]}" -ge 2 ]; then + DATA_DISK="${DISKS_SORTED[-1]%%:*}" + DATA_SIZE="${DISKS_SORTED[-1]##*:}" +fi + +if [ -n "$DATA_DISK" ] && [ "$DATA_SIZE" -lt "$BYTES_4TB" ]; then + zenity --warning --width=500 --text="Second disk detected (${DATA_DISK}), but it is smaller than 4TB.\n\nIt will NOT be used." + DATA_DISK="" + DATA_SIZE="" +fi + +SUMMARY="Boot disk: /dev/${BOOT_DISK} ($(human_size "$BOOT_SIZE"))" +if [ -n "$DATA_DISK" ]; then + SUMMARY="${SUMMARY}\nData disk: /dev/${DATA_DISK} ($(human_size "$DATA_SIZE"))" +else + SUMMARY="${SUMMARY}\nData disk: none" +fi + +ROLE=$(zenity --list --radiolist --width=500 --height=250 \ + --title="Choose Install Role" \ + --column="" --column="Role" \ + TRUE "Server-Desktop (default)" \ + FALSE "Desktop" \ + FALSE "Node (Bitcoin-only)" || true) + +if [ -z "$ROLE" ]; then + ROLE="Server-Desktop (default)" +fi + +CONFIRM=$(zenity --entry --width=500 --text="WARNING: This will ERASE ALL DATA on:\n\n${SUMMARY}\n\nType ERASE to continue.") +if [ "$CONFIRM" != "ERASE" ]; then + zenity --error --text="Install cancelled." + exit 1 +fi + +BOOT_PATH="/dev/${BOOT_DISK}" +PART_SUFFIX="" +if [[ "$BOOT_DISK" =~ ^(nvme|mmcblk) ]]; then + PART_SUFFIX="p" +fi + +parted --script "$BOOT_PATH" mklabel gpt +parted --script "$BOOT_PATH" mkpart ESP fat32 1MiB 512MiB +parted --script "$BOOT_PATH" set 1 esp on +parted --script "$BOOT_PATH" mkpart primary ext4 512MiB 100% + +partprobe "$BOOT_PATH" +udevadm settle + +mkfs.fat -F 32 -n boot "${BOOT_PATH}${PART_SUFFIX}1" +mkfs.ext4 -F -L sovran_systemsos "${BOOT_PATH}${PART_SUFFIX}2" + +if [ -n "$DATA_DISK" ]; then + DATA_PATH="/dev/${DATA_DISK}" + part_suffix_data="" + if [[ "$DATA_DISK" =~ ^(nvme|mmcblk) ]]; then + part_suffix_data="p" + fi + + parted --script "$DATA_PATH" mklabel gpt + parted --script "$DATA_PATH" mkpart primary ext4 1MiB 100% + partprobe "$DATA_PATH" + udevadm settle + mkfs.ext4 -F -L BTCEcoandBackup "${DATA_PATH}${part_suffix_data}1" +fi + +mkdir -p /mnt +mount /dev/disk/by-label/sovran_systemsos /mnt +mkdir -p /mnt/boot/efi +mount /dev/disk/by-label/boot /mnt/boot/efi + +if [ -n "$DATA_DISK" ]; then + mkdir -p /mnt/run/media/Second_Drive + mount /dev/disk/by-label/BTCEcoandBackup /mnt/run/media/Second_Drive +fi + +nixos-generate-config --root /mnt + +cp /mnt/etc/nixos/hardware-configuration.nix /tmp/hardware-configuration.nix +rm -rf /mnt/etc/nixos/* +cp -a /etc/sovran/flake/* /mnt/etc/nixos/ +cp /tmp/hardware-configuration.nix /mnt/etc/nixos/hardware-configuration.nix + +cat > /mnt/etc/nixos/custom.nix < $out/share/plymouth/themes/sovran/sovran.plymouth <<'EOF' +[Plymouth Theme] +Name=Sovran Systems +Description=Sovran Systems Splash +ModuleName=script + +[script] +ImageDir=/share/plymouth/themes/sovran +ScriptFile=/share/plymouth/themes/sovran/sovran.script +EOF + + cat > $out/share/plymouth/themes/sovran/sovran.script <<'EOF' +# Background color: #CFFFD7 (RGB 207,255,215) +bg_r = 207/255.0 +bg_g = 255/255.0 +bg_b = 215/255.0 + +Window.SetBackgroundTopColor (bg_r, bg_g, bg_b); +Window.SetBackgroundBottomColor (bg_r, bg_g, bg_b); + +logo = Image("logo.png"); +logo_sprite = Sprite(logo); +logo_sprite.SetX((Window.GetWidth() - logo.GetWidth()) / 2); +logo_sprite.SetY((Window.GetHeight() - logo.GetHeight()) / 2); + +spinner = Sprite(); +spinner.SetImage(Spinner()); +spinner.SetX((Window.GetWidth() - spinner.GetImage().GetWidth()) / 2); +spinner.SetY((Window.GetHeight() + logo.GetHeight()) / 2 + 20); +EOF + ''; +} \ No newline at end of file diff --git a/iso/iso_server.nix b/iso/iso_server.nix new file mode 100644 index 0000000..b604b4c --- /dev/null +++ b/iso/iso_server.nix @@ -0,0 +1,5 @@ +{ config, pkgs, lib, ... }: + +{ + imports = [ ./common.nix ]; +} \ No newline at end of file