Last active
April 8, 2024 17:44
-
-
Save sfan5/52aa53f5dca06ac3af30455b203d3404 to your computer and use it in GitHub Desktop.
bootable systemd-nspawn containers with Linux distributions: Alpine, Arch Linux, Ubuntu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# Creates a systemd-nspawn container with Alpine | |
MIRROR=http://dl-cdn.alpinelinux.org/alpine | |
VERSION=${VERSION:-v3.19} | |
APKTOOLS_VERSION=2.14.3-r1 | |
wget_or_curl () { | |
if command -v wget >/dev/null; then | |
wget -qO- "$1" | |
elif command -v curl >/dev/null; then | |
curl -Ls "$1" | |
else | |
echo "missing either curl or wget" >&2 | |
return 1 | |
fi | |
} | |
if [ $UID -ne 0 ]; then | |
echo "run this script as root" >&2 | |
exit 1 | |
fi | |
dest="$1" | |
if [ -z "$dest" ]; then | |
echo "Usage: $0 <destination>" >&2 | |
exit 0 | |
fi | |
if [ -e "$dest/usr/bin" ]; then | |
echo "destination already seems to contain a root file system" >&2 | |
exit 1 | |
fi | |
if [[ "$(uname -m)" =~ ^i[3456]86|x86 ]]; then | |
toolarch=x86 | |
guestarch=$toolarch | |
[ "$(uname -m)" = x86_64 ] && guestarch=x86_64 | |
elif [[ "$(uname -m)" =~ ^arm|aarch64 ]]; then | |
toolarch=armv7 | |
guestarch=$toolarch | |
[ "$(uname -m)" = aarch64 ] && guestarch=aarch64 | |
else | |
echo "unsupported architecture" >&2 | |
exit 1 | |
fi | |
apkdir=$(mktemp -d) | |
trap 'rm -rf $apkdir' EXIT | |
wget_or_curl "$MIRROR/latest-stable/main/$toolarch/apk-tools-static-$APKTOOLS_VERSION.apk" \ | |
| tar -xz -C $apkdir || \ | |
{ echo "couldn't download apk-tools, the version might have changed..." >&2; exit 1; } | |
$apkdir/sbin/apk.static \ | |
-X $MIRROR/$VERSION/main -U --arch $guestarch \ | |
--allow-untrusted --root "$dest" \ | |
--initdb add alpine-base | |
mkdir -p "$dest"/{etc/apk,root} | |
# configure mirror | |
printf '%s/%s/main\n%s/%s/community\n' "$MIRROR" $VERSION "$MIRROR" $VERSION >"$dest"/etc/apk/repositories | |
for i in $(seq 0 10); do # https://github.com/systemd/systemd/issues/852 | |
echo "pts/$i" >>"$dest/etc/securetty" | |
done | |
# make console work | |
sed '/tty[0-9]:/ s/^/#/' -i "$dest"/etc/inittab | |
printf 'console::respawn:/sbin/getty 38400 console\n' >>"$dest"/etc/inittab | |
# minimal boot services | |
for s in hostname bootmisc syslog; do | |
ln -s /etc/init.d/$s "$dest"/etc/runlevels/boot/$s | |
done | |
for s in killprocs savecache; do | |
ln -s /etc/init.d/$s "$dest"/etc/runlevels/shutdown/$s | |
done | |
echo "" | |
echo "Alpine $VERSION $guestarch container was created successfully." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# Creates a systemd-nspawn container with Arch Linux | |
MIRROR=http://mirror.fra10.de.leaseweb.net/archlinux | |
ISO_DATE=latest | |
PKG_GROUPS="base" | |
wget_or_curl () { | |
if command -v wget >/dev/null; then | |
wget "$1" -O "$2" | |
elif command -v curl >/dev/null; then | |
curl -L "$1" -o "$2" | |
else | |
echo "missing either curl or wget" >&2 | |
return 1 | |
fi | |
} | |
if [ $UID -ne 0 ]; then | |
echo "run this script as root" >&2 | |
exit 1 | |
fi | |
dest="$1" | |
if [ -z "$dest" ]; then | |
echo "Usage: $0 <destination>" >&2 | |
exit 0 | |
fi | |
if [ -e "$dest/usr/bin" ]; then | |
echo "destination already seems to contain a root file system" >&2 | |
exit 1 | |
fi | |
[ "$(uname -m)" = x86_64 ] || { echo "unsupported architecture" >&2; exit 1; } | |
tarfile=$(mktemp) | |
trap 'rm $tarfile' EXIT | |
wget_or_curl "$MIRROR/iso/$ISO_DATE/archlinux-bootstrap-x86_64.tar.gz" $tarfile | |
mkdir -p "$dest" | |
tar -xzf $tarfile -C "$dest" --strip-components=1 --numeric-owner | |
# configure mirror | |
printf 'Server = %s/$repo/os/$arch\n' $MIRROR >"$dest"/etc/pacman.d/mirrorlist | |
sed '/^root:/ s|\*||' -i "$dest/etc/shadow" # passwordless login | |
rm "$dest/etc/resolv.conf" # systemd configures this | |
# https://github.com/systemd/systemd/issues/852 | |
[ -f "$dest/etc/securetty" ] && \ | |
printf 'pts/%d\n' $(seq 0 10) >>"$dest/etc/securetty" | |
# seems to be this bug https://github.com/systemd/systemd/issues/3611 | |
systemd-machine-id-setup --root="$dest" | |
# install the packages | |
systemd-nspawn -q -D "$dest" sh -c " | |
pacman-key --init && pacman-key --populate | |
pacman -Sy --noconfirm --needed ${PKG_GROUPS} | |
" | |
echo "" | |
echo "Arch Linux container was created successfully (bootstrapped from $ISO_DATE)" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# Creates a systemd-nspawn container with Ubuntu | |
CODENAME=${CODENAME:-jammy} | |
wget_or_curl () { | |
if command -v wget >/dev/null; then | |
wget "$1" -O "$2" | |
elif command -v curl >/dev/null; then | |
curl -L "$1" -o "$2" | |
else | |
echo "missing either curl or wget" >&2 | |
return 1 | |
fi | |
} | |
if [ $UID -ne 0 ]; then | |
echo "run this script as root" >&2 | |
exit 1 | |
fi | |
dest="$1" | |
if [ -z "$dest" ]; then | |
echo "Usage: $0 <destination>" >&2 | |
exit 0 | |
fi | |
if [ -e "$dest/usr/bin" ]; then | |
echo "destination already seems to contain a root file system" >&2 | |
exit 1 | |
fi | |
if [ "$(uname -m)" = x86_64 ]; then | |
guestarch=amd64 | |
elif [ "$(uname -m)" = aarch64 ]; then | |
guestarch=arm64 | |
else | |
echo "unsupported architecture" >&2 | |
exit 1 | |
fi | |
rootfs=$(mktemp) | |
trap 'rm $rootfs' EXIT | |
wget_or_curl "http://cloud-images.ubuntu.com/${CODENAME}/current/${CODENAME}-server-cloudimg-${guestarch}-root.tar.xz" $rootfs | |
mkdir -p "$dest" | |
tar -xaf $rootfs -C "$dest" --numeric-owner | |
sed '/^root:/ s|\*||' -i "$dest/etc/shadow" # passwordless login | |
rm "$dest/etc/resolv.conf" # systemd configures this | |
# https://github.com/systemd/systemd/issues/852 | |
[ -f "$dest/etc/securetty" ] && \ | |
printf 'pts/%d\n' $(seq 0 10) >>"$dest/etc/securetty" | |
>"$dest/etc/fstab" | |
systemd-nspawn -q -D "$dest" /bin/systemctl disable \ | |
ssh systemd-{timesyncd,networkd-wait-online,resolved} | |
# uninstall some packages | |
systemd-nspawn -q -D "$dest" /usr/bin/apt-get -qq satisfy -y --purge 'Conflicts: lxcfs, lxd, snapd, cloud-init' || \ | |
systemd-nspawn -q -D "$dest" /usr/bin/apt-get -qq purge --autoremove snapd lxcfs lxd cloud-init | |
echo "" | |
echo "Ubuntu $CODENAME $guestarch container was created successfully" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you so much for this! I hope you don't mind me using bits of your scripts here: https://github.com/X0RW3LL/XenSpawn
Linked to this gist in the references section <3