Compare commits

...

10 commits

Author SHA1 Message Date
8db14b64ae autocommit 2025-04-26 12:51:13 +02:00
3eae48fcfb Fix Makefile 2025-04-26 09:07:51 +02:00
0996214159 Add release_version & iso_version to install.sh => inventory.yml 2025-04-26 01:28:11 +02:00
810c4ff1be Major Release 2412-1
* Replaced salt w. ansible
* Switched os-base to Alpine 3.21
* Reworked Installer
* * Added Installation Targets gaming,proxy,build
* * End-screen now presents options to reboot, poweroff or alpine-shell
2024-12-28 14:21:03 +01:00
3f9cd642e0 update Makefile 2024-05-30 21:24:15 +02:00
4f94ad8ca9 rework iso w. mkalpineiso, update base to 3.20 2024-05-30 21:10:03 +02:00
3e08a20f76 install - fix additional states, add tmpfs.size pillar 2024-03-10 12:40:20 +01:00
4c246b8b04 add serverspecific.sls 2024-03-09 21:18:39 +01:00
354a61dbbb rename system.timestamp => system.disks.timestamp 2024-03-09 17:50:48 +01:00
a73987107f populate pillars dynamically during installation 2024-03-09 17:50:19 +01:00
11 changed files with 650 additions and 119 deletions

View file

