|
|
|
@@ -1,5 +1,12 @@
|
|
|
|
|
#!/usr/bin/env nix-shell
|
|
|
|
|
#!nix-shell -i bash -p gum xkcdpass openssl sops ssh-to-age age sshpass envsubst pciutils usbutils mosquitto rsync
|
|
|
|
|
#!nix-shell -i bash -p gum xkcdpass sops ssh-to-age age sshpass envsubst pciutils usbutils mosquitto
|
|
|
|
|
|
|
|
|
|
NECESSARY_VARIABLES_LIST=("TARGET_HOST" "SSH_PUBLIC_KEY" "DOMAIN_NAME" "EMAIL_ADDRESS" \
|
|
|
|
|
"CF_DNS_API_TOKEN" "SENDER_EMAIL_ADDRESS" "SENDER_EMAIL_ADDRESS_PASSWORD" \
|
|
|
|
|
"SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" \
|
|
|
|
|
"HOME_SERVER_IP")
|
|
|
|
|
|
|
|
|
|
INSTALLED_REMOTE_PASS="changeMe!"
|
|
|
|
|
|
|
|
|
|
necessary_credentials() {
|
|
|
|
|
#TARGET SETTINGS
|
|
|
|
@@ -40,9 +47,8 @@ necessary_credentials_with_config() {
|
|
|
|
|
CONFIG_PATH="$(gum file)"
|
|
|
|
|
|
|
|
|
|
source "$CONFIG_PATH"
|
|
|
|
|
REQUIRED_VARS=(TARGET_HOST SSH_PUBLIC_KEY DOMAIN_NAME EMAIL_ADDRESS CF_DNS_API_TOKEN SENDER_EMAIL_ADDRESS SENDER_EMAIL_ADDRESS_PASSWORD SENDER_EMAIL_DOMAIN SENDER_EMAIL_PORT HOME_ROUTER_SUBNET HOME_ROUTER_IP HOME_SERVER_IP)
|
|
|
|
|
MISSING=0
|
|
|
|
|
for VAR in "${REQUIRED_VARS[@]}"; do
|
|
|
|
|
for VAR in "${NECESSARY_VARIABLES_LIST[@]}"; do
|
|
|
|
|
if [[ -v $VAR && -n ${!VAR} ]]; then
|
|
|
|
|
echo -e "\n ✅ $VAR imported successfully from the config file"
|
|
|
|
|
export $VAR
|
|
|
|
@@ -63,29 +69,34 @@ setup_ssh() {
|
|
|
|
|
chmod 700 extra-files/home/numbus-admin/.ssh/
|
|
|
|
|
ssh-keygen -t "ed25519" -C "numbus-admin@numbus-server" -f "extra-files/home/numbus-admin/.ssh/id_ed25519" -N "" -q
|
|
|
|
|
|
|
|
|
|
REMOTE_PASS=$(gum input --password --placeholder "Enter password for 'nixos' on '$TARGET_HOST'")
|
|
|
|
|
if [ -z "$REMOTE_PASS" ]; then
|
|
|
|
|
LIVE_REMOTE_PASS=$(gum input --password --placeholder "Enter password for 'nixos@$TARGET_HOST'")
|
|
|
|
|
if [ -z "$LIVE_REMOTE_PASS" ]; then
|
|
|
|
|
echo " ❌ Password is required to proceed. Aborting."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo -e "\n\n ➡️ Copying SSH key to target host 'nixos@$TARGET_HOST'..."
|
|
|
|
|
if sshpass -p "$REMOTE_PASS" ssh-copy-id -o StrictHostKeyChecking=no -i "extra-files/home/numbus-admin/.ssh/id_ed25519" "nixos@$TARGET_HOST"; then
|
|
|
|
|
if sshpass -p "$LIVE_REMOTE_PASS" ssh-copy-id -o StrictHostKeyChecking=no -i "extra-files/home/numbus-admin/.ssh/id_ed25519" "nixos@$TARGET_HOST"; then
|
|
|
|
|
echo " ✅ SSH key copied successfully."
|
|
|
|
|
else
|
|
|
|
|
echo " ❌ Failed to copy SSH key. Please check the host IP and password."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
export REMOTE_PASS
|
|
|
|
|
export LIVE_REMOTE_PASS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssh_to_host() {
|
|
|
|
|
ssh_to_live_host() {
|
|
|
|
|
ARG="$1"
|
|
|
|
|
ssh -i "extra-files/home/numbus-admin/.ssh/id_ed25519" "nixos@$TARGET_HOST" $ARG
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssh_to_installed_host() {
|
|
|
|
|
ARG="$1"
|
|
|
|
|
ssh -i "extra-files/home/numbus-admin/.ssh/id_ed25519" "numbus-admin@$TARGET_HOST" $ARG
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hardware_detection() {
|
|
|
|
|
echo -e "\n\n 🔎 Detecting graphics card on target host..."
|
|
|
|
|
VGA_INFO=$(ssh_to_host "lspci -nn | grep -i 'vga'")
|
|
|
|
|
VGA_INFO=$(ssh_to_live_host "lspci -nn | grep -i 'vga'")
|
|
|
|
|
if echo "$VGA_INFO" | grep -iq "intel" 2>/dev/null; then
|
|
|
|
|
echo -e " ✅ Intel graphics card detected."
|
|
|
|
|
export TARGET_GRAPHICS="true"
|
|
|
|
@@ -100,7 +111,7 @@ hardware_detection() {
|
|
|
|
|
export TARGET_GRAPHICS="false"
|
|
|
|
|
fi
|
|
|
|
|
echo -e "\n\n 🔎 Detecting transconding acceleration on target host..."
|
|
|
|
|
if ssh_to_host "ls /dev/dri/ | grep -iq 'renderD128'" 2>/dev/null; then
|
|
|
|
|
if ssh_to_live_host "ls /dev/dri/ | grep -iq 'renderD128'" 2>/dev/null; then
|
|
|
|
|
echo -e " ✅ Transcoding capable card detected."
|
|
|
|
|
TARGET_GRAPHICS_RENDERER="true"
|
|
|
|
|
else
|
|
|
|
@@ -108,7 +119,7 @@ hardware_detection() {
|
|
|
|
|
TARGET_GRAPHICS_RENDERER="false"
|
|
|
|
|
fi
|
|
|
|
|
echo -e "\n\n 🔎 Detecting USB Google Coral TPU on target host..."
|
|
|
|
|
if ssh_to_host "lsusb | grep -iq 'google'" 2>/dev/null; then
|
|
|
|
|
if ssh_to_live_host "lsusb | grep -iq 'google'" 2>/dev/null; then
|
|
|
|
|
echo -e " ✅ USB Google Coral TPU detected."
|
|
|
|
|
TARGET_USB_CORAL="true"
|
|
|
|
|
else
|
|
|
|
@@ -116,9 +127,9 @@ hardware_detection() {
|
|
|
|
|
TARGET_USB_CORAL="false"
|
|
|
|
|
fi
|
|
|
|
|
echo -e "\n\n 🔎 Detecting Zigbee coordinator on target host..."
|
|
|
|
|
if ssh_to_host "ls /dev/serial/by-id/ | grep -i 'zigbee'" 2>/dev/null; then
|
|
|
|
|
if ssh_to_live_host "ls /dev/serial/by-id/ | grep -i 'zigbee'" 2>/dev/null; then
|
|
|
|
|
echo -e " ✅ Zigbee device found in /dev/serial/by-id/."
|
|
|
|
|
TARGET_ZIGBEE_DEVICE=$(ssh_to_host "ls /dev/serial/by-id/ | grep -i 'zigbee'")
|
|
|
|
|
TARGET_ZIGBEE_DEVICE=$(ssh_to_live_host "ls /dev/serial/by-id/ | grep -i 'zigbee'")
|
|
|
|
|
else
|
|
|
|
|
echo -e " ⚠️ No Zigbee device found."
|
|
|
|
|
TARGET_ZIGBEE_DEVICE=""
|
|
|
|
@@ -268,7 +279,7 @@ disk_config_generation() {
|
|
|
|
|
TMPFILE="/tmp/nixos-deployment-temp-file"
|
|
|
|
|
|
|
|
|
|
### --> Get disk information
|
|
|
|
|
DISK_DETAILS=$(ssh_to_host 'bash -s' <<EOF
|
|
|
|
|
DISK_DETAILS=$(ssh_to_live_host 'bash -s' <<EOF
|
|
|
|
|
HDD=1
|
|
|
|
|
|
|
|
|
|
DISK_DEVPATH=()
|
|
|
|
@@ -292,7 +303,7 @@ for DISK in \$(lsblk -x SIZE -d -n -e 7,11 -o NAME); do
|
|
|
|
|
else DISK_TYPE+=("Other")
|
|
|
|
|
fi
|
|
|
|
|
# Disk health
|
|
|
|
|
if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') -eq "PASSED" ]]; then
|
|
|
|
|
if [[ \$(echo "$LIVE_REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') -eq "PASSED" ]]; then
|
|
|
|
|
DISK_HEALTH+=("PASSED")
|
|
|
|
|
else
|
|
|
|
|
DISK_HEALTH+=("N/A")
|
|
|
|
@@ -345,16 +356,19 @@ EOF
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "Boot ; ${BOOT_DISKS_ID[@]}, ${#BOOT_DISKS_ID[@]}"
|
|
|
|
|
|
|
|
|
|
if [[ "${#BOOT_DISKS_ID[@]}" -eq 0 ]]; then
|
|
|
|
|
echo -e "\n\n ❌ No boot disk selected. Aborting."
|
|
|
|
|
exit 1
|
|
|
|
|
elif [[ "${#BOOT_DISKS_ID[@]}" -eq 1 ]]; then
|
|
|
|
|
echo -e "\n\n ⚠️ One boot disk selected, continuing with striped boot disk configuration."
|
|
|
|
|
echo -e " Consider using 2 boot disks instead to get data protection features on the boot disks."
|
|
|
|
|
export BOOT_DISK_1_ID=${BOOT_DISKS_ID[0]}
|
|
|
|
|
elif [[ "${#BOOT_DISKS_ID[@]}" -eq 2 ]]; then
|
|
|
|
|
echo -e "\n\n ✅ Two boot disks selected, continuing with mirrored boot disks configuration."
|
|
|
|
|
echo -e "\n\n ⚠️ If the two disks are different sizes, the resulting usable space size will be \
|
|
|
|
|
the one of the smallest disk."
|
|
|
|
|
export BOOT_DISK_1_ID=${BOOT_DISKS_ID[0]}
|
|
|
|
|
export BOOT_DISK_2_ID=${BOOT_DISKS_ID[1]}
|
|
|
|
|
else
|
|
|
|
|
echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting."
|
|
|
|
|
exit 1
|
|
|
|
@@ -491,7 +505,7 @@ EOF
|
|
|
|
|
### Config generation <--
|
|
|
|
|
|
|
|
|
|
### --> Generate unlock keys
|
|
|
|
|
for i in ${!BOOT_DISKS_ID[@]}; do
|
|
|
|
|
for i in ${#BOOT_DISKS_ID[@]}; do
|
|
|
|
|
declare "/etc/secrets/disks/boot-disk-${i}=$(xkcdpass -d "-")"
|
|
|
|
|
done
|
|
|
|
|
for i in $CONTENT_DISK_NUMBER; do
|
|
|
|
@@ -547,11 +561,63 @@ postrun_action() {
|
|
|
|
|
echo -e "\n\n Now the remote machine will reboot. You will need to input the boot disk(s) passphrase.
|
|
|
|
|
This will be the only time you will have to do so, it will be automatic in the future."
|
|
|
|
|
|
|
|
|
|
gum spin --spinner dot --title "Rebooting the remote..." -- sleep 60
|
|
|
|
|
gum spin --spinner dot --title "Rebooting the remote..." -- sleep 120
|
|
|
|
|
|
|
|
|
|
ssh
|
|
|
|
|
# Add TPM2 boot disk decryption
|
|
|
|
|
# Add pcr-check.nix
|
|
|
|
|
gum confirm " ➡️ Select 'yes' once the machine rebooted and you unlocked the disks." || { echo -e "\n\n ❌ Aborting as requested."; exit 1; }
|
|
|
|
|
|
|
|
|
|
gum spin --spinner dot --title "\n\n 🔄 Waiting for the server to boot up..." --auto <<EOF
|
|
|
|
|
while FOUND="false"; do
|
|
|
|
|
if ping -c1 -W1 $HOME_SERVER_IP >/dev/null 2>&1; then
|
|
|
|
|
FOUND="true"
|
|
|
|
|
exit 0
|
|
|
|
|
(i++)
|
|
|
|
|
if [[ "\${i}" -gt 150 ]]; then
|
|
|
|
|
echo -e "\n\n ❌ Could not connect to the server after 150 retries. \
|
|
|
|
|
This is most likely due to a networking issue. Please double check your network settings. Aborting."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
ssh_to_installed_host 'bash -s' <<EOF
|
|
|
|
|
sed -i "s|# ./disks/pcr-check.nix| ./disks/pcr-check.nix|" /etc/nixos/configuration.nix
|
|
|
|
|
|
|
|
|
|
if [[ ${#BOOT_DISKS_ID[@]} -eq 1 ]]; then
|
|
|
|
|
echo $INSTALLED_REMOTE_PASS | sudo -S systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/mapper/crypted-boot-1
|
|
|
|
|
elif [[ ${#BOOT_DISKS_ID[@]} -eq 2 ]]; then
|
|
|
|
|
echo $INSTALLED_REMOTE_PASS | sudo -S systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/mapper/crypted-boot-1
|
|
|
|
|
echo $INSTALLED_REMOTE_PASS | sudo -S systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/mapper/crypted-boot-2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
PCR_HASH=\$(echo $INSTALLED_REMOTE_PASS | sudo -S systemd-analyze pcrs 15 --json=short)
|
|
|
|
|
|
|
|
|
|
sed -i "s|# systemIdentity.enable = true;| systemIdentity.enable = true;|" /etc/nixos/configuration.nix
|
|
|
|
|
sed -i "s|# systemIdentity.pcr15 = "PCR_HASH";| systemIdentity.pcr15 = "PCR_HASH";|" /etc/nixos/configuration.nix
|
|
|
|
|
sed -i "s|PCR_HASH|\${PCR_HASH}|" /etc/nixos/configuration.nix
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "
|
|
|
|
|
⚠️ $(gum style --foreground 212 'WARNING:') You will now set the password of the numbus-admin user. \
|
|
|
|
|
You will almost never user it. Consider using a very strong password : you can write it down \
|
|
|
|
|
securely on a hidden sheet of paper or add it to your password manager (local with Passbolt \
|
|
|
|
|
any other online password manager provider.)."
|
|
|
|
|
|
|
|
|
|
gum confirm " ➡️ I understand, 'yes' to proceed." || { echo -e "\n\n ❌ Aborting as requested."; exit 1; }
|
|
|
|
|
|
|
|
|
|
echo $INSTALLED_REMOTE_PASS | sudo -S passwd numbus-admin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
congrats() {
|
|
|
|
|
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "
|
|
|
|
|
⚠️ $(gum style --foreground 212 'CONGRATULATIONS !!:') You now have a working home server. \
|
|
|
|
|
Data stored on there will be fully yours and protected. Keep in my mind this comes with the \
|
|
|
|
|
responsability of managing it and keeping it secure. Now, you have to log in the webpages of \
|
|
|
|
|
the services you installed. Create an admin account for all of them and configure them (or keep \
|
|
|
|
|
it simple and use defaults) and take care to note down all the passwords. Change all default passwords \
|
|
|
|
|
and create user accounts for your family or friends that will use the server.
|
|
|
|
|
|
|
|
|
|
Cheers !!"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nixos_update() {
|
|
|
|
@@ -605,6 +671,7 @@ if [[ "$ACTION_ANSWER" -eq "[1] 🌐 Deploy NixOS on a remote machine" ]]; then
|
|
|
|
|
disk_config_generation
|
|
|
|
|
deploy
|
|
|
|
|
postrun_action
|
|
|
|
|
congrats
|
|
|
|
|
elif [[ "$ACTION_ANSWER" -eq "[2] 💽 Deploy NixOS on a remote machine with a file configuration" ]]; then
|
|
|
|
|
echo -e "\n ➡️ Proceeding with deployment using a config file…"
|
|
|
|
|
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : start the computer and boot into the NixOS iso.
|
|
|
|
@@ -619,6 +686,7 @@ elif [[ "$ACTION_ANSWER" -eq "[2] 💽 Deploy NixOS on a remote machine with a f
|
|
|
|
|
deploy
|
|
|
|
|
sum_up
|
|
|
|
|
postrun_action
|
|
|
|
|
congrats
|
|
|
|
|
elif [[ "$ACTION_ANSWER" -eq "[3] 🛠️ Update a NixOS remote machine" ]]; then
|
|
|
|
|
echo -e "\n ➡️ Proceeding with update…"
|
|
|
|
|
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : make sure the NixOS installation you want
|
|
|
|
|