ungleich-tools/opennebula-images/freebsd-build-opennebula-image.sh

200 lines
6.9 KiB
Bash
Raw Normal View History

#!/bin/sh
# This script generates FreeBSD images for OpenNebula, being heavily inspired
# from srht's FreeBSD build image definition. It assumes running on a FreeBSD host.
# ZFS installation as documented by the FreeBSD project
# https://wiki.freebsd.org/RootOnZFS/GPTZFSBoot
set -e
set -x
# XXX: Handle command-line arguments?
RELEASE=13.1-RELEASE
ARCH=amd64
2022-05-25 10:09:19 +00:00
IMAGE_PATH_ZFS="freebsd-zfs-$RELEASE-$(date -I).img.qcow2"
IMAGE_PATH_UFS="freebsd-ufs-$RELEASE-$(date -I).img.qcow2"
IMAGE_SIZE=10G
DIST_BASE="https://download.freebsd.org/ftp/releases/$ARCH/$RELEASE"
2022-05-25 09:04:46 +00:00
CLOUDSETUP_COMMIT=4ac15b8647d5525048c5faa5fd4b28491905d000
CLOUDSETUP_URL="https://git.sr.ht/~jornane/cloudsetup/archive/$CLOUDSETUP_COMMIT.tar.gz"
ZPOOL=zroot
ZPOOL_TMP="zinstalling"
ZFSTARGET="$(mktemp -d /var/tmp/zfsbuild.XXXXX)"
UFSTARGET="$(mktemp -d /var/tmp/ufsbuild.XXXXX)"
2022-05-25 09:04:46 +00:00
CLOUDSETUP_WORK="$(mktemp -d /var/tmp/cloudsetup.XXXXX)"
2022-05-25 10:09:19 +00:00
if zpool list -Ho name "$ZPOOL_TMP" 2>/dev/null; then
echo "The pool $ZPOOL_TMP is already imported." >&2
exit 1
fi
cleanup() {
sync ||:
umount "$UFSTARGET/dev" ||:
umount "$UFSTARGET/tmp" ||:
umount "$UFSTARGET/var/tmp" ||:
umount "$UFSTARGET" ||:
2022-05-25 10:09:19 +00:00
zpool export "$ZPOOL_TMP" ||:
mdconfig -du md0 ||:
mdconfig -du md1 ||:
2022-05-25 10:04:36 +00:00
rm -rf "$CLOUDSETUP_WORK" ||:
rmdir "$ZFSTARGET" ||:
rmdir "$UFSTARGET" ||:
}
trap cleanup EXIT
if [ "$(whoami)" != 'root' ]; then
echo "This script must be run as root." >&2
exit 1
fi
if ! command -v rsync >/dev/null
then
env ASSUME_ALWAYS_YES=YES pkg install -y rsync
fi
if ! command -v qemu-img >/dev/null
then
env ASSUME_ALWAYS_YES=YES pkg install -y qemu-tools
fi
2022-05-25 09:04:46 +00:00
fetch -qo- "$CLOUDSETUP_URL" | tar -C "$CLOUDSETUP_WORK" --strip-components 1 -xzf-
2022-05-25 10:09:19 +00:00
ufsdisk="$(mktemp /var/tmp/ufsdisk.XXXXX)"
truncate -s 6G "$ufsdisk"
mdconfig -a -t vnode -f "$ufsdisk" -u md1
gpart create -s gpt /dev/md1
2022-05-27 20:04:42 +00:00
#gpart add -t efi -l efiboot0 -s 260M md1
gpart add -t freebsd-boot -l gptboot0 -b 40 -s 512K md1
gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 md1
gpart add -t freebsd-ufs -l rootfs -b 1M -s 5G md1
newfs -U /dev/md1p2
# Mount allocated image.
mount /dev/md1p2 "$UFSTARGET"
# Allocate and partition/format disk image.
# We use "legacy boot", aka BIOS boot
# Preferably, we'd use EFI boot here, check the FreeBSD wiki link in the header
# to see how to make that change, but make the EFI partition larger
2022-05-25 10:09:19 +00:00
zfsdisk="$(mktemp /var/tmp/zfsdisk.XXXXX)"
truncate -s 6G "$zfsdisk"
mdconfig -a -t vnode -f "$zfsdisk" -u md0
gpart create -s gpt /dev/md0
2022-05-27 20:04:42 +00:00
#gpart add -t efi -l efiboot0 -s 260M md1
gpart add -t freebsd-boot -l gptboot0 -b 40 -s 512K md0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 md0
gpart add -t freebsd-zfs -l zfs0 -b 1M -s 5G md0
2022-05-25 10:09:19 +00:00
zpool create -O compression=on -o ashift=12 -o "altroot=$ZFSTARGET" -m none -t "$ZPOOL_TMP" "$ZPOOL" md0p2
2022-05-25 10:09:19 +00:00
zfs create -o mountpoint=none "$ZPOOL_TMP/ROOT"
# We set zstd-19 so our image will become smaller, at the cost of a longer build time.
# At the end of the process, we disable zstd-19 again using zfs inherit compression,
# but all files already written will remain zstd-19 compressed
2022-05-25 10:09:19 +00:00
zfs create -o mountpoint=/ -o canmount=noauto "$ZPOOL_TMP/ROOT/default"
mount -t zfs "$ZPOOL_TMP/ROOT/default" "$ZFSTARGET"
zpool set "bootfs=$ZPOOL_TMP/ROOT/default" "$ZPOOL_TMP"
zfs create -o mountpoint=/tmp -o exec=on -o setuid=off "$ZPOOL_TMP/tmp"
zfs create -o canmount=off -o mountpoint=/usr "$ZPOOL_TMP/usr"
zfs create "$ZPOOL_TMP/usr/home"
zfs create -o exec=off -o setuid=off "$ZPOOL_TMP/usr/src"
zfs create -o mountpoint=/usr/ports -o setuid=off "$ZPOOL_TMP/usr/ports"
zfs create -o canmount=off -o mountpoint=/var "$ZPOOL_TMP/var"
zfs create -o exec=off -o setuid=off "$ZPOOL_TMP/var/audit"
zfs create -o exec=off -o setuid=off "$ZPOOL_TMP/var/crash"
zfs create -o exec=off -o setuid=off "$ZPOOL_TMP/var/log"
zfs create -o atime=on -o exec=off -o setuid=off "$ZPOOL_TMP/var/mail"
zfs create -o exec=on -o setuid=off "$ZPOOL_TMP/var/tmp"
ln -s /usr/home "$ZFSTARGET/home"
chmod 1777 "$ZFSTARGET/var/tmp"
chmod 1777 "$ZFSTARGET/tmp"
# Mount dev in chroot
mkdir -p "$UFSTARGET/dev"
mount -t devfs devfs "$UFSTARGET/dev"
# Download and extract base system.
dist_files="kernel.txz base.txz"
dist_dir="/usr/freebsd-dist/$ARCH/$RELEASE"
mkdir -p "$dist_dir" "$UFSTARGET"
for f in $dist_files
do
fetch -m -o "$dist_dir/$f" "$DIST_BASE/$f"
tar -C "$UFSTARGET" -xJf "$dist_dir/$f"
done
# Avoid writing temporary files while building
mount_nullfs /tmp "$UFSTARGET/tmp"
mount_nullfs /var/tmp "$UFSTARGET/var/tmp"
# Install the first-boot script that configures the network and ssh key
2022-05-25 09:04:46 +00:00
make -C "$CLOUDSETUP_WORK/" PREFIX="$UFSTARGET/usr/local" install
# Configure new system.
touch "$UFSTARGET/firstboot"
sysrc -f "$UFSTARGET/boot/loader.conf" \
zfs_load=YES \
autoboot_delay=-1 \
sysrc -f "$UFSTARGET/etc/rc.conf" \
ntpd_enable=YES \
sshd_enable=YES \
growfs_enable=YES \
hostname=freebsd \
2022-05-25 09:04:46 +00:00
firstboot_cloudsetup_enable=YES \
2022-05-25 09:04:46 +00:00
# The resolv.conf file is written by firstboot_cloudsetup
#cp /etc/resolv.conf "$UFSTARGET/etc/resolv.conf"
tzsetup -s -C "$UFSTARGET" UTC
cat >>"$UFSTARGET/etc/ssh/sshd_config" <<EOF
PermitRootLogin yes
PasswordAuthentication no
PermitEmptyPasswords no
EOF
# freebsd-update is only supported for RELEASE
if printf %s "$RELEASE" | grep -q '.-RELEASE$'
then
env PAGER=true /usr/sbin/freebsd-update \
-b "$UFSTARGET" \
--currently-running "$RELEASE" \
--not-running-from-cron -F \
fetch install
fi
rm -rf "$UFSTARGET/var/db/freebsd-update/"* ||:
# Set zstd-19 compression, copy all data to the pool, and then set compression to default again
# This will make the base image smaller, at the cost of taking longer to generate, as zstd-19 is slow to write
# Therefore, afterwards we restore compression to default, so written files stay zstd-19, which is fast to read,
# but files written by the user afterwards will be written with the default compression algorihtm.
2022-05-25 10:09:19 +00:00
zfs set compression=zstd-19 "$ZPOOL_TMP/ROOT/default"
umount "$UFSTARGET/dev" "$UFSTARGET/tmp" "$UFSTARGET/var/tmp"
rsync -aH --fileflags --inplace "$UFSTARGET/." "$ZFSTARGET"
2022-05-27 20:04:42 +00:00
sysrc -f "$UFSTARGET/boot/loader.conf" -x zfs_load
2022-05-27 20:04:42 +00:00
printf '# Device\tMountpoint\tFStype\tOptions\t\tDump\tPass#\n' \
>"$ZFSTARGET/etc/fstab"
printf '# Device\tMountpoint\tFStype\tOptions\t\tDump\tPass#\n%s\t%s\t\t%s\t%s\t%s\t%s\n' \
/dev/gpt/rootfs / ufs rw,noatime 1 1 \
>"$UFSTARGET/etc/fstab"
sync ||:
2022-05-25 10:09:19 +00:00
zfs inherit compression "$ZPOOL_TMP/ROOT/default"
trap : EXIT
cleanup
mkdir -p "$ARCH"
qemu-img convert -f raw -O qcow2 "$zfsdisk" "$ARCH/$IMAGE_PATH_ZFS"
qemu-img convert -f raw -O qcow2 "$ufsdisk" "$ARCH/$IMAGE_PATH_UFS"
rm "$zfsdisk" "$ufsdisk"
# Filesystem will be enlarged by growfs(7) on next startup
qemu-img resize "$ARCH/$IMAGE_PATH_ZFS" "$IMAGE_SIZE"
qemu-img resize "$ARCH/$IMAGE_PATH_UFS" "$IMAGE_SIZE"