diff --git a/.gitignore b/.gitignore index 565c8bf..4867feb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +debian/ final/ authorized_keys.gunet *.env \ No newline at end of file diff --git a/README.md b/README.md index 539724c..d5a1e45 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,36 @@ # JeOS + GUNet Just enough OS (based on Debian) ## Docker + The final ISO image will be in the folder `/var/jeos/final`. We must volume mount it in order to have it available after the Docker container has finished. -The recommened way to run the container is: -`docker run --rm -v ${PWD}/final:/var/jeos/final --privileged ghcr.io/gunet/jeos-builder:` +The recommended way to run the container is: + +```bash +docker run --rm -v ${PWD}/final:/var/jeos/final --privileged ghcr.io/gunet/jeos-builder: +``` ### Environment variables + The following environment variables are available. For network configuration, the general path is to use DHCP provided ones and *only* if these are not available, then use the ones in environment variables (if they are provided): + * `NET_IP`: The static IP in CIDR form (ie `192.168.2.1/24`). * `NET_GATEWAY`: The gateway IP. Only if IP has already been passed. -* `NET_NAMESERVERS`: Nameserver IPs to use, separated by space (ie `8.8.8.8 4.4.4.4`) +* `NET_NAMESERVERS`: Name Server IPs to use, separated by space (ie `8.8.8.8 4.4.4.4`) * `NET_HOSTNAME`: The hostname to set (ie `sso.gunet.gr`) * `NET_DOMAIN`: The domain to set (ie `gunet.gr`) * `NET_STATIC`: If set to `yes` then we only perform static network configuration and **all** the above variables **must** be set * `ROOT_PASSWORD`: The (plaintext) root password -The `NET_HOSTNAME` and `NET_DOMAIN` can be helpful even in a DHCP configuration in order to *avoid* the installer asking for the corresponing values. +The `NET_HOSTNAME` and `NET_DOMAIN` can be helpful even in a DHCP configuration in order to *avoid* the installer asking for the corresponding values. -If no environment variables are passed then the installer will just ask more questions. The purpose of the environment variables is mainly to avoid asking questions and making the installation completely non-interactive (for instace in order to use the produced ISO as input to a [packer](https://github.com/gunet/packer) template). +If no environment variables are passed then the installer will just ask more questions. The purpose of the environment variables is mainly to avoid asking questions and making the installation completely non-interactive (for instance in order to use the produced ISO as input to a [packer](https://github.com/gunet/packer) template). Sample full `vm.env` file (include with `--env-file vm.env` option in `docker run`): -``` + +```bash NET_IP=123.123.123.123/25 NET_GATEWAY=123.123.123.1 NET_NAMESERVERS=8.8.8.8 @@ -33,50 +41,65 @@ ROOT_PASSWORD=password ``` ### ssh keys + * By default root is allowed public key ssh access in the resulting VM * If you volume mount an `authorized_keys` file under `gunet/` folder then it will be used in the resulting ISO: `-v ${PWD}/authorized_keys:/var/jeos/gunet/authorized_keys` ### Special Notes + * The ssh server will listen on port `65432` instead of the default `22` ### Building + * Default `ARG` values: - - ARG DEBIAN_VERSION=11.8.0 - - ARG DEBIAN_REPO=https://cdimage.debian.org/mirror/cdimage/archive/${DEBIAN_VERSION}/amd64/iso-cd - - ARG DEBIAN_ISO=debian-${DEBIAN_VERSION}-amd64-netinst.iso + * ARG DEBIAN_VERSION=11.8.0 + * ARG DEBIAN_REPO= + * ARG DEBIAN_ISO=debian-${DEBIAN_VERSION}-amd64-netinst.iso * Simple build: `docker build -t ghcr.io/gunet/jeos-builder .` * Build for another debian version: `docker build --build-arg DEBIAN_VERSION= -t ghcr.io/gunet/jeos-builder .` ### Available versions + * Debian 11: `latest`: `11.8.0` * Debian 12: `12.2.0` ## HTTP Server -You can use the `httpd` Docker image to run an httpd server to temporarilly expose the ISO image in order to use in web installations (will listen on port `80`): + +You can use the `httpd` Docker image to run an httpd server to temporarily expose the ISO image in order to use in web installations (will listen on port `80`): `docker run --rm -p 80:80 --name jeos-web -v ${PWD}/final:/usr/local/apache2/htdocs/ httpd:2.4` ## Mount + If you want to mount the resulting ISO image locally: + * `mkdir /mnt/iso` * `mount -o loop final/gunet-jeos-debian-.iso /mnt/iso` * To unmount: `umount /mnt/iso` ## Size + * Docker image: - - Debian 11: `510 MB` - - Debian 12: `760 MB` + * Debian 11: `510 MB` + * Debian 12: `760 MB` * JeOS ISO CD: - - Debian 11: `450 MB` - - Debian 12: `750 MB` + * Debian 11: `450 MB` + * Debian 12: `750 MB` * JeOS installation: - - Debian 11: `1.2 GB` - - Debian 12: `1.8 GB` + * Debian 11: `1.2 GB` + * Debian 12: `1.8 GB` ## Notes for repo files + ### Run -In order to produce a Just Enough Operating System iso image, we need to run the script __mkiso.sh__ as follows: -`sudo ./mkiso.sh` + +In order to produce a Just Enough Operating System iso image, we need to run the script [mkiso.sh](mkiso.sh) as follows: + +```bash +sudo ./mkiso.sh +``` + It uses the following two environment variables: + * `DEBIAN_ISO` to find the Debian ISO in `$(pwd)/debian/${DEBIAN_ISO}` * `DEBIAN_VERSION` (if available) to use it in the name of the produced ISO file. The default name is `$(pwd)/final/gunet-jeos-debian.iso` and if the `DEBIAN_VERSION` variable is available `$(pwd)/final/gunet-jeos-debian-${DEBIAN_VERSION}.iso` @@ -84,15 +107,17 @@ The `DEBIAN_ISO` file is a Debian ISO file from the Debian project. An archive o Debian versions can be found [here](https://cdimage.debian.org/mirror/cdimage/archive/) ### Configuration -The produced .iso file installs a Debian OS, by requesting only the root password and the network configuration paramenters, in case DHCP fails, during the installation if the necessary environment variables are not available. All the configuration must be located into _gunet/_ folder. In the current configuration, _gunet/_ folder contains the follwing: -* _preseed.cfg_: This file contains all the configuration of d-i installer that automates the installation procedure. The parameters are set to produce an as minimal as possible installation. During the _late_command_ step, we add further configuration and run scripts that we want to include in the installation procedure. -* _00norecommends_: This file is copied into the _/etc/apt/apt.conf.d/_ folder by the late_command of d-i installer and prevents the installation of suggested and recommended packages during package installation via ```apt```. -* _disableipv6.conf_: This file is copied into the _/etc/sysctl.d/_ folder by the late_command of d-i installer and disables ipv6 network configuration. -* _locale_: This file is copied into the _/etc/default/_ folder by the late_command of d-i installer and sets up the locale configuration. -* _sources.list_: This file is copied into the _/etc/apt/_ folder by the late_command of d-i installer and defines the repos from which the packages will be installed via ```apt```. -* _internal_custom_script.sh_: This script is executed by the late_command of d-i installer and adds or removes packages to/from the initial installation. Any package addition or removal should be included here. -* _custom_script.sh_: This script is executed by the late_command of d-i installer and configures services(i.e. the port of the ssh server) and removes files or folders. Any configuration of system services should be included here. - - In our case we change the ssh port from the default `22` to `65432`. -* _install_docker_: This script installs docker. - -***Note***: For any further addition to the above, the new configuration file or script must be included in the _gunet/_ file and the respective changes in the late_command of the preseed.cfg file must be performed. \ No newline at end of file + +The produced .iso file installs a Debian OS, by requesting only the root password and the network configuration parameters, in case DHCP fails, during the installation if the necessary environment variables are not available. All the configuration must be located into [gunet/](gunet/) folder. In the current configuration, [gunet/](gunet/) folder contains the following: + +* [preseed.cfg](gunet/preseed.cfg): This file contains all the configuration of d-i installer that automates the installation procedure. The parameters are set to produce an as minimal as possible installation. During the *late_command* step, we add further configuration and run scripts that we want to include in the installation procedure. +* [00norecommends](gunet/00norecommends): This file is copied into the */etc/apt/apt.conf.d/* folder by the late_command of d-i installer and prevents the installation of suggested and recommended packages during package installation via ```apt```. +* [disableipv6.conf](gunet/disableipv6.conf): This file is copied into the */etc/sysctl.d/* folder by the late_command of d-i installer and disables ipv6 network configuration. +* [locale](gunet/locale): This file is copied into the */etc/default/* folder by the late_command of d-i installer and sets up the locale configuration. +* [sources.list](gunet/sources.list): This file is copied into the */etc/apt/* folder by the late_command of d-i installer and defines the repos from which the packages will be installed via ```apt```. +* [internal_custom_script.sh](gunet/internal_custom_script.sh): This script is executed by the late_command of d-i installer and adds or removes packages to/from the initial installation. Any package addition or removal should be included here. +* [custom_script.sh](gunet/custom_script.sh): This script is executed by the late_command of d-i installer and configures services(i.e. the port of the ssh server) and removes files or folders. Any configuration of system services should be included here. + * In our case we change the ssh port from the default `22` to `65432`. +* [install_docker](gunet/install_docker): This script installs docker. + +***Note***: For any further addition to the above, the new configuration file or script must be included in the [gunet/](gunet/) file and the respective changes in the late_command of the preseed.cfg file must be performed. diff --git a/cspell-words.txt b/cspell-words.txt new file mode 100644 index 0000000..8505214 --- /dev/null +++ b/cspell-words.txt @@ -0,0 +1,23 @@ +00norecommends +cdrom +cpio +disableipv6 +emul +genisoimage +htdocs +irmod +ISODIR* +ISOFILE* +isofiles # see https://cspell.org/docs/dictionaries-custom/ +isohybrid +isolinux +gunet +jeos +mkiso +mknod +netinst +newc +notset +preseed +syslinux +xorriso diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..5b716f1 --- /dev/null +++ b/cspell.json @@ -0,0 +1,17 @@ +{ + // Enable your dictionary by adding it to the list of `dictionaries` + "dictionaries": ["custom-words"], + + // Tell CSpell about your dictionary + "dictionaryDefinitions": [ + { + // The name of the dictionary is used to look it up. + "name": "custom-words", + // Path to the custom word file. Relative to this `cspell.json` file. + "path": "./cspell-words.txt", + // Some editor extensions will use `addWords` for adding words to your + // personal dictionary. + "addWords": true + } + ] +} diff --git a/gunet/install_docker.sh b/gunet/install_docker.sh index 71f694f..04faf0c 100644 --- a/gunet/install_docker.sh +++ b/gunet/install_docker.sh @@ -8,7 +8,7 @@ echo "Install git.." apt -qqy install git echo "Add Docker repository GPG key.." curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - -echo "Add Docker reposity.." +echo "Add Docker repository.." add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" echo "apt update (second time).." apt update @@ -18,7 +18,7 @@ echo "Show docker status.." systemctl status docker echo "Running docker version.." docker version -echo "Dowloading docker-compose.." +echo "Downloading docker-compose.." curl -fsSL https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64 >/usr/local/bin/docker-compose chmod 0755 /usr/local/bin/docker-compose echo "Checking docker-compose version" diff --git a/gunet/preseed.cfg b/gunet/preseed.cfg index e1de828..1ec0787 100644 --- a/gunet/preseed.cfg +++ b/gunet/preseed.cfg @@ -1,3 +1,4 @@ +# cSpell: disable #### Contents of the preconfiguration file (bullseye) ### Localization d-i debian-installer/language string en diff --git a/mkiso.sh b/mkiso.sh index 77b1d17..48ffaa9 100755 --- a/mkiso.sh +++ b/mkiso.sh @@ -1,6 +1,7 @@ #!/bin/bash # Include the helper functions -source $(dirname "$0")/helper_functions.sh +# shellcheck disable=SC1091 +source "$(dirname "$0")"/helper_functions.sh set -e set -u @@ -23,7 +24,7 @@ if [[ ! -v DEBIAN_ISO || ! -v DEBIAN_VERSION ]]; then exit 1 fi -DEBIAN_MAJOR=$(echo -n ${DEBIAN_VERSION}|cut -d. -f 1) +DEBIAN_MAJOR=${DEBIAN_VERSION%%.*} echo "Debian major version is ${DEBIAN_MAJOR}.." if [[ ${DEBIAN_MAJOR} != "11" && ${DEBIAN_MAJOR} != "12" ]]; then echo "Debian major version not supported!" @@ -31,7 +32,7 @@ if [[ ${DEBIAN_MAJOR} != "11" && ${DEBIAN_MAJOR} != "12" ]]; then fi if [[ ${DEBIAN_MAJOR} == "12" ]]; then echo "Updating sources.list for Debian 12.." - sed -i'' 's/bullseye/bookworm/g' ${PRESEED_DIR}/sources.list + sed -i'' 's/bullseye/bookworm/g' "${PRESEED_DIR}"/sources.list fi ISOFILE=${PROJECT_DIR}/debian/${DEBIAN_ISO} @@ -45,20 +46,20 @@ if [[ ${NET_STATIC} == "yes" ]]; then echo "Environment variable NET_STATIC is yes but some NET_* variables are not set!" exit 1 fi - sed -i'' -e "s/^#STATIC#//g" ${PRESEED_DIR}/preseed.cfg + sed -i'' -e "s/^#STATIC#//g" "${PRESEED_DIR}"/preseed.cfg fi if [[ ${NET_IP} != "notset" ]]; then if [[ ${NET_GATEWAY} == "notset" || ${NET_NAMESERVERS} == "notset" ]]; then echo "Environment variable NET_IP is set but NET_GATEWAY or NET_NAMESERVERS are not!" exit 1 fi - NET_IP_PLAIN=$(cidr_ip ${NET_IP}) - NET_PREFIX=$(cidr_prefix ${NET_IP}) + NET_IP_PLAIN=$(cidr_ip "${NET_IP}") + NET_PREFIX=$(cidr_prefix "${NET_IP}") if [[ ${NET_PREFIX} == "" ]]; then echo "NET_IP should be of CIDR form" exit 1 fi - NET_NETMASK=$(netmask_of_prefix ${NET_PREFIX}) + NET_NETMASK=$(netmask_of_prefix "${NET_PREFIX}") echo "Network configuration:" echo "IP (CIDR): ${NET_IP}" @@ -70,7 +71,7 @@ if [[ ${NET_IP} != "notset" ]]; then echo "-------------------------------" sed -i'' -e "s/^#NET#//g" -e "s/__IP__/${NET_IP_PLAIN}/" -e "s/__NETMASK__/${NET_NETMASK}/" \ - -e "s/__GATEWAY__/${NET_GATEWAY}/" -e "s/__NAMESERVERS__/${NET_NAMESERVERS}/" ${PRESEED_DIR}/preseed.cfg + -e "s/__GATEWAY__/${NET_GATEWAY}/" -e "s/__NAMESERVERS__/${NET_NAMESERVERS}/" "${PRESEED_DIR}"/preseed.cfg fi if [[ ${NET_HOSTNAME} != "notset" ]]; then @@ -84,15 +85,15 @@ if [[ ${NET_HOSTNAME} != "notset" ]]; then echo "----------------------------" sed -i'' -e "s/^#HOST#//g" \ - -e "s/__HOSTNAME__/${NET_HOSTNAME}/" -e "s/__DOMAIN__/${NET_DOMAIN}/" ${PRESEED_DIR}/preseed.cfg + -e "s/__HOSTNAME__/${NET_HOSTNAME}/" -e "s/__DOMAIN__/${NET_DOMAIN}/" "${PRESEED_DIR}"/preseed.cfg fi if [[ ${ROOT_PASSWORD} != "notset" ]]; then echo "Root passwd: ${ROOT_PASSWORD}" - sed -i'' -e "s/^#ROOT#//g" -e "s/__ROOT_PASSWORD__/${ROOT_PASSWORD}/" ${PRESEED_DIR}/preseed.cfg + sed -i'' -e "s/^#ROOT#//g" -e "s/__ROOT_PASSWORD__/${ROOT_PASSWORD}/" "${PRESEED_DIR}"/preseed.cfg fi -sed -i "s/^M//" $PRESEED_DIR/custom_script.sh +sed -i "s/^M//" "$PRESEED_DIR"/custom_script.sh if [[ ! -e /dev/loop0 ]]; then echo 'Creating loop device..' @@ -100,54 +101,54 @@ if [[ ! -e /dev/loop0 ]]; then fi echo 'mounting ISO9660 filesystem...' # source: http://wiki.debian.org/DebianInstaller/ed/EditIso -[ -d $ISODIR ] || mkdir -p $ISODIR -mount -o loop $ISOFILE $ISODIR +[ -d "$ISODIR" ] || mkdir -p "$ISODIR" +mount -o loop "$ISOFILE" "$ISODIR" echo 'copying to writable dir...' -rm -rf $ISODIR_WRITE || true -[ -d $ISODIR_WRITE ] || mkdir -p $ISODIR_WRITE -rsync --info=progress2 -a -H --exclude=TRANS.TBL $ISODIR/ $ISODIR_WRITE +rm -rf "$ISODIR_WRITE" || true +[ -d "$ISODIR_WRITE" ] || mkdir -p "$ISODIR_WRITE" +rsync --info=progress2 -a -H --exclude=TRANS.TBL "$ISODIR"/ "$ISODIR_WRITE" echo 'unmount iso dir' -umount $ISODIR +umount "$ISODIR" echo 'correcting permissions...' -chmod 755 -R $ISODIR_WRITE +chmod 755 -R "$ISODIR_WRITE" echo 'copying preseed files...' -cp gunet/isolinux.cfg $ISODIR_WRITE/isolinux/ -cp -r $PRESEED_DIR/ $ISODIR_WRITE/ +cp gunet/isolinux.cfg "$ISODIR_WRITE"/isolinux/ +cp -r "$PRESEED_DIR"/ "$ISODIR_WRITE"/ echo 'edit isolinux/txt.cfg...' -sed 's/initrd.gz/initrd.gz file=\/cdrom\/gunet\/preseed.cfg/' -i $ISODIR_WRITE/isolinux/txt.cfg +sed 's/initrd.gz/initrd.gz file=\/cdrom\/gunet\/preseed.cfg/' -i "$ISODIR_WRITE"/isolinux/txt.cfg echo 'creating initrd.gz..' mkdir -p irmod cd irmod -gzip -d < $ISODIR_WRITE/install.amd/initrd.gz | \ +gzip -d < "$ISODIR_WRITE"/install.amd/initrd.gz | \ cpio --extract --make-directories --no-absolute-filenames -cp $PRESEED_DIR/preseed.cfg preseed.cfg +cp "$PRESEED_DIR"/preseed.cfg preseed.cfg chown root:root preseed.cfg -chmod o+w $ISODIR_WRITE/install.amd/initrd.gz +chmod o+w "$ISODIR_WRITE"/install.amd/initrd.gz find . | cpio -H newc --create | \ - gzip -9 > $ISODIR_WRITE/install.amd/initrd.gz -chmod o-w $ISODIR_WRITE/install.amd/initrd.gz + gzip -9 > "$ISODIR_WRITE"/install.amd/initrd.gz +chmod o-w "$ISODIR_WRITE"/install.amd/initrd.gz cd ../ rm -fr irmod/ echo 'fixing MD5 checksums...' -pushd $ISODIR_WRITE - md5sum $(find -type f) > md5sum.txt +pushd "$ISODIR_WRITE" + # shellcheck disable=SC2185 + md5sum "$(find -type f)" > md5sum.txt popd echo 'making ISO...' -genisoimage -o $ISOFILE_FINAL \ +genisoimage -o "$ISOFILE_FINAL" \ -r -J -no-emul-boot -boot-load-size 4 \ -boot-info-table -quiet \ -b isolinux/isolinux.bin \ - -c isolinux/boot.cat $ISODIR_WRITE + -c isolinux/boot.cat "$ISODIR_WRITE" -isohybrid $ISOFILE_FINAL +isohybrid "$ISOFILE_FINAL" rm -r isofiles* echo 'finished' -