#!/bin/bash release=${1%-netinst.iso} execution_directory=$(pwd) release_name=${release}-netinst newrelease=${release}-custom myfiles=${HOME}/myfiles wantedfile=${execution_directory}/wanted.txt excludedfile=${execution_directory}/excluded.txt # global parameters original_iso=${execution_directory}/${release_name}.iso newrelease_iso=${execution_directory}/${newrelease}.iso cd "${execution_directory}" || exit 1 temp_file=/tmp/tmp_iso_directory.txt if [ -e ${temp_file} ] then temp_dir=$(cat ${temp_file}) else temp_dir=$(mktemp -d) echo "${temp_dir}" > ${temp_file} fi if [ ! -e "${original_iso}" ] then echo "image not found : ${original_iso}" exit 0 fi package_list='xorriso isolinux python3-apt apt-utils python3-requests rsync wget' # shellcheck disable=SC2086 if apt-get -s install ${package_list} |grep ^Inst then echo "sudo apt install ${package_list} !!!" exit 0 fi ask() { USER_ANSWER="?"; while [ "$USER_ANSWER" != "n" ] && [ "$USER_ANSWER" != "y" ] ; do echo -n "$1 ? [y/n] " read -r -n 1 USER_ANSWER echo ""; done if [ "$USER_ANSWER" == "y" ] ; then return 0 else return 1 fi } if [ ! -e "${wantedfile}" ] then cat > "${wantedfile}" < "${excludedfile}" < /tmp/preseed.cfg <<"EOF" #_preseed_V1 ### Locale configuration d-i debian-installer/language string fr d-i debian-installer/country string FR d-i debian-installer/locale select fr_FR.UTF-8 d-i keyboard-configuration/xkb-keymap select fr(latin9) #d-i keyboard-configuration/toggle select No toggling d-i keyboard-configuration/layoutcode string fr d-i keyboard-configuration/modelcode string pc105 d-i keyboard-configuration/variantcode string latin9 ### Network configuration d-i netcfg/enable boolean false ### account configuration #d-i passwd/root-password-crypted password [$6$tYi0kNPyvi45IWqW$vOvUycJFPqZhg.N.g7wNZ96UriyvrxoumTuWpRD0OoRp47iuqGfvICxNrsVE0IRHaTs.KkU/btWqJYdetRlpE1] #d-i passwd/user-fullname string Cyril CONSTANTIN #d-i passwd/username string constcyr #d-i passwd/user-password-crypted password [$6$tYi0kNPyvi45IWqW$vOvUycJFPqZhg.N.g7wNZ96UriyvrxoumTuWpRD0OoRp47iuqGfvICxNrsVE0IRHaTs.KkU/btWqJYdetRlpE1] #d-i passwd/user-uid string 1000 #d-i passwd/user-default-groups string audio cdrom video ### Clock and time zone setup d-i clock-setup/utc boolean true d-i time/zone string Europe/Paris # Controls whether to use NTP to set the clock during the install #d-i clock-setup/ntp boolean true # NTP server to use. The default is almost always fine here. #d-i clock-setup/ntp-server string ntp.example.com ### Partitioning ### Base system installation ### Apt setup d-i apt-setup/use_mirror boolean false apt-cdrom-setup apt-setup/cdrom/set-next boolean false ### Package selection popularity-contest popularity-contest/participate boolean false EOF cat > "${myfiles}"/libdvdcss2.README <<"EOF" libdvd-pkg: Downloading orig source... I: libdvdcss_1.4.3 /usr/bin/wget --tries=3 --timeout=40 --read-timeout=40 --continue -O libdvdcss_1.4.3.orig.tar.bz2 \ https://download.videolan.org/pub/libdvdcss/1.4.3/libdvdcss-1.4.3.tar.bz2 \ || /usr/bin/uscan --noconf --verbose --rename --destdir=/usr/src/libdvd-pkg --check-dirname-level=0 --force-download --download-current-version /usr/share/libdvd-pkg/debian --2026-01-02 21:06:57-- https://download.videolan.org/pub/libdvdcss/1.4.3/libdvdcss-1.4.3.tar.bz2 Résolution de download.videolan.org (download.videolan.org)… 213.36.253.2, 2a01:e0d:1:3:58bf:fa02:c0de:5 Connexion à download.videolan.org (download.videolan.org)|213.36.253.2|:443… connecté. requête HTTP transmise, en attente de la réponse… 200 OK Taille: 388404 (379K) [application/octet-stream] Sauvegarde en: «libdvdcss_1.4.3.orig.tar.bz2» libdvdcss_1.4.3.orig.tar.bz2 100%[==============================================================>] 379,30K 725KB/s ds 0,5s 2026-01-02 21:06:58 (725 KB/s) — «libdvdcss_1.4.3.orig.tar.bz2» sauvegardé [388404/388404] EOF cat > "${myfiles}"/cs46xx.README <<"EOF" # not included apt install alsa-utils tar xvf alsa-firmware-1.2.4.tar.bz2 cd alsa-firmware-1.2.4/cs46xx mkdir /lib/firmware/cs46xx cp ba1 cwc4630 cwcasync cwcbinhack cwcdma cwcsnoop /lib/firmware/cs46xx modprobe -r snd-cs46xx modprobe snd-cs46xx adduser yourusername audio alsamixer : demute aplay /usr/share/sounds/alsa/Noise.wav speaker-test -t sine -f 440 -c 2 speaker-test -t wav -c 2 EOF cat > "${myfiles}"/local-apt-repository.sh <<"EOF" #!/bin/bash help() { echo "rsync and local-apt-repository packages are mandatory" } if [[ -n $(find "$(pwd)" -name "rsync*deb") ]] then find "$(pwd)" -name "rsync*deb" -exec dpkg -i {} \; else help fi if [[ -n $(find "$(pwd)" -name "local-apt-repository*deb") ]] then find "$(pwd)" -name "local-apt-repository*deb" -exec dpkg -i {} \; else help fi mkdir /srv/local-apt-repository mkdir /srv/zips rsync --recursive "$(pwd)"/pool /srv/local-apt-repository/ rsync --recursive "$(pwd)"/firmware /srv/local-apt-repository/ rsync --recursive "$(pwd)"/zips/ /srv/zips apt update EOF cat > "${myfiles}"/README.custom <<"EOF" You can add package under or with dpkg e.g. # find /mnt/cdrom0 -name "rsync*.deb" -exec dpkg -i {} \; But you have to install dependencies one by one as the same method. The most convenient is to execute : # mount # cd # bash local-apt-repository.sh It copy all packages into /srv/local-apt-repository and populate apt with all package Check you have enough space on /srv before (size of the disk/iso). Start the systemd service # systemctl start local-apt-repository.service Check after one or two minutes with # apt list And you can install them # apt install tmux EOF if ask "customize installer (add preseed and modify installation option) ?" then chmod -R +w "${temp_dir}" cp -v /tmp/preseed.cfg "${temp_dir}"/preseed.cfg # sed -e "s#quiet#priority=high locale=fr_FR.UTF-8 keymap=fr file=/cdrom/preseed.cfg#" ${temp_dir}/isolinux/txt.cfg # sed -i -e "s#quiet#priority=high locale=fr_FR.UTF-8 keymap=fr file=/cdrom/preseed.cfg#" ${temp_dir}/isolinux/txt.cfg sed -e "s#quiet#file=/cdrom/preseed.cfg#" "${temp_dir}"/isolinux/txt.cfg sed -i -e "s#quiet#file=/cdrom/preseed.cfg#" "${temp_dir}"/isolinux/txt.cfg fi rsync --dry-run --verbose --recursive "${myfiles}"/ "${temp_dir}" if ask "copy additionnal packages ?" then rsync --verbose --recursive "${myfiles}"/ "${temp_dir}" # echo "Generate Release file" # apt-ftparchive \ # -o "APT::FTPArchive::Release::Origin=local-apt-repository" \ # -o "APT::FTPArchive::Release::Description=Local APT repository" \ # release ${custom_dir} > ${custom_dir}/Release fi # Final steps # Calculate md5 and generate iso echo "calculate md5sum.txt" chmod +w "${temp_dir}"/md5sum.txt cd "${temp_dir}" && find . -follow -type f ! -name "md5sum.txt" -print0 | xargs -0 md5sum > md5sum.txt chmod -R -w "${temp_dir}" cd "${HOME}" || exit 1 if ask "generate final iso ?" then xorriso -as mkisofs -o "${newrelease_iso}" \ -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \ -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot \ -boot-load-size 4 -boot-info-table "${temp_dir}" fi echo "=== End of script ===" exit 0