Skip to content

Commit

Permalink
Revise installer
Browse files Browse the repository at this point in the history
  • Loading branch information
foxeng committed Jun 10, 2021
1 parent 0765f82 commit 5789825
Show file tree
Hide file tree
Showing 12 changed files with 461 additions and 0 deletions.
1 change: 1 addition & 0 deletions archlive/airootfs/root/.zlogin
@@ -0,0 +1 @@
chmod +x ~/install.sh && ~/install.sh
35 changes: 35 additions & 0 deletions archlive/airootfs/root/README.md
@@ -0,0 +1,35 @@
# Base system installer

Installs and configures the minimal base system, i.e. just enough to hand over
to ansible (bootloader, fs, network, SSH, python). Based on the installation
[guide](https://wiki.archlinux.org/index.php/Installation_guide).

- Supports UEFI and BIOS.
- RTC in localtime (for Win XP compatibility).
- Installs on the largest disk present.
- Single root partition (btrfs with subvolumes) + swap [+ FAT32 ESP when on
UEFI].
- If `/etc/pacman.d/mirrorlist.override` exists, it is used as the mirrorlist
(during installation and for the installed system). Else a mirrorlist is
generated at installation time using
[reflector](https://wiki.archlinux.org/index.php/Reflector).
- Installs the packages specified in `/root/packages` (one package name per
line) to the new system.
- Uses `/root/config/` as an overlay directory for the new system (i.e. copies
anything under it to the corresponding location in the new system). **NOTE**
that file ownership and permissions are _lost_ when creating the image with
[archiso](https://wiki.archlinux.org/index.php/Archiso#Adding_files_to_image).
- Configures DHCP on all ethernet interfaces, using
[systemd-networkd](https://wiki.archlinux.org/index.php/Systemd-networkd).
- If `/root/hostnames` exists, it is used for looking up the desirable hostname
by MAC (one entry per line, formatted as IP;MAC;hostname). Else, a default
hostname is assigned.
- Enables and configures both english the greek UTF locales.
- Generates the
[initramfs](https://wiki.archlinux.org/index.php/Arch_boot_process#initramfs)
with [mkinitcpio](https://wiki.archlinux.org/index.php/Mkinitcpio), adding the
`revert` hook responsible for reverting the file systems state on boot.
- Uses the contents of `/root/root_password` as the root password in the new
system.
- Sets up root SSH access, key-only, using the public key in
`/root/ssh_key.pub`.
14 changes: 14 additions & 0 deletions archlive/airootfs/root/config/etc/initcpio/hooks/revert
@@ -0,0 +1,14 @@
#!/bin/sh

run_hook() {
mkdir -p /mnt/btrfs-root
mount -o subvol=/ -L ROOT /mnt/btrfs-root

rec-sub-del.sh rootfs /mnt/btrfs-root
# This will, as always, not snapshot any subvolumes below rootfs-snap (but
# there shouldn't be any)
btrfs subvolume snapshot /mnt/btrfs-root/rootfs-snap /mnt/btrfs-root/rootfs

umount /mnt/btrfs-root
rmdir /mnt/btrfs-root
}
7 changes: 7 additions & 0 deletions archlive/airootfs/root/config/etc/initcpio/install/revert
@@ -0,0 +1,7 @@
#!/bin/sh

build() {
add_binary btrfs
add_binary rec-sub-del.sh
add_runscript
}
28 changes: 28 additions & 0 deletions archlive/airootfs/root/config/usr/local/sbin/rec-sub-del.sh
@@ -0,0 +1,28 @@
#!/bin/sh

# Recursively delete all subvolumes under the directory given in the first
# argument (as a path relative to the top level subvolume). If this directory
# is a subvolume, delete it as well. Need to provide the mount point for the
# top level subvolume as the second argument as an absolute path.

if [ $# -lt 2 ]
then
echo "Usage: ${0} <target-dir> <top-level-mount-point>"
exit
fi
target=${1}
# Mount point for top level subvolume (remove trailing / if there is any)
top=${2%/}

# List of subvolume paths (relative to the top level subvolume) under the target
# subvolume (including the target), sorted by their path (descending, ie bottom-up).
# 'btrfs subvolume list' lists all subvolumes in the filesystem.
# NOTE: '^${target}' instead of '^${target}$|^${target}/' would include eg
# 'home-snap' when target is 'home'
subvols=$(btrfs subvolume list --sort=-path ${top} | awk '{print $NF}' | grep -E "^${target}$|^${target}/")

# Delete all subvolumes in subvols
for sub in ${subvols}
do
btrfs subvolume delete ${top}/${sub}
done
18 changes: 18 additions & 0 deletions archlive/airootfs/root/config/usr/local/sbin/replace-snap.sh
@@ -0,0 +1,18 @@
#!/bin/sh

# Replace root filesystem snapshot with one taken of the current filesystem
# (when it powers off). In essence, make the system state when it is next
# powered off permanent.

mv /root/btrfs-root/rootfs /root/btrfs-root/rootfs-tmp
mv /root/btrfs-root/rootfs-snap /root/btrfs-root/rootfs
mv /root/btrfs-root/rootfs-tmp /root/btrfs-root/rootfs-snap

# Swapping the subvolumes above means that on the next boot, the bootloader will
# load the kernel image in /root/btrfs-root/rootfs/boot, which is the OLD one
# (the one from the previous snapshot). To correct that, we copy /boot from the
# current system there.
rm -rf /root/btrfs-root/rootfs/boot
cp -r /boot /root/btrfs-root/rootfs/

# TODO OPT: Keep a temporary backup of /boot on the snapshot?
15 changes: 15 additions & 0 deletions archlive/airootfs/root/config/usr/local/sbin/revert-home.sh
@@ -0,0 +1,15 @@
#!/bin/sh

# Revert /home before login (assuming we are successfully booted already, /home
# should be mounted).

if umount -R /home
then
/usr/local/sbin/rec-sub-del.sh home /root/btrfs-root
btrfs subvolume snapshot /root/btrfs-root/home-snap /root/btrfs-root/home
mount /home
else
rm -rf /home/labuser/
cp -r /root/btrfs-root/home-snap/labuser/ /home/ # could use --reflink
chown -R labuser:labuser /home/labuser/
fi
95 changes: 95 additions & 0 deletions archlive/airootfs/root/install-chroot.sh
@@ -0,0 +1,95 @@
#!/bin/bash

# Script to perform initial system configuration inside chroot

set -v
set -o pipefail

# Figure out which device we are on
# TODO OPT: Receive as argument
disk=$(lsblk --nodeps --noheadings --list --output PKNAME \
$(findmnt --noheadings --list --nofsroot --output SOURCE / \
| head --lines 1)) || exit 1
echo "chroot disk=${disk}"
# Enable TRIM, if supported
trim=$(lsblk --nodeps --noheadings --list --output DISC-GRAN "/dev/${disk}" \
| head --lines 1 | xargs) || exit 1 # xargs to remove whitespace
[[ "${trim}" != "0B" ]] && systemctl enable fstrim.timer

# Timezone
# We can't use timedatectl under a chroot because it requires an active dbus
# (see note in https://wiki.archlinux.org/index.php/Time#Time_standard)
ln -sf /usr/share/zoneinfo/Europe/Athens /etc/localtime &&
hwclock --systohc --localtime || exit 1 # necessary to create /etc/adjtime

# Localization
# Uncomment en_US.UTF-8 UTF-8 and el_GR.UTF-8 UTF-8 in /etc/locale.gen
sed -i -e 's/#en_US\.UTF-8 UTF-8/en_US\.UTF-8 UTF-8/g
s/#el_GR\.UTF-8 UTF-8/el_GR\.UTF-8 UTF-8/g' /etc/locale.gen &&
locale-gen &&
cat > /etc/locale.conf <<-'EOF' || exit 1
LANG=en_US.UTF-8
LC_NUMERIC=el_GR.UTF-8
LC_TIME=el_GR.UTF-8
LC_MONETARY=el_GR.UTF-8
LC_PAPER=el_GR.UTF-8
LC_MEASUREMENT=el_GR.UTF-8
EOF

# Network configuration
hostname="${1}"
echo ${hostname} > /etc/hostname &&
cat >> /etc/hosts <<-EOF &&
127.0.0.1 localhost
::1 localhost
127.0.1.1 ${hostname}.localdomain ${hostname}
EOF
cat > /etc/systemd/network/20-wired.network <<-EOF &&
[Match]
Type=ether
[Network]
DHCP=yes
EOF
systemctl enable systemd-networkd.service systemd-resolved.service || exit 1

# Initramfs
# Add 'revert' as the last hook in mkinitcpio.conf
gawk -i inplace -f - /etc/mkinitcpio.conf <<-'EOF' &&
BEGIN { FS = ")" }
/^HOOKS=/ {
print $1 " revert)"
next
}
{ print } # Default action
EOF
mkinitcpio -P || exit 1

# Root password
root_password="${2}"
echo "root:${root_password}" | chpasswd || exit 1

# Configure SSH (root access, only with a key)
ssh_key="${3}"
install --directory --mode 700 /root/.ssh &&
echo "${ssh_key}" > /root/.ssh/authorized_keys &&
chmod 600 /root/.ssh/authorized_keys &&
cat >> /etc/ssh/sshd_config <<-'EOF' &&
# Disable password logins (only use SSH keys)
PasswordAuthentication no
EOF
systemctl enable sshd.service || exit 1

# Boot loader
# Check if / and /boot are on different devices to see if on UEFI or not
if [[ $(stat -c '%d' /) = $(stat -c '%d' /boot) ]]; then
grub-install --target=i386-pc "/dev/${disk}" || exit 1
else
grub-install \
--target=x86_64-efi \
--efi-directory=/boot \
--bootloader-id=GRUB || exit 1
fi
grub-mkconfig -o /boot/grub/grub.cfg || exit 1

0 comments on commit 5789825

Please sign in to comment.