329 lines
7.6 KiB
Go
329 lines
7.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// MiasmaInstaller represents the installer for Miasma OS
|
|
type MiasmaInstaller struct {
|
|
device string
|
|
username string
|
|
password string
|
|
installHardened bool
|
|
installPackages []string
|
|
}
|
|
|
|
// NewMiasmaInstaller creates a new MiasmaInstaller instance
|
|
func NewMiasmaInstaller() *MiasmaInstaller {
|
|
return &MiasmaInstaller{
|
|
installHardened: true,
|
|
installPackages: []string{},
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
installer := NewMiasmaInstaller()
|
|
|
|
// Get system information
|
|
fmt.Println("Miasma OS Installer")
|
|
fmt.Println("===================")
|
|
|
|
// Create temporary config file
|
|
if err := installer.createTempConfig(); err != nil {
|
|
fmt.Printf("Error creating config: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Make sure we have root privileges
|
|
if err := checkRootPrivileges(); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Get user input
|
|
if err := installer.getUserInput(); err != nil {
|
|
fmt.Printf("Error getting user input: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Validate disk selection
|
|
if err := installer.validateDisk(); err != nil {
|
|
fmt.Printf("Error validating disk: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Run the actual installation
|
|
if err := installer.runInstallation(); err != nil {
|
|
fmt.Printf("Installation failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("Installation completed successfully!")
|
|
}
|
|
|
|
// detectDisks returns a list of available disks
|
|
func detectDisks() ([]string, error) {
|
|
cmd := exec.Command("lsblk", "-o", "NAME,SIZE,TYPE,MOUNTPOINT", "-n", "-l")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
|
|
var disks []string
|
|
|
|
for _, line := range lines {
|
|
fields := strings.Fields(line)
|
|
if len(fields) >= 3 {
|
|
name := fields[0]
|
|
deviceType := fields[2]
|
|
|
|
// Only include whole disks (not partitions)
|
|
if deviceType == "disk" {
|
|
disks = append(disks, "/dev/"+name)
|
|
}
|
|
}
|
|
}
|
|
|
|
return disks, nil
|
|
}
|
|
|
|
// checkRootPrivileges checks if the installer is running with root privileges
|
|
func checkRootPrivileges() error {
|
|
cmd := exec.Command("id", "-u")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check privileges: %v", err)
|
|
}
|
|
|
|
outputStr := strings.TrimSpace(string(output))
|
|
if outputStr != "0" {
|
|
return fmt.Errorf("this installer must be run as root")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// getUserInput prompts user for installation parameters
|
|
func (m *MiasmaInstaller) getUserInput() error {
|
|
// Get disk selection
|
|
diskList, err := detectDisks()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to detect disks: %v", err)
|
|
}
|
|
|
|
if len(diskList) == 0 {
|
|
return fmt.Errorf("no disks detected")
|
|
}
|
|
|
|
fmt.Println("Available disks:")
|
|
for i, disk := range diskList {
|
|
fmt.Printf("%d. %s\n", i+1, disk)
|
|
}
|
|
|
|
fmt.Printf("Select disk (1-%d): ", len(diskList))
|
|
var diskChoice int
|
|
_, err = fmt.Scanf("%d", &diskChoice)
|
|
if err != nil || diskChoice < 1 || diskChoice > len(diskList) {
|
|
return fmt.Errorf("invalid disk selection")
|
|
}
|
|
|
|
m.device = diskList[diskChoice-1]
|
|
|
|
// Get username and password
|
|
fmt.Print("Enter username: ")
|
|
_, err = fmt.Scanf("%s", &m.username)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read username: %v", err)
|
|
}
|
|
|
|
fmt.Print("Enter password: ")
|
|
_, err = fmt.Scanf("%s", &m.password)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read password: %v", err)
|
|
}
|
|
|
|
fmt.Printf("Installing to %s with user %s\n", m.device, m.username)
|
|
return nil
|
|
}
|
|
|
|
// validateDisk validates the selected disk
|
|
func (m *MiasmaInstaller) validateDisk() error {
|
|
if m.device == "" {
|
|
return fmt.Errorf("no device selected")
|
|
}
|
|
|
|
// Simple check: device should start with /dev/
|
|
if !strings.HasPrefix(m.device, "/dev/") {
|
|
return fmt.Errorf("invalid device path: %s", m.device)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// createTempConfig creates a temporary alis configuration for Miasma OS
|
|
func (m *MiasmaInstaller) createTempConfig() error {
|
|
config := fmt.Sprintf(`# Miasma OS Installer Configuration
|
|
# Based on alis configuration format
|
|
|
|
# init
|
|
LOG_TRACE="true"
|
|
LOG_FILE="false"
|
|
|
|
# partition
|
|
DEVICE="%s"
|
|
DEVICE_TRIM="true"
|
|
LVM="false"
|
|
LUKS_PASSWORD=""
|
|
LUKS_PASSWORD_RETYPE=""
|
|
FILE_SYSTEM_TYPE="btrfs"
|
|
BTRFS_SUBVOLUMES_MOUNTPOINTS=("root,root,/" "home,home,/home" "var,var,/var" "snapshots,snapshots,/.snapshots")
|
|
SWAP_SIZE="4096"
|
|
PARTITION_MODE="auto"
|
|
PARTITION_MOUNT_POINTS=("1=/boot" "2=/")
|
|
GPT_AUTOMOUNT="false"
|
|
|
|
# install
|
|
REFLECTOR="true"
|
|
REFLECTOR_COUNTRIES=("United States")
|
|
PACMAN_MIRROR=""
|
|
PACMAN_PARALLEL_DOWNLOADS="true"
|
|
KERNELS="linux-hardened"
|
|
KERNELS_COMPRESSION="zstd"
|
|
KERNELS_PARAMETERS=""
|
|
|
|
# aur
|
|
AUR_PACKAGE="paru-bin"
|
|
|
|
# display driver
|
|
DISPLAY_DRIVER="auto"
|
|
KMS="true"
|
|
FASTBOOT="true"
|
|
FRAMEBUFFER_COMPRESSION="true"
|
|
DISPLAY_DRIVER_DDX="false"
|
|
VULKAN="true"
|
|
DISPLAY_DRIVER_HARDWARE_VIDEO_ACCELERATION="true"
|
|
DISPLAY_DRIVER_HARDWARE_VIDEO_ACCELERATION_INTEL="intel-media-driver"
|
|
|
|
# config
|
|
TIMEZONE="UTC"
|
|
LOCALES=("en_US.UTF-8 UTF-8")
|
|
LOCALE_CONF=("LANG=en_US.UTF-8")
|
|
KEYLAYOUT="us"
|
|
KEYMODEL=""
|
|
KEYVARIANT=""
|
|
KEYOPTIONS=""
|
|
KEYMAP="us"
|
|
FONT=""
|
|
FONT_MAP=""
|
|
HOSTNAME="miasma"
|
|
ROOT_PASSWORD="%s"
|
|
ROOT_PASSWORD_RETYPE="%s"
|
|
|
|
# user
|
|
USER_NAME="%s"
|
|
USER_PASSWORD="%s"
|
|
USER_PASSWORD_RETYPE="%s"
|
|
ADDITIONAL_USERS=()
|
|
|
|
# systemd-homed
|
|
SYSTEMD_HOMED="false"
|
|
SYSTEMD_HOMED_STORAGE="directory"
|
|
SYSTEMD_HOMED_STORAGE_LUKS_TYPE="ext4"
|
|
|
|
# mkinitcpio
|
|
HOOKS="base udev autodetect microcode modconf kms keyboard keymap consolefont block btrfs filesystems fsck"
|
|
MODULES=""
|
|
UKI="false"
|
|
PLYMOUTH="false"
|
|
|
|
# bootloader
|
|
BOOTLOADER="systemd"
|
|
SECURE_BOOT="false"
|
|
|
|
# shell
|
|
CUSTOM_SHELL="zsh"
|
|
|
|
# desktop
|
|
DESKTOP_ENVIRONMENT="cosmic"
|
|
DISPLAY_MANAGER="auto"
|
|
|
|
# packages
|
|
PACKAGES_MULTILIB="false"
|
|
PACKAGES_INSTALL="true"
|
|
PACKAGES_PIPEWIRE="true"
|
|
|
|
# provision
|
|
PROVISION="false"
|
|
|
|
# misc
|
|
FWUPD="false"
|
|
VAGRANT="false"
|
|
|
|
# systemd
|
|
SYSTEMD_UNITS="+systemd-timesyncd.service +apparmor.service"
|
|
|
|
# reboot
|
|
REBOOT="false"
|
|
`,
|
|
m.device, m.password, m.password, m.username, m.password, m.password)
|
|
|
|
return os.WriteFile("alis.conf", []byte(config), 0644)
|
|
}
|
|
|
|
// runInstallation executes the installation process
|
|
func (m *MiasmaInstaller) runInstallation() error {
|
|
// Create a temporary file to store the username for post-install script
|
|
err := os.WriteFile("/tmp/miasma-username", []byte(m.username), 0644)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create username file: %v", err)
|
|
}
|
|
|
|
// Copy our custom packages configuration to the alis directory
|
|
cmd := exec.Command("cp", "alis-packages.conf", "alis/alis-packages.conf")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to copy packages config: %v", err)
|
|
}
|
|
|
|
// Copy post-install script to the chroot environment
|
|
cmd = exec.Command("cp", "miasma-post-install.sh", "/mnt/miasma-post-install.sh")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to copy post-install script: %v", err)
|
|
}
|
|
|
|
// Prepare the alis script command
|
|
cmd = exec.Command("./alis.sh")
|
|
cmd.Dir = "./alis"
|
|
|
|
// Set environment variables
|
|
cmd.Env = append(os.Environ(),
|
|
"WARNING_CONFIRM=false",
|
|
"ALIS_CONF_FILE=../alis.conf",
|
|
)
|
|
|
|
// Start the installation
|
|
fmt.Println("Starting Arch Linux installation with alis...")
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("installation failed: %v\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
fmt.Printf("Installation completed. Applying Miasma OS configurations...\n")
|
|
|
|
// Run post-installation script
|
|
fmt.Println("Running post-installation setup...")
|
|
cmd = exec.Command("bash", "/mnt/miasma-post-install.sh")
|
|
output, err = cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("post-installation failed: %v\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
fmt.Printf("Post-installation output: %s\n", output)
|
|
|
|
return nil
|
|
}
|
|
|