@ -1,5 +1,6 @@
iso:
sudo mkteaiso -o ${PWD}/out -p ${PWD}
sed "s|%REL_VER%|$(shell grep -E 'release_version.' profiledef.sh | cut -d= -f2 | jq -r '.')|g; s|%ALP_VER%|$(shell grep -E 'iso_version.' profiledef.sh | cut -d= -f2 | jq -r '.')|" template/root/install.sh > airootfs/root/install.sh
sudo mkalpineiso -o ${PWD}/out
clean:
sudo rm -f ${PWD}/out/*.iso

View file

@ -1,6 +1,6 @@
# NoveriaOS files
# Novos files
This are the official NoveriaOS files.
The ISO is generated using teaiso.
This are the official Novos files.
The ISO is generated using mkalpineiso.
Within the ISO, you'll be greeted by a installation-script to guide you through the installation-process of NoveriaOS.
Within the ISO, you'll be greeted by an installation-script to guide you through the installation-process of Novos.

View file

@ -1,3 +0,0 @@
https://dl-cdn.alpinelinux.org/alpine/v3.19/main
https://dl-cdn.alpinelinux.org/alpine/v3.19/community
@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing

View file

@ -1,5 +0,0 @@
state_verbose: False
file_client: local
file_roots:
base:
- /srv/salt

View file

@ -2,7 +2,7 @@
###
##
## NoveriaOS Install script
## Novos Install script
##
###
@ -22,11 +22,10 @@ readonly INSTALLATION_ESP_PARTITION_SIZE=4
readonly INSTALLATION_MOUNTPOINT='/mnt'
readonly INSTALLATION_NOVERIA_BIN='/usr/local/noveria/bin'
readonly INSTALLATION_SECRETS_FILE="/root/installation.secrets"
readonly INSTALLATION_SALT_ROOT="srv/salt"
readonly INSTALLATION_SALT_GIT="https://git.noveria.org/NoveriaOS/salt-statetree.git"
readonly INSTALLATION_PILLAR_ROOT="srv/pillar"
readonly INSTALLATION_PILLAR_GIT="https://git.noveria.org/NoveriaOS/salt-pillartree.git"
readonly INSTALLATION_ANSIBLE_ROOT="srv/ansible"
readonly INSTALLATION_ANSIBLE_GIT="https://git.noveria.org/Novos/ansible-playbooks.git"
readonly INSTALLATION_ALPINE_VERSION=$(cat /etc/os-release | grep VERSION_ID | cut -d= -f2)
readonly INSTALLATION_REL_VERSION=2412
# Colors
readonly RED='\033[0;31m'
@ -46,6 +45,14 @@ trap "errorHardExit 'Interrupted with CTRL+C'" SIGINT SIGHUP SIGTERM SIGABRT
## Helper Functions
###
##
# Run commands in chroot
# - $1: command
##
function runInChroot() {
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "$1"
}
##
# Installation subtask title output
# - $1: subtask title
@ -113,7 +120,7 @@ function preChecks() {
0)
clear
COUNTER=5
echo "NoveriaOS is shutting down in: "
echo "Novos is shutting down in: "
while [ 1 ]; do
if [ ${COUNTER} -eq 0 ]; then
break
@ -148,16 +155,15 @@ function preChecks() {
function introDialogue() {
local introtext="\n\n\n
Velkommen til
_ _ _
| \ | | _____ _____ _ __(_) __ _
| \| |/ _ \ \ / / _ \ '__| |/ _ |
| |\ | (_) \ V / __/ | | | (_| |
|_| \_|\___/ \_/ \___|_| |_|\__,_|
OS: NoveriaOS
Version: $(date "+%Y%m")
_ _\n
| \ | | _____ _____ ___\n
| \| |/ _ \ \ / / _ \/ __|\n
| |\ | (_) \ V / (_) \__ \ \n
|_| \_|\___/ \_/ \___/|___/\n\n
OS: Novos
Version: $INSTALLATION_REL_VERSION
IP: $(ifconfig eth0 | grep "inet addr" | awk '{$1=$1};1' | awk '{print $2}' | cut -d: -f2)
How do you want to continue?
"
dialog --stdout --clear --cr-wrap --no-collapse --yes-label "Graphical Guide" --no-label "Alpine shell" --yesno "$introtext" 31 93
@ -223,6 +229,9 @@ function prepareInstallation() {
INSTALLATION_DOMAIN=$(dialog --clear --title "What's the domain of this device?" --inputbox "Enter domain (leave empty for localhost)" 10 70 3>&1 1>&2 2>&3 3>&-)
[[ -z "$INSTALLATION_DOMAIN" ]] && INSTALLATION_DOMAIN="localhost"
# installation type
INSTALLATION_TYPE=$(dialog --clear --title "Choose the main installation type of this host" --radiolist "Select one" 10 70 3 gaming Game-Server false proxy Proxy-Server false build Build-Server false 3>&1 1>&2 2>&3 3>&-)
# show summary
summary
}
@ -233,7 +242,8 @@ function prepareInstallation() {
function summary() {
dialog --stdout --clear --title "Summary" --yes-label "Confirm" --no-label "Abort" --yesno "\n
Hostname: ${INSTALLATION_HOSTNAME}.${INSTALLATION_DOMAIN}\n
Disk: $INSTALLATION_DISK
Type: ${INSTALLATION_TYPE}\n
Disk: ${INSTALLATION_DISK}
" 9 60
case $? in
@ -255,7 +265,7 @@ Disk: $INSTALLATION_DISK
function installation() {
# clear display
clear
# lock file
touch "$INSTALLATION_LOCK_FILE" || installationFailed
@ -319,7 +329,7 @@ function installation() {
installationSubtaskTitle "Mount ESP"
mount -o nodev,nosuid,noexec "${ESP_PARTITION}" "${INSTALLATION_MOUNTPOINT}/efi" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Install and configure OS │"
@ -337,8 +347,8 @@ function installation() {
cp /etc/resolv.conf "${INSTALLATION_MOUNTPOINT}/etc/resolv.conf" || installationFailed
installationSubtaskTitle "Setup PATH"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'" || installationFailed
runInChroot "export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'" || installationFailed
installationSubtaskTitle "Mount extra mounts for chroot"
mount -t proc /proc "${INSTALLATION_MOUNTPOINT}/proc" || installationFailed
mount -t sysfs /sys "${INSTALLATION_MOUNTPOINT}/sys" || installationFailed
@ -348,93 +358,94 @@ function installation() {
installationSubtaskTitle "Install base-packages"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "apk add alpine-base --no-cache" || installationFailed
runInChroot "apk add alpine-base tzdata eudev udev-init-scripts --no-cache" || installationFailed
installationSubtaskTitle "Overwrite default repositories"
cp /etc/apk/repositories "${INSTALLATION_MOUNTPOINT}/etc/apk/repositories" || installationFailed
installationSubtaskTitle "Install SaltStack"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "apk add salt-minion envsubst" || installationFailed
installationSubtaskTitle "Install Ansible"
runInChroot "apk add ansible envsubst" || installationFailed
installationSubtaskTitle "Setup keymap"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "setup-keymap ch ch" || installationFailed
runInChroot "setup-keymap ch ch" || installationFailed
installationSubtaskTitle "Setting localtime to Europe/Zurich"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "setup-timezone Europe/Zurich" || installationFailed
runInChroot "ln -s /usr/share/zoneinfo/Europe/Zurich /etc/localtime" || installationFailed
installationSubtaskTitle "Time sync"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "hwclock --systohc" || installationFailed
runInChroot "hwclock --systohc" || installationFailed
installationSubtaskTitle "Setup hostname"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "echo '${INSTALLATION_HOSTNAME}.${INSTALLATION_DOMAIN}' > /etc/hostname" || installationFailed
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "hostname -F /etc/hostname" || installationFailed
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "rc-update add hostname" || installationFailed
runInChroot "echo '${INSTALLATION_HOSTNAME}.${INSTALLATION_DOMAIN}' > /etc/hostname" || installationFailed
runInChroot "hostname -F /etc/hostname" || installationFailed
runInChroot "rc-update add hostname" || installationFailed
installationSubtaskTitle "Setup hosts"
cp /etc/hosts "${INSTALLATION_MOUNTPOINT}/etc/hosts" || installationFailed
installationSubtaskTitle "Set root password"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "echo -e \"${INSTALLATION_ROOT_PW}\n${INSTALLATION_ROOT_PW}\" | passwd" || installationFailed
runInChroot "echo -e \"${INSTALLATION_ROOT_PW}\n${INSTALLATION_ROOT_PW}\" | passwd" || installationFailed
installationSubtaskTitle "Enable btrfs module"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "echo 'btrfs' >> /etc/modules"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "echo 'efivarfs' >> /etc/modules"
runInChroot "echo 'btrfs' >> /etc/modules"
runInChroot "echo 'efivarfs' >> /etc/modules"
installationSubtaskTitle "Enable udev services"
runInChroot "rc-update add udev sysinit"
runInChroot "rc-update add udev-trigger sysinit"
runInChroot "rc-update add udev-settle sysinit"
runInChroot "rc-update add udev-postmount default"
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Configure SaltStack and highstate │"
echo "│ Configure Ansible and playbook-run │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Clone Salt-Repo"
mkdir -p ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_SALT_ROOT}
git clone ${INSTALLATION_SALT_GIT} ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_SALT_ROOT}
installationSubtaskTitle "Clone Playbook-repo"
mkdir -p ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/playbooks
git clone ${INSTALLATION_ANSIBLE_GIT} ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/playbooks
cat >"${INSTALLATION_MOUNTPOINT}/etc/salt/minion" <<EOT || installationFailed
---
state_verbose: False
file_client: local
file_roots:
base:
- /srv/salt
pillar_roots:
base:
- /srv/pillar
...
mkdir -p ${INSTALLATION_MOUNTPOINT}/etc/ansible
cat >"${INSTALLATION_MOUNTPOINT}/etc/ansible/ansible.cfg" <<EOT || installationFailed
[defaults]
inventory=/${INSTALLATION_ANSIBLE_ROOT}/inventory.yml
EOT
cat >"${INSTALLATION_MOUNTPOINT}/etc/salt/grains" <<EOT || installationFailed
os: Alpine
os_family: Alpine
cat >"${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/inventory.yml" <<EOT
ungrouped:
hosts:
localhost
vars:
ansible_connection: local
start_timestamp: ${START_TIMESTAMP}
tmpfs_size: 4G
installation_type: ${INSTALLATION_TYPE}
mysql_root_password: $(randomPasswordGen 32)
release_version: 2412
alpine_version: v3.21
EOT
installationSubtaskTitle "Clone Pillar-Repo"
mkdir -p ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_PILLAR_ROOT}
git clone ${INSTALLATION_PILLAR_GIT} ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_PILLAR_ROOT}
cat >"${INSTALLATION_MOUNTPOINT}/${INSTALLATION_PILLAR_ROOT}/system/init.sls" << EOT
timestamp: ${START_TIMESTAMP}
EOT
installationSubtaskTitle "Salt highstate"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "salt-call state.highstate" || installationFailed
installationSubtaskTitle "Execute Ansible playbooks"
runInChroot "ansible-playbook /${INSTALLATION_ANSIBLE_ROOT}/playbooks/top.ansible.yml" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Boot │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Make EFI boot image with mkinitfs"
latest_kernel="$(chroot $INSTALLATION_MOUNTPOINT /bin/ash -c 'echo $(apk search linux-lts | head -n1 | cut -d- -f3- | sed "s|r||")-lts')"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "mkinitfs $latest_kernel" || installationFailed
runInChroot "mkinitfs $latest_kernel" || installationFailed
installationSubtaskTitle "Installing grub to /efi"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=alpine" || installationFailed
runInChroot "grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=alpine" || installationFailed
installationSubtaskTitle "Generating Bootmenu entries"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/noveriablcgen --noconfirm" || installationFailed
installationSubtaskTitle "Generating motd"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/generate_motd" || installationFailed
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/nsm check remote" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
@ -458,17 +469,18 @@ EOT
# remove shell histories
rm -f /root/.zsh_history
dialog --stdout --clear --cr-wrap --no-collapse --yes-label "Reboot" --no-label "Alpine shell" --yesno "\n Installation finished" 7 50
case $? in
0) reboot ;;
1)
clear
exit
;;
255)
clear
exit
;;
selected_option=$(dialog --output-fd 1 --menu "What would you like to do?" 10 70 5 reboot "Reboot into your newly installed system" poweroff "Shut down the current live system" alpine-shell "Switch to an interactive shell")
case "$selected_option" in
"reboot")
reboot
;;
"poweroff")
poweroff
;;
"alpine-shell")
clear
exit
;;
esac
}

View file

@ -1,6 +0,0 @@
insmod all_video
insmod part_msdos
insmod part_gpt
insmod fat
set timeout=1

View file

@ -1,7 +1,7 @@
#!/usr/bin/env ash
# overwrite default-hostname
echo "noveriaos-live" > /etc/hostname
echo "novos-live" > /etc/hostname
hostname -F /etc/hostname
# Enable networking on boot
@ -10,8 +10,6 @@ rc-update add networking
# Enable hostname service
rc-update add hostname
rc-update add sshd
# Set Swiss keymap
setup-keymap ch ch
@ -20,9 +18,9 @@ setup-timezone Europe/Zurich
hwclock --systohc
# Change default shell of root from ash => zsh
sed -i 's~root:/bin/ash~root:/bin/zsh~' /etc/passwd
sed -i 's~root:/bin/sh~root:/bin/zsh~' /etc/passwd
sed -i 's~/sbin/getty 38400~/sbin/mingetty --autologin root --noclear~' /etc/inittab
sed -i 's~/sbin/getty 38400~/usr/sbin/mingetty --autologin root --noclear~' /etc/inittab
# Add btrfs module
echo "btrfs" | tee -a /etc/modules

View file

@ -1,6 +1,6 @@
linux-lts
linux-firmware-none
salt-minion
linux-firmware
ansible
zsh
vim
btrfs-progs

View file

@ -1,17 +0,0 @@
name: noveriaos
distro: alpine
publisher: Noveria Network <https://noveria.org>
label: NOVERIAOS
codename: latest-stable
application_id: Alpine Linux Live Media
airootfs_directory: airootfs
#iso_merge: iso_merge
compression: squashfs||-comp gzip
grub_cfg: grub.cfg
packages:
- packages.x86_64
file_permissions:
- /etc/shadow|0:0:400
- /root/install.sh|0:0:755
customize_airootfs:
- customize-airootfs.sh

18
profiledef.sh Normal file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
iso_name="novos-ansible"
iso_label="NOVOS_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m%d)-ANSIBLE"
iso_publisher="Noveria Network <https://noveria.org>"
iso_application="Alpine-Linux Based Server OS for Noveria"
iso_version="v3.21"
release_version="2412"
airootfs_image_type="squashfs"
airootfs_image_tool_options="-comp gzip"
declare -gA file_permissions=(
["/etc/shadow"]="0:0:400"
["/root/install.sh"]="0:0:755"
)
customize_airootfs=(
"novos-base.sh"
)

533
template/root/install.sh Normal file
View file

@ -0,0 +1,533 @@
#!/usr/bin/env bash
###
##
## Novos Install script
##
###
###
## Definitions
###
# Checks
readonly CHECK_INTERNET_URL='www.alpinelinux.org'
# Installation
readonly INSTALLATION_LOCK_FILE='/root/.installation.lock'
readonly INSTALLATION_LOGFILE='/root/installation.log'
readonly INSTALLATION_PARTLABEL_ESP="ESP"
readonly INSTALLATION_PARTLABEL_ROOT="ROOT"
readonly INSTALLATION_ESP_PARTITION_SIZE=4
readonly INSTALLATION_MOUNTPOINT='/mnt'
readonly INSTALLATION_NOVERIA_BIN='/usr/local/noveria/bin'
readonly INSTALLATION_SECRETS_FILE="/root/installation.secrets"
readonly INSTALLATION_ANSIBLE_ROOT="srv/ansible"
readonly INSTALLATION_ANSIBLE_GIT="https://git.noveria.org/Novos/ansible-playbooks.git"
readonly INSTALLATION_ALPINE_VERSION=$(cat /etc/os-release | grep VERSION_ID | cut -d= -f2)
readonly INSTALLATION_REL_VERSION=%REL_VER%
# Colors
readonly RED='\033[0;31m'
readonly NC='\033[0m' # No Color
###
## Errorhandling
###
# set -e exit script when a command fails
# set -o pipefail check any command in pipeline for error, not just last one
# set -eo pipefail
# catch ^C and other signals and clean up
trap "errorHardExit 'Interrupted with CTRL+C'" SIGINT SIGHUP SIGTERM SIGABRT
###
## Helper Functions
###
##
# Run commands in chroot
# - $1: command
##
function runInChroot() {
chroot "${INSTALLATION_MOUNTPOINT}" /bin/ash -c "$1"
}
##
# Installation subtask title output
# - $1: subtask title
##
function installationSubtaskTitle() {
echo -e "\n=> $1"
}
##
# Random password generator (alphanumeric)
# - $1: password length (default 11)
# - $2: avoid poorly readable characters: l/I/1, O/0 (default false)
##
function randomPasswordGen() {
# character set
if ${2:-false}; then
local character_set='a-km-zA-HJ-NP-Z2-9'
else
local character_set='a-zA-Z0-9'
fi
# https://en.wikipedia.org/wiki/randomPasswordGen#Bash
LC_ALL=C tr -dc "$character_set" </dev/urandom | head -c "${1:-11}"
echo
}
##
# Hard exit with console error message
##
function errorHardExit() {
echo -e "${RED}$1${NC} \nAborting \n"
exit 1
}
###
## Functions
###
##
# Pre checks
##
function preChecks() {
# Check if another installation is in progress
if [ -f $INSTALLATION_LOCK_FILE ]; then
dialog --stdout --clear --no-collapse --yes-label "Exit" --no-label "Start anyway" --yesno " Another installation is in progress" 6 50
case $? in
0)
clear
exit
;;
1) rm "$INSTALLATION_LOCK_FILE" ;;
255)
clear
exit
;;
esac
fi
# Check if booted in UEFI
if [ ! -d /sys/firmware/efi ]; then
dialog --stdout --clear --no-collapse --yes-label "Shutdown" --nolabel "Alpine shell" --yesno "The ISO hasn't been booted in UEFI mode. Please boot the ISO in UEFI to proceed installation" 6 50
case $? in
0)
clear
COUNTER=5
echo "Novos is shutting down in: "
while [ 1 ]; do
if [ ${COUNTER} -eq 0 ]; then
break
fi
echo -n "${COUNTER}"
COUNTER=$( echo "${COUNTER}-1" | bc )
sleep 0.2
for (( i=0; i<4; i++ )); do
echo -n "."
sleep 0.2
done
done
poweroff
;;
1)
clear
exit 0
;;
255)
clear
exit
;;
esac
fi
introDialogue
}
##
# Introduction dialog
##
function introDialogue() {
local introtext="\n\n\n
Velkommen til
_ _\n
| \ | | _____ _____ ___\n
| \| |/ _ \ \ / / _ \/ __|\n
| |\ | (_) \ V / (_) \__ \ \n
|_| \_|\___/ \_/ \___/|___/\n\n
OS: Novos
Version: $INSTALLATION_REL_VERSION
IP: $(ifconfig eth0 | grep "inet addr" | awk '{$1=$1};1' | awk '{print $2}' | cut -d: -f2)
How do you want to continue?
"
dialog --stdout --clear --cr-wrap --no-collapse --yes-label "Graphical Guide" --no-label "Alpine shell" --yesno "$introtext" 31 93
case $? in
1)
clear
exit
;;
255)
clear
exit
;;
esac
checkInternetConnection
}
##
# Internet connection
##
function checkInternetConnection() {
dialog --no-collapse --infobox "\n Check internet connection" 5 35
# wait 5 seconds to give some more time for network initialization
sleep 5
while ! ping -c 1 "$CHECK_INTERNET_URL" >/dev/null 2>&1; do
dialog --clear --title "No internet connection" --msgbox "
Insert network cable, wait 5 seconds and press 'OK'" 7 65
done
prepareInstallation
}
##
# Installation preparation
##
function prepareInstallation() {
# disk
readonly AVAILABLE_DISKS=($(lsblk | grep -vE "p[0-9]+" | grep -vE "[s,v]d[a-z][0-9]+" | grep -v "luks" | grep -v "rom" | grep -vE "sd[a-z][0-9]+" | grep -v "/" | tail -n +2 | awk '{print $1}'))
for available_disk in ${AVAILABLE_DISKS[@]}; do
if [[ -z "$diskString" ]]; then
diskString="$available_disk /dev/$available_disk off"
else
diskString="$diskString $available_disk /dev/$available_disk off"
fi
done
INSTALLATION_DISK=$(dialog --clear --radiolist "Select Disk to install the system" 10 70 3 $(echo $diskString) 3>&1 1>&2 2>&3 3>&-)
INSTALLATION_DISK_BYID=$(lshw -class disk | grep ${INSTALLATION_DISK} | tr -d "[:space:]" | cut -d: -f2)
# root password
INSTALLATION_ROOT_PW=$(randomPasswordGen 5)
for _ in {0..2}; do
INSTALLATION_ROOT_PW="${INSTALLATION_ROOT_PW}-$(randomPasswordGen 5)"
done
# hostname
INSTALLATION_HOSTNAME=$(dialog --clear --title "What's the hostname of this device?" --inputbox "Enter hostname" 10 70 3>&1 1>&2 2>&3 3>&-)
# domain
INSTALLATION_DOMAIN=$(dialog --clear --title "What's the domain of this device?" --inputbox "Enter domain (leave empty for localhost)" 10 70 3>&1 1>&2 2>&3 3>&-)
[[ -z "$INSTALLATION_DOMAIN" ]] && INSTALLATION_DOMAIN="localhost"
# installation type
INSTALLATION_TYPE=$(dialog --clear --title "Choose the main installation type of this host" --radiolist "Select one" 10 70 3 gaming Game-Server false proxy Proxy-Server false build Build-Server false 3>&1 1>&2 2>&3 3>&-)
# show summary
summary
}
##
# Summary to confirm
##
function summary() {
dialog --stdout --clear --title "Summary" --yes-label "Confirm" --no-label "Abort" --yesno "\n
Hostname: ${INSTALLATION_HOSTNAME}.${INSTALLATION_DOMAIN}\n
Type: ${INSTALLATION_TYPE}\n
Disk: ${INSTALLATION_DISK}
" 9 60
case $? in
0) installation ;;
1)
clear
errorHardExit "Abort on summary dialog"
;;
255)
clear
errorHardExit "Abort on summary dialog"
;;
esac
}
##
# Installation
##
function installation() {
# clear display
clear
# lock file
touch "$INSTALLATION_LOCK_FILE" || installationFailed
# log all output to logfile
rm -f "$INSTALLATION_LOGFILE" || installationFailed
exec &> >(tee -a "$INSTALLATION_LOGFILE")
# create boot environment timestamp
START_TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Swipe and repartition disk │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Wipe disk"
blkdiscard -f "${INSTALLATION_DISK_BYID}" || installationFailed
installationSubtaskTitle "Repartitioning disk"
parted -s "${INSTALLATION_DISK_BYID}" mklabel gpt || installationFailed
parted -s "${INSTALLATION_DISK_BYID}" mkpart "${INSTALLATION_PARTLABEL_ESP}" fat32 1MiB ${INSTALLATION_ESP_PARTITION_SIZE}GiB || installationFailed
parted -s "${INSTALLATION_DISK_BYID}" set 1 esp on || installationFailed
parted -s "${INSTALLATION_DISK_BYID}" mkpart "${INSTALLATION_PARTLABEL_ROOT}" btrfs ${INSTALLATION_ESP_PARTITION_SIZE}GiB 100% || installationFailed
# Informing the Kernel of the changes.
sleep 0.1
partprobe "${INSTALLATION_DISK_BYID}" || installationFailed
# loop until lsblk is updated and gives the partition back
while
sleep 0.1
ESP_PARTITION="/dev/$(lsblk "${INSTALLATION_DISK_BYID}" -o NAME,PARTLABEL | grep "${INSTALLATION_PARTLABEL_ESP}" | cut -d " " -f1 | cut -c7-)" || installationFailed
ROOT_PARTITION="/dev/$(lsblk "${INSTALLATION_DISK_BYID}" -o NAME,PARTLABEL | grep "${INSTALLATION_PARTLABEL_ROOT}" | cut -d " " -f1 | cut -c7-)" || installationFailed
[[ "${ESP_PARTITION}" == '/dev/' || "${ROOT_PARTITION}" == '/dev/' ]]
do :; done
installationSubtaskTitle "File system creation"
mkfs.vfat -F 32 -n EFI "${ESP_PARTITION}" || installationFailed
mkfs.btrfs -f -L ROOT "${ROOT_PARTITION}" || installationFailed
installationSubtaskTitle "Create btrfs subvolumes"
mount -t btrfs "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}" || installationFailed
btrfs sub create "${INSTALLATION_MOUNTPOINT}/@root_${START_TIMESTAMP}" || installationFailed
btrfs sub create "${INSTALLATION_MOUNTPOINT}/@home" || installationFailed
btrfs sub create "${INSTALLATION_MOUNTPOINT}/@podman" || installationFailed
btrfs sub create "${INSTALLATION_MOUNTPOINT}/@mysql" || installationFailed
umount "${INSTALLATION_MOUNTPOINT}" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Mount filesystems │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Mount btrfs subvolumes"
mount -o noatime,nodiratime,discard=async,space_cache=v2,subvol=@root_"${START_TIMESTAMP}" "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}" || installationFailed
mkdir -p ${INSTALLATION_MOUNTPOINT}/{efi,home,btrfs,var/lib/mysql,opt/podman,sys/firmware/efi/efivars} || installationFailed
mount -o noatime,nodiratime,discard=async,space_cache=v2,subvol=@home "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}/home" || installationFailed
mount -o noatime,nodiratime,discard=async,space_cache=v2,subvol=@podman "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}/opt/podman" || installationFailed
mount -o noatime,nodiratime,discard=async,space_cache=v2,subvol=@mysql "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}/var/lib/mysql" || installationFailed
mount -o noatime,nodiratime,discard=async,space_cache=v2,subvol=/ "${ROOT_PARTITION}" "${INSTALLATION_MOUNTPOINT}/btrfs" || installationFailed
installationSubtaskTitle "Mount ESP"
mount -o nodev,nosuid,noexec "${ESP_PARTITION}" "${INSTALLATION_MOUNTPOINT}/efi" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Install and configure OS │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Install base packages"
wget https://raw.githubusercontent.com/alpinelinux/alpine-make-rootfs/v0.7.0/alpine-make-rootfs
chmod u+x alpine-make-rootfs
./alpine-make-rootfs --no-cleanup --branch 'v'$(echo ${INSTALLATION_ALPINE_VERSION} | rev | cut -d. -f2- | rev) --packages "apk-tools alpine-base linux-lts linux-firmware-none zsh vim btrfs-progs dialog wget git mkinitfs lsblk parted lshw shadow" ${INSTALLATION_MOUNTPOINT}
installationSubtaskTitle "Setup resolv.conf"
if [[ -f "${INSTALLATION_MOUNTPOINT}/etc/resolv.conf" ]]; then
rm -f "${INSTALLATION_MOUNTPOINT}/etc/resolv.conf"
fi
cp /etc/resolv.conf "${INSTALLATION_MOUNTPOINT}/etc/resolv.conf" || installationFailed
installationSubtaskTitle "Setup PATH"
runInChroot "export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'" || installationFailed
installationSubtaskTitle "Mount extra mounts for chroot"
mount -t proc /proc "${INSTALLATION_MOUNTPOINT}/proc" || installationFailed
mount -t sysfs /sys "${INSTALLATION_MOUNTPOINT}/sys" || installationFailed
mount -t efivarfs efivarfs "${INSTALLATION_MOUNTPOINT}/sys/firmware/efi/efivars" || installationFailed
mount -o bind /dev "${INSTALLATION_MOUNTPOINT}/dev" || installationFailed
mount -o bind /run "${INSTALLATION_MOUNTPOINT}/run" || installationFailed
installationSubtaskTitle "Install base-packages"
runInChroot "apk add alpine-base tzdata eudev udev-init-scripts --no-cache" || installationFailed
installationSubtaskTitle "Overwrite default repositories"
cp /etc/apk/repositories "${INSTALLATION_MOUNTPOINT}/etc/apk/repositories" || installationFailed
installationSubtaskTitle "Install Ansible"
runInChroot "apk add ansible envsubst" || installationFailed
installationSubtaskTitle "Setup keymap"
runInChroot "setup-keymap ch ch" || installationFailed
installationSubtaskTitle "Setting localtime to Europe/Zurich"
runInChroot "ln -s /usr/share/zoneinfo/Europe/Zurich /etc/localtime" || installationFailed
installationSubtaskTitle "Time sync"
runInChroot "hwclock --systohc" || installationFailed
installationSubtaskTitle "Setup hostname"
runInChroot "echo '${INSTALLATION_HOSTNAME}.${INSTALLATION_DOMAIN}' > /etc/hostname" || installationFailed
runInChroot "hostname -F /etc/hostname" || installationFailed
runInChroot "rc-update add hostname" || installationFailed
installationSubtaskTitle "Setup hosts"
cp /etc/hosts "${INSTALLATION_MOUNTPOINT}/etc/hosts" || installationFailed
installationSubtaskTitle "Set root password"
runInChroot "echo -e \"${INSTALLATION_ROOT_PW}\n${INSTALLATION_ROOT_PW}\" | passwd" || installationFailed
installationSubtaskTitle "Enable btrfs module"
runInChroot "echo 'btrfs' >> /etc/modules"
runInChroot "echo 'efivarfs' >> /etc/modules"
installationSubtaskTitle "Enable udev services"
runInChroot "rc-update add udev sysinit"
runInChroot "rc-update add udev-trigger sysinit"
runInChroot "rc-update add udev-settle sysinit"
runInChroot "rc-update add udev-postmount default"
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Configure Ansible and playbook-run │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Clone Playbook-repo"
mkdir -p ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/playbooks
git clone ${INSTALLATION_ANSIBLE_GIT} ${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/playbooks
mkdir -p ${INSTALLATION_MOUNTPOINT}/etc/ansible
cat >"${INSTALLATION_MOUNTPOINT}/etc/ansible/ansible.cfg" <<EOT || installationFailed
[defaults]
inventory=/${INSTALLATION_ANSIBLE_ROOT}/inventory.yml
EOT
cat >"${INSTALLATION_MOUNTPOINT}/${INSTALLATION_ANSIBLE_ROOT}/inventory.yml" <<EOT
ungrouped:
hosts:
localhost
vars:
ansible_connection: local
start_timestamp: ${START_TIMESTAMP}
tmpfs_size: 4G
installation_type: ${INSTALLATION_TYPE}
mysql_root_password: $(randomPasswordGen 32)
release_version: %REL_VER%
alpine_version: %ALP_VER%
EOT
installationSubtaskTitle "Execute Ansible playbooks"
runInChroot "ansible-playbook /${INSTALLATION_ANSIBLE_ROOT}/playbooks/top.ansible.yml" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Boot │"
echo "└──────────────────────────────────────────┘"
installationSubtaskTitle "Make EFI boot image with mkinitfs"
latest_kernel="$(chroot $INSTALLATION_MOUNTPOINT /bin/ash -c 'echo $(apk search linux-lts | head -n1 | cut -d- -f3- | sed "s|r||")-lts')"
runInChroot "mkinitfs $latest_kernel" || installationFailed
installationSubtaskTitle "Installing grub to /efi"
runInChroot "grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=alpine" || installationFailed
installationSubtaskTitle "Generating Bootmenu entries"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/noveriablcgen --noconfirm" || installationFailed
installationSubtaskTitle "Generating motd"
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/generate_motd" || installationFailed
chroot "${INSTALLATION_MOUNTPOINT}" /bin/bash -c "/usr/local/noveria/bin/nsm check remote" || installationFailed
echo ""
echo "┌──────────────────────────────────────────┐"
echo "│ Finishing │"
echo "└──────────────────────────────────────────┘"
#installationSubtaskTitle "Unmount"
#umount -l ${INSTALLATION_MOUNTPOINT} || installationFailed
installationSubtaskTitle "End of installation"
# end log all output to logfile
exec &>"$(tty)"
# write secrets file
writeInstallationSecretsToFile
# remove installation lock file
rm -f "$INSTALLATION_LOCK_FILE"
# remove shell histories
rm -f /root/.zsh_history
selected_option=$(dialog --output-fd 1 --menu "What would you like to do?" 10 70 5 reboot "Reboot into your newly installed system" poweroff "Shut down the current live system" alpine-shell "Switch to an interactive shell")
case "$selected_option" in
"reboot")
reboot
;;
"poweroff")
poweroff
;;
"alpine-shell")
clear
exit
;;
esac
}
##
# Write installation secrets to file
##
writeInstallationSecretsToFile() {
rm -f "$INSTALLATION_SECRETS_FILE"
{
echo "# Installation secrets from $START_TIMESTAMP"
echo ""
echo "FQDN: $(cat /mnt/etc/hostname)"
echo ""
echo "root_pw: ${INSTALLATION_ROOT_PW}"
echo ""
} >>"$INSTALLATION_SECRETS_FILE"
}
##
# Installation failed
# - $1: comment
##
installationFailed() {
# log error
echo -e "\n=> ERROR"
if [ -n "$1" ]; then
echo -e "=> Comment: $1"
fi
# end log all output to logfile
exec &>"$(tty)"
# Remove lock file
rm -f $INSTALLATION_LOCK_FILE
dialog --no-collapse --ok-label "Exit" --msgbox "\n Installation failed\n\nLog: ${INSTALLATION_LOGFILE} " 9 32
clear
exit 1
}
###
## Script Start
###
preChecks
###
## Script End
###