#!/bin/sh # Copyright 2022 Helmut Grohne # SPDX-License-Identifier: MIT # shellcheck disable=SC2016 # Intentional quoting technique set -u ARCHITECTURE=$(dpkg --print-architecture) IMAGE=rootfs.ext2 INCLUDE_PACKAGES=init MIRROR="http://deb.debian.org/debian" SIZE=$((1024*1024*1024)) SSHKEY= SUITE=unstable VMNAME=testvm die() { echo "$*" 1>&2 exit 1 } usage() { die "usage: $0 [-a architecture] [-h hostname] [-k sshkey] [-m mirror] [-o output] [-p packages] [-r release] [-s size_in_GB] [-- mmdebstrap options]" } while test "$#" -gt 0; do case "$1" in -a) test "$#" -eq 1 && usage ARCHITECTURE=$2 shift 2 ;; -h) test "$#" -eq 1 && usage VMNAME=$2 shift 2 ;; -k) test "$#" -eq 1 && usage SSHKEY=$2 shift 2 ;; -m) test "$#" -eq 1 && usage MIRROR=$2 shift 2 ;; -o) test "$#" -eq 1 && usage IMAGE=$2 shift 2 ;; -p) test "$#" -eq 1 && usage INCLUDE_PACKAGES="$INCLUDE_PACKAGES,$2" shift 2 ;; -r) test "$#" -eq 1 && usage SUITE=$2 shift 2 ;; -s) test "$#" -eq 1 && usage SIZE=$(($2*1024*1024*1024)) shift 2 ;; --) shift break ;; *) usage ;; esac done if test -n "$SSHKEY" && ! test -f "$SSHKEY"; then die "error: ssh keyfile '$SSHKEY' not found" fi KERNEL_SUFFIX=-$ARCHITECTURE case "$ARCHITECTURE" in amd64) KERNEL_SUFFIX=-cloud-amd64 if test "$SUITE" = jessie || test "$SUITE" = stretch; then KERNEL_SUFFIX=-amd64 fi ;; armhf) KERNEL_SUFFIX=-armmp ;; i386) KERNEL_SUFFIX=-686-pae ;; mips64el) KERNEL_SUFFIX=-mips64r2el ;; mipsel) KERNEL_SUFFIX=-mips32r2el ;; ppc64el) KERNEL_SUFFIX=-powerpc64le ;; esac INCLUDE_PACKAGES="$INCLUDE_PACKAGES,linux-image$KERNEL_SUFFIX" if test -n "$SSHKEY"; then INCLUDE_PACKAGES="$INCLUDE_PACKAGES,openssh-server" fi # construct mmdebstrap options as $@: set -- \ --verbose \ --variant=apt \ --format=ext2 \ "--architecture=$ARCHITECTURE" \ "--include=$INCLUDE_PACKAGES" \ "$@" # unless we set up a fstab, / will be read-only set -- "--customize-hook=echo '/dev/vda / ext4 defaults 0 1' >"'"$1/etc/fstab"' "$@" # set up a hostname set -- \ "--customize-hook=echo $VMNAME >"'"$1/etc/hostname"' \ "--customize-hook=echo 127.0.0.1 localhost $VMNAME >"'"$1/etc/hosts"' \ "$@" # allow password-less root login set -- '--customize-hook=chroot "$1" passwd --delete root' "$@" # dhcp on all network interfaces set -- \ '--customize-hook=chroot "$1" systemctl enable systemd-networkd.service' \ "--customize-hook=printf '"'[Match]\nName=en*\nName=eth*\n[Network]\nDHCP=yes\n'"'"' > "$1/etc/systemd/network/20-wired.network"' \ "$@" # add ssh key for root if test -n "$SSHKEY"; then set -- \ '--customize-hook=mkdir -p "$1/root/.ssh"' \ "--customize-hook=upload $SSHKEY /root/.ssh/authorized_keys" \ "$@" fi set -- --skip=cleanup/apt "$@" case "$SUITE" in jessie) # Use obsolete and expired keys. set -- '--keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg' "$@" set -- --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"' "$@" # chfn does not work, because libpam-runtime.postinst is late setting up /etc/pam.d/common-auth et al, see #1026765 set -- --extract-hook='chroot "$1" pam-auth-update --package --force' "$@" ;; buster) # We need /var/lib/dpkg/available for dpkg --set-selections to work. set -- '--customize-hook=cat "$1"/var/lib/apt/lists/*_Packages | chroot "$1" dpkg --update-avail' "$@" ;; bookworm|testing|sid|unstable) # Avoid the usrmerge package set -- --hook-dir=/usr/share/mmdebstrap/hooks/merged-usr "$@" ;; esac # suite target mirror set -- "$@" "$SUITE" "$IMAGE" "deb $MIRROR $SUITE main" set -ex mmdebstrap "$@" truncate -s "$SIZE" "$IMAGE" /sbin/resize2fs "$IMAGE" /sbin/tune2fs -i 0 -O extents,uninit_bg,dir_index,has_journal "$IMAGE"