22set -Eeuo pipefail
33
44function cleanup() {
5- trap - SIGINT SIGTERM ERR EXIT
6- if [ -n " ${tmpdir+x} " ]; then
7- rm -rf " $tmpdir "
8- log " 🚽 Deleted temporary working directory $tmpdir "
9- fi
5+ trap - SIGINT SIGTERM ERR EXIT
6+ if [ -n " ${tmpdir+x} " ]; then
7+ rm -rf " $tmpdir "
8+ log " 🚽 Deleted temporary working directory $tmpdir "
9+ fi
1010}
1111
1212trap cleanup SIGINT SIGTERM ERR EXIT
1313script_dir=$( cd " $( dirname " ${BASH_SOURCE[0]} " ) " & > /dev/null && pwd -P)
14- today=$( /usr/bin/date +" %Y-%m-%d" )
14+ [[ ! -x " $( command -v date) " ]] && echo " 💥 date command not found." && exit 1
15+ today=$( date +" %Y-%m-%d" )
1516
1617function log() {
17- echo >&2 -e " [$( date +" %Y-%m-%d %H:%M:%S" ) ] ${1-} "
18+ echo >&2 -e " [$( date +" %Y-%m-%d %H:%M:%S" ) ] ${1-} "
1819}
1920
2021function die() {
21- local msg=$1
22- local code=${2-1} # Bash parameter expansion - default exit status 1. See https://wiki.bash-hackers.org/syntax/pe#use_a_default_value
23- log " $msg "
24- exit " $code "
22+ local msg=$1
23+ local code=${2-1} # Bash parameter expansion - default exit status 1. See https://wiki.bash-hackers.org/syntax/pe#use_a_default_value
24+ log " $msg "
25+ exit " $code "
2526}
2627
2728usage () {
28- cat << EOF
29+ cat << EOF
2930Usage: $( basename " ${BASH_SOURCE[0]} " ) [-h] [-v] [-a] [-u user-data-file] [-m meta-data-file]
3031
3132💁 This script will create fully-automated Ubuntu 20.04 Focal Fossa installation media.
@@ -40,8 +41,8 @@ Available options:
4041 For more information see: https://ubuntu.com/server/docs/install/autoinstall-quickstart
4142-u, --user-data Path to user-data file. Required if using -a
4243-m, --meta-data Path to meta-data file. Will be an empty file if not specified and using -a
43- -k, --no-verify Disable GPG verification of the source ISO file. By default SHA256SUMS and
44- SHA256SUMS.gpg in ${script_dir} will be used to verify the authenticity and integrity
44+ -k, --no-verify Disable GPG verification of the source ISO file. By default SHA256SUMS- $today and
45+ SHA256SUMS- $today .gpg in ${script_dir} will be used to verify the authenticity and integrity
4546 of the source ISO file. If they are not present the latest daily SHA256SUMS will be
4647 downloaded and saved in ${script_dir} . The Ubuntu signing key will be downloaded and
4748 saved in a new keyring in ${script_dir}
@@ -51,63 +52,63 @@ Available options:
5152-d, --destination Destination ISO file. By default ${script_dir} /ubuntu-autoinstall-$today .iso will be
5253 created, overwriting any existing file.
5354EOF
54- exit
55+ exit
5556}
5657
5758function parse_params() {
58- # default values of variables set from params
59- user_data_file=' '
60- meta_data_file=' '
61- source_iso=" ${script_dir} /ubuntu-original-$today .iso"
62- destination_iso=" ${script_dir} /ubuntu-autoinstall-$today .iso"
63- gpg_verify=1
64- all_in_one=0
65-
66- while : ; do
67- case " ${1-} " in
68- -h | --help) usage ;;
69- -v | --verbose) set -x ;;
70- -a | --all-in-one) all_in_one=1 ;;
71- -k | --no-verify) gpg_verify=0 ;;
72- -u | --user-data)
73- user_data_file=" ${2-} "
74- shift
75- ;;
76- -s | --source)
77- source_iso=" ${2-} "
78- shift
79- ;;
80- -d | --destination)
81- destination_iso=" ${2-} "
82- shift
83- ;;
84- -m | --meta-data)
85- meta_data_file=" ${2-} "
86- shift
87- ;;
88- -?* ) die " Unknown option: $1 " ;;
89- * ) break ;;
90- esac
91- shift
92- done
93-
94- log " 👶 Starting up..."
95-
96- # check required params and arguments
97- if [ ${all_in_one} -ne 0 ]; then
98- [[ -z " ${user_data_file} " ]] && die " 💥 user-data file was not specified."
99- [[ ! -f " $user_data_file " ]] && die " 💥 user-data file could not be found."
100- [[ -n " ${meta_data_file} " ]] && [[ ! -f " $meta_data_file " ]] && die " 💥 meta-data file could not be found."
101- fi
102-
103- if [ " ${source_iso} " != " ${script_dir} /ubuntu-original-$today .iso" ]; then
104- [[ ! -f " ${source_iso} " ]] && die " 💥 Source ISO file could not be found."
105- fi
106-
107- destination_iso=$( realpath " ${destination_iso} " )
108- source_iso=$( realpath " ${source_iso} " )
109-
110- return 0
59+ # default values of variables set from params
60+ user_data_file=' '
61+ meta_data_file=' '
62+ source_iso=" ${script_dir} /ubuntu-original-$today .iso"
63+ destination_iso=" ${script_dir} /ubuntu-autoinstall-$today .iso"
64+ gpg_verify=1
65+ all_in_one=0
66+
67+ while : ; do
68+ case " ${1-} " in
69+ -h | --help) usage ;;
70+ -v | --verbose) set -x ;;
71+ -a | --all-in-one) all_in_one=1 ;;
72+ -k | --no-verify) gpg_verify=0 ;;
73+ -u | --user-data)
74+ user_data_file=" ${2-} "
75+ shift
76+ ;;
77+ -s | --source)
78+ source_iso=" ${2-} "
79+ shift
80+ ;;
81+ -d | --destination)
82+ destination_iso=" ${2-} "
83+ shift
84+ ;;
85+ -m | --meta-data)
86+ meta_data_file=" ${2-} "
87+ shift
88+ ;;
89+ -?* ) die " Unknown option: $1 " ;;
90+ * ) break ;;
91+ esac
92+ shift
93+ done
94+
95+ log " 👶 Starting up..."
96+
97+ # check required params and arguments
98+ if [ ${all_in_one} -ne 0 ]; then
99+ [[ -z " ${user_data_file} " ]] && die " 💥 user-data file was not specified."
100+ [[ ! -f " $user_data_file " ]] && die " 💥 user-data file could not be found."
101+ [[ -n " ${meta_data_file} " ]] && [[ ! -f " $meta_data_file " ]] && die " 💥 meta-data file could not be found."
102+ fi
103+
104+ if [ " ${source_iso} " != " ${script_dir} /ubuntu-original-$today .iso" ]; then
105+ [[ ! -f " ${source_iso} " ]] && die " 💥 Source ISO file could not be found."
106+ fi
107+
108+ destination_iso=$( realpath " ${destination_iso} " )
109+ source_iso=$( realpath " ${source_iso} " )
110+
111+ return 0
111112}
112113
113114ubuntu_gpg_key_id=" 843938DF228D22F7B3742BC0D94AA3F0EFE21092"
@@ -117,105 +118,105 @@ parse_params "$@"
117118tmpdir=$( mktemp -d)
118119
119120if [[ ! " $tmpdir " || ! -d " $tmpdir " ]]; then
120- die " 💥 Could not create temporary working directory."
121+ die " 💥 Could not create temporary working directory."
121122else
122- log " 📁 Created temporary working directory $tmpdir "
123+ log " 📁 Created temporary working directory $tmpdir "
123124fi
124125
125126log " 🔎 Checking for required utilities..."
126- [[ ! -f " /usr/bin/7z " ]] && die " 💥 7z is not installed."
127- [[ ! -f " /usr/bin/ sed" ]] && die " 💥 sed is not installed."
128- [[ ! -f " /usr/bin/ curl" ]] && die " 💥 curl is not installed."
129- [[ ! -f " /usr/bin/ mkisofs" ]] && die " 💥 mkisofs is not installed."
130- [[ ! -f " /usr/bin/ gpg" ]] && die " 💥 gpg is not installed."
127+ [[ ! -x " $( command -v 7z ) " ]] && die " 💥 7z is not installed."
128+ [[ ! -x " $( command -v sed) " ]] && die " 💥 sed is not installed."
129+ [[ ! -x " $( command -v curl) " ]] && die " 💥 curl is not installed."
130+ [[ ! -x " $( command -v mkisofs) " ]] && die " 💥 mkisofs is not installed."
131+ [[ ! -x " $( command -v gpg) " ]] && die " 💥 gpg is not installed."
131132log " 👍 All required utilities are installed."
132133
133134if [ ! -f " ${source_iso} " ]; then
134- log " 🌎 Downloading current daily ISO image for Ubuntu 20.04 Focal Fossa..."
135- /usr/bin/ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/focal-live-server-amd64.iso" -o " ${source_iso} "
136- log " 👍 Downloaded and saved to ${source_iso} "
135+ log " 🌎 Downloading current daily ISO image for Ubuntu 20.04 Focal Fossa..."
136+ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/focal-live-server-amd64.iso" -o " ${source_iso} "
137+ log " 👍 Downloaded and saved to ${source_iso} "
137138else
138- log " ☑️ Using existing ${source_iso} file."
139- if [ ${gpg_verify} -eq 1 ]; then
140- if [ " ${source_iso} " != " ${script_dir} /ubuntu-original-$today .iso" ]; then
141- log " ⚠️ Automatic GPG verification is enabled. If the source ISO file is not the latest daily image, verification will fail!"
142- fi
143- fi
139+ log " ☑️ Using existing ${source_iso} file."
140+ if [ ${gpg_verify} -eq 1 ]; then
141+ if [ " ${source_iso} " != " ${script_dir} /ubuntu-original-$today .iso" ]; then
142+ log " ⚠️ Automatic GPG verification is enabled. If the source ISO file is not the latest daily image, verification will fail!"
143+ fi
144+ fi
144145fi
145146
146147if [ ${gpg_verify} -eq 1 ]; then
147- if [ ! -f " ${script_dir} /SHA256SUMS-${today} " ]; then
148- log " 🌎 Downloading SHA256SUMS & SHA256SUMS.gpg files..."
149- /usr/bin/ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/SHA256SUMS" -o " ${script_dir} /SHA256SUMS-${today} "
150- /usr/bin/ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/SHA256SUMS.gpg" -o " ${script_dir} /SHA256SUMS-${today} .gpg"
151- else
152- log " ☑️ Using existing SHA256SUMS-${today} & SHA256SUMS-${today} .gpg files."
153- fi
154-
155- if [ ! -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring" ]; then
156- log " 🌎 Downloading and saving Ubuntu signing key..."
157- /usr/bin/ gpg -q --no-default-keyring --keyring " ${script_dir} /${ubuntu_gpg_key_id} .keyring" --keyserver " hkp://keyserver.ubuntu.com" --recv-keys " ${ubuntu_gpg_key_id} "
158- log " 👍 Downloaded and saved to ${script_dir} /${ubuntu_gpg_key_id} .keyring"
159- else
160- log " ☑️ Using existing Ubuntu signing key saved in ${script_dir} /${ubuntu_gpg_key_id} .keyring"
161- fi
162-
163- log " 🔐 Verifying ${source_iso} integrity and authenticity..."
164- /usr/bin/ gpg -q --keyring " ${script_dir} /${ubuntu_gpg_key_id} .keyring" --verify " ${script_dir} /SHA256SUMS-${today} .gpg" " ${script_dir} /SHA256SUMS-${today} " 2> /dev/null
165- if [ $? -ne 0 ]; then
166- rm -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring~"
167- die " 👿 Verification of SHA256SUMS signature failed."
168- fi
169-
170- rm -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring~"
171- digest=$( sha256sum " ${source_iso} " | cut -f1 -d ' ' )
172- set +e
173- /usr/bin/ grep -Fq " $digest " " ${script_dir} /SHA256SUMS-${today} "
174- if [ $? -eq 0 ]; then
175- log " 👍 Verification succeeded."
176- set -e
177- else
178- die " 👿 Verification of ISO digest failed."
179- fi
148+ if [ ! -f " ${script_dir} /SHA256SUMS-${today} " ]; then
149+ log " 🌎 Downloading SHA256SUMS & SHA256SUMS.gpg files..."
150+ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/SHA256SUMS" -o " ${script_dir} /SHA256SUMS-${today} "
151+ curl -NsSL " https://cdimage.ubuntu.com/ubuntu-server/focal/daily-live/current/SHA256SUMS.gpg" -o " ${script_dir} /SHA256SUMS-${today} .gpg"
152+ else
153+ log " ☑️ Using existing SHA256SUMS-${today} & SHA256SUMS-${today} .gpg files."
154+ fi
155+
156+ if [ ! -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring" ]; then
157+ log " 🌎 Downloading and saving Ubuntu signing key..."
158+ gpg -q --no-default-keyring --keyring " ${script_dir} /${ubuntu_gpg_key_id} .keyring" --keyserver " hkp://keyserver.ubuntu.com" --recv-keys " ${ubuntu_gpg_key_id} "
159+ log " 👍 Downloaded and saved to ${script_dir} /${ubuntu_gpg_key_id} .keyring"
160+ else
161+ log " ☑️ Using existing Ubuntu signing key saved in ${script_dir} /${ubuntu_gpg_key_id} .keyring"
162+ fi
163+
164+ log " 🔐 Verifying ${source_iso} integrity and authenticity..."
165+ gpg -q --keyring " ${script_dir} /${ubuntu_gpg_key_id} .keyring" --verify " ${script_dir} /SHA256SUMS-${today} .gpg" " ${script_dir} /SHA256SUMS-${today} " 2> /dev/null
166+ if [ $? -ne 0 ]; then
167+ rm -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring~"
168+ die " 👿 Verification of SHA256SUMS signature failed."
169+ fi
170+
171+ rm -f " ${script_dir} /${ubuntu_gpg_key_id} .keyring~"
172+ digest=$( sha256sum " ${source_iso} " | cut -f1 -d ' ' )
173+ set +e
174+ grep -Fq " $digest " " ${script_dir} /SHA256SUMS-${today} "
175+ if [ $? -eq 0 ]; then
176+ log " 👍 Verification succeeded."
177+ set -e
178+ else
179+ die " 👿 Verification of ISO digest failed."
180+ fi
180181else
181- log " 🤞 Skipping verification of source ISO."
182+ log " 🤞 Skipping verification of source ISO."
182183fi
183184log " 🔧 Extracting ISO image..."
184- /usr/bin/ 7z -y x " ${source_iso} " -o" $tmpdir " > /dev/null
185+ 7z -y x " ${source_iso} " -o" $tmpdir " > /dev/null
185186rm -rf " $tmpdir /" ' [BOOT]'
186187log " 👍 Extracted to $tmpdir "
187188
188189log " 🧩 Adding autoinstall parameter to kernel command line..."
189- /usr/bin/ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /isolinux/txt.cfg"
190- /usr/bin/ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /boot/grub/grub.cfg"
191- /usr/bin/ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /boot/grub/loopback.cfg"
190+ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /isolinux/txt.cfg"
191+ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /boot/grub/grub.cfg"
192+ sed -i -e ' s/---/ autoinstall ---/g' " $tmpdir /boot/grub/loopback.cfg"
192193log " 👍 Added parameter to UEFI and BIOS kernel command lines."
193194
194195if [ ${all_in_one} -eq 1 ]; then
195- log " 🧩 Adding user-data and meta-data files..."
196- mkdir " $tmpdir /nocloud"
197- cp " $user_data_file " " $tmpdir /nocloud/user-data"
198- if [ -n " ${meta_data_file} " ]; then
199- cp " $meta_data_file " " $tmpdir /nocloud/meta-data"
200- else
201- touch " $tmpdir /nocloud/meta-data"
202- fi
203- /usr/bin/ sed -i -e ' s,---, ds=nocloud;s=/cdrom/nocloud/ ---,g' " $tmpdir /isolinux/txt.cfg"
204- /usr/bin/ sed -i -e ' s,---, ds=nocloud\\\;s=/cdrom/nocloud/ ---,g' " $tmpdir /boot/grub/grub.cfg"
205- /usr/bin/ sed -i -e ' s,---, ds=nocloud\\\;s=/cdrom/nocloud/ ---,g' " $tmpdir /boot/grub/loopback.cfg"
206- log " 👍 Added data and configured kernel command line."
196+ log " 🧩 Adding user-data and meta-data files..."
197+ mkdir " $tmpdir /nocloud"
198+ cp " $user_data_file " " $tmpdir /nocloud/user-data"
199+ if [ -n " ${meta_data_file} " ]; then
200+ cp " $meta_data_file " " $tmpdir /nocloud/meta-data"
201+ else
202+ touch " $tmpdir /nocloud/meta-data"
203+ fi
204+ sed -i -e ' s,---, ds=nocloud;s=/cdrom/nocloud/ ---,g' " $tmpdir /isolinux/txt.cfg"
205+ sed -i -e ' s,---, ds=nocloud\\\;s=/cdrom/nocloud/ ---,g' " $tmpdir /boot/grub/grub.cfg"
206+ sed -i -e ' s,---, ds=nocloud\\\;s=/cdrom/nocloud/ ---,g' " $tmpdir /boot/grub/loopback.cfg"
207+ log " 👍 Added data and configured kernel command line."
207208fi
208209
209210log " 👷 Updating $tmpdir /md5sum.txt with hashes of modified files..."
210- md5=$( /usr/bin/ md5sum " $tmpdir /boot/grub/grub.cfg" | /usr/bin/ cut -f1 -d ' ' )
211- /usr/bin/ sed -i -e ' s,^.*[[:space:]] ./boot/grub/grub.cfg,' " $md5 " ' ./boot/grub/grub.cfg,' " $tmpdir /md5sum.txt"
212- md5=$( /usr/bin/ md5sum " $tmpdir /boot/grub/loopback.cfg" | /usr/bin/ cut -f1 -d ' ' )
213- /usr/bin/ sed -i -e ' s,^.*[[:space:]] ./boot/grub/loopback.cfg,' " $md5 " ' ./boot/grub/loopback.cfg,' " $tmpdir /md5sum.txt"
211+ md5=$( md5sum " $tmpdir /boot/grub/grub.cfg" | cut -f1 -d ' ' )
212+ sed -i -e ' s,^.*[[:space:]] ./boot/grub/grub.cfg,' " $md5 " ' ./boot/grub/grub.cfg,' " $tmpdir /md5sum.txt"
213+ md5=$( md5sum " $tmpdir /boot/grub/loopback.cfg" | cut -f1 -d ' ' )
214+ sed -i -e ' s,^.*[[:space:]] ./boot/grub/loopback.cfg,' " $md5 " ' ./boot/grub/loopback.cfg,' " $tmpdir /md5sum.txt"
214215log " 👍 Updated hashes."
215216
216217log " 📦 Repackaging extracted files into an ISO image..."
217218cd " $tmpdir "
218- /usr/bin/ mkisofs -quiet -D -r -V " ubuntu-autoinstall-$today " -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -o " ${destination_iso} " .
219+ mkisofs -quiet -D -r -V " ubuntu-autoinstall-$today " -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -o " ${destination_iso} " .
219220cd " $OLDPWD "
220221log " 👍 Repackaged into ${destination_iso} "
221222
0 commit comments