Last active
January 31, 2026 21:43
-
-
Save crappyrules/a8b78942decd19d62c94426d430af8a0 to your computer and use it in GitHub Desktop.
debian-unattended.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #upon first boot run sudo /root/upgrade-to-sid.sh if you want to upgrade your apt to the latest unstable version of Debian | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| OUTDIR="${1:-.}" | |
| # Early check for xorriso | |
| if ! command -v xorriso >/dev/null 2>&1; then | |
| echo "ERROR: xorriso is not installed." | |
| echo "Install it first, e.g.:" | |
| echo " sudo apt install xorriso -y" | |
| exit 1 | |
| fi | |
| echo "=== Unattended Debian preseed/late.sh + ISO builder for VMs ===" | |
| echo | |
| echo "NOTE: You must have a valid Debian *netinst* ISO in the current directory." | |
| echo " (e.g. debian-13.1.0-amd64-netinst.iso)" | |
| # Find a default netinst ISO if possible | |
| DEFAULT_ISO="" | |
| shopt -s nullglob | |
| for f in debian-*-netinst*.iso; do | |
| DEFAULT_ISO="$f" | |
| break | |
| done | |
| shopt -u nullglob | |
| if [[ -n "${DEFAULT_ISO}" ]]; then | |
| read -rp "Base Debian netinst ISO [${DEFAULT_ISO}]: " BASE_ISO | |
| BASE_ISO="${BASE_ISO:-$DEFAULT_ISO}" | |
| else | |
| read -rp "Base Debian netinst ISO filename (must exist in this dir): " BASE_ISO | |
| fi | |
| if [[ ! -f "$BASE_ISO" ]]; then | |
| echo "ERROR: ISO '$BASE_ISO' not found in current directory." >&2 | |
| exit 1 | |
| fi | |
| read -rp "Name for the new unattended ISO [unattended-${BASE_ISO}]: " NEW_ISO | |
| NEW_ISO="${NEW_ISO:-unattended-${BASE_ISO}}" | |
| echo | |
| read -rp "Full name for primary user: " FULLNAME | |
| while :; do | |
| read -rp "Username (e.g. crappy): " USERNAME | |
| [[ -n "$USERNAME" ]] && break | |
| echo "Username cannot be empty." | |
| done | |
| while :; do | |
| read -rsp "Password for $USERNAME: " PASSWORD; echo | |
| read -rsp "Confirm password: " PASSWORD2; echo | |
| if [[ "$PASSWORD" == "$PASSWORD2" && -n "$PASSWORD" ]]; then | |
| break | |
| fi | |
| echo "Passwords do not match or are empty. Try again." | |
| done | |
| while :; do | |
| read -rp "Hostname for this VM: " HOSTNAME | |
| [[ -n "$HOSTNAME" ]] && break | |
| echo "Hostname cannot be empty." | |
| done | |
| echo | |
| echo "Select the timezone for the installed system:" | |
| echo " 1) America/New_York (US Eastern)" | |
| echo " 2) America/Chicago (US Central)" | |
| echo " 3) America/Denver (US Mountain)" | |
| echo " 4) America/Los_Angeles (US Pacific)" | |
| echo " 5) Europe/London" | |
| echo " 6) Europe/Berlin" | |
| echo " 7) Asia/Tokyo" | |
| echo " 8) UTC" | |
| echo " 9) Other (enter manually, e.g. America/Denver)" | |
| read -rp "Choice [1-9, default 1]: " TZ_CHOICE | |
| TZ_CHOICE="${TZ_CHOICE:-1}" | |
| case "$TZ_CHOICE" in | |
| 1) TIMEZONE="America/New_York" ;; | |
| 2) TIMEZONE="America/Chicago" ;; | |
| 3) TIMEZONE="America/Denver" ;; | |
| 4) TIMEZONE="America/Los_Angeles" ;; | |
| 5) TIMEZONE="Europe/London" ;; | |
| 6) TIMEZONE="Europe/Berlin" ;; | |
| 7) TIMEZONE="Asia/Tokyo" ;; | |
| 8) TIMEZONE="Etc/UTC" ;; | |
| 9) | |
| read -rp "Enter timezone (e.g. America/Denver, Europe/Paris): " TIMEZONE | |
| TIMEZONE="${TIMEZONE:-Etc/UTC}" | |
| ;; | |
| *) TIMEZONE="America/New_York" ;; | |
| esac | |
| echo | |
| echo "Using timezone: $TIMEZONE" | |
| echo | |
| echo "Paste the SSH public key for $USERNAME (single line, e.g. ssh-ed25519 ...):" | |
| read -r SSH_KEY | |
| echo | |
| echo "The next question is about the DISK *inside the VM* that Debian will install to." | |
| echo "Examples:" | |
| echo " - /dev/sda (common for ESXi/VMware)" | |
| echo " - /dev/vda (virtio on KVM/QEMU)" | |
| echo | |
| echo "This is NOT your USB stick and has nothing to do with how the ISO is written." | |
| read -rp "Target install disk device inside the VM [/dev/sda]: " DISK | |
| DISK="${DISK:-/dev/sda}" | |
| echo | |
| read -rp "Any additional Debian packages to install (space-separated, optional): " EXTRA_PKGS | |
| mkdir -p "$OUTDIR" | |
| ############################################################################### | |
| # Generate preseed.cfg | |
| ############################################################################### | |
| cat >"$OUTDIR/preseed.cfg" <<EOF | |
| ### Localization | |
| d-i debian-installer/locale string en_US.UTF-8 | |
| d-i console-setup/ask_detect boolean false | |
| d-i keyboard-configuration/xkb-keymap select us | |
| ### Network | |
| d-i netcfg/choose_interface select auto | |
| d-i netcfg/disable_dhcp boolean false | |
| d-i netcfg/get_hostname string $HOSTNAME | |
| d-i netcfg/get_domain string localdomain | |
| d-i netcfg/hostname string $HOSTNAME | |
| d-i hw-detect/load_firmware boolean true | |
| ### Mirror | |
| d-i mirror/country string manual | |
| d-i mirror/http/hostname string deb.debian.org | |
| d-i mirror/http/directory string /debian | |
| d-i mirror/http/proxy string | |
| d-i apt-setup/use_mirror boolean true | |
| d-i apt-setup/contrib boolean true | |
| d-i apt-setup/non-free boolean true | |
| d-i apt-setup/non-free-firmware boolean true | |
| d-i mirror/suite string stable | |
| ### Clock and time zone | |
| d-i clock-setup/utc boolean true | |
| d-i time/zone string $TIMEZONE | |
| d-i clock-setup/ntp boolean true | |
| ### Users | |
| d-i passwd/root-login boolean false | |
| d-i passwd/make-user boolean true | |
| d-i passwd/user-fullname string $FULLNAME | |
| d-i passwd/username string $USERNAME | |
| d-i passwd/user-password password $PASSWORD | |
| d-i passwd/user-password-again password $PASSWORD | |
| d-i user-setup/allow-password-weak boolean true | |
| ### Partitioning (single disk, / + swap) | |
| d-i partman-auto/disk string $DISK | |
| d-i partman-auto/method string regular | |
| 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-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/choose_recipe select atomic | |
| d-i partman-partitioning/confirm_write_new_label boolean true | |
| d-i partman/choose_partition select finish | |
| d-i partman/confirm boolean true | |
| d-i partman/confirm_nooverwrite boolean true | |
| ### Base system | |
| d-i base-installer/kernel/override-image string linux-image-amd64 | |
| ### Package selection | |
| tasksel tasksel/first multiselect standard, ssh-server | |
| # Include wget so late.sh can fetch MOTD; sudo for passwordless sudo script | |
| # EXTRA_PKGS comes from the interactive prompt and may be empty | |
| d-i pkgsel/include string openssh-server wget sudo ${EXTRA_PKGS} | |
| d-i pkgsel/upgrade select safe-upgrade | |
| popularity-contest popularity-contest/participate boolean false | |
| ### Boot loader | |
| d-i grub-installer/only_debian boolean true | |
| d-i grub-installer/bootdev string $DISK | |
| ### Finishing the installation | |
| d-i finish-install/reboot_in_progress note | |
| ### Late command: run /root/late.sh from the ISO | |
| d-i preseed/late_command string cp /cdrom/late.sh /target/root/late.sh; in-target /bin/sh /root/late.sh | |
| EOF | |
| ############################################################################### | |
| # Generate late.sh | |
| ############################################################################### | |
| cat >"$OUTDIR/late.sh" <<EOF | |
| #!/bin/sh | |
| set -e | |
| # Set up SSH key-based auth for user $USERNAME | |
| if id $USERNAME >/dev/null 2>&1; then | |
| USER_HOME=\$(getent passwd $USERNAME | cut -d: -f6) | |
| mkdir -p "\$USER_HOME/.ssh" | |
| printf '%s\n' '$SSH_KEY' > "\$USER_HOME/.ssh/authorized_keys" | |
| chown -R $USERNAME:$USERNAME "\$USER_HOME/.ssh" | |
| chmod 700 "\$USER_HOME/.ssh" | |
| chmod 600 "\$USER_HOME/.ssh/authorized_keys" | |
| fi | |
| # Disable SSH password authentication and root login | |
| if [ -f /etc/ssh/sshd_config ]; then | |
| sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^#PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config || true | |
| fi | |
| systemctl enable ssh || true | |
| # Give user $USERNAME passwordless sudo | |
| mkdir -p /etc/sudoers.d | |
| printf '%s\n' '$USERNAME ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/90-$USERNAME-nopasswd | |
| chmod 440 /etc/sudoers.d/90-$USERNAME-nopasswd | |
| # Fetch MOTD from your gist (requires wget) | |
| if command -v wget >/dev/null 2>&1; then | |
| wget -qO /etc/motd 'https://gist.githubusercontent.com/crappyrules/ade9dc076f8611cec4332c5decf8e37e/raw/05bcf17bc2356257159703301c9056a68b415a20/motd' || true | |
| fi | |
| # Point APT to sid but don't auto-upgrade here | |
| printf '%s\n' 'deb http://deb.debian.org/debian sid main contrib non-free-firmware' > /etc/apt/sources.list | |
| # Create helper script to upgrade to sid, clean, and reboot | |
| cat >/root/upgrade-to-sid.sh <<'EOS' | |
| #!/bin/sh | |
| set -e | |
| apt-get update | |
| DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::=--force-confnew dist-upgrade | |
| apt-get -y autoremove --purge | |
| apt-get -y autoclean | |
| reboot | |
| EOS | |
| chmod +x /root/upgrade-to-sid.sh | |
| EOF | |
| chmod +x "$OUTDIR/late.sh" | |
| echo "Generated: $OUTDIR/preseed.cfg and $OUTDIR/late.sh" | |
| ############################################################################### | |
| # Build new ISO with xorriso | |
| ############################################################################### | |
| echo | |
| echo "Building new unattended ISO: $NEW_ISO" | |
| xorriso -indev "$BASE_ISO" \ | |
| -outdev "$NEW_ISO" \ | |
| -map "$OUTDIR/preseed.cfg" /preseed.cfg \ | |
| -map "$OUTDIR/late.sh" /late.sh \ | |
| -boot_image any replay | |
| echo "Created ISO: $NEW_ISO" | |
| ############################################################################### | |
| # How to use the ISO | |
| ############################################################################### | |
| echo | |
| echo "How do you want to proceed with $NEW_ISO?" | |
| echo " 1) Save ISO file only (default)" | |
| echo " 2) Write ISO to a USB drive" | |
| read -rp "Choice [1/2]: " CHOICE | |
| CHOICE="${CHOICE:-1}" | |
| if [[ "$CHOICE" != "2" ]]; then | |
| echo "Leaving ISO as file only. Done." | |
| exit 0 | |
| fi | |
| # Option 2: write to USB | |
| read -rp "USB device to OVERWRITE (e.g. /dev/sdb): " USB_DEV | |
| if [[ -z "$USB_DEV" ]]; then | |
| echo "No USB device specified; skipping write." | |
| exit 0 | |
| fi | |
| echo | |
| echo "WARNING: This will ERASE ALL DATA on $USB_DEV." | |
| read -rp "Type 'YES' to confirm: " CONFIRM | |
| if [[ "$CONFIRM" != "YES" ]]; then | |
| echo "Confirmation not given; skipping USB write." | |
| exit 0 | |
| fi | |
| echo "Writing $NEW_ISO to $USB_DEV ..." | |
| sudo dd if="$NEW_ISO" of="$USB_DEV" bs=4M status=progress conv=fsync | |
| sync | |
| echo "Done writing ISO to $USB_DEV." | |
| crappy@craptastic:~/Downloads/iso/debian | |
| $ cat debian-unattended.sh | |
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| OUTDIR="${1:-.}" | |
| # Early check for xorriso | |
| if ! command -v xorriso >/dev/null 2>&1; then | |
| echo "ERROR: xorriso is not installed." | |
| echo "Install it first, e.g.:" | |
| echo " sudo apt install xorriso -y" | |
| exit 1 | |
| fi | |
| echo "=== Unattended Debian preseed/late.sh + ISO builder for VMs ===" | |
| echo | |
| echo "NOTE: You must have a valid Debian *netinst* ISO in the current directory." | |
| echo " (e.g. debian-13.1.0-amd64-netinst.iso)" | |
| # Find a default netinst ISO if possible | |
| DEFAULT_ISO="" | |
| shopt -s nullglob | |
| for f in debian-*-netinst*.iso; do | |
| DEFAULT_ISO="$f" | |
| break | |
| done | |
| shopt -u nullglob | |
| if [[ -n "${DEFAULT_ISO}" ]]; then | |
| read -rp "Base Debian netinst ISO [${DEFAULT_ISO}]: " BASE_ISO | |
| BASE_ISO="${BASE_ISO:-$DEFAULT_ISO}" | |
| else | |
| read -rp "Base Debian netinst ISO filename (must exist in this dir): " BASE_ISO | |
| fi | |
| if [[ ! -f "$BASE_ISO" ]]; then | |
| echo "ERROR: ISO '$BASE_ISO' not found in current directory." >&2 | |
| exit 1 | |
| fi | |
| read -rp "Name for the new unattended ISO [unattended-${BASE_ISO}]: " NEW_ISO | |
| NEW_ISO="${NEW_ISO:-unattended-${BASE_ISO}}" | |
| echo | |
| read -rp "Full name for primary user: " FULLNAME | |
| while :; do | |
| read -rp "Username (e.g. crappy): " USERNAME | |
| [[ -n "$USERNAME" ]] && break | |
| echo "Username cannot be empty." | |
| done | |
| while :; do | |
| read -rsp "Password for $USERNAME: " PASSWORD; echo | |
| read -rsp "Confirm password: " PASSWORD2; echo | |
| if [[ "$PASSWORD" == "$PASSWORD2" && -n "$PASSWORD" ]]; then | |
| break | |
| fi | |
| echo "Passwords do not match or are empty. Try again." | |
| done | |
| while :; do | |
| read -rp "Hostname for this VM: " HOSTNAME | |
| [[ -n "$HOSTNAME" ]] && break | |
| echo "Hostname cannot be empty." | |
| done | |
| echo | |
| echo "Select the timezone for the installed system:" | |
| echo " 1) America/New_York (US Eastern)" | |
| echo " 2) America/Chicago (US Central)" | |
| echo " 3) America/Denver (US Mountain)" | |
| echo " 4) America/Los_Angeles (US Pacific)" | |
| echo " 5) Europe/London" | |
| echo " 6) Europe/Berlin" | |
| echo " 7) Asia/Tokyo" | |
| echo " 8) UTC" | |
| echo " 9) Other (enter manually, e.g. America/Denver)" | |
| read -rp "Choice [1-9, default 1]: " TZ_CHOICE | |
| TZ_CHOICE="${TZ_CHOICE:-1}" | |
| case "$TZ_CHOICE" in | |
| 1) TIMEZONE="America/New_York" ;; | |
| 2) TIMEZONE="America/Chicago" ;; | |
| 3) TIMEZONE="America/Denver" ;; | |
| 4) TIMEZONE="America/Los_Angeles" ;; | |
| 5) TIMEZONE="Europe/London" ;; | |
| 6) TIMEZONE="Europe/Berlin" ;; | |
| 7) TIMEZONE="Asia/Tokyo" ;; | |
| 8) TIMEZONE="Etc/UTC" ;; | |
| 9) | |
| read -rp "Enter timezone (e.g. America/Denver, Europe/Paris): " TIMEZONE | |
| TIMEZONE="${TIMEZONE:-Etc/UTC}" | |
| ;; | |
| *) TIMEZONE="America/New_York" ;; | |
| esac | |
| echo | |
| echo "Using timezone: $TIMEZONE" | |
| echo | |
| echo "Paste the SSH public key for $USERNAME (single line, e.g. ssh-ed25519 ...):" | |
| read -r SSH_KEY | |
| echo | |
| echo "The next question is about the DISK *inside the VM* that Debian will install to." | |
| echo "Examples:" | |
| echo " - /dev/sda (common for ESXi/VMware)" | |
| echo " - /dev/vda (virtio on KVM/QEMU)" | |
| echo | |
| echo "This is NOT your USB stick and has nothing to do with how the ISO is written." | |
| read -rp "Target install disk device inside the VM [/dev/sda]: " DISK | |
| DISK="${DISK:-/dev/sda}" | |
| echo | |
| read -rp "Any additional Debian packages to install (space-separated, optional): " EXTRA_PKGS | |
| mkdir -p "$OUTDIR" | |
| ############################################################################### | |
| # Generate preseed.cfg | |
| ############################################################################### | |
| cat >"$OUTDIR/preseed.cfg" <<EOF | |
| ### Localization | |
| d-i debian-installer/locale string en_US.UTF-8 | |
| d-i console-setup/ask_detect boolean false | |
| d-i keyboard-configuration/xkb-keymap select us | |
| ### Network | |
| d-i netcfg/choose_interface select auto | |
| d-i netcfg/disable_dhcp boolean false | |
| d-i netcfg/get_hostname string $HOSTNAME | |
| d-i netcfg/get_domain string localdomain | |
| d-i netcfg/hostname string $HOSTNAME | |
| d-i hw-detect/load_firmware boolean true | |
| ### Mirror | |
| d-i mirror/country string manual | |
| d-i mirror/http/hostname string deb.debian.org | |
| d-i mirror/http/directory string /debian | |
| d-i mirror/http/proxy string | |
| d-i apt-setup/use_mirror boolean true | |
| d-i apt-setup/contrib boolean true | |
| d-i apt-setup/non-free boolean true | |
| d-i apt-setup/non-free-firmware boolean true | |
| d-i mirror/suite string stable | |
| ### Clock and time zone | |
| d-i clock-setup/utc boolean true | |
| d-i time/zone string $TIMEZONE | |
| d-i clock-setup/ntp boolean true | |
| ### Users | |
| d-i passwd/root-login boolean false | |
| d-i passwd/make-user boolean true | |
| d-i passwd/user-fullname string $FULLNAME | |
| d-i passwd/username string $USERNAME | |
| d-i passwd/user-password password $PASSWORD | |
| d-i passwd/user-password-again password $PASSWORD | |
| d-i user-setup/allow-password-weak boolean true | |
| ### Partitioning (single disk, / + swap) | |
| d-i partman-auto/disk string $DISK | |
| d-i partman-auto/method string regular | |
| 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-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/choose_recipe select atomic | |
| d-i partman-partitioning/confirm_write_new_label boolean true | |
| d-i partman/choose_partition select finish | |
| d-i partman/confirm boolean true | |
| d-i partman/confirm_nooverwrite boolean true | |
| ### Base system | |
| d-i base-installer/kernel/override-image string linux-image-amd64 | |
| ### Package selection | |
| tasksel tasksel/first multiselect standard, ssh-server | |
| # Include wget so late.sh can fetch MOTD; sudo for passwordless sudo script | |
| # Also always install fail2ban for basic SSH hardening on servers | |
| # EXTRA_PKGS comes from the interactive prompt and may be empty | |
| d-i pkgsel/include string openssh-server wget sudo fail2ban ${EXTRA_PKGS} | |
| d-i pkgsel/upgrade select safe-upgrade | |
| popularity-contest popularity-contest/participate boolean false | |
| ### Boot loader | |
| d-i grub-installer/only_debian boolean true | |
| d-i grub-installer/bootdev string $DISK | |
| ### Finishing the installation | |
| d-i finish-install/reboot_in_progress note | |
| ### Late command: run /root/late.sh from the ISO | |
| d-i preseed/late_command string cp /cdrom/late.sh /target/root/late.sh; in-target /bin/sh /root/late.sh | |
| EOF | |
| ############################################################################### | |
| # Generate late.sh | |
| ############################################################################### | |
| cat >"$OUTDIR/late.sh" <<EOF | |
| #!/bin/sh | |
| set -e | |
| # Set up SSH key-based auth for user $USERNAME | |
| if id $USERNAME >/dev/null 2>&1; then | |
| USER_HOME=\$(getent passwd $USERNAME | cut -d: -f6) | |
| mkdir -p "\$USER_HOME/.ssh" | |
| printf '%s\n' '$SSH_KEY' > "\$USER_HOME/.ssh/authorized_keys" | |
| chown -R $USERNAME:$USERNAME "\$USER_HOME/.ssh" | |
| chmod 700 "\$USER_HOME/.ssh" | |
| chmod 600 "\$USER_HOME/.ssh/authorized_keys" | |
| fi | |
| # Disable SSH password authentication and root login | |
| if [ -f /etc/ssh/sshd_config ]; then | |
| sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^#PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config || true | |
| sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config || true | |
| fi | |
| systemctl enable ssh || true | |
| # Give user $USERNAME passwordless sudo | |
| mkdir -p /etc/sudoers.d | |
| printf '%s\n' '$USERNAME ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/90-$USERNAME-nopasswd | |
| chmod 440 /etc/sudoers.d/90-$USERNAME-nopasswd | |
| # Fetch MOTD from your gist (requires wget) | |
| if command -v wget >/dev/null 2>&1; then | |
| wget -qO /etc/motd 'https://gist.githubusercontent.com/crappyrules/ade9dc076f8611cec4332c5decf8e37e/raw/05bcf17bc2356257159703301c9056a68b415a20/motd' || true | |
| fi | |
| # Point APT to sid but don't auto-upgrade here | |
| printf '%s\n' 'deb http://deb.debian.org/debian sid main contrib non-free-firmware' > /etc/apt/sources.list | |
| # Create helper script to upgrade to sid, clean, and reboot | |
| cat >/root/upgrade-to-sid.sh <<'EOS' | |
| #!/bin/sh | |
| set -e | |
| apt-get update | |
| DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::=--force-confnew dist-upgrade | |
| apt-get -y autoremove --purge | |
| apt-get -y autoclean | |
| reboot | |
| EOS | |
| chmod +x /root/upgrade-to-sid.sh | |
| EOF | |
| chmod +x "$OUTDIR/late.sh" | |
| echo "Generated: $OUTDIR/preseed.cfg and $OUTDIR/late.sh" | |
| ############################################################################### | |
| # Build new ISO with xorriso | |
| ############################################################################### | |
| echo | |
| echo "Building new unattended ISO: $NEW_ISO" | |
| xorriso -indev "$BASE_ISO" \ | |
| -outdev "$NEW_ISO" \ | |
| -map "$OUTDIR/preseed.cfg" /preseed.cfg \ | |
| -map "$OUTDIR/late.sh" /late.sh \ | |
| -boot_image any replay | |
| echo "Created ISO: $NEW_ISO" | |
| ############################################################################### | |
| # How to use the ISO | |
| ############################################################################### | |
| echo | |
| echo "How do you want to proceed with $NEW_ISO?" | |
| echo " 1) Save ISO file only (default)" | |
| echo " 2) Write ISO to a USB drive" | |
| read -rp "Choice [1/2]: " CHOICE | |
| CHOICE="${CHOICE:-1}" | |
| if [[ "$CHOICE" != "2" ]]; then | |
| echo "Leaving ISO as file only. Done." | |
| exit 0 | |
| fi | |
| # Option 2: write to USB | |
| read -rp "USB device to OVERWRITE (e.g. /dev/sdb): " USB_DEV | |
| if [[ -z "$USB_DEV" ]]; then | |
| echo "No USB device specified; skipping write." | |
| exit 0 | |
| fi | |
| echo | |
| echo "WARNING: This will ERASE ALL DATA on $USB_DEV." | |
| read -rp "Type 'YES' to confirm: " CONFIRM | |
| if [[ "$CONFIRM" != "YES" ]]; then | |
| echo "Confirmation not given; skipping USB write." | |
| exit 0 | |
| fi | |
| echo "Writing $NEW_ISO to $USB_DEV ..." | |
| sudo dd if="$NEW_ISO" of="$USB_DEV" bs=4M status=progress conv=fsync | |
| sync | |
| echo "Done writing ISO to $USB_DEV." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment