A framework for building boot environments
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
tests
LICENSE
README
build_fsimg.sh
build_initramfs.sh
build_iso.sh
build_modules.sh
build_qcow2.sh
build_stage3.sh
build_vmlinuz.sh
config
config.nosquash
configure_stage3.sh
pack_portdir.sh
prepare_dracut.sh
stage_template.sh

README

#!/bin/bash
###########
# Genboot #
###########

# A framework for building boot environments
############################################
#
# Example usage in a qemu/kvm environment
#
# $ qemu-system-x86_64 \
# $     -m 10G \
# $     -enable-kvm \
# $     -smp 6 \
# $     -kernel vmlinuz \
# $     -net nic,model=virtio \
# $     -net user \
# $     -nographic \
# $     -append console=ttyS0 \
# $     -fsdev local,id=portage,path=/usr/portage,security_model=none \
# $     -fsdev local,id=packages,path=/var/lib/portage/packages,security_model=none \
# $     -device virtio-9p-pci,fsdev=portage,mount_tag=portage \
# $     -device virtio-9p-pci,fsdev=packages,mount_tag=packages
#
# Mount the shared portage and package trees using the plan9 filesystem
# # mount -t 9p portage /usr/portage
# # mount -t 9p packages /var/lib/portage/packages
#
# Example usage in a Xen environment
#
# $ cat << EOF > genboot.cfg
# > kernel="/path/to/vmlinuz"
# > vcpus=4
# > memory=10240
# > name="genboot"
# > device_model_override="/usr/bin/qemu-system-x86_64"
# > vif=['script=/path/to/vif-br0']
# > EOF
#
# $ cat << EOF > vif-br0
# > #!/bin/bash
# > test "$1" = "offline" && exit
# > ip link set dev "$vif" master br0
# > ip link set dev "$vif" up
# > EOF
# $ chmod +x vif-br0
#
# This involves lots of RAM, and assumes that you already
# have a bridged network device, br0, configured on the host.
#

# When inside the VM, login as root and run this README file.

# You can use the supplied the kernel image available from
# the github releases page.

# In the meantime, any disposable Gentoo-like environment will do.
# But not the minimal install cd, since that doesn't have 'emerge'.

# If you do have a copy of the all-in-one kernel then you should be aware of
# the changes I have made.
# It does some things atypical to a standard distro initramfs.
#   - Only a kernel is supplied to qemu, there is no stateful disk needed.
#   - The root= kernel cmdline is set inside the initramfs and does not need
#     to be supplied to qemu's "-append".
#   - The VM uses a lot of RAM. All writes are on a RAM backed AUFS rootfs.
#   - QEMU User networking provides a crippled network environment,
#     enough for TCP to download the portage tree and distfiles.
#   - Alternatively use bridged networking, or Xen.
#   - Pointing to a local portage/distfiles mirror is recommended.
#     This involves setting SYNC, GENTOO_MIRRORS and optionally,
#     PORTAGE_BINHOST in /etc/portage/make.conf
#   - No other special networking needs to be made. Qemu can be run as a
#     non-privilaged user.
#   - However, bridged networking is more performant that user networking,
#     and may require administratice access on the host. Not covered here.
#   - While the kernel is fairly standard (sys-kernel/gentoo-sources), however
#     network drivers and other config is tailored for my environment,
#     i.e. qemu/kvm virtio.
#     PXE booting may work, but your hardware might be different.
#   - Kernel modules inside the initramfs are coupled to the kernel version.
#     In theory, the kernel could be compiled without CONFIG_MODULES.
#   - The single kernel image couples the version of kernel modules
#     in the initramfs to the kernel, so the above point is not an issue.
#   - The final image is at least as big as any generated stage tarball and
#     the initramfs will perform a stage3 install during the boot process.
#     This presents a chicken/egg problem to visitors of this git repo that
#     requires the stage3 to build the boot environment, and the boot
#     environment to (cleanly) build the stage tarball.
#   - My custom dracut module is not documented or described here.
#     See prepare_dracut.sh for details.
#   - Once booted, root login is permitted (no password) on the console.
#     This can have security consequences, but this scheme does not allow
#     remote logins, or any password based authentication (e.g. pam/sudo/su)
#     to gain root access.
#     See 'grep root /etc/shadow' for details.
#   - Set a password or download an ssh key on first login.
#     e.g. https://github.com/{username}.keys -> ~/.ssh/authorized_keys

# Set SYNC and GENTOO_MIRRORS variables in /etc/portage/make.conf to
# use a local (and preferably internal) mirror to reduce load on upstream
# Gentoo infrastructure.
set -xe

# If binutils is not installed in $ROOT/usr/portage/profiles
# programs like ar and ld can't be found.
# make the symlinks with binutils-config when a portage tree is available.
ar -V || {
    source /etc/env.d/binutils/$(gcc -dumpmachine)-*
    binutils-config "$TARGET-$VER" && env-update
    source /etc/profile
}

# We'll need git to download these scripts.
# To save on compilation time, skip some of the bigger dependencies.
git --version || {

    # Do we need automake?
    eix -I sys-devel/automake$ || \
    emerge --deep --newuse --verbose --update --jobs \
        --usepkg --buildpkg --getbinpkg \
        sys-devel/automake

    emerge --deep --newuse --verbose --update --jobs \
        --usepkg --buildpkg --getbinpkg \
        dev-vcs/git
}

# These are the steps to run, in order
STAGES=(
  stage_template
  build_stage3
  configure_stage3
  build_modules
  prepare_dracut
  build_initramfs
  build_vmlinuz
  build_fsimg
  build_iso
  build_qcow2
  pack_portdir
)

# Create chroot and .complete files here
cd /root/genboot

# Index the STAGES array, and track the current and next STAGE
for SEQ in $(seq 0 $((${#STAGES} - 1))); do
  STAGE="${STAGES[${SEQ}]}"
  NEXT_STAGE="${STAGES[$((${SEQ} + 1))]}"

  # If the current stage has already run successfully, skip it
  # If the current stage needs to be rebuilt, also rebuild the next stage
  if [[ ! -e ".${STAGE}.complete" ]]; then
    # It is okay if the last +1 stage never exists.
    rm -f ".${NEXT_STAGE}.complete"
    bash "${STAGE}.sh" && touch ".${STAGE}.complete"
  else
    echo "Skipping stage: ${STAGE}"
  fi
done

# Turn off tracing
set +x

# Build artifacts are stored in /root
cd /root

# These files can be used to install Gentoo from stage3
ls -l stage3-systemd.tar.xz # Stage 3 tarball of the rootfs
ls -l systemd.squashfs      # Stage 3 squashfs of the rootfs
ls -l portage.tar.xz        # portage snapshot, with distfiles and binpkgs

ls -l initramfs.cpio        # Uncompressed initramfs with embedded squashfs
                            # Useful for anyone repacking the kernel.

# These are the normal linux image archives, without an embedded squashfs
ls -l linux-image.tar.xz    # vmlinuz + modules tarball (no squash)
ls -l vmlinuz.nosquash      # Normal kernel image, no initramfs
ls -l initramfs.nosquash    # Normal initramfs (with modules), no rootfs

# This is the ultimate build artifact, a self contained kernel image
# with the bundled initramfs and squashfs/overlayfs live environment.
ls -l vmlinuz               # Single kernel image, with initramfs and rootfs
ls -l gentoo-systemd.qcow2  # Cloud-init compatible VM image
ls -l rootfs.img.xz         # Ext4 filesystem based rootfs, good for AMIs
ls -l gentoo-systemd.iso    # ISO-9660 bootable image

# To install a new system, PXE boot into the bundled kernel image, partition and
# create a filesystem and then extract the stage3 tarball, linux-image tarball
# and portage tree (to /usr).
# Grub2 is also included, so the new system can be self hosting.