added cosmic packages to installer. Still no auto reboot
Some checks failed
Build / build (push) Failing after 4m53s
Some checks failed
Build / build (push) Failing after 4m53s
This commit is contained in:
71
TESTING.md
Normal file
71
TESTING.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Miasma OS Installer - Testing Guide
|
||||
|
||||
## Testing in a Minimal Arch VM
|
||||
|
||||
### Setup Test Environment
|
||||
|
||||
1. **Create Arch VM with minimal install:**
|
||||
- Boot Arch ISO
|
||||
- Choose "Install Arch Linux"
|
||||
- When prompted for profile, select "minimal" (no desktop)
|
||||
- Complete basic installation
|
||||
- Reboot into minimal Arch system
|
||||
|
||||
2. **Prepare for testing:**
|
||||
```bash
|
||||
# Login as root
|
||||
# Ensure network is working
|
||||
ping -c 3 archlinux.org
|
||||
|
||||
# Install git and go (for building)
|
||||
pacman -Sy git go base-devel
|
||||
|
||||
# Clone the installer
|
||||
git clone https://git.miasma-os.com/miasma/miasma-installer.git
|
||||
cd miasma-installer
|
||||
|
||||
# Build the installer
|
||||
make build
|
||||
```
|
||||
|
||||
3. **Run the installer:**
|
||||
```bash
|
||||
# Must be run as root
|
||||
sudo ./build/miasma-installer
|
||||
```
|
||||
|
||||
### What Should Happen
|
||||
|
||||
1. **During Installation:**
|
||||
- Installer detects available disks
|
||||
- Partitions selected disk (GPT with EFI + root)
|
||||
- Formats with btrfs (with subvolumes)
|
||||
- Optional LUKS2 encryption
|
||||
- Installs base system + linux-hardened
|
||||
- Installs Cosmic Desktop packages
|
||||
- Configures bootloader (systemd-boot)
|
||||
- Sets up user account with sudo
|
||||
|
||||
2. **After Installation:**
|
||||
- Installer exits cleanly
|
||||
- Unmount filesystems: `umount -R /mnt`
|
||||
- Reboot: `reboot`
|
||||
- System boots into Cosmic Desktop login
|
||||
- Login with created user credentials
|
||||
|
||||
### For archiso Integration
|
||||
|
||||
The installer will be included as a custom package in the archiso build:
|
||||
- ISO boots directly to root shell
|
||||
- Installer auto-starts or user runs `miasma-installer`
|
||||
- After installation completes, user reboots
|
||||
- System boots into installed Miasma OS with Cosmic Desktop
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If installation fails:
|
||||
- Check `/mnt` is empty before starting
|
||||
- Ensure UEFI mode: `ls /sys/firmware/efi`
|
||||
- Check disk permissions: `lsblk`
|
||||
- View detailed errors in the TUI
|
||||
- Manually unmount if needed: `umount -R /mnt`
|
||||
29
main.go
29
main.go
@@ -9,17 +9,34 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := tea.NewProgram(tui.NewModel(), tea.WithAltScreen())
|
||||
|
||||
if _, err := p.Run(); err != nil {
|
||||
fmt.Printf("An error has occured during installation: %v\n", err)
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Println("Error: This installer must be run as root")
|
||||
fmt.Println("Please run: sudo miasma-installer")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := os.Stat("/sys/firmware/efi"); os.IsNotExist(err) {
|
||||
fmt.Println("Error: UEFI boot mode not detected")
|
||||
fmt.Println("Miasma OS requires UEFI boot mode")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
p := tea.NewProgram(tui.NewModel(), tea.WithAltScreen())
|
||||
|
||||
finalModel, err := p.Run()
|
||||
if err != nil {
|
||||
fmt.Printf("\nAn error occurred during installation: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
finalModel, _ := p.Run()
|
||||
if root, ok := finalModel.(tui.RootModel); ok {
|
||||
if root.State == tui.StateFinished {
|
||||
fmt.Println("\nMiasma OS Installation Complete! Please reboot.")
|
||||
fmt.Println("\n✓ Miasma OS Installation Complete!")
|
||||
fmt.Println("\nThe system will reboot in 5 seconds...")
|
||||
fmt.Println("Press Ctrl+C to cancel reboot")
|
||||
|
||||
fmt.Print("\nUnmounting filesystems...")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ func (m InstallModel) configureSystem() error {
|
||||
genfstab := exec.Command("genfstab", "-U", "/mnt")
|
||||
fstab, err := genfstab.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("genfstab failed: %w", err)
|
||||
}
|
||||
os.WriteFile("/mnt/etc/fstab", fstab, 0644)
|
||||
|
||||
@@ -277,7 +277,9 @@ func (m InstallModel) configureSystem() error {
|
||||
os.WriteFile("/mnt/etc/hosts", []byte(hosts), 0644)
|
||||
|
||||
os.WriteFile("/mnt/etc/locale.gen", []byte("en_US.UTF-8 UTF-8\n"), 0644)
|
||||
chroot([]string{"locale-gen"})
|
||||
if _, err := chroot([]string{"locale-gen"}); err != nil {
|
||||
return fmt.Errorf("locale-gen failed: %w", err)
|
||||
}
|
||||
|
||||
os.WriteFile("/mnt/etc/locale.conf", []byte("LANG=en_US.UTF-8\n"), 0644)
|
||||
|
||||
@@ -285,24 +287,38 @@ func (m InstallModel) configureSystem() error {
|
||||
chroot([]string{"hwclock", "--systohc"})
|
||||
|
||||
useraddCmd := fmt.Sprintf("useradd -m -G wheel -s /bin/bash %s", m.config.Username)
|
||||
chroot([]string{"sh", "-c", useraddCmd})
|
||||
if _, err := chroot([]string{"sh", "-c", useraddCmd}); err != nil {
|
||||
return fmt.Errorf("useradd failed: %w", err)
|
||||
}
|
||||
|
||||
passwdCmd := fmt.Sprintf("echo '%s:%s' | chpasswd", m.config.Username, m.config.UserPassword)
|
||||
chroot([]string{"sh", "-c", passwdCmd})
|
||||
if _, err := chroot([]string{"sh", "-c", passwdCmd}); err != nil {
|
||||
return fmt.Errorf("user password set failed: %w", err)
|
||||
}
|
||||
|
||||
rootPasswdCmd := fmt.Sprintf("echo 'root:%s' | chpasswd", m.config.RootPassword)
|
||||
chroot([]string{"sh", "-c", rootPasswdCmd})
|
||||
rootPasswd := m.config.RootPassword
|
||||
if rootPasswd == "" {
|
||||
rootPasswd = m.config.UserPassword
|
||||
}
|
||||
rootPasswdCmd := fmt.Sprintf("echo 'root:%s' | chpasswd", rootPasswd)
|
||||
if _, err := chroot([]string{"sh", "-c", rootPasswdCmd}); err != nil {
|
||||
return fmt.Errorf("root password set failed: %w", err)
|
||||
}
|
||||
|
||||
sudoers := "%wheel ALL=(ALL:ALL) ALL\n"
|
||||
os.WriteFile("/mnt/etc/sudoers.d/wheel", []byte(sudoers), 0440)
|
||||
|
||||
chroot([]string{"systemctl", "enable", "NetworkManager"})
|
||||
if _, err := chroot([]string{"systemctl", "enable", "NetworkManager"}); err != nil {
|
||||
return fmt.Errorf("failed to enable NetworkManager: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m InstallModel) installBootloader() error {
|
||||
chroot([]string{"bootctl", "install"})
|
||||
if _, err := chroot([]string{"bootctl", "install"}); err != nil {
|
||||
return fmt.Errorf("bootctl install failed: %w", err)
|
||||
}
|
||||
|
||||
loaderConf := `default arch.conf
|
||||
timeout 3
|
||||
@@ -317,25 +333,18 @@ editor no
|
||||
rootPart = disk + "p2"
|
||||
}
|
||||
|
||||
rootUUID := ""
|
||||
if m.config.EnableLUKS {
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
rootUUID = strings.TrimSpace(string(output))
|
||||
} else {
|
||||
rootPart = "/dev/mapper/cryptroot"
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
rootUUID = strings.TrimSpace(string(output))
|
||||
}
|
||||
|
||||
options := fmt.Sprintf("root=UUID=%s rootflags=subvol=@ rw", rootUUID)
|
||||
var options string
|
||||
if m.config.EnableLUKS {
|
||||
cryptUUID := ""
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", disk+"2")
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
cryptUUID = strings.TrimSpace(string(output))
|
||||
options = fmt.Sprintf("cryptdevice=UUID=%s:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw", cryptUUID)
|
||||
options = fmt.Sprintf("cryptdevice=UUID=%s:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw quiet splash", cryptUUID)
|
||||
} else {
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
rootUUID := strings.TrimSpace(string(output))
|
||||
options = fmt.Sprintf("root=UUID=%s rootflags=subvol=@ rw quiet splash", rootUUID)
|
||||
}
|
||||
|
||||
entryConf := fmt.Sprintf(`title Miasma OS
|
||||
@@ -346,21 +355,55 @@ options %s
|
||||
os.WriteFile("/mnt/boot/loader/entries/arch.conf", []byte(entryConf), 0644)
|
||||
|
||||
if m.config.EnableLUKS {
|
||||
mkinitcpio, _ := os.ReadFile("/mnt/etc/mkinitcpio.conf")
|
||||
newConf := strings.Replace(string(mkinitcpio),
|
||||
mkinitcpioConf, err := os.ReadFile("/mnt/etc/mkinitcpio.conf")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read mkinitcpio.conf: %w", err)
|
||||
}
|
||||
|
||||
newConf := string(mkinitcpioConf)
|
||||
newConf = strings.Replace(newConf,
|
||||
"HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems fsck)",
|
||||
"HOOKS=(base udev autodetect keyboard keymap consolefont modconf kms block encrypt filesystems fsck)",
|
||||
1)
|
||||
newConf = strings.Replace(newConf,
|
||||
"HOOKS=(base udev autodetect modconf block filesystems keyboard fsck)",
|
||||
"HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt filesystems fsck)",
|
||||
1)
|
||||
os.WriteFile("/mnt/etc/mkinitcpio.conf", []byte(newConf), 0644)
|
||||
chroot([]string{"mkinitcpio", "-P"})
|
||||
|
||||
if err := os.WriteFile("/mnt/etc/mkinitcpio.conf", []byte(newConf), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write mkinitcpio.conf: %w", err)
|
||||
}
|
||||
|
||||
if _, err := chroot([]string{"mkinitcpio", "-P"}); err != nil {
|
||||
return fmt.Errorf("mkinitcpio failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m InstallModel) installDesktop() error {
|
||||
chroot([]string{"pacman", "-Sy", "--noconfirm", "cosmic-session", "cosmic-greeter"})
|
||||
chroot([]string{"systemctl", "enable", "cosmic-greeter"})
|
||||
cosmicPackages := []string{
|
||||
"cosmic-session",
|
||||
"cosmic-greeter",
|
||||
"cosmic-files",
|
||||
"cosmic-edit",
|
||||
"cosmic-term",
|
||||
"cosmic-store",
|
||||
"cosmic-settings",
|
||||
"xorg-xwayland",
|
||||
}
|
||||
|
||||
for _, pkg := range cosmicPackages {
|
||||
if _, err := chroot([]string{"pacman", "-Sy", "--noconfirm", pkg}); err != nil {
|
||||
return fmt.Errorf("failed to install %s: %w", pkg, err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := chroot([]string{"systemctl", "enable", "cosmic-greeter"}); err != nil {
|
||||
return fmt.Errorf("failed to enable cosmic-greeter: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -414,7 +457,7 @@ func (m InstallModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.status = "Installation complete!"
|
||||
}
|
||||
m.Finished = true
|
||||
return m, nil
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
return m, nil
|
||||
@@ -445,10 +488,10 @@ func (m InstallModel) View() string {
|
||||
}
|
||||
|
||||
if m.Finished && m.err == nil {
|
||||
success := "✓ Installation successful!\n\nYou can now reboot your system."
|
||||
success := "✓ Installation successful!\n\nPress Ctrl+C to exit and reboot."
|
||||
content.WriteString(styles.BoxStyle.Render(success))
|
||||
content.WriteString("\n\n")
|
||||
content.WriteString(styles.RenderHelp("Ctrl+C", "Exit"))
|
||||
content.WriteString(styles.RenderHelp("Ctrl+C", "Exit and reboot"))
|
||||
}
|
||||
|
||||
return styles.AppStyle.Render(content.String())
|
||||
|
||||
Reference in New Issue
Block a user