Skip to content

Instantly share code, notes, and snippets.

@nmaupu
Last active February 11, 2024 14:34
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save nmaupu/1040657ac7728adff0356ec3139a22f9 to your computer and use it in GitHub Desktop.
Save nmaupu/1040657ac7728adff0356ec3139a22f9 to your computer and use it in GitHub Desktop.
Create Debian USB key automatic installation (preseed)
#!/usr/bin/env bash
set -e -x -o pipefail
DIRNAME="$(dirname $0)"
DISK="$1"
: "${DEBIAN_RELEASE:=stretch}"
: "${DEBIAN_VERSION:=9.2.1}"
: "${DEBIAN_MIRROR:=http://ftp.debian.org}"
: "${ARCH:=amd64}"
: "${REMOTE_ISO:=https://cdimage.debian.org/debian-cd/current/${ARCH}/iso-cd/debian-${DEBIAN_VERSION}-${ARCH}-netinst.iso}"
ISO_NAME="${REMOTE_ISO##*/}"
usage() {
cat << EOF
Usage: $0 <disk> <iso>
disk Disk to use (e.g. /dev/sdb) - will be wiped out
Overriding options via environment variables
DEBIAN_RELEASE Release of Debian (default: buster)
DEBIAN_VERSION VERSION of Debian (default: 9.2.1)
DEBIAN_MIRROR Debian mirror (default: http://ftp.debian.org)
ARCH Architecture (default: amd64)
EOF
}
[ $# -ne 1 ] && echo "Please provide required args" && usage && exit 1
[ -z "${DISK}" ] && echo "Please provide a disk" && usage && exit 1
PART="${DISK}1"
echo "Getting ISO"
wget --continue -O "${DIRNAME}/${ISO_NAME}" "${REMOTE_ISO}"
ISO="${DIRNAME}/${ISO_NAME}"
echo "Wiping out beginning of ${DISK}"
dd if=/dev/zero of="${DISK}" bs=10M count=5
echo "Preparing disk partitions"
(echo n; echo p; echo 1; echo ; echo ; echo w) | fdisk "${DISK}"
partx -u /dev/sdb
echo "Creating a filesystem on ${PART}"
mkfs.ext2 "${PART}"
mkdir -p /mnt/usb
mount "${PART}" /mnt/usb
grub-install --root-directory=/mnt/usb "${DISK}"
echo "Download the initrd image"
mkdir "/mnt/usb/hdmedia-${DEBIAN_RELEASE}"
wget -O "/mnt/usb/hdmedia-${DEBIAN_RELEASE}/vmlinuz" "${DEBIAN_MIRROR}/debian/dists/${DEBIAN_RELEASE}/main/installer-${ARCH}/current/images/hd-media/vmlinuz"
wget -O "/mnt/usb/hdmedia-${DEBIAN_RELEASE}/initrd.gz" "${DEBIAN_MIRROR}/debian/dists/${DEBIAN_RELEASE}/main/installer-${ARCH}/current/images/hd-media/initrd.gz"
mkdir -p /mnt/usb/isos
rsync -aP "${ISO}" /mnt/usb/isos
echo "Create grub config file"
cat << EOF > /mnt/usb/boot/grub/grub.cfg
set hdmedia="/hdmedia-${DEBIAN_RELEASE}"
set preseed="/hd-media/preseed"
set iso="/isos/${ISO_NAME}"
menuentry "Debian ${DEBIAN_RELEASE} ${ARCH} manual install" {
linux \$hdmedia/vmlinuz iso-scan/filename=\$iso priority=critical
initrd \$hdmedia/initrd.gz
}
menuentry "Debian ${DEBIAN_RELEASE} ${ARCH} auto install" {
linux \$hdmedia/vmlinuz iso-scan/filename=\$iso priority=critical auto=true preseed/file=\$preseed/debian.preseed
initrd \$hdmedia/initrd.gz
}
EOF
mkdir /mnt/usb/preseed
cat << EOF > /mnt/usb/preseed/debian.preseed
d-i debian-installer/locale string en_US
d-i keyboard-configuration/xkb-keymap select us
d-i console-tools/archs select skip-config
d-i time/zone string EU/Paris
d-i netcfg/enable boolean true
d-i hw-detect/load_firmware boolean true
d-i passwd/make-user boolean true
d-i passwd/root-password password root
d-i passwd/root-password-again password root
d-i netcfg/enable boolean false
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
# We assume the target computer has only one harddrive.
# In most case the USB Flash drive is attached on /dev/sda
# but sometimes the harddrive is detected before the USB flash drive and
# it is attached on /dev/sda and the USB flash drive on /dev/sdb
# You can set manually partman-auto/disk and grub-installer/bootdev or
# used the early_command option to automatically set the device to use.
d-i partman/early_command string \
USBDEV=\$(mount | grep hd-media | cut -d" " -f1 | sed "s/\(.*\)./\1/");\
BOOTDEV=\$(list-devices disk | grep -v \$USBDEV | head -1);\
debconf-set partman-auto/disk \$BOOTDEV;\
debconf-set grub-installer/bootdev \$BOOTDEV;
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean false
# Partioning
d-i partman-auto/method string lvm
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-auto-lvm/new_vg_name string sys
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-lvm/confirm boolean true
d-i partman/alignment string optimal
d-i partman-auto-lvm/guided_size string max
d-i partman-auto/expert_recipe string \
my-scheme :: \
2000 10000 2000 xfs \
\$primary{ } \
\$bootable{ } \
method{ format } format{ } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ / } \
. \
100 1000 1000000000 xfs \
\$defaultignore{ } \
\$primary{ } \
method{ lvm } \
vg_name{ sys } \
. \
8000 512 8000 swap \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ swap } \
method{ swap } \
format{ } \
. \
8000 1000 10000 usr \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ usr } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /usr } \
format{ } \
. \
8000 1000 10000 var \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ var } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /var } \
format{ } \
. \
10000 1000 50000 var-docker \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ var-docker } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /var/lib/docker } \
format{ } \
. \
2000 1000 2000 tmp \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ tmp } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /tmp } \
format{ } \
. \
5000 1000 10000 opt \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ opt } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /opt } \
format{ } \
. \
5000 1000 50000 home \
\$lvmok{ } \
in_vg{ sys } \
lv_name{ home } \
method{ format } \
use_filesystem{ } filesystem{ xfs } \
mountpoint{ /home } \
format{ } \
.
# This makes partman automatically partition without confirmation, provided
# that you told it what to do using one of the methods above.
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/mount_style select uuid
# We don't want use a remote mirror (all stuff we need is on the USB flash drive)
d-i base-installer/install-recommends boolean false
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
d-i apt-setup/use_mirror boolean true
d-i debian-installer/allow_unauthenticated boolean true
# Install a standard debian system (some recommended packages) + openssh-server
tasksel tasksel/first multiselect standard
d-i pkgsel/include string openssh-server
d-i pkgsel/upgrade select none
popularity-contest popularity-contest/participate boolean false
d-i finish-install/reboot_in_progress note
EOF
sync
umount /mnt/usb
@vdhub
Copy link

