Created
February 27, 2025 21:36
-
-
Save kfiresmith/695f1f1377938d7cd1c711ff8fc06ece to your computer and use it in GitHub Desktop.
Revisions
-
kfiresmith created this gist
Feb 27, 2025 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,220 @@ #!/bin/bash # Does the equivalent of sysprep for linux boxes to prepare them for cloning. # Based on https://lonesysadmin.net/2013/03/26/preparing-linux-template-vms/ AUTHOR='kfiresmith' BASENAME="${0##*/}" MODIFIED='20231020' VERSION='0.1.1' parse_args() { [[ -n $1 ]] || { printf 'No arguments specified, use -h for help.\n' exit 0 } while [[ -n $1 ]]; do if [[ $1 == -v ]]; then printf '%s: Version %s, updated %s by %s\n' \ "$BASENAME" "$VERSION" "$MODIFIED" "$AUTHOR" shift [[ -n $1 ]] || exit 0 elif [[ $1 == -h ]]; then printf 'Cloning preparation script for linux systems.\n\n' printf 'Usage: %s [-v ] (-h | -y [-b] [-l <log_file>] [-s])\n\n' \ "$BASENAME" printf 'Options:\n' printf ' -h Display this help text.\n' printf ' -b Used for firstboot (internal).\n' printf ' -l Specify log file location.\n' printf ' -s Shutdown on completion.\n' printf ' -v Emit version header.\n' printf ' -y Confirm sysprep.\n' exit 0 elif [[ $1 == -b ]]; then FIRSTBOOT=true break elif [[ $1 == -l ]]; then shift LOGFILE=$1 shift elif [[ $1 == -s ]]; then SHUTDOWN=true shift elif [[ $1 == -y ]]; then CONFIRM=true shift else printf 'Invalid argument specified, use -h for help.\n' exit 0 fi done } say() { LOGFILE=${LOGFILE:=/var/log/sysprep.log} if [[ -n $LOGFILE && ! $LOGFILE == no ]]; then [[ -f $LOGFILE ]] || UMASK=027 /usr/bin/touch "$LOGFILE" printf '%s: %s\n' "$(date -u +%FT%TZ)" "$@" | tee -a "$LOGFILE" else printf '%s: %s\n' "$(date -u +%FT%TZ)" "$@" fi } apt_purge() { vers=$(/bin/ls -tr /boot/vmlinuz-* | /usr/bin/head -n -1 | /bin/grep -v "$(uname -r)" | /usr/bin/cut -d- -f2-) for i in $vers; do debs+="$(echo linux-{image,headers,modules}-$i) " done /usr/bin/apt remove -qy --purge $debs &> /dev/null && /usr/bin/apt autoremove -qy --purge &> /dev/null } firstboot() { say 'Running sysprep first-boot setup script.' /usr/bin/find /etc/ssh/*key &>/dev/null || { say 'Regenerating SSH host keys...' /usr/sbin/dpkg-reconfigure openssh-server } [[ $(hostname) == CHANGEME ]] && { say 'Regenerating hostname and rebooting...' /bin/hostnamectl set-hostname changeme.local /bin/systemctl reboot } [[ -f /var/lib/aide/aide.db.gz ]] && { say 'Regenerating AIDE database...' /sbin/aide --update /bin/mv -f /var/lib/aide/aide.db{.new,}.gz } say 'Sysprep firtst-boot setup complete, disabling service.' /bin/systemctl disable sysprep-firstboot exit 0 } clean_packages() { say 'Removing old kernels.' if ! command -v purge-old-kernels &> /dev/null; then /usr/bin/apt install -qy byobu &> /dev/null fi /usr/bin/purge-old-kernels -qy --keep 1 &> /dev/null || apt_purge say 'Clearing package cache.' /usr/bin/apt clean &> /dev/null /bin/rm -rf /var/cache/apt/archives/* return 0 } clean_logs() { say 'Clearing old logs.' /usr/sbin/logrotate -f /etc/logrotate.conf /usr/bin/find /var/log -type f -regextype posix-extended -regex \ ".*/*(-[0-9]{8}|.[0-9]|.gz)$" -delete /bin/rm -rf /var/log/journal && /bin/mkdir /var/log/journal /bin/rm -f /var/log/dmesg.old /bin/rm -f /var/log/anaconda/* say 'Clearing audit logs.' : > /var/log/audit/audit.log : > /var/log/wtmp : > /var/log/lastlog : > /var/log/grubby return 0 } clean_network() { say 'Clearing udev persistent rules.' /bin/rm -f /etc/udev/rules.d/70* say 'Wipe netplan config' /bin/rm -f /etc/netplan/*.yaml /bin/cp 02-no-network.yaml.example 02-no-network.yaml /usr/sbin/netplan apply return 0 } clean_files() { say 'Cleaning out temp directories.' /bin/rm -rf /tmp/* /bin/rm -rf /var/tmp/* /bin/rm -rf /var/cache/* say 'Cleaning up root home directory.' unset HISTFILE /bin/rm -f /root/.bash_history /bin/rm -f /root/anaconda-ks.cfg /bin/rm -rf /root/.ssh/ /bin/rm -rf /root/.gnupg/ return 0 } generalize() { say 'Removing SSH host keys.' /bin/rm -f /etc/ssh/*key* say 'Clearing machine-id' : > /etc/machine-id say 'Removing random-seed' /bin/rm -f /var/lib/systemd/random-seed say 'Resetting hostname.' /bin/hostnamectl set-hostname 'CHANGEME' return 0 } setup_firstboot() { say 'Enabling sysprep firstboot service.' FBSERVICE=/etc/systemd/system/sysprep-firstboot.service [[ -f $FBSERVICE ]] || /bin/cat <<'EOF' > $FBSERVICE [Unit] Description=Sysprep first-boot setup tasks [Service] Type=simple ExecStart=/usr/local/sbin/sysprep -y -b [Install] WantedBy=multi-user.target EOF /bin/systemctl enable sysprep-firstboot return 0 } sysprep() { parse_args "$@" [[ $CONFIRM == true ]] || { say 'Confirm with -y to start sysprep.' exit 0 } say 'Beginning sysprep.' [[ $FIRSTBOOT == true ]] && firstboot say 'Stopping logging and auditing daemons.' /bin/systemctl stop rsyslog.service /usr/sbin/service auditd stop clean_packages clean_logs clean_network clean_files generalize setup_firstboot say 'End of sysprep.' [[ $SHUTDOWN == true ]] && { say 'Shutting down the system.' /bin/systemctl poweroff } exit 0 } # Only execute if not being sourced [[ ${BASH_SOURCE[0]} == "$0" ]] && sysprep "$@"