Skip to content

Instantly share code, notes, and snippets.

@mkjaer
Created May 28, 2018 09:17
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mkjaer/cd4a1fa72fa3224a4651982b86b5d487 to your computer and use it in GitHub Desktop.
Save mkjaer/cd4a1fa72fa3224a4651982b86b5d487 to your computer and use it in GitHub Desktop.
Create unattended Ubuntu ISO
#!/bin/bash
cd $(dirname "${0}")
UBUNTU_VERSION=${UBUNTU_VERSION:=16.04.3}
INSTALL_HOSTNAME=${INSTALL_HOSTNAME:=ubuntu}
USERNAME=${USERNAME:=username}
PASSWORD=${PASSWORD:=password}
SEED_FILE=${SEED_FILE:=lvm.seed}
TIMEZONE=${TIMEZONE:=$(cat /etc/timezone)}
DOWNLOAD_FILE="ubuntu-$UBUNTU_VERSION-server-amd64.iso"
DOWNLOAD_LOCATION="http://releases.ubuntu.com/$UBUNTU_VERSION/"
NEW_ISO_NAME="ubuntu-$UBUNTU_VERSION-server-amd64-unattended.iso"
SCRIPT_PATH="${PWD}"
TMP="${PWD}/tmp" # Working folder
# Only run as root
if [ $(whoami) != "root" ]; then
echo "This script can only be run as root..."
exit 1
fi
# Download the iso file if it doesn't already exist
if [[ ! -f $TMP/$DOWNLOAD_FILE ]]; then
echo -n "Downloading $DOWNLOAD_FILE: "
wget "$DOWNLOAD_LOCATION$DOWNLOAD_FILE" --directory-prefix=$TMP
if [[ $? -ne 0 ]]; then
echo "Error: Failed to download ISO: $DOWNLOAD_LOCATION$DOWNLOAD_FILE"
echo "You can download it manually and move it to $TMP/$DOWNLOAD_FILE"
exit 1
fi
fi
# Copy seed file
echo -n "Copying $SEED_FILE: "
if [[ ! -f $SCRIPT_PATH/$SEED_FILE ]]; then
echo "No seed file ($SEED_FILE) found. Aborting..."
exit 1
fi
cp $SCRIPT_PATH/$SEED_FILE $TMP/
# install required packages
if [ -z $(which mkpasswd) ] || [ -z $(which mkisofs) ] || [ -z $(which isohybrid) ]; then
echo "Installing required packages..."
apt-get -y update > /dev/null 2>&1
apt-get -y install whois genisoimage syslinux > /dev/null
#16.04
if [ $(fgrep "16.04" /etc/os-release) ]; then
apt-get -y install syslinux-utils > /dev/null
fi
fi
# Create working folders
echo "Creating working folders..."
mkdir -p $TMP/iso_org $TMP/iso_new
# Mount the image
if [[ -z $(grep $TMP/iso_org /proc/mounts) ]]; then
echo "Mounting original iso file..."
mount -o loop $TMP/$DOWNLOAD_FILE $TMP/iso_org
fi
# Copy the iso contents to the working directory
cp -rT $TMP/iso_org $TMP/iso_new > /dev/null 2>&1
# Boot without waiting for user input
sed -i -r 's/timeout\s+[0-9]+/timeout 1/g' $TMP/iso_new/isolinux/isolinux.cfg
# Copy the seed file to the iso
cp -rT $TMP/$SEED_FILE $TMP/iso_new/preseed/$SEED_FILE
# Copy debian packages to be installed later
if [[ -d "packages" ]]; then
echo "Creating $TMP/iso_new/pool/extras/ and copying $(ls packages | wc -l) files/folders..."
mkdir -p $TMP/iso_new/pool/extras/
cp -R packages/ $TMP/iso_new/pool/extras/
else
echo "No packages folder found so nothing extra added..."
fi
# Generate a password hash for the seed file
PWHASH=$(echo $PASSWORD | mkpasswd -s -m sha-512)
# Update the seed file with our input
sed -i "s@{{username}}@$USERNAME@g" $TMP/iso_new/preseed/$SEED_FILE
sed -i "s@{{pwhash}}@$PWHASH@g" $TMP/iso_new/preseed/$SEED_FILE
sed -i "s@{{hostname}}@$INSTALL_HOSTNAME@g" $TMP/iso_new/preseed/$SEED_FILE
sed -i "s@{{timezone}}@$TIMEZONE@g" $TMP/iso_new/preseed/$SEED_FILE
# Calculate checksum for seed file
SEED_CHECKSUM=$(md5sum $TMP/iso_new/preseed/$SEED_FILE)
# Add the autoinstall option to the menu
sed -i "/label install/ilabel autoinstall\n\
menu label ^Autoinstall Ubuntu Server\n\
kernel /install/vmlinuz\n\
append file=/cdrom/preseed/ubuntu-server.seed initrd=/install/initrd.gz pcie_aspm=off auto=true priority=high preseed/file=/cdrom/preseed/$SEED_FILE preseed/file/checksum=$SEED_CHECKSUM --" $TMP/iso_new/isolinux/txt.cfg
echo "Creating the new iso..."
cd $TMP/iso_new
mkisofs -D -r -V "UNATTENDED_UBUNTU" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o $TMP/$NEW_ISO_NAME . > /dev/null 2>&1
# Make iso bootable (for dd'ing to USB stick)
isohybrid $TMP/$NEW_ISO_NAME
# Cleanup
umount $TMP/iso_org
rm -rf $TMP/iso_new $TMP/iso_org $TMP/$SEED_FILE
mkdir -p $SCRIPT_PATH/target
mv $TMP/*-unattended.iso $SCRIPT_PATH/target/
echo
echo "Finished the new iso (target/$NEW_ISO_NAME) created using $SEED_FILE"
echo
# regional setting
d-i debian-installer/language string en_US:en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US
d-i localechooser/supported-locales multiselect en_US.UTF-8
d-i pkgsel/install-language-support boolean true
# Verbose output and no boot splash screen
d-i debian-installer/quiet boolean false
d-i debian-installer/splash boolean false
# force unmount any old disk
d-i preseed/early_command string umount /media || true
# Install hwe kernel
d-i base-installer/kernel/altmeta string hwe-16.04
# Use the following option to add additional boot parameters for the installed system
# cgroup_enable=memory swapaccount=1 is for https://docs.docker.com/engine/installation/linux/linux-postinstall/
d-i debian-installer/add-kernel-opts string vga=normal nomodeset cgroup_enable=memory swapaccount=1 pcie_aspm=off transparent_hugepage=never
# keyboard selection
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/modelcode string pc105
d-i keyboard-configuration/layoutcode string us
d-i keyboard-configuration/variantcode string intl
d-i keyboard-configuration/xkb-keymap select us(intl)
d-i debconf/language string en_US:en
# network settings
d-i netcfg/enable boolean true
d-i netcfg/choose_interface select auto
d-i netcfg/dhcp_timeout string 5
d-i netcfg/get_hostname string {{hostname}}
d-i netcfg/get_domain string {{hostname}}
# mirror settings
d-i apt-setup/no_mirror boolean true
#d-i mirror/country string manual
#d-i mirror/http/hostname string archive.ubuntu.com
#d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string
# clock and timezone settings
d-i time/zone string {{timezone}}
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean false
# user account setup
d-i passwd/root-login boolean false
# Root password, encrypted
d-i passwd/root-password-crypted password {{pwhash}}
d-i passwd/root-password-crypted password {{pwhash}}
d-i passwd/make-user boolean true
d-i passwd/user-fullname string {{username}}
d-i passwd/username string {{username}}
d-i passwd/user-password-crypted password {{pwhash}}
d-i passwd/user-uid string
d-i user-setup/allow-password-weak boolean false
d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare
d-i user-setup/encrypt-home boolean false
# configure apt
d-i apt-setup/restricted boolean true
d-i apt-setup/universe boolean true
d-i apt-setup/backports boolean true
d-i apt-setup/services-select multiselect security
d-i apt-setup/security_host string security.ubuntu.com
d-i apt-setup/security_path string /ubuntu
tasksel tasksel/first multiselect Basic Ubuntu server, openssh-server
d-i pkgsel/upgrade select none
d-i pkgsel/update-policy select none
d-i pkgsel/updatedb boolean false
# disk partitioning
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm_nooverwrite boolean true
d-i partman/confirm boolean true
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
#d-i partman-auto-lvm/no_boot boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman-auto/method string lvm
d-i partman-auto-lvm/guided_size string max
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman-basicfilesystems/no_swap boolean false
d-i partman/default_filesystem string ext4
d-i partman-auto/choose_recipe select preseedrecipe
d-i partman-auto-lvm/new_vg_name string ubuntu-x64-templ
d-i partman-auto/expert_recipe string \
preseedrecipe :: \
512 600 512 ext3 \
$primary{ } $bootable{ } \
method{ format } format{ } \
use_filesystem{ } filesystem{ ext3 } \
mountpoint{ /boot } \
. \
6144 6146 -1 ext4 method{ lvm } $lvmok{ } \
lv_name{ whatever } format{ } \
use_filesystem{ } filesystem{ ext4 } \
mountpoint{ / } \
.
# grub boot loader
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
# finish installation
d-i finish-install/reboot_in_progress note
d-i finish-install/keep-consoles boolean false
d-i cdrom-detect/eject boolean true
d-i debian-installer/exit/halt boolean false
d-i debian-installer/exit/poweroff boolean false
d-i preseed/late_command string cp -a /cdrom/pool/extras/packages/changeip.sh /target/usr/local/bin/changeip;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment