feat: dinit or die
why the FUCK did i think making an init selector was a good idea
artix themselves dont even ship services in their online installer
they just give you a bare system and say "figure it out" and
it WORKS because people can just install their init of choice
afterwards. but nooooo i had to be clever and build a whole
netinstall-add monstrosity with openrc/runit/s6 service groups
that broke constantly because basestrap --overwrite is a lie
and init packages conflict with each other and sddm-openrc +
lightdm-openrc both Provide: init-displaymanager and pacman
just goes 🖕 during install.
so anyway. dinit only now. you want something else? read
changing-init.md, i literally copied the artix wiki tutorial.
i am not maintaining four init service groups in netinstall.yaml
for the rest of my life. this is my villain origin story.
actual changes:
- ripped out offline calamares mode (was never truly offline)
- ripped out packagechooser.conf (good fucking riddance)
- added packagechooser_dm.conf so you can at least pick your DM
- added BYODE offline installer (bare system + btrfs + snapper,
no DE, you pacman -Sy plasma-meta yourself)
- added yay + snapper + btrfs-progs to rootfs
- shoved Init Services + DM groups into netinstall.yaml (dinit
only, obviously)
- updated every markdown file that mentioned another init like
they were cursed (they were)
- wrote changing-init.md so i can just paste the link next time
someone asks
- X-KDE-IsAdminApplication=true so KDE stops acting like
calamares is a virus (its not, its just desperate)
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
#!/bin/bash
|
||||
# Antergos NeXT Offline Installer
|
||||
# Stolen with love from Valve's SteamOS repair_device.sh
|
||||
# "If it works for a Steam Deck, it works for you." -- some drunk developer
|
||||
|
||||
set -eu
|
||||
|
||||
SQUASHFS="/run/artix/bootmnt/LiveOS/rootfs.img"
|
||||
|
||||
# ── Stolen from SteamOS: pretty output ──
|
||||
sh_c() { [[ $_sh_c_colors -le 0 ]] || echo -ne "\e[${*:-0}m"; }
|
||||
_sh_c_colors=0
|
||||
[[ -n $TERM && -t 1 && ${TERM,,} != dumb ]] && _sh_c_colors=$(tput colors 2>/dev/null || echo 0)
|
||||
estat() { echo -e "$(sh_c 32 1)::$(sh_c) $*"; }
|
||||
einfo() { echo -e "$(sh_c 34 1)::$(sh_c) $*"; }
|
||||
ewarn() { echo -e "$(sh_c 33 1);;$(sh_c) $*"; }
|
||||
eerr() { echo -e "$(sh_c 31 1)!!$(sh_c) $*" >&2; }
|
||||
die() { eerr "${1:-script terminated}"; exit 1; }
|
||||
cmd() { echo -e "$(sh_c 30 1)+$(sh_c) $*"; "$@"; }
|
||||
|
||||
# ── Stolen from SteamOS: read heredoc into var ──
|
||||
readvar() { IFS= read -r -d '' "$1" || true; }
|
||||
|
||||
# ── Stolen from SteamOS: partition helpers ──
|
||||
diskpart() { echo "${DISK}${DISK_SUFFIX}$1"; }
|
||||
|
||||
# ── Stolen from SteamOS: zenity prompts ──
|
||||
prompt_confirm() {
|
||||
zenity --title "$1" --question --ok-label "Proceed" --cancel-label "Cancel" --no-wrap --text "$2" 2>/dev/null
|
||||
}
|
||||
|
||||
prompt_msg() {
|
||||
zenity --title "$1" --info --no-wrap --text "$2" 2>/dev/null
|
||||
}
|
||||
|
||||
# ── Pre-flight ──
|
||||
[[ $EUID -eq 0 ]] || die "Must be run as root"
|
||||
|
||||
if [[ ! -f "$SQUASHFS" ]]; then
|
||||
die "Cannot find rootfs squashfs at $SQUASHFS. Are you booted from an Antergos NeXT ISO?"
|
||||
fi
|
||||
|
||||
# ── WARNING: NO DE ──
|
||||
prompt_msg "Antergos NeXT Offline Installer" \
|
||||
"This will install a BARE MINIMUM system — no desktop environment, no apps, just the base system + Calamares.
|
||||
|
||||
After boot, connect to the internet and run:
|
||||
sudo pacman -Sy plasma-meta
|
||||
(or xfce4, or whatever DE you want)
|
||||
|
||||
This is for people who want a minimal base to build on, or who are trapped in a cave with no internet.
|
||||
This WILL DESTROY ALL DATA on the target disk."
|
||||
|
||||
prompt_confirm "Select target disk" \
|
||||
"This will list available disks. Choose carefully — ALL DATA WILL BE DESTROYED." || die "Aborted by user"
|
||||
|
||||
# ── Select disk ──
|
||||
DISK=$(lsblk -dno NAME,SIZE,MODEL,TYPE | grep disk | \
|
||||
zenity --list --title "Select target disk" \
|
||||
--column "Device" --column "Size" --column "Model" \
|
||||
--print-column=1 --width=500 --height=300 2>/dev/null | tail -1)
|
||||
[[ -n "$DISK" ]] || die "No disk selected"
|
||||
DISK="/dev/$DISK"
|
||||
[[ -b "$DISK" ]] || die "$DISK is not a block device"
|
||||
|
||||
# Determine partition suffix (p for NVMe/mmcblk, nothing for sdX)
|
||||
if [[ "$DISK" =~ /dev/nvme || "$DISK" =~ /dev/mmcblk ]]; then
|
||||
DISK_SUFFIX="p"
|
||||
else
|
||||
DISK_SUFFIX=""
|
||||
fi
|
||||
|
||||
prompt_confirm "DESTROY $DISK?" \
|
||||
"Target: $DISK
|
||||
All partitions will be wiped. This cannot be undone.
|
||||
|
||||
Type YES below to confirm." || die "Aborted by user"
|
||||
|
||||
# ── Partition ──
|
||||
estat "Partitioning $DISK..."
|
||||
cmd sfdisk --delete "$DISK" 2>/dev/null || true
|
||||
|
||||
readvar PARTITION_TABLE << END_PTABLE
|
||||
label: gpt
|
||||
$(diskpart 1): size=512MiB, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
|
||||
$(diskpart 2): size=300MiB, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
|
||||
$(diskpart 3): type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
|
||||
END_PTABLE
|
||||
|
||||
echo "$PARTITION_TABLE" | cmd sfdisk "$DISK"
|
||||
|
||||
PART_ESP=$(diskpart 1)
|
||||
PART_SWAP=$(diskpart 2)
|
||||
PART_ROOT=$(diskpart 3)
|
||||
|
||||
# ── Format ──
|
||||
estat "Formatting partitions..."
|
||||
cmd mkfs.fat -F32 -n ESP "$PART_ESP"
|
||||
cmd mkswap -L swap "$PART_SWAP"
|
||||
cmd mkfs.btrfs -f -L antergos "$PART_ROOT"
|
||||
|
||||
# ── Create btrfs subvolumes ──
|
||||
estat "Creating btrfs subvolumes..."
|
||||
cmd mkdir -p /mnt/btrfs
|
||||
cmd mount "$PART_ROOT" /mnt/btrfs
|
||||
cmd btrfs subvolume create /mnt/btrfs/@
|
||||
cmd btrfs subvolume create /mnt/btrfs/@home
|
||||
cmd btrfs subvolume create /mnt/btrfs/@cache
|
||||
cmd btrfs subvolume create /mnt/btrfs/@log
|
||||
cmd btrfs subvolume create /mnt/btrfs/@snapshots
|
||||
cmd umount /mnt/btrfs
|
||||
|
||||
# ── Mount subvolumes ──
|
||||
estat "Mounting subvolumes..."
|
||||
TARGET=/mnt/target
|
||||
cmd mkdir -p "$TARGET"
|
||||
cmd mount -o subvol=@ "$PART_ROOT" "$TARGET"
|
||||
cmd mkdir -p "$TARGET/{home,var/cache,var/log,.snapshots,boot}"
|
||||
cmd mount -o subvol=@home "$PART_ROOT" "$TARGET/home"
|
||||
cmd mount -o subvol=@cache "$PART_ROOT" "$TARGET/var/cache"
|
||||
cmd mount -o subvol=@log "$PART_ROOT" "$TARGET/var/log"
|
||||
cmd mount -o subvol=@snapshots "$PART_ROOT" "$TARGET/.snapshots"
|
||||
cmd mount "$PART_ESP" "$TARGET/boot"
|
||||
|
||||
# ── Extract squashfs ──
|
||||
estat "Extracting rootfs to $TARGET... (this will take a while)"
|
||||
cmd unsquashfs -f -d "$TARGET" "$SQUASHFS"
|
||||
|
||||
# ── Generate fstab ──
|
||||
estat "Generating fstab with btrfs subvolumes..."
|
||||
ROOT_UUID=$(blkid -o value -s UUID "$PART_ROOT")
|
||||
SWAP_UUID=$(blkid -o value -s UUID "$PART_SWAP")
|
||||
ESP_UUID=$(blkid -o value -s UUID "$PART_ESP")
|
||||
|
||||
cat > "$TARGET/etc/fstab" << FSTAB
|
||||
# /etc/fstab generated by Antergos NeXT Offline Installer
|
||||
# Stolen from SteamOS, adapted for your sins — now with btrfs snapshots
|
||||
|
||||
UUID=$ROOT_UUID / btrfs subvol=@,defaults,noatime,compress=zstd 0 1
|
||||
UUID=$ROOT_UUID /home btrfs subvol=@home,defaults,noatime,compress=zstd 0 0
|
||||
UUID=$ROOT_UUID /var/cache btrfs subvol=@cache,defaults,noatime,compress=zstd 0 0
|
||||
UUID=$ROOT_UUID /var/log btrfs subvol=@log,defaults,noatime,compress=zstd 0 0
|
||||
UUID=$ROOT_UUID /.snapshots btrfs subvol=@snapshots,defaults,noatime 0 0
|
||||
UUID=$SWAP_UUID none swap sw 0 0
|
||||
UUID=$ESP_UUID /boot vfat defaults,noatime 0 2
|
||||
FSTAB
|
||||
|
||||
# ── Chroot setup ──
|
||||
estat "Setting up chroot for bootloader..."
|
||||
cmd mount --bind /dev "$TARGET/dev"
|
||||
cmd mount --bind /proc "$TARGET/proc"
|
||||
cmd mount --bind /sys "$TARGET/sys"
|
||||
cmd mount --bind /run "$TARGET/run"
|
||||
|
||||
# Install GRUB
|
||||
estat "Installing GRUB..."
|
||||
cmd chroot "$TARGET" /bin/bash -c "grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Antergos"
|
||||
cmd chroot "$TARGET" /bin/bash -c "grub-mkconfig -o /boot/grub/grub.cfg" 2>/dev/null || true
|
||||
|
||||
# Set hostname
|
||||
cmd chroot "$TARGET" /bin/bash -c "echo antergos > /etc/hostname"
|
||||
|
||||
# Root password prompt
|
||||
PASSWD=$(zenity --password --title="Set root password" --text="Enter root password for the installed system" 2>/dev/null)
|
||||
if [[ -n "$PASSWD" ]]; then
|
||||
echo "root:$PASSWD" | cmd chroot "$TARGET" chpasswd
|
||||
fi
|
||||
|
||||
# Create user
|
||||
USERNAME=$(zenity --entry --title="Create user" --text="Enter username for daily use:" 2>/dev/null)
|
||||
if [[ -n "$USERNAME" ]]; then
|
||||
cmd chroot "$TARGET" useradd -m -G wheel,audio,video,storage -s /bin/bash "$USERNAME"
|
||||
UPASS=$(zenity --password --title="User password" --text="Enter password for $USERNAME:" 2>/dev/null)
|
||||
[[ -n "$UPASS" ]] && echo "$USERNAME:$UPASS" | cmd chroot "$TARGET" chpasswd
|
||||
cmd chroot "$TARGET" sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
|
||||
fi
|
||||
|
||||
# ── Enable services via artix-service ──
|
||||
estat "Enabling services..."
|
||||
for sv in sddm NetworkManager dbus acpid bluetoothd cronie cupsd dhcpcd power-profiles-daemon syslog-ng userspawn; do
|
||||
cmd chroot "$TARGET" artix-service enable "$sv" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# ── Configure snapper for automatic snapshots ──
|
||||
estat "Setting up snapper..."
|
||||
cmd chroot "$TARGET" snapper -c root create-config /
|
||||
cmd chroot "$TARGET" sed -i 's/^TIMELINE_CREATE="no"/TIMELINE_CREATE="yes"/' /etc/snapper/configs/root
|
||||
cmd chroot "$TARGET" sed -i 's/^TIMELINE_LIMIT_HOURLY="[0-9]*"/TIMELINE_LIMIT_HOURLY="6"/' /etc/snapper/configs/root
|
||||
cmd chroot "$TARGET" sed -i 's/^TIMELINE_LIMIT_DAILY="[0-9]*"/TIMELINE_LIMIT_DAILY="7"/' /etc/snapper/configs/root
|
||||
cmd chroot "$TARGET" sed -i 's/^TIMELINE_LIMIT_WEEKLY="[0-9]*"/TIMELINE_LIMIT_WEEKLY="4"/' /etc/snapper/configs/root
|
||||
cmd chroot "$TARGET" sed -i 's/^TIMELINE_LIMIT_MONTHLY="[0-9]*"/TIMELINE_LIMIT_MONTHLY="0"/' /etc/snapper/configs/root
|
||||
|
||||
cat > "$TARGET/etc/cron.hourly/snapper-timeline" << 'CRON'
|
||||
#!/bin/bash
|
||||
# Automatic btrfs snapshots via snapper
|
||||
/usr/bin/snapper -c root cleanup timeline
|
||||
/usr/bin/snapper -c root cleanup number
|
||||
CRON
|
||||
cmd chroot "$TARGET" chmod +x /etc/cron.hourly/snapper-timeline
|
||||
|
||||
# Also run cleanup daily to be safe
|
||||
cat > "$TARGET/etc/cron.daily/snapper-cleanup" << 'CRON'
|
||||
#!/bin/bash
|
||||
# Clean up old btrfs snapshots
|
||||
/usr/bin/snapper -c root cleanup timeline
|
||||
/usr/bin/snapper -c root cleanup number
|
||||
CRON
|
||||
cmd chroot "$TARGET" chmod +x /etc/cron.daily/snapper-cleanup
|
||||
|
||||
# ── Cleanup ──
|
||||
estat "Cleaning up..."
|
||||
for d in dev proc sys run; do
|
||||
umount -l "$TARGET/$d" 2>/dev/null || true
|
||||
done
|
||||
for m in home var/log var/cache .snapshots boot; do
|
||||
umount "$TARGET/$m" 2>/dev/null || true
|
||||
done
|
||||
cmd umount "$TARGET"
|
||||
|
||||
# ── Final warning ──
|
||||
prompt_msg "Installation complete" \
|
||||
"Antergos NeXT has been installed to $DISK.
|
||||
|
||||
Filesystem: btrfs with subvolumes (@, @home, @cache, @log, @snapshots)
|
||||
Snapshots: snapper creates hourly snapshots, keeps 6 hourly + 7 daily + 4 weekly
|
||||
(no monthly — those are your problem)
|
||||
|
||||
Remember: NO DESKTOP ENVIRONMENT was installed.
|
||||
Boot up, log in as root or $USERNAME, connect to the internet, and run:
|
||||
|
||||
sudo pacman -Sy plasma-meta
|
||||
|
||||
(or whatever DE tickles your fancy)
|
||||
|
||||
Choose Proceed to reboot, or Cancel to stay in the live environment."
|
||||
|
||||
if zenity --question --title "Reboot?" --text "Reboot now?" 2>/dev/null; then
|
||||
cmd reboot
|
||||
fi
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Install Antergos NeXT (Offline — NO DE)
|
||||
Name[en]=Install Antergos NeXT (Offline — NO DE)
|
||||
Comment=Bare minimum install from the live ISO. No desktop environment included. Internet recommended after boot.
|
||||
Exec=sudo -E antergos-offline-install
|
||||
Icon=calamares
|
||||
Terminal=false
|
||||
Categories=Qt;System;Settings;
|
||||
StartupNotify=true
|
||||
X-KDE-IsAdminApplication=true
|
||||
@@ -8,3 +8,4 @@ Icon=calamares
|
||||
Terminal=false
|
||||
Categories=Qt;System;Settings;
|
||||
StartupNotify=true
|
||||
X-KDE-IsAdminApplication=true
|
||||
|
||||
Reference in New Issue
Block a user