vdhub commented Jan 4, 2021

Will this install on a UEFI system ?

As well , how I can change little bit the disk formatting part ? In my setup I have always 2 Disks , on the smaller disk I need to install the OS and the swap and on the big disk I need to prepare it to store the data , I can automate that ?
How I can detect which one is the smallest one as I cannot rely on /dev/sda ; /dev/sdb part as some times they are swapping depending on the motherboard.
And last part, can I install some mandatory needed packages in my case ? I need zip htop unzip git curl sqlite3 libunwind8 libglib2.0

Thanks

@paigeadelethompson
Copy link

paigeadelethompson commented Mar 28, 2023

@vdhub I'd be curious to find out if it ever worked on a non-uefi system,

qemu-system-x86_64 -nodefaults -nographic -bios /usr/share/ovmf/OVMF.fd -hda installer.bin -serial mon:stdio

[    4.185799] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-5 04/01/2014
[    4.186281] Call Trace:
[    4.187762]  dump_stack+0x6b/0x83
[    4.187970]  ? rest_init+0x20/0xb4
[    4.188097]  panic+0x101/0x2d7
[    4.188252]  ? kernel_execve+0x15c/0x1a0
[    4.188578]  ? rest_init+0xb4/0xb4
[    4.188705]  kernel_init+0x101/0x10c
[    4.188959]  ret_from_fork+0x22/0x30
[    4.189976] Kernel Offset: 0xbe00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[    4.190685] ---[ end Kernel panic - not syncing: No working init found.  Try passing init= option to kernel. See Linux Documentation/admin-gu-

I decided I'm going to make this uefi no matter what, but strangely I can't get grub-efi to load this kernel:

qemu-system-x86_64 -nodefaults -nographic -bios /usr/share/ovmf/OVMF.fd -hda installer.bin -serial mon:stdio

grub-efi has this error:

error: can't allocate kernel.
error: you need to load the kernel first.

Press any key to continue...

I think what I'll have to do is open up this initrd and see how it works, not to mention figure out why the kernel won't work with this bootloader,

EDIT:

THE EFI works now, just figured out I needed to run qemu with -m it just didn't have enough memory to allocate the kernel lol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment