Check the machine before installing, and keep old shells' mise working
shellcheck / shellcheck (push) Successful in 11s
shellcheck / shellcheck (push) Successful in 11s
install.sh now stops early, with a clear message, if this isn't 64-bit Arch, it's run as root, there's no internet, or sudo doesn't work. system/preflight.sh then asks before going on with too little disk space or / not on btrfs, and offers to switch another login screen to GDM and PulseAudio to PipeWire. Keeping another login screen puts GDM in services-off, so install and update stop failing to enable it; a migration does the same on existing machines. It says nothing when all is well, as refresh runs install.sh again. Intel GPUs also get intel-media-driver for hardware video decoding, with a migration for existing machines. The mise migration links ~/.local/bin/mise to /usr/bin/mise instead of deleting it, so shells opened before the update don't print an error at every prompt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,8 @@ wget -qO- https://gitea.federated.computer/Federated_Computer/coredesktop/raw/br
|
||||
```
|
||||
3) Enter your password when asked, once at the start. Be patient: it takes a while.
|
||||
|
||||
First it checks the machine. It stops if this isn't Arch, if you run it as root, if your user can't use sudo, or if there's no internet. It asks before going on if there's less than about 60 GB free, or if / isn't on btrfs (then there are no snapshots before updates, and only reinstalling Arch with btrfs changes that). If the login screen isn't GNOME's, or sound goes through PulseAudio, it offers to switch to GNOME's login screen and to PipeWire.
|
||||
|
||||
4) At the end, it offers to run `configure`, which connects to your Federated Core, sets up backups and signs you in to the AI agents (see "Configure" below). If the install brought in a newer kernel, it asks you to reboot first; run `configure` after the reboot.
|
||||
|
||||
5) If something fails, just run the command again. It skips what's already done.
|
||||
@@ -149,7 +151,7 @@ sudo umount /mnt
|
||||
|
||||
### GPU drivers
|
||||
|
||||
The installer adds the Vulkan driver for Intel and AMD GPUs. If there's an NVIDIA GPU and archinstall's proprietary driver wasn't chosen, it installs NVIDIA's driver: the open kernel modules for GTX 16xx / RTX 20xx and newer, or the 580xx legacy driver for older cards back to the GTX 900 series. Reboot afterwards.
|
||||
The installer adds the Vulkan driver for Intel and AMD GPUs, and Intel's video decoding driver, so videos and calls don't decode on the CPU (AMD's comes with Mesa). If there's an NVIDIA GPU and archinstall's proprietary driver wasn't chosen, it installs NVIDIA's driver: the open kernel modules for GTX 16xx / RTX 20xx and newer, or the 580xx legacy driver for older cards back to the GTX 900 series. Reboot afterwards.
|
||||
|
||||
### System defaults
|
||||
|
||||
|
||||
+28
-1
@@ -24,10 +24,33 @@ cd
|
||||
# Exit on any error
|
||||
set -e
|
||||
|
||||
# What can't be fixed from here, checked before anything changes. The rest of
|
||||
# the checks need the repo (system/preflight.sh, below).
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
echo "Run this as your own user, not as root. It asks for your password when it needs sudo."
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f /etc/arch-release ] || ! command -v pacman &> /dev/null; then
|
||||
echo "CoreDesktop needs Arch Linux. See \"Installing Arch\" in the README."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$(uname -m)" != x86_64 ]; then
|
||||
echo "CoreDesktop needs a 64-bit PC (x86_64); this is $(uname -m)."
|
||||
exit 1
|
||||
fi
|
||||
if ! curl -fsS --max-time 15 -o /dev/null https://archlinux.org; then
|
||||
echo "Couldn't reach archlinux.org. Connect to the internet and run this again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ask for the password once, then keep sudo's cached credentials fresh until
|
||||
# the install exits, so long builds don't stop for a password again. Unlike a
|
||||
# passwordless sudoers entry, nothing is left behind if the install is killed.
|
||||
sudo -v
|
||||
if ! sudo -v; then
|
||||
echo "Couldn't use sudo. If your password was right, your user needs sudo rights (in"
|
||||
echo "archinstall, make the user a superuser): https://wiki.archlinux.org/title/Sudo"
|
||||
exit 1
|
||||
fi
|
||||
while kill -0 $$ 2> /dev/null; do sudo -n -v; sleep 60; done 2> /dev/null &
|
||||
SUDO_KEEPALIVE_PID=$!
|
||||
trap 'kill "$SUDO_KEEPALIVE_PID" 2> /dev/null' EXIT
|
||||
@@ -70,6 +93,10 @@ fi
|
||||
source packages.conf
|
||||
source remove-packages.conf
|
||||
|
||||
# Disk space, btrfs, display manager and sound server: stops, asks, or offers
|
||||
# to fix what it finds
|
||||
bash ~/.local/share/coredesktop/system/preflight.sh
|
||||
|
||||
echo "Starting full system setup..."
|
||||
|
||||
# Federated Computer's own packages (Federated Calendar, ...)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# mise now comes from pacman, and shell/bashrc activates it, so remove the copy
|
||||
# mise.run installed in ~/.local/bin and the line it added to ~/.bashrc. Ruby and
|
||||
# Rails are no longer installed for everyone, only with configure languages:
|
||||
# machines that have them keep them, and update keeps Rails on new Rubies.
|
||||
# mise now comes from pacman, and shell/bashrc activates it, so replace the copy
|
||||
# mise.run installed in ~/.local/bin with a link to it, and remove the line
|
||||
# mise.run added to ~/.bashrc. Ruby and Rails are no longer installed for
|
||||
# everyone, only with configure languages: machines that have them keep them,
|
||||
# and update keeps Rails on new Rubies.
|
||||
LANGUAGES_CONF="$HOME/.config/coredesktop/languages"
|
||||
DEFAULT_GEMS="$HOME/.default-gems"
|
||||
|
||||
@@ -19,7 +20,9 @@ if [ -f ~/.bashrc ] && grep -qE '\.local/bin/mise activate' ~/.bashrc; then
|
||||
rm -f "$tmp"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
fi
|
||||
rm -f ~/.local/bin/mise
|
||||
# A link, not nothing: shells opened before this update still run the old
|
||||
# copy's path before every prompt, and would print an error until closed
|
||||
ln -sfn /usr/bin/mise ~/.local/bin/mise || exit 1
|
||||
|
||||
# Ruby that CoreDesktop installed: count it as chosen with configure languages.
|
||||
# From home, so a project's mise.toml in the current directory doesn't count.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Intel GPUs get their video decoding driver (intel-media-driver) too, so
|
||||
# video and calls don't decode on the CPU
|
||||
bash "$HOME/.local/share/coredesktop/system/vulkan.sh"
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# update turns on GDM, which fails every time while another login screen is
|
||||
# on. Keep that one, as install.sh now offers, by marking GDM as turned off.
|
||||
SERVICES_OFF="$HOME/.config/coredesktop/services-off"
|
||||
|
||||
dm="$(readlink /etc/systemd/system/display-manager.service 2> /dev/null)"
|
||||
dm="$(basename "${dm:-none}")"
|
||||
[ "$dm" = none ] || [ "$dm" = gdm.service ] && exit 0
|
||||
grep -qsx "system gdm.service" "$SERVICES_OFF" && exit 0
|
||||
|
||||
mkdir -p "$(dirname "$SERVICES_OFF")" || exit 1
|
||||
echo "system gdm.service" >> "$SERVICES_OFF"
|
||||
echo "Your login screen is ${dm%.service}, so update no longer tries to turn on GNOME's (GDM)."
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Purpose : Check the machine before install.sh sets it up, and offer to fix
|
||||
# what can be fixed: too little disk space, / not on btrfs, a login
|
||||
# screen other than GNOME's GDM, PulseAudio instead of PipeWire.
|
||||
# Exits 1 to stop the install. refresh runs install.sh again, so it
|
||||
# says nothing on a machine where all is well.
|
||||
|
||||
COREDESKTOP="$HOME/.local/share/coredesktop"
|
||||
source "$COREDESKTOP/utils.sh"
|
||||
|
||||
SERVICES_OFF="$HOME/.config/coredesktop/services-off"
|
||||
|
||||
# install.sh is usually piped into bash, so ask on the terminal
|
||||
TTY="${COREDESKTOP_TTY:-/dev/tty}"
|
||||
|
||||
# ask <question> <default y|n> <answer without a terminal y|n>
|
||||
ask() {
|
||||
local answer
|
||||
if ! { : < "$TTY"; } 2> /dev/null; then
|
||||
[ "$3" = y ]
|
||||
return
|
||||
fi
|
||||
if [ "$2" = y ]; then
|
||||
read -rp "$1 [Y/n] " answer < "$TTY"
|
||||
[[ "$answer" != [nN]* ]]
|
||||
else
|
||||
read -rp "$1 [y/N] " answer < "$TTY"
|
||||
[[ "$answer" == [yY]* ]]
|
||||
fi
|
||||
}
|
||||
|
||||
# Set up before: install.sh records migrations as its last step
|
||||
already_installed() {
|
||||
[ -d "$HOME/.local/state/coredesktop/migrations" ]
|
||||
}
|
||||
|
||||
check_disk() {
|
||||
local need=60 free
|
||||
already_installed && need=10
|
||||
free="$(df -k --output=avail / | tail -n 1 | tr -d ' ')"
|
||||
[[ "$free" =~ ^[0-9]+$ ]] || return 0
|
||||
free=$(( free / 1024 / 1024 ))
|
||||
(( free < need )) || return 0
|
||||
echo "Only $free GB is free on /, and this needs about $need GB."
|
||||
ask "Continue anyway?" n n
|
||||
}
|
||||
|
||||
# Can't be fixed without reinstalling Arch, so only asked about the first time
|
||||
check_btrfs() {
|
||||
local fstype
|
||||
already_installed && return 0
|
||||
fstype="$(findmnt -no FSTYPE /)"
|
||||
[ "$fstype" = btrfs ] && return 0
|
||||
echo "/ is on $fstype, not btrfs, so update can't take a snapshot first, and a bad"
|
||||
echo "update can't be rolled back (see Snapshots in the README). Only reinstalling Arch"
|
||||
echo "with btrfs, archinstall's default, changes that."
|
||||
ask "Continue without snapshots?" y y
|
||||
}
|
||||
|
||||
# CoreDesktop turns on GDM, which fails while another login screen is on
|
||||
check_display_manager() {
|
||||
local dm
|
||||
dm="$(readlink /etc/systemd/system/display-manager.service 2> /dev/null)"
|
||||
dm="$(basename "${dm:-none}")"
|
||||
[ "$dm" = none ] || [ "$dm" = gdm.service ] && return 0
|
||||
grep -qsx "system gdm.service" "$SERVICES_OFF" && return 0
|
||||
|
||||
echo "This machine's login screen is ${dm%.service}, not GNOME's (GDM)."
|
||||
if ask "Switch to GNOME's login screen? It takes over when you restart." y n; then
|
||||
# enable_services turns GDM on later in the install
|
||||
sudo systemctl disable "$dm" || return 1
|
||||
else
|
||||
mkdir -p "$(dirname "$SERVICES_OFF")"
|
||||
echo "system gdm.service" >> "$SERVICES_OFF"
|
||||
echo "Keeping ${dm%.service}. Choose GNOME from its session menu when you log in."
|
||||
echo "To switch later: sudo systemctl disable $dm && sudo systemctl enable gdm"
|
||||
echo "then delete the line \"system gdm.service\" from $SERVICES_OFF"
|
||||
fi
|
||||
}
|
||||
|
||||
# PipeWire replaces PulseAudio; GNOME's screen sharing needs it, and calls in
|
||||
# Jitsi and Element work best with it
|
||||
check_sound() {
|
||||
local plugins=()
|
||||
is_installed pulseaudio || return 0
|
||||
|
||||
echo "This machine plays sound through PulseAudio. PipeWire replaces it: GNOME's"
|
||||
echo "screen sharing needs it, and calls in Jitsi and Element work best with it."
|
||||
if ! ask "Switch to PipeWire?" y n; then
|
||||
echo "Keeping PulseAudio."
|
||||
return 0
|
||||
fi
|
||||
# Its modules (bluetooth, ...) need it, so they go first; PipeWire does
|
||||
# what they did
|
||||
mapfile -t plugins < <(pacman -Qq | grep '^pulseaudio-')
|
||||
if (( ${#plugins[@]} > 0 )); then
|
||||
sudo pacman -R --noconfirm "${plugins[@]}" || return 1
|
||||
fi
|
||||
# --ask=4 answers yes to removing pulseaudio, which pipewire-pulse replaces
|
||||
sudo pacman -S --needed --noconfirm --ask=4 pipewire pipewire-pulse pipewire-alsa wireplumber || return 1
|
||||
echo "Switched to PipeWire. It takes over when you log out and in again."
|
||||
}
|
||||
|
||||
check_disk || exit 1
|
||||
check_btrfs || exit 1
|
||||
check_display_manager || exit 1
|
||||
check_sound || exit 1
|
||||
exit 0
|
||||
+6
-3
@@ -1,7 +1,9 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Purpose : Install the Vulkan driver for each Intel or AMD GPU in the machine.
|
||||
# NVIDIA's Vulkan driver comes with nvidia-utils (see nvidia.sh).
|
||||
# Purpose : Install the Vulkan driver for each Intel or AMD GPU in the machine,
|
||||
# and Intel's video decoding driver (VA-API), so video and calls
|
||||
# don't decode on the CPU. AMD's comes with mesa, NVIDIA's with its
|
||||
# driver (see nvidia.sh).
|
||||
|
||||
set -e
|
||||
|
||||
@@ -12,7 +14,8 @@ PACKAGES=()
|
||||
for device in /sys/bus/pci/devices/*; do
|
||||
[[ $(< "$device/class") == 0x03* ]] || continue
|
||||
case "$(< "$device/vendor")" in
|
||||
0x8086) PACKAGES+=(vulkan-intel) ;;
|
||||
# intel-media-driver covers Broadwell (2014) and newer
|
||||
0x8086) PACKAGES+=(vulkan-intel intel-media-driver) ;;
|
||||
0x1002) PACKAGES+=(vulkan-radeon) ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
# A machine where all is well: lots of space, / on btrfs, GDM or no login
|
||||
# screen yet, no PulseAudio. Tests change one thing each.
|
||||
setup() {
|
||||
common_setup
|
||||
mkdir -p "$HOME/.local/share"
|
||||
ln -s "$REPO" "$HOME/.local/share/coredesktop"
|
||||
export FREE_KIB=$((200 * 1024 * 1024)) FSTYPE=btrfs DM="" INSTALLED=""
|
||||
stub df 'printf "Avail\n%s\n" "$FREE_KIB"'
|
||||
stub findmnt 'echo "$FSTYPE"'
|
||||
stub readlink '[ -n "$DM" ] && echo "/usr/lib/systemd/system/$DM"'
|
||||
stub pacman '
|
||||
case "$1" in
|
||||
-Qi) [[ " $INSTALLED " == *" $2 "* ]] ;;
|
||||
-Qq) for p in $INSTALLED; do echo "$p"; done ;;
|
||||
esac'
|
||||
stub sudo
|
||||
# No terminal unless a test gives answers
|
||||
export COREDESKTOP_TTY="$BATS_TEST_TMPDIR/no-tty/tty"
|
||||
}
|
||||
|
||||
answer() {
|
||||
export COREDESKTOP_TTY="$BATS_TEST_TMPDIR/answer"
|
||||
echo "$1" > "$COREDESKTOP_TTY"
|
||||
}
|
||||
|
||||
already_installed() {
|
||||
mkdir -p "$HOME/.local/state/coredesktop/migrations"
|
||||
}
|
||||
|
||||
@test "preflight says nothing and changes nothing when all is well" {
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
[ -z "$output" ]
|
||||
not_called sudo
|
||||
}
|
||||
|
||||
@test "preflight stops on too little disk space unless told to go on" {
|
||||
export FREE_KIB=$((30 * 1024 * 1024))
|
||||
answer n
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *"Only 30 GB is free"* ]]
|
||||
|
||||
answer y
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "preflight needs less space on a machine that's already set up" {
|
||||
export FREE_KIB=$((30 * 1024 * 1024))
|
||||
already_installed
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
[ -z "$output" ]
|
||||
}
|
||||
|
||||
@test "preflight warns once that / isn't btrfs, and goes on without a terminal" {
|
||||
export FSTYPE=ext4
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"/ is on ext4, not btrfs"* ]]
|
||||
|
||||
already_installed
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
[ -z "$output" ]
|
||||
}
|
||||
|
||||
@test "preflight switches another login screen to GDM when asked to" {
|
||||
export DM=sddm.service
|
||||
answer y
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
called sudo systemctl disable sddm.service
|
||||
}
|
||||
|
||||
@test "preflight keeps another login screen, and update then leaves GDM off" {
|
||||
export DM=sddm.service
|
||||
answer n
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
not_called sudo
|
||||
grep -qx "system gdm.service" "$HOME/.config/coredesktop/services-off"
|
||||
|
||||
# Not asked again
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ -z "$output" ]
|
||||
}
|
||||
|
||||
@test "preflight changes no login screen without a terminal to ask on" {
|
||||
export DM=sddm.service
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
not_called sudo
|
||||
}
|
||||
|
||||
@test "preflight replaces PulseAudio and its modules with PipeWire when asked to" {
|
||||
export INSTALLED="pulseaudio pulseaudio-bluetooth"
|
||||
answer y
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
called sudo pacman -R --noconfirm pulseaudio-bluetooth
|
||||
called sudo pacman -S --needed --noconfirm --ask=4 pipewire pipewire-pulse pipewire-alsa wireplumber
|
||||
}
|
||||
|
||||
@test "preflight keeps PulseAudio when told to, or without a terminal" {
|
||||
export INSTALLED="pulseaudio"
|
||||
answer n
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Keeping PulseAudio."* ]]
|
||||
not_called sudo
|
||||
|
||||
export COREDESKTOP_TTY="$BATS_TEST_TMPDIR/no-tty/tty"
|
||||
run bash "$REPO/system/preflight.sh"
|
||||
[ "$status" -eq 0 ]
|
||||
not_called sudo
|
||||
}
|
||||
Reference in New Issue
Block a user