Add instructions for testing ostree-boot
Co-authored-by: Felix Krull <f_krull@gmx.de>
This commit is contained in:
parent
784abb792c
commit
7fb5ae2204
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Testing ostree-boot on an existing system
|
||||||
|
|
||||||
|
Start from an amd64 Debian system (9 or newer, as long as a backported
|
||||||
|
ostree-boot package is available) - it will be switched to a Debian
|
||||||
|
unstable (sid) OSTree-based installation as part of following these
|
||||||
|
instructions. A VM is obviously most convenient, but bare metal should
|
||||||
|
work equally.
|
||||||
|
|
||||||
|
The installation needs to satisfy the following requirements:
|
||||||
|
|
||||||
|
* It must have a separate /boot partition (this is a general libostree
|
||||||
|
limitation [1]).
|
||||||
|
* The root partition must not be encrypted.
|
||||||
|
* It must use GRUB and BIOS booting. Other bootloaders or EFI may require
|
||||||
|
different bootloader setup steps. [2]
|
||||||
|
|
||||||
|
[1]: https://github.com/ostreedev/ostree/issues/1452
|
||||||
|
[2]: https://pagure.io/workstation-ostree-config/blob/5b574d39c63b82b397df789eb4a75a5bdcc13dd0/f/README-install-inside.md
|
||||||
|
|
||||||
|
We need the bootloader integration files on the non-OSTree system from
|
||||||
|
which we are switching, as well as in the OSTree-based installation,
|
||||||
|
so the bootloader gets configured properly when we "ostree admin deploy":
|
||||||
|
|
||||||
|
# apt-get update
|
||||||
|
# apt-get install ostree ostree-boot multistrap
|
||||||
|
|
||||||
|
Create the ostree system repository and a stateroot:
|
||||||
|
|
||||||
|
# ostree admin init-fs /
|
||||||
|
# ostree admin os-init debian
|
||||||
|
|
||||||
|
Copy modified-deb-ostree-builder, ostree-1.conf and ostree-2.conf from
|
||||||
|
debian/ostree-boot-examples/ to the test machine, and run the builder
|
||||||
|
script:
|
||||||
|
|
||||||
|
# chmod +x ./deb-ostree-builder
|
||||||
|
# ./deb-ostree-builder ./ostree-1.conf sid-1 /ostree/repo
|
||||||
|
# ./deb-ostree-builder ./ostree-2.conf sid-2 /ostree/repo
|
||||||
|
|
||||||
|
If ostree-boot is not available in the target suite in the Debian
|
||||||
|
archive yet, then you will need to edit ostree-1.conf and ostree-2.conf to
|
||||||
|
remove ostree-boot from the bootstrap, and instead put the ostree-boot,
|
||||||
|
ostree and libostree-1-1 packages in /root/extra-packages, and use
|
||||||
|
modified-deb-ostree-builder instead of deb-ostree-builder. This is a
|
||||||
|
temporary hack to solve the chicken-and-egg situation of not adding
|
||||||
|
ostree-boot to the Debian archive until it is testable, but not being
|
||||||
|
able to test it until it is in the archive.
|
||||||
|
|
||||||
|
Then we deploy the first of those commits:
|
||||||
|
|
||||||
|
# ostree admin deploy --karg-proc-cmdline --os=debian os/debian/amd64/sid-1
|
||||||
|
# deploy=$(find /ostree/deploy/debian/deploy/* -maxdepth 0 -type d)
|
||||||
|
|
||||||
|
Next, we set the root password and copy a few essential configuration files
|
||||||
|
into the initial deployment:
|
||||||
|
|
||||||
|
# chroot $deploy passwd root
|
||||||
|
# : > $deploy/etc/machine-id
|
||||||
|
# for f in etc/fstab etc/default/grub; do cp /$f $deploy/$f; done
|
||||||
|
|
||||||
|
Finally, we set up the bootloader by pointing GRUB at the configuration file
|
||||||
|
managed by ostree. Alternatively, you can run update-grub by hand after every
|
||||||
|
new ostree deployment. This step may be different or unnecessary for other
|
||||||
|
bootloaders.
|
||||||
|
|
||||||
|
# mv /boot/grub/grub.cfg /boot/grub/grub.cfg.backup
|
||||||
|
# ln -s ../loader/grub.cfg /boot/grub/grub.cfg
|
||||||
|
|
||||||
|
Now reboot. Make sure to select the new ostree entry in the bootloader. Log in
|
||||||
|
as root using the password you selected before. The system is rather
|
||||||
|
unconfigured (network access can be set up in /etc/network/interfaces). This is
|
||||||
|
the commit built from the ostree-1.conf file, so it doesn't have the hello
|
||||||
|
package:
|
||||||
|
|
||||||
|
# hello
|
||||||
|
-bash: hello: command not found
|
||||||
|
|
||||||
|
Now we can deploy the second commit from inside the ostree system:
|
||||||
|
|
||||||
|
# ostree admin deploy --karg-proc-cmdline --os=debian os/debian/amd64/sid-2
|
||||||
|
|
||||||
|
Reboot again. Note that your new deployment will again be the first ostree
|
||||||
|
entry in the menu, labelled `ostree:0`. Your old deployment has been moved
|
||||||
|
down the menu to `ostree:1`. The root password and the other configuration
|
||||||
|
was copied from the first deployment, so you can log in as before.
|
||||||
|
|
||||||
|
Now try running the hello command again:
|
||||||
|
|
||||||
|
# hello
|
||||||
|
Hello, world!
|
||||||
|
|
||||||
|
This shows we've now booted the second commit built from ostree-2.conf, which
|
||||||
|
includes the hello package.
|
||||||
|
|
@ -0,0 +1,309 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# deb-ostree-builder - Build bootable Debian OSTree commits
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Dan Nicholson <nicholson@endlessm.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
PROG=$(readlink -f "$0")
|
||||||
|
PROGDIR=$(dirname "$PROG")
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
ARCH=$(dpkg --print-architecture)
|
||||||
|
BUILDDIR=
|
||||||
|
GPG_SIGN=()
|
||||||
|
GPG_HOMEDIR=
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [OPTION...] CONFIG SUITE REPO
|
||||||
|
|
||||||
|
-a, --arch build architecture
|
||||||
|
-d, --dir build directory
|
||||||
|
--gpg-sign GPG key ID to use for signing
|
||||||
|
--gpg-homedir GPG homedir to find keys
|
||||||
|
-h, --help show this message and exit
|
||||||
|
|
||||||
|
deb-ostree-builder constructs a Debian OS for use as a bootable
|
||||||
|
OSTree. It uses debootstrap to construct the OS, adjusts it to be
|
||||||
|
compatible with OSTree, and then commits it to a repository.
|
||||||
|
|
||||||
|
CONFIG is a multistrap configuration file. SUITE is the distribution
|
||||||
|
codename. This is used for the OSTree ref and must match the
|
||||||
|
multistrap configuration. REPO is the path the the OSTree repository
|
||||||
|
where the commit will be made.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
ARGS=$(getopt -n "$0" \
|
||||||
|
-o a:d:h \
|
||||||
|
-l arch:,dir:,gpg-sign:,gpg-homedir:,help \
|
||||||
|
-- "$@")
|
||||||
|
eval set -- "$ARGS"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-a|--arch)
|
||||||
|
ARCH=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-d|--dir)
|
||||||
|
BUILDDIR=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gpg-sign)
|
||||||
|
GPG_SIGN+=($2)
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gpg-homedir)
|
||||||
|
GPG_HOMEDIR=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo "Must specify CONFIG, SUITE and REPO" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONFIG=$1
|
||||||
|
SUITE=$2
|
||||||
|
REPO=$3
|
||||||
|
|
||||||
|
# Mount cleanup handler
|
||||||
|
DEVICES_MOUNTED=false
|
||||||
|
cleanup_mounts()
|
||||||
|
{
|
||||||
|
if $DEVICES_MOUNTED; then
|
||||||
|
echo "Unmounting filesystems in $BUILDDIR"
|
||||||
|
for dir in dev/pts dev sys proc; do
|
||||||
|
umount "$BUILDDIR/$dir"
|
||||||
|
done
|
||||||
|
DEVICES_MOUNTED=false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exit handler
|
||||||
|
TMP_BUILDDIR=
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
cleanup_mounts || true
|
||||||
|
if [ -n "$TMP_BUILDDIR" ]; then
|
||||||
|
rm -rf "$TMP_BUILDDIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
if [ -n "$BUILDDIR" ]; then
|
||||||
|
# Create specified build directory
|
||||||
|
echo "Creating $BUILDDIR"
|
||||||
|
mkdir -p "$BUILDDIR"
|
||||||
|
else
|
||||||
|
# Create a temporary build directory in /var/tmp since it could be
|
||||||
|
# fairly large
|
||||||
|
TMP_BUILDDIR=$(mktemp -d -p /var/tmp deb-ostree-builder-XXXXXXXX)
|
||||||
|
BUILDDIR=$TMP_BUILDDIR
|
||||||
|
echo "Using temporary directory $BUILDDIR for build"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure that dracut makes generic initramfs instead of looking just
|
||||||
|
# at the host configuration. This is also in the dracut-config-generic
|
||||||
|
# package, but that only gets installed after dracut makes the first
|
||||||
|
# initramfs.
|
||||||
|
echo "Configuring dracut for generic initramfs"
|
||||||
|
mkdir -p "$BUILDDIR"/etc/dracut.conf.d
|
||||||
|
cat > "$BUILDDIR"/etc/dracut.conf.d/90-deb-ostree.conf <<EOF
|
||||||
|
# Don't make host-specific initramfs
|
||||||
|
hostonly=no
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Define a temporary policy-rc.d that ensures that no daemons are
|
||||||
|
# launched from the installation.
|
||||||
|
mkdir -p "$BUILDDIR"/usr/sbin
|
||||||
|
cat > "$BUILDDIR"/usr/sbin/policy-rc.d <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
exit 101
|
||||||
|
EOF
|
||||||
|
chmod +x "$BUILDDIR"/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
# Mount common kernel filesystems. dracut expects /dev to be mounted.
|
||||||
|
echo "Mounting filesystems in $BUILDDIR"
|
||||||
|
DEVICES_MOUNTED=true
|
||||||
|
for dir in proc sys dev dev/pts; do
|
||||||
|
mkdir -p "$BUILDDIR/$dir"
|
||||||
|
mount --bind "/$dir" "$BUILDDIR/$dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build with multistrap
|
||||||
|
echo "Building system with multistrap in $BUILDDIR"
|
||||||
|
multistrap -f "$CONFIG" -d "$BUILDDIR"
|
||||||
|
|
||||||
|
# All done with filesystems
|
||||||
|
cleanup_mounts
|
||||||
|
|
||||||
|
# Remove temporary policy-rc.d
|
||||||
|
rm -f "$BUILDDIR"/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
# Cleanup cruft
|
||||||
|
echo "Preparing system for OSTree"
|
||||||
|
rm -rf \
|
||||||
|
"$BUILDDIR"/boot/*.bak \
|
||||||
|
"$BUILDDIR"/etc/apt/sources.list~ \
|
||||||
|
"$BUILDDIR"/etc/apt/trusted.gpg~ \
|
||||||
|
"$BUILDDIR"/etc/{passwd,group,shadow,gshadow}- \
|
||||||
|
"$BUILDDIR"/var/cache/debconf/*-old \
|
||||||
|
"$BUILDDIR"/var/lib/dpkg/*-old \
|
||||||
|
"$BUILDDIR"/boot/{initrd.img,vmlinuz} \
|
||||||
|
"$BUILDDIR"/{initrd.img,vmlinuz}{,.old}
|
||||||
|
|
||||||
|
# Remove dbus machine ID cache (makes each system unique)
|
||||||
|
rm -f "$BUILDDIR"/var/lib/dbus/machine-id "$BUILDDIR"/etc/machine-id
|
||||||
|
|
||||||
|
# Remove resolv.conf copied from the host by debootstrap. The settings
|
||||||
|
# are only valid on the target host and will be populated at runtime.
|
||||||
|
rm -f "$BUILDDIR"/etc/resolv.conf
|
||||||
|
|
||||||
|
# Remove temporary files
|
||||||
|
rm -rf "$BUILDDIR"/var/cache/man/*
|
||||||
|
rm -rf "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
mkdir -p "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
chmod 1777 "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
|
||||||
|
# OSTree uses a single checksum of the combined kernel and initramfs
|
||||||
|
# to manage boot. Determine the checksum and rename the files the way
|
||||||
|
# OSTree expects.
|
||||||
|
echo "Renaming kernel and initramfs per OSTree requirements"
|
||||||
|
pushd "$BUILDDIR"/boot >/dev/null
|
||||||
|
|
||||||
|
vmlinuz_match=(vmlinuz*)
|
||||||
|
vmlinuz_file=${vmlinuz_match[0]}
|
||||||
|
initrd_match=(initrd.img* initramfs*)
|
||||||
|
initrd_file=${initrd_match[0]}
|
||||||
|
|
||||||
|
csum=$(cat ${vmlinuz_file} ${initrd_file} | \
|
||||||
|
sha256sum --binary | \
|
||||||
|
awk '{print $1}')
|
||||||
|
echo "OSTree boot checksum: ${csum}"
|
||||||
|
|
||||||
|
mv ${vmlinuz_file} ${vmlinuz_file}-${csum}
|
||||||
|
mv ${initrd_file} ${initrd_file/initrd.img/initramfs}-${csum}
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
# OSTree only commits files or symlinks
|
||||||
|
rm -rf "$BUILDDIR"/dev
|
||||||
|
mkdir -p "$BUILDDIR"/dev
|
||||||
|
|
||||||
|
# Fixup home directory base paths for OSTree
|
||||||
|
sed -i -e 's|DHOME=/home|DHOME=/sysroot/home|g' \
|
||||||
|
"${BUILDDIR}"/etc/adduser.conf
|
||||||
|
sed -i -e 's|# HOME=/home|HOME=/sysroot/home|g' \
|
||||||
|
"${BUILDDIR}"/etc/default/useradd
|
||||||
|
|
||||||
|
# Move /etc to /usr/etc.
|
||||||
|
#
|
||||||
|
# FIXME: Need to handle passwd and group to be updatable. This can be
|
||||||
|
# done with libnss-altfiles, though that has other drawbacks.
|
||||||
|
if [ -d "${BUILDDIR}"/usr/etc ]; then
|
||||||
|
echo "ERROR: Non-empty /usr/etc found!" >&2
|
||||||
|
ls -lR "${BUILDDIR}"/usr/etc
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mv "${BUILDDIR}"/etc "${BUILDDIR}"/usr
|
||||||
|
|
||||||
|
# Move dpkg database to /usr so it's accessible after the OS /var is
|
||||||
|
# mounted, but make a symlink so it works without modifications to dpkg
|
||||||
|
# or apt
|
||||||
|
mkdir -p "${BUILDDIR}"/usr/share/dpkg
|
||||||
|
if [ -e "${BUILDDIR}"/usr/share/dpkg/database ]; then
|
||||||
|
echo "ERROR: /usr/share/dpkg/database already exists!" >&2
|
||||||
|
ls -lR "${BUILDDIR}"/usr/share/dpkg/database >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mv "${BUILDDIR}"/var/lib/dpkg "${BUILDDIR}"/usr/share/dpkg/database
|
||||||
|
ln -sr "${BUILDDIR}"/usr/share/dpkg/database \
|
||||||
|
"${BUILDDIR}"/var/lib/dpkg
|
||||||
|
|
||||||
|
# tmpfiles.d setup to make the ostree root compatible with persistent
|
||||||
|
# directories in the sysroot.
|
||||||
|
cat > "${BUILDDIR}"/usr/lib/tmpfiles.d/ostree.conf <<EOF
|
||||||
|
d /sysroot/home 0755 root root -
|
||||||
|
d /sysroot/root 0700 root root -
|
||||||
|
d /var/opt 0755 root root -
|
||||||
|
d /var/local 0755 root root -
|
||||||
|
d /run/media 0755 root root -
|
||||||
|
L /var/lib/dpkg - - - - ../../usr/share/dpkg/database
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create symlinks in the ostree for persistent directories.
|
||||||
|
mkdir -p "${BUILDDIR}"/sysroot
|
||||||
|
rm -rf "${BUILDDIR}"/{home,root,media,opt} "${BUILDDIR}"/usr/local
|
||||||
|
ln -s /sysroot/ostree "${BUILDDIR}"/ostree
|
||||||
|
ln -s /sysroot/home "${BUILDDIR}"/home
|
||||||
|
ln -s /sysroot/root "${BUILDDIR}"/root
|
||||||
|
ln -s /var/opt "${BUILDDIR}"/opt
|
||||||
|
ln -s /var/local "${BUILDDIR}"/usr/local
|
||||||
|
ln -s /run/media "${BUILDDIR}"/media
|
||||||
|
|
||||||
|
# Now ready to commit. Make the repo if necessary. An archive-z2 repo
|
||||||
|
# is used since the intention is to use this repo to serve updates
|
||||||
|
# from.
|
||||||
|
mkdir -p "$REPO"
|
||||||
|
if [ ! -f "$REPO"/config ]; then
|
||||||
|
echo "Initialiazing OSTree repo $REPO"
|
||||||
|
ostree --repo="$REPO" init --mode=archive-z2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make the commit. The ostree ref is flatpak style.
|
||||||
|
branch="os/debian/$ARCH/$SUITE"
|
||||||
|
COMMIT_OPTS=(
|
||||||
|
--repo="$REPO"
|
||||||
|
--branch="$branch"
|
||||||
|
--subject="Build $SUITE $ARCH $(date --iso-8601=seconds)"
|
||||||
|
--skip-if-unchanged
|
||||||
|
--table-output
|
||||||
|
)
|
||||||
|
for id in ${GPG_SIGN[@]}; do
|
||||||
|
COMMIT_OPTS+=(--gpg-sign="$id")
|
||||||
|
done
|
||||||
|
if [ -n "$GPG_HOMEDIR" ]; then
|
||||||
|
COMMIT_OPTS+=(--gpg-homedir="$GPG_HOMEDIR")
|
||||||
|
fi
|
||||||
|
echo "Committing $BUILDDIR to $REPO branch $branch"
|
||||||
|
ostree commit "${COMMIT_OPTS[@]}" "$BUILDDIR"
|
||||||
|
|
||||||
|
# Update the repo summary
|
||||||
|
SUMMARY_OPTS=(
|
||||||
|
--repo="$REPO"
|
||||||
|
--update
|
||||||
|
)
|
||||||
|
for id in ${GPG_SIGN[@]}; do
|
||||||
|
SUMMARY_OPTS+=(--gpg-sign="$id")
|
||||||
|
done
|
||||||
|
if [ -n "$GPG_HOMEDIR" ]; then
|
||||||
|
SUMMARY_OPTS+=(--gpg-homedir="$GPG_HOMEDIR")
|
||||||
|
fi
|
||||||
|
echo "Updating $REPO summary file"
|
||||||
|
ostree summary "${SUMMARY_OPTS[@]}"
|
||||||
|
|
@ -0,0 +1,321 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# deb-ostree-builder - Build bootable Debian OSTree commits
|
||||||
|
# This version has been modified to install extra packages from
|
||||||
|
# /root/extra-packages.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Dan Nicholson <nicholson@endlessm.com>
|
||||||
|
# Copyright (C) 2019 Simon McVittie
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
PROG=$(readlink -f "$0")
|
||||||
|
PROGDIR=$(dirname "$PROG")
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
ARCH=$(dpkg --print-architecture)
|
||||||
|
BUILDDIR=
|
||||||
|
GPG_SIGN=()
|
||||||
|
GPG_HOMEDIR=
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [OPTION...] CONFIG SUITE REPO
|
||||||
|
|
||||||
|
-a, --arch build architecture
|
||||||
|
-d, --dir build directory
|
||||||
|
--gpg-sign GPG key ID to use for signing
|
||||||
|
--gpg-homedir GPG homedir to find keys
|
||||||
|
-h, --help show this message and exit
|
||||||
|
|
||||||
|
deb-ostree-builder constructs a Debian OS for use as a bootable
|
||||||
|
OSTree. It uses debootstrap to construct the OS, adjusts it to be
|
||||||
|
compatible with OSTree, and then commits it to a repository.
|
||||||
|
|
||||||
|
CONFIG is a multistrap configuration file. SUITE is the distribution
|
||||||
|
codename. This is used for the OSTree ref and must match the
|
||||||
|
multistrap configuration. REPO is the path the the OSTree repository
|
||||||
|
where the commit will be made.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
ARGS=$(getopt -n "$0" \
|
||||||
|
-o a:d:h \
|
||||||
|
-l arch:,dir:,gpg-sign:,gpg-homedir:,help \
|
||||||
|
-- "$@")
|
||||||
|
eval set -- "$ARGS"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-a|--arch)
|
||||||
|
ARCH=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-d|--dir)
|
||||||
|
BUILDDIR=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gpg-sign)
|
||||||
|
GPG_SIGN+=($2)
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--gpg-homedir)
|
||||||
|
GPG_HOMEDIR=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $# -lt 3 ]; then
|
||||||
|
echo "Must specify CONFIG, SUITE and REPO" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONFIG=$1
|
||||||
|
SUITE=$2
|
||||||
|
REPO=$3
|
||||||
|
|
||||||
|
# Mount cleanup handler
|
||||||
|
DEVICES_MOUNTED=false
|
||||||
|
cleanup_mounts()
|
||||||
|
{
|
||||||
|
if $DEVICES_MOUNTED; then
|
||||||
|
echo "Unmounting filesystems in $BUILDDIR"
|
||||||
|
for dir in dev/pts dev sys proc; do
|
||||||
|
umount "$BUILDDIR/$dir"
|
||||||
|
done
|
||||||
|
DEVICES_MOUNTED=false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exit handler
|
||||||
|
TMP_BUILDDIR=
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
cleanup_mounts || true
|
||||||
|
if [ -n "$TMP_BUILDDIR" ]; then
|
||||||
|
rm -rf "$TMP_BUILDDIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
if [ -n "$BUILDDIR" ]; then
|
||||||
|
# Create specified build directory
|
||||||
|
echo "Creating $BUILDDIR"
|
||||||
|
mkdir -p "$BUILDDIR"
|
||||||
|
else
|
||||||
|
# Create a temporary build directory in /var/tmp since it could be
|
||||||
|
# fairly large
|
||||||
|
TMP_BUILDDIR=$(mktemp -d -p /var/tmp deb-ostree-builder-XXXXXXXX)
|
||||||
|
BUILDDIR=$TMP_BUILDDIR
|
||||||
|
echo "Using temporary directory $BUILDDIR for build"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure that dracut makes generic initramfs instead of looking just
|
||||||
|
# at the host configuration. This is also in the dracut-config-generic
|
||||||
|
# package, but that only gets installed after dracut makes the first
|
||||||
|
# initramfs.
|
||||||
|
echo "Configuring dracut for generic initramfs"
|
||||||
|
mkdir -p "$BUILDDIR"/etc/dracut.conf.d
|
||||||
|
cat > "$BUILDDIR"/etc/dracut.conf.d/90-deb-ostree.conf <<EOF
|
||||||
|
# Don't make host-specific initramfs
|
||||||
|
hostonly=no
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Define a temporary policy-rc.d that ensures that no daemons are
|
||||||
|
# launched from the installation.
|
||||||
|
mkdir -p "$BUILDDIR"/usr/sbin
|
||||||
|
cat > "$BUILDDIR"/usr/sbin/policy-rc.d <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
exit 101
|
||||||
|
EOF
|
||||||
|
chmod +x "$BUILDDIR"/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
# Mount common kernel filesystems. dracut expects /dev to be mounted.
|
||||||
|
echo "Mounting filesystems in $BUILDDIR"
|
||||||
|
DEVICES_MOUNTED=true
|
||||||
|
for dir in proc sys dev dev/pts; do
|
||||||
|
mkdir -p "$BUILDDIR/$dir"
|
||||||
|
mount --bind "/$dir" "$BUILDDIR/$dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build with multistrap
|
||||||
|
echo "Building system with multistrap in $BUILDDIR"
|
||||||
|
multistrap -f "$CONFIG" -d "$BUILDDIR"
|
||||||
|
|
||||||
|
# This is a hack for testing ostree-boot before it is in the Debian archive
|
||||||
|
if [ -d /root/extra-packages ]; then
|
||||||
|
mkdir "$BUILDDIR/root/extra-packages"
|
||||||
|
cp /root/extra-packages/*.deb "$BUILDDIR/root/extra-packages"
|
||||||
|
chroot "$BUILDDIR" apt -y update
|
||||||
|
chroot "$BUILDDIR" apt -y install /root/extra-packages/*.deb
|
||||||
|
rm -fr "$BUILDDIR/root/extra-packages"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# All done with filesystems
|
||||||
|
cleanup_mounts
|
||||||
|
|
||||||
|
# Remove temporary policy-rc.d
|
||||||
|
rm -f "$BUILDDIR"/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
# Cleanup cruft
|
||||||
|
echo "Preparing system for OSTree"
|
||||||
|
rm -rf \
|
||||||
|
"$BUILDDIR"/boot/*.bak \
|
||||||
|
"$BUILDDIR"/etc/apt/sources.list~ \
|
||||||
|
"$BUILDDIR"/etc/apt/trusted.gpg~ \
|
||||||
|
"$BUILDDIR"/etc/{passwd,group,shadow,gshadow}- \
|
||||||
|
"$BUILDDIR"/var/cache/debconf/*-old \
|
||||||
|
"$BUILDDIR"/var/lib/dpkg/*-old \
|
||||||
|
"$BUILDDIR"/boot/{initrd.img,vmlinuz} \
|
||||||
|
"$BUILDDIR"/{initrd.img,vmlinuz}{,.old}
|
||||||
|
|
||||||
|
# Remove dbus machine ID cache (makes each system unique)
|
||||||
|
rm -f "$BUILDDIR"/var/lib/dbus/machine-id "$BUILDDIR"/etc/machine-id
|
||||||
|
|
||||||
|
# Remove resolv.conf copied from the host by debootstrap. The settings
|
||||||
|
# are only valid on the target host and will be populated at runtime.
|
||||||
|
rm -f "$BUILDDIR"/etc/resolv.conf
|
||||||
|
|
||||||
|
# Remove temporary files
|
||||||
|
rm -rf "$BUILDDIR"/var/cache/man/*
|
||||||
|
rm -rf "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
mkdir -p "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
chmod 1777 "$BUILDDIR"/tmp "$BUILDDIR"/var/tmp
|
||||||
|
|
||||||
|
# OSTree uses a single checksum of the combined kernel and initramfs
|
||||||
|
# to manage boot. Determine the checksum and rename the files the way
|
||||||
|
# OSTree expects.
|
||||||
|
echo "Renaming kernel and initramfs per OSTree requirements"
|
||||||
|
pushd "$BUILDDIR"/boot >/dev/null
|
||||||
|
|
||||||
|
vmlinuz_match=(vmlinuz*)
|
||||||
|
vmlinuz_file=${vmlinuz_match[0]}
|
||||||
|
initrd_match=(initrd.img* initramfs*)
|
||||||
|
initrd_file=${initrd_match[0]}
|
||||||
|
|
||||||
|
csum=$(cat ${vmlinuz_file} ${initrd_file} | \
|
||||||
|
sha256sum --binary | \
|
||||||
|
awk '{print $1}')
|
||||||
|
echo "OSTree boot checksum: ${csum}"
|
||||||
|
|
||||||
|
mv ${vmlinuz_file} ${vmlinuz_file}-${csum}
|
||||||
|
mv ${initrd_file} ${initrd_file/initrd.img/initramfs}-${csum}
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
# OSTree only commits files or symlinks
|
||||||
|
rm -rf "$BUILDDIR"/dev
|
||||||
|
mkdir -p "$BUILDDIR"/dev
|
||||||
|
|
||||||
|
# Fixup home directory base paths for OSTree
|
||||||
|
sed -i -e 's|DHOME=/home|DHOME=/sysroot/home|g' \
|
||||||
|
"${BUILDDIR}"/etc/adduser.conf
|
||||||
|
sed -i -e 's|# HOME=/home|HOME=/sysroot/home|g' \
|
||||||
|
"${BUILDDIR}"/etc/default/useradd
|
||||||
|
|
||||||
|
# Move /etc to /usr/etc.
|
||||||
|
#
|
||||||
|
# FIXME: Need to handle passwd and group to be updatable. This can be
|
||||||
|
# done with libnss-altfiles, though that has other drawbacks.
|
||||||
|
if [ -d "${BUILDDIR}"/usr/etc ]; then
|
||||||
|
echo "ERROR: Non-empty /usr/etc found!" >&2
|
||||||
|
ls -lR "${BUILDDIR}"/usr/etc
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mv "${BUILDDIR}"/etc "${BUILDDIR}"/usr
|
||||||
|
|
||||||
|
# Move dpkg database to /usr so it's accessible after the OS /var is
|
||||||
|
# mounted, but make a symlink so it works without modifications to dpkg
|
||||||
|
# or apt
|
||||||
|
mkdir -p "${BUILDDIR}"/usr/share/dpkg
|
||||||
|
if [ -e "${BUILDDIR}"/usr/share/dpkg/database ]; then
|
||||||
|
echo "ERROR: /usr/share/dpkg/database already exists!" >&2
|
||||||
|
ls -lR "${BUILDDIR}"/usr/share/dpkg/database >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mv "${BUILDDIR}"/var/lib/dpkg "${BUILDDIR}"/usr/share/dpkg/database
|
||||||
|
ln -sr "${BUILDDIR}"/usr/share/dpkg/database \
|
||||||
|
"${BUILDDIR}"/var/lib/dpkg
|
||||||
|
|
||||||
|
# tmpfiles.d setup to make the ostree root compatible with persistent
|
||||||
|
# directories in the sysroot.
|
||||||
|
cat > "${BUILDDIR}"/usr/lib/tmpfiles.d/ostree.conf <<EOF
|
||||||
|
d /sysroot/home 0755 root root -
|
||||||
|
d /sysroot/root 0700 root root -
|
||||||
|
d /var/opt 0755 root root -
|
||||||
|
d /var/local 0755 root root -
|
||||||
|
d /run/media 0755 root root -
|
||||||
|
L /var/lib/dpkg - - - - ../../usr/share/dpkg/database
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create symlinks in the ostree for persistent directories.
|
||||||
|
mkdir -p "${BUILDDIR}"/sysroot
|
||||||
|
rm -rf "${BUILDDIR}"/{home,root,media,opt} "${BUILDDIR}"/usr/local
|
||||||
|
ln -s /sysroot/ostree "${BUILDDIR}"/ostree
|
||||||
|
ln -s /sysroot/home "${BUILDDIR}"/home
|
||||||
|
ln -s /sysroot/root "${BUILDDIR}"/root
|
||||||
|
ln -s /var/opt "${BUILDDIR}"/opt
|
||||||
|
ln -s /var/local "${BUILDDIR}"/usr/local
|
||||||
|
ln -s /run/media "${BUILDDIR}"/media
|
||||||
|
|
||||||
|
# Now ready to commit. Make the repo if necessary. An archive-z2 repo
|
||||||
|
# is used since the intention is to use this repo to serve updates
|
||||||
|
# from.
|
||||||
|
mkdir -p "$REPO"
|
||||||
|
if [ ! -f "$REPO"/config ]; then
|
||||||
|
echo "Initialiazing OSTree repo $REPO"
|
||||||
|
ostree --repo="$REPO" init --mode=archive-z2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make the commit. The ostree ref is flatpak style.
|
||||||
|
branch="os/debian/$ARCH/$SUITE"
|
||||||
|
COMMIT_OPTS=(
|
||||||
|
--repo="$REPO"
|
||||||
|
--branch="$branch"
|
||||||
|
--subject="Build $SUITE $ARCH $(date --iso-8601=seconds)"
|
||||||
|
--skip-if-unchanged
|
||||||
|
--table-output
|
||||||
|
)
|
||||||
|
for id in ${GPG_SIGN[@]}; do
|
||||||
|
COMMIT_OPTS+=(--gpg-sign="$id")
|
||||||
|
done
|
||||||
|
if [ -n "$GPG_HOMEDIR" ]; then
|
||||||
|
COMMIT_OPTS+=(--gpg-homedir="$GPG_HOMEDIR")
|
||||||
|
fi
|
||||||
|
echo "Committing $BUILDDIR to $REPO branch $branch"
|
||||||
|
ostree commit "${COMMIT_OPTS[@]}" "$BUILDDIR"
|
||||||
|
|
||||||
|
# Update the repo summary
|
||||||
|
SUMMARY_OPTS=(
|
||||||
|
--repo="$REPO"
|
||||||
|
--update
|
||||||
|
)
|
||||||
|
for id in ${GPG_SIGN[@]}; do
|
||||||
|
SUMMARY_OPTS+=(--gpg-sign="$id")
|
||||||
|
done
|
||||||
|
if [ -n "$GPG_HOMEDIR" ]; then
|
||||||
|
SUMMARY_OPTS+=(--gpg-homedir="$GPG_HOMEDIR")
|
||||||
|
fi
|
||||||
|
echo "Updating $REPO summary file"
|
||||||
|
ostree summary "${SUMMARY_OPTS[@]}"
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
[general]
|
||||||
|
arch=amd64
|
||||||
|
noauth=false
|
||||||
|
aptsources=debian
|
||||||
|
bootstrap=debian
|
||||||
|
addimportant=true
|
||||||
|
cleanup=true
|
||||||
|
|
||||||
|
[debian]
|
||||||
|
packages=linux-image-amd64 grub-pc dracut ostree-boot
|
||||||
|
# to boot root partitions on LVM
|
||||||
|
packages=lvm2
|
||||||
|
# usrmerge is required by the builder script
|
||||||
|
packages=usrmerge
|
||||||
|
source=http://deb.debian.org/debian
|
||||||
|
keyring=debian-archive-keyring
|
||||||
|
suite=sid
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
[general]
|
||||||
|
arch=amd64
|
||||||
|
noauth=false
|
||||||
|
aptsources=debian
|
||||||
|
bootstrap=debian
|
||||||
|
addimportant=true
|
||||||
|
cleanup=true
|
||||||
|
|
||||||
|
[debian]
|
||||||
|
packages=linux-image-amd64 grub-pc dracut ostree-boot
|
||||||
|
# to boot root partitions on LVM
|
||||||
|
packages=lvm2
|
||||||
|
# usrmerge is required by the builder script
|
||||||
|
packages=usrmerge
|
||||||
|
# an extra package to verify deployment change
|
||||||
|
packages=hello
|
||||||
|
source=http://deb.debian.org/debian
|
||||||
|
keyring=debian-archive-keyring
|
||||||
|
suite=sid
|
||||||
Loading…
Reference in New Issue