pumpkin
November 17, 2023, 8:21pm
1
I have been attempting to follow the NixOS guide for generating a Live CD , but I am uncertain as to how to incorporate it into my Flake configuration. My goal is to make an ISO image that covers the whole system.
{
description = "My NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = github:nix-community/home-manager;
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nixpkgs, home-manager, ... }:
let
user = "lukas";
configDir = "nix-config";
in {
nixosConfigurations = import ./hosts {
inherit (nixpkgs) lib;
inherit inputs nixpkgs home-manager user configDir;
};
};
}
What do I have to add to the flake above so nix build works?
Carrot
November 18, 2023, 9:40am
2
Below you can see a working example. It’s what I do, with some bits removed:
run with nix build .#iso
# flake.nix
{
inputs = {
nixpkgs.url = "flake:nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
nixos-generators.url = "github:nix-community/nixos-generators";
nixos-generators.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs@{ self, nixpkgs, flake-utils, ... }: {
## nix build .#iso
## nixcfg --build-iso && nixcfg --burn-iso 00000111112222333
packages.x86_64-linux.iso = inputs.nixos-generators.nixosGenerate {
system = "x86_64-linux";
format = "install-iso";
specialArgs = {
inherit inputs;
};
modules = [
"${inputs.nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
./images/iso.nix
{
system.stateVersion = "23.11";
}
];
};
};
}
# images/iso.nix
{ lib
, pkgs
, ...
}:
## - Build iso:
# nix build .#iso
## - Find installation device (eg. /dev/sdX):
# lsblk
## - Write to thumb-drive:
# sudo dd bs=4M if=result/iso/my-nixos-live.iso of=/dev/sdX status=progress oflag=sync
{
imports = [
./base-config.nix
];
isoImage.volumeID = lib.mkForce "my-nixos-live";
isoImage.isoName = lib.mkForce "my-nixos-live.iso";
# Use zstd instead of xz for compressing the liveUSB image, it's 6x faster and 15% bigger.
isoImage.squashfsCompression = "zstd -Xcompression-level 6";
}
# images/base-config.nix
{ lib
, pkgs
, ...
}:
{
imports = [
# ../modules/base-system.nix
# ../modules/services/numlock-on-tty
];
networking = {
useDHCP = false;
hostName = "my-nixos-live"; # default: "nixos"
usePredictableInterfaceNames = false;
interfaces.eth0.useDHCP = true;
# interfaces.eth0.ipv4.addresses = [
# {
# address = "192.168.1.2";
# prefixLength = 24;
# }
# ];
# defaultGateway = "192.168.1.1";
# nameservers = [ "192.168.1.1" "1.1.1.1" "8.8.8.8" ];
};
boot.supportedFilesystems = [ "zfs" "f2fs" ];
# serial connection for apu
boot.kernelParams = [ "console=ttyS0,115200n8" ];
users.mutableUsers = false;
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 xxxx me@mypc"
];
users.users = {
"nixos" = {
isNormalUser = true;
home = "/home/nixos";
password = "";
uid = 1000;
extraGroups = [ "systemd-journal" "wheel" ];
};
};
# sshd
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.PermitRootLogin = lib.mkDefault "prohibit-password";
hostKeys = [
{ type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; }
{ type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
};
services.avahi = {
enable = true;
nssmdns = true;
publish.addresses = true;
publish.domain = true;
publish.enable = true;
publish.userServices = true;
publish.workstation = true;
};
# Turn on flakes.
nix.package = pkgs.nixVersions.stable;
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
# includes this flake in the live iso : "/etc/nixcfg"
environment.etc.nixcfg.source =
builtins.filterSource
(path: type:
baseNameOf path
!= ".git"
&& type != "symlink"
&& !(pkgs.lib.hasSuffix ".qcow2" path)
&& baseNameOf path != "secrets")
../.;
environment.systemPackages = with pkgs; [
git
htop
tmux
tree
nano
rsync
ripgrep
cryptsetup
nixpkgs-fmt
];
## FIX for running out of space / tmp, which is used for building
fileSystems."/nix/.rw-store" = {
fsType = "tmpfs";
options = [ "mode=0755" "nosuid" "nodev" "relatime" "size=14G" ];
neededForBoot = true;
};
# Part of base-system.nix:
time.timeZone = lib.mkDefault "Etc/UTC";
i18n = {
defaultLocale = "en_IE.UTF-8";
extraLocaleSettings = {
LC_TIME = "en_GB.UTF-8";
};
supportedLocales = lib.mkDefault [
"en_GB.UTF-8/UTF-8"
"en_IE.UTF-8/UTF-8"
"en_US.UTF-8/UTF-8"
];
};
environment.variables = {
TERM = "xterm-256color";
};
# # Use a high-res font.
# boot.loader.systemd-boot.consoleMode = "0";
console = {
# https://github.com/NixOS/nixpkgs/issues/114698
earlySetup = true; # Sets the font size much earlier in the boot process
colors = [
# # frappe colors
"51576d"
"e78284"
"a6d189"
"e5c890"
"8caaee"
"f4b8e4"
"81c8be"
"b5bfe2"
"626880"
"e78284"
"a6d189"
"e5c890"
"8caaee"
"f4b8e4"
"81c8be"
"a5adce"
];
font = "Lat2-Terminus16";
useXkbConfig = true; # Use same config for linux console
};
services.xserver = {
enable = lib.mkDefault false; # but still here so we can copy the XKB config to TTYs
autoRepeatDelay = 300;
autoRepeatInterval = 35;
} // lib.optionalAttrs false {
xkbVariant = "colemak";
xkbOptions = "caps:super,compose:ralt,shift:both_capslock";
};
}
2 Likes
pumpkin
November 18, 2023, 10:31am
3
Thank you! I’ll look into it!
the import
"${inputs.nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
should not be needed as it is already imported by the format from nixos-generators. Or did you run into issues without that line?
2 Likes
Carrot
November 18, 2023, 4:49pm
5
I removed it and it still builds. It was a line from before I used the generator.
1 Like
@Carrot thank you very much for your example above! I generated my image and booted my VPS into it. How can I install it on the system? How do you do it?
Carrot:
run with nix build .#iso
I’m trying this, but I get an error telling me to use --impure, cause “/nix/store” is forbidden in pure eval mode
If I try to use --impure, I get
BASHY $ nix build .#iso --impure
trace: warning: The option `services.avahi.nssmdns' defined in `/nix/store/zhl7mjj562c2sdndkrl4kdprbp65vlj5-source/base-config.nix' has been renamed to `services.avahi.nssmdns4'.
evaluating derivation 'path:/home/b0ef/proj/2024-01-24.iso-for-a-dead-manerror (ignored): error: reached end of FramedSource
error: opening file '/nix/store/0wbygchdl9aq921xqmp06kcsvjpmhshq-ext4-fs.img.zst.lock': Permission denied
(use '--show-trace' to show detailed location information)
Carrot
January 25, 2024, 11:07pm
9
I use my custom script, which looks for a host with the live image on the local network, and installs one of my hosts defined in the flake.
I’m working on a version which installs from an encrypted thumbdrive. This usb contains my flake and other secrets.
I’ll have to look into nixos-anywhere, It’ll be useful for your vps usage. But I don’t think it supports all the things I need. (eg. host secrets shouldn’t leave the host, so no injection)
The script expect all configurations in the flake to have settings for disko(my disko options).
These settings I use for:
disko during install
disko in system configuration (build,boot,switching)
my disko module which uses a disko-ext4 or disko-zfs module.
modules = [
{
ncfg = {
disko.disks = [ "/dev/disk/by-id/ata-SAMSUNGxxxxxxxxxxx" "/dev/disk/by-id/ataxxxxxx" ];
disko.bootloader = "grub"; # Mirrored Disks only with grub
disko.filesystem = "zfs";
disko.luks_encryption = true;
# ssh root@10.10.10.10 -p 2222
# systemd-tty-ask-password-agent
disko.luks_remote_unlock = true;
disko.zfs_ashift = 12;
disko.zfs_refreservationInGB = 10;
};}];
#!/usr/bin/env bash
VERSION="20240105"
ARG_USE_ROOT_USERNAME=false
ARG_IGNORE_UNMOUNT=false
ARG_REBOOT_AFTER=false
ARG_SHUTDOWN_AFTER=false
# REMOTE_CONFIG_PATH="/tmp"
HOSTNAME_IMAGE="my-nixos" # TODO CHANGE
HOSTNAME_INSTALLER="my-nixos-live" # TODO CHANGE
# DEFAULTS:
LOCAL_CONFIG_PATH="/PathToYourFlake" # TODO CHANGE
DEFAULT_DESTINATION="root@${HOSTNAME_INSTALLER}.local"
#################################################
L_0EMERGENCY=0
L_1ALERT=1
L_2CRITICAL=2
L_3ERROR=3
L_4WARNING=4
L_5NOTICE=5
L_6INFO=6
L_7DEBUG=7
LOG_LEVEL=$L_5NOTICE
_COLOR_RESET="\033[0m"
_COLOR_START="\033["
_COLOR_END="m"
_NORMAL=0
_BOLD=1
_UNDERLINED=4
_BLINKING=5
_REVERSE_VIDEO=7
_FG_BLACK=30
_FG_RED=31
_FG_GREEN=32
_FG_YELLOW=33
_FG_BLUE=34
_FG_MAGENTA=35
_FG_CYAN=36
_FG_WHITE=37
_BG_BLACK=40
_BG_RED=41
_BG_GREEN=42
_BG_YELLOW=43
_BG_BLUE=44
_BG_MAGENTA=45
_BG_WHITE=47
_BG_CYAN=46
set -euo pipefail
set -f
# set -x # Print all executed commands to the terminal
function usage() {
printf "%b" "
Helper script to manage my nixos configurations.
Usage
$(basename "${BASH_SOURCE[0]}") [options]
Options:
-h, --help Display this message
--version Show version
-v, --verbose Show what is being done
--debug Show everything that can be shown
-t --tty
-p --ssh-port
--ssh-option
--config=PATH nixos config path (default: ${LOCAL_CONFIG_PATH})
--config-path=PATH nixos config path (default: ${LOCAL_CONFIG_PATH})
--dest=user@host user@host of the live image (default: ${DEFAULT_DESTINATION})
--destination=user@host user@host of the live image (default: ${DEFAULT_DESTINATION})
--root Use root@ instead of the primaryUser
--poweroff Shutdown the system after
--shutdown Shutdown the system after
--reboot Reboot the system after
--rollback Rollback to the previous generation
--offline In some cases capable of handling rebuilds without network connections
Arguments:
ssh
build-iso Generate iso
build-image-rpi4 Generate iso
burn-iso [serial] Write iso to usb with serial
burn-image [serial] Write image to usb with serial
is-uefi-mode Is it using uefi mode or legacy
install [hostname] Install a nixos config: remote or locally.
install-anywhere [hostname] Install a nixos config
unmount Unmount /mnt & export zpool
restart-sway
reboot
shutdown
poweroff
update Update flake
build
build-vm
build-vm-with-bootloader
test
boot
switch
list Show generations
compare-generations Show difference between generations
delete Delete old generations, except 1day
delete-all Delete old generations
"
}
function ask_question() {
echo -e "\n${_COLOR_START}${_BOLD};${_FG_WHITE};${_BG_GREEN}${_COLOR_END} > $1${_COLOR_RESET}"
}
function ask_question_yn() {
ask_question "$1"
read -n 1 -r
echo
}
function set_log_level() {
local level=$1
if [ "$level" -gt "$LOG_LEVEL" ]; then
LOG_LEVEL=$level
fi
}
declare -A LOG_LEVELS
# https://en.wikipedia.org/wiki/Syslog#Severity_level
LOG_LEVELS=([$L_0EMERGENCY]="emerg" [$L_1ALERT]="alert" [$L_2CRITICAL]="crit" [$L_3ERROR]="ERROR" [$L_4WARNING]="warning" [$L_5NOTICE]="notice" [$L_6INFO]="info" [$L_7DEBUG]="debug")
function .log() {
local level=$1
shift
# Trim trailing whitespace
msg=$(echo "${@}" | awk '{gsub(/ +$/,"")} {print $0 }')
if [ "$LOG_LEVEL" -ge "$level" ]; then
if [ "$level" == 0 ]; then
echo -e " ${_COLOR_START}${_BOLD};${_FG_MAGENTA};${_BLINKING};${_UNDERLINED}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 1 ]; then
echo -e " ${_COLOR_START}${_BOLD};${_FG_MAGENTA};${_BLINKING}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 2 ]; then
echo -e " ${_COLOR_START}${_NORMAL};${_FG_MAGENTA}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 3 ]; then
echo -e " ${_COLOR_START}${_NORMAL};${_FG_RED}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 4 ]; then
echo -e " ${_COLOR_START}${_NORMAL};${_FG_WHITE}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 5 ]; then
echo "$msg"
elif [ "$level" == 6 ]; then
echo -e " ${_COLOR_START}${_NORMAL};${_FG_WHITE}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
elif [ "$level" == 7 ]; then
echo -e " ${_COLOR_START}${_NORMAL};${_FG_WHITE}${_COLOR_END}[${LOG_LEVELS[$level]}] $msg${_COLOR_RESET}"
fi
fi
}
function clear_warning_line() {
echo -ne "\033[0K\r" # clear warning line
}
function warn_countdown() {
timeout=$(($1 * 10)) # in seconds
message=$2
while [ ${timeout} -gt 0 ]; do
echo -ne " ${_COLOR_START}${_NORMAL};${_BG_MAGENTA}${_COLOR_END}[WARNING] $message $timeout${_COLOR_RESET}\033[0K\r"
((timeout--))
sleep 0.1
done
if [ "${3-}" == "clear" ]; then
clear_warning_line
else
echo # show warning line
fi
}
function now() {
date +"%Y%m%d_%H%M%S"
}
function get_date() {
# returns the date x days in the future or past
date --date="$1 day" +%Y%m%d
}
function formatTime() {
printf '%02d:%02d:%02d\n' $(($1 / 3600)) $(($1 % 3600 / 60)) $(($1 % 60))
}
function die() {
.log $L_2CRITICAL "$*"
exit 1
}
function validateConfigPath() {
# Validate $LOCAL_CONFIG_PATH
if [ ! -f "${LOCAL_CONFIG_PATH}/flake.nix" ]; then
.log $L_3ERROR "nixos config not found: '${LOCAL_CONFIG_PATH}/flake.nix'"
exit 1
fi
}
# ssh wrapper
function timeout_ssh_() {
# timeout 10 ssh -i "$ssh_key_dir"/nixos-anywhere -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${ssh_args[@]}" "$ssh_connection" "$@"
timeout 10 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${ssh_args[@]}" "$dest" "$@"
}
function ssh_() {
# ssh "$ssh_tty_param" -i "$ssh_key_dir"/nixos-anywhere -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${ssh_args[@]}" "$ssh_connection" "$@"
ssh "$ssh_tty_param" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${ssh_args[@]}" "$dest" "$@"
}
function nix_copy() {
# NIX_SSHOPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $ssh_key_dir/nixos-anywhere ${ssh_args[*]}" nix copy \
NIX_SSHOPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${ssh_args[*]}" nix copy \
"${nix_options[@]}" \
"$@"
# "${nix_copy_options[@]}" \
}
function nix_build() {
# NIX_SSHOPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $ssh_key_dir/nixos-anywhere ${ssh_args[*]}" nix build \
NIX_SSHOPTS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${ssh_args[*]}" nix build \
--print-out-paths \
--no-link \
"${nix_options[@]}" \
"$@"
}
# true if the current OS in the nixos live iso
function is_iso() {
grep -q 'VARIANT_ID=installer' < "/etc/os-release"
}
function exit_when_iso() {
if is_iso; then
.log $L_3ERROR "Not supported on live iso"
exit 1
fi
}
function exit_when_stateversion_between_iso_and_flake_system_missmatch() {
hostname="$1"
version_in_iso="$2"
# version_in_iso="$(grep "VERSION_ID=" < /etc/os-release | cut -d '=' -f2 | xargs)"
version_in_flake_for_system="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.stateVersion" | xargs)"
if [ "$version_in_flake_for_system" != "$version_in_iso" ]; then
.log $L_3ERROR "stateVersions don't match for >$hostname< : $version_in_flake_for_system (flake) != $version_in_iso (iso)"
exit 1
fi
}
HOSTNAMES=""
function get_all_hostnames() {
if [ -z "$HOSTNAMES" ]; then
HOSTNAMES=$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations" --apply 'pkgs: builtins.concatStringsSep " " (builtins.attrNames pkgs)' | xargs | tr ' ' '\n')
fi
echo "${HOSTNAMES}"
}
# Check if argument hostname exists in flake
function check_hostname_exists() {
if ! get_all_hostnames | grep -q "^${1}\$"; then
.log $L_3ERROR "hostname not found '$1'"
echo "hostnames: "
get_all_hostnames
exit 1
fi
}
function get_all_hostnames_localhost_first() {
local all_but_local
all_but_local=$(get_all_hostnames | grep --invert-match "^${HOSTNAME}\$")
printf '%s\n%s\n' "${HOSTNAME} (localhost)" "${all_but_local}"
}
function get_all_hostnames_installer_first() {
printf '%s\n%s\n' "${HOSTNAME_INSTALLER} (installer)" "$(get_all_hostnames)"
}
function validate_hostname_or_choose_when_empty() {
local hostname
if [ $# -eq 0 ] || [ -z "$1" ]; then
hostname=$(get_all_hostnames | gum choose | cut -d ' ' -f1)
else
hostname="$1"
check_hostname_exists "$hostname"
fi
if [ ! "$hostname" ] || [ -z "$hostname" ] || [ "$hostname" == "" ]; then
.log $L_3ERROR "No hostname .."
exit 1
fi
echo "$hostname"
}
function validate_hostname_or_choose_with_localhost_first_when_empty() {
local hostname
if [ $# -eq 0 ] || [ -z "$1" ]; then
hostname=$(get_all_hostnames_localhost_first | gum choose | cut -d ' ' -f1)
else
hostname="$1"
check_hostname_exists "$hostname"
fi
if [ ! "$hostname" ] || [ -z "$hostname" ] || [ "$hostname" == "" ]; then
.log $L_3ERROR "No hostname ..."
exit 1
fi
echo "$hostname"
}
function validate_hostname_or_choose_with_installer_first_when_empty() {
local hostname
if [ $# -eq 0 ] || [ -z "$1" ]; then
hostname=$(get_all_hostnames_installer_first | gum choose | cut -d ' ' -f1)
else
hostname="$1"
if [ "$hostname" != "$HOSTNAME_INSTALLER" ]; then
check_hostname_exists "$hostname"
fi
fi
if [ ! "$hostname" ] || [ -z "$hostname" ] || [ "$hostname" == "" ]; then
.log $L_3ERROR "No hostname ...."
exit 1
fi
echo "$hostname"
}
function extract_hostname_from_destination() {
local destination str
destination="$1"
# Subtract username@, only keep last after delimiter
str=${destination##*@}
# Remove .local if at the end of the string
str=${str%".local"}
echo "$str"
}
function empty_when_localhost() {
local destination hostname
destination="$1"
hostname=$(extract_hostname_from_destination "$destination")
if [ "$hostname" == "$HOSTNAME" ]; then
destination=""
fi
echo "$destination"
}
function convert_hostname_in_destination() {
local use_root_user destination
use_root_user="$1"
destination="$2"
destination="$(empty_when_localhost "$destination")"
if [ "$destination" == "" ]; then
# Empty destination for localhost
echo ""
else
# The argument can be:
# - hostname (live iso OR nixos configuration in flake)
# - username@hostname
# - username@hostname.local
# - hostname.local
# - ipv4
# - ipv6
# - username@ipv4
# - username@ipv6
local userName
if [ "$use_root_user" = true ]; then
# Use root user as default
userName="root"
else
# Use primary user as default
hostname=$(extract_hostname_from_destination "$destination")
userName="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.primaryUserName" | xargs)"
fi
if [ "$userName" == "" ]; then
userName="root"
fi
[[ $destination =~ ^.+@.+$ ]] || destination="${userName}@${destination}"
# Append .local if it's no ipv4 or ipv6
[[ $destination =~ ^.+\.local$ ]] || contains_ip_address "$destination" || destination="${destination}.local"
echo "$destination"
fi
}
function is_ipv4_address() {
# Set up local variables
local ip="$1"
local IFS=.
local -a a=("$ip")
# Start with a regex format test
[[ $ip =~ ^[0-9]+(\.[0-9]+){3}$ ]] || return 1
# Test values of quads
local quad
for quad in {0..3}; do
[[ ${a[$quad]} -gt 255 ]] && return 1
done
return 0
}
function is_ipv6_address() {
[[ $1 =~ ^([0-9a-fA-F]{0,4}:){0,7}[0-9a-fA-F]{1,4}$ ]]
}
function contains_ip_address() {
str="$1"
# Subtract username@, only keep last after delimiter
str=${str##*@}
if is_ipv4_address "$str"; then
return 0
elif is_ipv6_address "$str"; then
return 0
else
return 1
fi
}
function get_device_path_by_serial() {
local device_serial device_path
device_serial=$1
if [ -z "$device_serial" ]; then
.log $L_3ERROR " device serial not supplied"
exit 1
fi
device_path=$(sudo lsblk -n -o serial,path | grep "${device_serial}" | head -n1 | awk -F' ' '{print $2}')
if [ -z "$device_path" ]; then
.log $L_3ERROR " device path not found"
exit 1
fi
echo "${device_path}"
}
function check_uefi_mode() {
local dest
dest="$1"
.log $L_5NOTICE " > Checking Uefi mode: ${dest}"
if is_iso || [ -z "$dest" ]; then
if [ -d "/sys/firmware/efi/efivars" ]; then
echo "uefi supported"
else
echo "uefi not supported"
fi
else
ssh_ test -d "/sys/firmware/efi/efivars" && echo "uefi supported" || echo "uefi not supported"
fi
}
function install() {
local hostname dest
hostname="$1"
dest="$2"
if is_iso; then
.log $L_5NOTICE " > install (localhost)"
version_in_iso="$(grep "VERSION_ID=" < /etc/os-release | cut -d '=' -f2 | xargs)"
exit_when_stateversion_between_iso_and_flake_system_missmatch "$hostname" "$version_in_iso"
# TODO Install through live iso on host machine (localhost)
# TODO use drvi to mount drive
.log $L_3ERROR "Not YET supported on live iso"
exit 1
else
.log $L_5NOTICE " > install (remote)"
version_in_iso=$(ssh_ '( grep "VERSION_ID=" < /etc/os-release | cut -d '=' -f2 | xargs )')
exit_when_stateversion_between_iso_and_flake_system_missmatch "$hostname" "$version_in_iso"
.log $L_5NOTICE " > Extract hardware-configuration.nix:"
ssh_ '( nixos-generate-config --no-filesystems --root /mnt --show-hardware-config )' > "${LOCAL_CONFIG_PATH}/hosts/${hostname}/hardware-configuration.nix"
nixpkgs-fmt "${LOCAL_CONFIG_PATH}/hosts/${hostname}/hardware-configuration.nix"
.log $L_5NOTICE " > Extract machine-id:"
rsync -ah "${dest}:/etc/machine-id" "${LOCAL_CONFIG_PATH}/hosts/${hostname}/"
# disks="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.disks")"
# # TODO: Check the disks from flake are found on the destination, otherwise exit 1
# swapInGB="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.swapInGB")"
# filesystem="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.filesystem" | xargs)"
# luks="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.luks")"
# disko_zfs_options=""
# if [ "$filesystem" == "zfs" ]; then
# zfs_ashift="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.zfs_ashift")"
# disks_string=$(echo "$disks" | tr -d '[]' | xargs)
# remote_zfs_ashift=$(ssh_ -- ashift-calculation "$disks_string")
# if [ "$zfs_ashift" == "$remote_zfs_ashift" ]; then
# .log $L_5NOTICE " ashift = <$zfs_ashift>"
# else
# .log $L_4WARNING "ashift is not optimal flake:$zfs_ashift calculation:$remote_zfs_ashift"
# warn_countdown 10 " Please cancel script execution and change ashift, ignore warning & continue in:"
# fi
# zfs_refreservationInGB="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.zfs_refreservationInGB")"
# disko_zfs_options="--arg zfs_ashift '$zfs_ashift' --arg zfs_refreservationInGB '$zfs_refreservationInGB'"
# fi
# .log $L_5NOTICE " > Push disko config to remote:"
# rsync --mkpath -ah --delete "${LOCAL_CONFIG_PATH}/diskos/disko_${filesystem}.nix" "${dest}:${REMOTE_CONFIG_PATH}"
# .log $L_5NOTICE " > Execute disko: partition, format, mount:"
# ssh_ << SSH
# ssh_ disko --mode disko ${REMOTE_CONFIG_PATH}/disko_${filesystem}.nix --arg disks "$disks" --arg swapInGB "$swapInGB" --arg luks "$luks" ${disko_zfs_options}
# echo "$dest disko --mode disko ${REMOTE_CONFIG_PATH}/disko_${filesystem}.nix --arg disks '$disks' --arg swapInGB '$swapInGB' --arg luks '$luks' ${disko_zfs_options}" | xargs bash -x -c "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -tt ${0}" {}
.log $L_5NOTICE " > Build disko config:"
# disko_script=$(nix_build "${flake}#nixosConfigurations.\"${flakeAttr}\".config.system.build.diskoScript")
disko_script=$(nix_build "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.system.build.diskoScript")
# nix_copy --to "ssh://$ssh_connection" "$disko_script"
.log $L_5NOTICE " > Copy disko config to remote:"
nix_copy --to "ssh://$dest?remote-store=local?root=/mnt" "$disko_script"
nix_copy --to "ssh://$dest" "$disko_script"
# nix copy --to "ssh://$dest?remote-store=local?root=/mnt" "$sys" |& nom
# NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix copy --to "ssh://${dest}" "$disko"
# # NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix copy --to "ssh://${dest}?remote-store=local?root=/mnt" "$disko"
.log $L_5NOTICE " > Execute disko: partition, format, mount:"
ssh_ "$disko_script"
# sys="$(nix eval --raw "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.system.build.toplevel")"
# ssh_ "pkill -KILL -u ${user}"
# ssh_ << SSH
# bash -l -c "bash";
# disko --mode disko ${REMOTE_CONFIG_PATH}/disko_${filesystem}.nix --arg disks '$disks' --arg swapInGB '$swapInGB' --arg luks '$luks' ${disko_zfs_options}
# SSH
# warn_countdown 100 "manual disko for luks moment"
.log $L_5NOTICE " > Extract hardware-configuration.nix:"
ssh_ '( nixos-generate-config --no-filesystems --root /mnt --show-hardware-config )' > "${LOCAL_CONFIG_PATH}/hosts/${hostname}/hardware-configuration.nix"
nixpkgs-fmt "${LOCAL_CONFIG_PATH}/hosts/${hostname}/hardware-configuration.nix"
# NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix copy --to "ssh://${dest}" "$disko"
# # NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix copy --to "ssh://${dest}?remote-store=local?root=/mnt" "$disko"
# # NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix-copy-closure --to "$dest" "$disko"
nixpkgs-fmt "${LOCAL_CONFIG_PATH}/hosts/${hostname}/hardware-configuration.nix"
ssh_ '( mount | grep /mnt )'
luks_remote_unlock_enabled="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.disko.luks_remote_unlock" | xargs)"
if [ "$luks_remote_unlock_enabled" = true ]; then
## [ "/persist/etc/secrets/initrd/host_ecdsa_key" ]
init_hostkey_path="/mnt$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.boot.initrd.network.ssh.hostKeys" | tr -d '[]' | xargs)"
## /mnt/persist/etc/secrets/initrd/host_ecdsa_key
init_hostkey_dir="$(dirname "${init_hostkey_path}")"
.log $L_5NOTICE " > ssh init: Execute mkdir ${init_hostkey_dir}:"
ssh_ "( mkdir -p ${init_hostkey_dir} )"
.log $L_5NOTICE " > ssh init: Execute ssh-keygen ${init_hostkey_path}:"
ssh_ "( ssh-keygen -t ecdsa -N '' -f ${init_hostkey_path} )"
fi
.log $L_5NOTICE " > Execute mkdir /mnt/etc/ssh:"
ssh_ "( mkdir -p /mnt/etc/ssh )"
.log $L_5NOTICE " > Execute mkdir /mnt/persist/etc/ssh:"
ssh_ "( mkdir -p /mnt/persist/etc/ssh )"
.log $L_5NOTICE " > Extract ssh key.pub:"
rsync -ah "${dest}:/etc/ssh/ssh_host_ed25519_key.pub" "${LOCAL_CONFIG_PATH}/hosts/${hostname}/key.pub"
.log $L_5NOTICE " > Execute cp ssh keys from iso to /mnt:"
ssh_ "( cp /etc/ssh/ssh_host_ed25519_key* /mnt/etc/ssh/ )"
.log $L_5NOTICE " > Execute cp ssh keys from iso to /mnt/persist:"
ssh_ "( cp /etc/ssh/ssh_host_ed25519_key* /mnt/persist/etc/ssh/ )"
.log $L_5NOTICE " > Rekey agenix:"
cd "${LOCAL_CONFIG_PATH}"
agenix --rekey
git add "${LOCAL_CONFIG_PATH}/secrets"
git add "${LOCAL_CONFIG_PATH}/hosts/${hostname}"
git commit -m "add host ${hostname}"
.log $L_5NOTICE " > system eval"
sys="$(nix eval --raw "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.system.build.toplevel")"
.log $L_5NOTICE " > system build"
nix build "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.system.build.toplevel" --out-link "$(mktemp -d)/result" |& nom
.log $L_5NOTICE " > system copy"
nix copy --to "ssh://$dest?remote-store=local?root=/mnt" "$sys" |& nom
.log $L_5NOTICE " > system nixos-install"
ssh_ << SSH
nixos-install --no-root-passwd --no-channel-copy --system "$sys"
SSH
# # format
# if ! (ssh_ -- mountpoint /mnt); then
# if ! (ssh_ -- type -p nix); then
# nix run github:nix-community/nixos-anywhere -- --stop-after-disko --store-paths "$(nix-build --no-out-link -I stockholm="$HOME/sync/stockholm" -I nixos-config="$HOME"/sync/stockholm/lass/1systems/"$hostname"/physical.nix '<nixpkgs/nixos>' -A config.system.build.diskoNoDeps)" /dev/null "$dest"
# else
# disko=$(nix-build -I stockholm="$HOME/sync/stockholm" -I secrets="$HOME/sync/stockholm/lass/2configs/tests/dummy-secrets" -I nixos-config="$HOME/sync/stockholm/lass/1systems/$hostname/physical.nix" '<nixpkgs/nixos>' -A config.system.build.disko)
# NIX_SSHOPTS='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' nix-copy-closure --to "$dest" "$disko"
# ssh_ -- "$disko"
# fi
# fi
# # echo " > $FUTURE_HOSTNAME : nixos-anywhere Test in VM" ; nixos-anywhere --flake .#${FUTURE_HOSTNAME} --vm-test
# # echo " > $FUTURE_HOSTNAME : nixos-anywhere Install:" ; nixos-anywhere --flake .#${FUTURE_HOSTNAME} root@$REMOTE_IP
# # populate
# $(nix-build --no-out-link "$HOME"/sync/stockholm/lass/krops.nix -A populate --argstr name "$hostname" --argstr target "$TARGET"/mnt/var/src --arg force true)
# NIXOS_CONFIG=/var/src/nixos-config nixos-install --no-root-password -I /mnt/var/src
# nixos-enter -- nixos-rebuild -I /var/src switch --install-bootloader
unmount_and_export_pool "$dest"
fi
}
function unmount_and_export_pool() {
local dest
dest="$1"
if [ "$ARG_IGNORE_UNMOUNT" = false ]; then
if is_iso; then
.log $L_5NOTICE " > unmount_and_export_pool: localhost"
.log $L_5NOTICE " > Execute unmount:"
ssh_ '( umount -R /mnt )'
.log $L_5NOTICE " > Execute zpool export:"
ssh_ '( zpool export -fa )'
else
.log $L_5NOTICE " > unmount_and_export_pool: $dest"
.log $L_5NOTICE " > Execute unmount:"
ssh_ '( umount -R /mnt )'
.log $L_5NOTICE " > Execute zpool export:"
ssh_ '( zpool export -fa )'
fi
fi
}
function restart_sway() {
dest="${1:-""}"
.log $L_5NOTICE " > Restart Sway: ${dest}"
warn_countdown 2 "Restarting Sway in:"
if [ -n "$dest" ]; then
local user
hostname=$(extract_hostname_from_destination "$dest")
user="$(nix eval "${LOCAL_CONFIG_PATH}#nixosConfigurations.${hostname}.config.ncfg.primaryUserName")"
# TODO: Check if flake has sway running/enabled
ssh_ "pkill -KILL -u ${user}"
else
pkill -KILL -u "$USER"
fi
}
function shutdown_or_reboot() {
dest="${1:-""}"
# ssh: Could not resolve hostname hp-t520-5: Name or service not known # TODO TODO TOODOO tttttttttttttt xxxxxxxx
if [ "$ARG_SHUTDOWN_AFTER" = true ]; then
.log $L_5NOTICE " > Poweroff: ${dest}"
warn_countdown 2 "Poweroff in:"
if is_iso || [ -z "$dest" ]; then
systemctl poweroff -i
else
ssh_ '( sudo systemctl poweroff -i )'
fi
elif [ "$ARG_REBOOT_AFTER" = true ]; then
.log $L_5NOTICE " > Reboot: ${dest}"
warn_countdown 2 "Rebooting in:"
if is_iso || [ -z "$dest" ]; then
systemctl reboot -i
else
ssh_ '( sudo systemctl reboot -i )'
fi
fi
}
function flake_update() {
.log $L_5NOTICE " > Flake update"
nix flake update --commit-lock-file "$LOCAL_CONFIG_PATH"
}
function rebuild() {
local mode hostname destination
mode="${1}"
if [ -z "$mode" ]; then
.log $L_3ERROR "mode not found"
fi
hostname="${2}"
destination="${3:-""}"
local remote_part1 remote_part2
remote_part1=()
remote_part2=()
if [ -n "$destination" ]; then
.log $L_5NOTICE " > Remote: ${hostname} ${destination}"
remote_part1=(/#"${hostname}")
if [ "$mode" != "build" ] && [ "$mode" != "build-vm" ] && [ "$mode" != "build-vm-with-bootloader" ]; then
# setting --build-host localhost Works the same as without it, except that it'll use sude, which will require you to accept keys for your localUser and your localRoot
# remote_part2=(--target-host "${destination}" --build-host localhost)
remote_part2=(--target-host "${destination}")
fi
fi
if [ "$LOG_LEVEL" -ge 7 ]; then
(
set -x
nixos-rebuild --use-remote-sudo "${mode}" --flake "${LOCAL_CONFIG_PATH}${remote_part1[*]}" "${remote_part2[@]}" "${rollback[@]}" "${offline[@]}" -L |& nom
)
else
(
set -x
nixos-rebuild --use-remote-sudo "${mode}" --flake "${LOCAL_CONFIG_PATH}${remote_part1[*]}" "${remote_part2[@]}" "${rollback[@]}" "${offline[@]}" |& nom
)
fi
}
function list_generations() {
dest="${1:-""}"
.log $L_5NOTICE " > List Generations: ${dest}"
if [ -n "$dest" ]; then
ssh_ '( sudo nix-env --list-generations --profile /nix/var/nix/profiles/system )'
else
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# find /nix/var/nix/profiles/system* -printf "%f\n"
##TODO: https://github.com/NixOS/nixpkgs/pull/105910
fi
}
function show_difference_between_generations() {
dest="${1:-""}"
.log $L_5NOTICE " > Show Generation's Differences: ${dest}"
if [ -n "$dest" ]; then
ssh_ '( sudo nix profile diff-closures --profile /nix/var/nix/profiles/system )'
else
nix profile diff-closures --profile /nix/var/nix/profiles/system
fi
}
function delete_previous_generations() {
dest="${1:-""}"
.log $L_5NOTICE " > nix-collect-garbage --delete-old --delete-older-than 1d: ${dest}"
if [ -n "$dest" ]; then
ssh_ '( sudo nix-collect-garbage --delete-old --delete-older-than 1d )'
else
## You can no longer rollback after running this
sudo nix-collect-garbage --delete-old --delete-older-than 1d
## They will still be listed in grub, but won't work.
## switch your configuration to remove them from grub
fi
}
function delete_all_previous_generations() {
dest="${1:-""}"
.log $L_5NOTICE " > nix-collect-garbage --delete-old: ${dest}"
if [ -n "$dest" ]; then
ssh_ '( sudo nix-collect-garbage --delete-old )'
else
## You can no longer rollback after running this
sudo nix-collect-garbage --delete-old
## They will still be listed in grub, but won't work.
## switch your configuration to remove them from grub
fi
}
1 Like
Carrot
January 25, 2024, 11:07pm
10
part2
nix_options=(
--extra-experimental-features 'nix-command flakes'
"--no-write-lock-file"
)
ssh_tty_param="-T"
# declare -a nix_copy_options
declare -a ssh_args
rollback=()
offline=()
function _main() {
# uuid: (the single colon means the option has a required argument, double colon means optional https://www.bahmanm.com/2015/01/command-line-options-parse-with-getopt.html)
# getopt -o vhu12c34s5r
if ! OPTS=$(getopt -o vhtp --long debug,verbose,version,help,tty,ssh-port:,ssh-option:,config:,config-path:,dest:,destination:,root,ignore-unmount,reboot,shutdown,poweroff,rollback,offline -n 'parse-options' -- "$@"); then
echo "Failed parsing options." >&2
exit 1
fi
eval set -- "$OPTS"
while true; do
case "$1" in
--debug)
set_log_level $L_7DEBUG
set -x
shift
;;
-v | --verbose)
set_log_level $L_6INFO
shift
;;
--version)
echo $VERSION
exit 0
;;
-h | --help)
usage
exit 0
;;
-t | --tty)
ssh_tty_param="-t"
shift
;;
-p | --ssh-port)
ssh_args+=("-p" "$2")
shift 2
;;
--ssh-option)
ssh_args+=("-o" "$2")
shift 2
;;
# --from)
# nix_copy_options+=("--from" "$2")
# shift
# ;;
# --option)
# key=$2
# shift
# value=$2
# shift
# nix_options+=("--option" "$key" "$value")
# ;;
--config)
LOCAL_CONFIG_PATH=$2
shift 2
;;
--config-path)
LOCAL_CONFIG_PATH=$2
shift 2
;;
--dest)
ARG_DEST=$2
shift 2
;;
--destination)
ARG_DEST=$2
shift 2
;;
--root)
ARG_USE_ROOT_USERNAME=true
shift
;;
--ignore-unmount)
ARG_IGNORE_UNMOUNT=true
shift
;;
--reboot)
ARG_REBOOT_AFTER=true
shift
;;
--shutdown)
ARG_SHUTDOWN_AFTER=true
shift
;;
--poweroff)
ARG_SHUTDOWN_AFTER=true
shift
;;
--rollback)
rollback=(--rollback)
shift
;;
--offline)
offline=(--option substitute false)
shift
;;
--)
shift
break
;;
*) break ;;
esac
done
if [ "${1-}" == "ssh" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_installer_first_when_empty "${1-}")")
ssh_tty_param="-t" # force interactive
.log $L_5NOTICE " > $dest"
# TODO: add general args option
ssh_
elif [ "${1-}" == "build-iso" ]; then
shift
exit_when_iso
validateConfigPath
.log $L_5NOTICE " > Build Iso"
nix build "${LOCAL_CONFIG_PATH}#iso" |& nom
elif [ "${1-}" == "build-image-rpi4" ]; then
shift
exit_when_iso
validateConfigPath
.log $L_5NOTICE " > Build Image rpi4"
nix build "${LOCAL_CONFIG_PATH}#image-rpi4" |& nom
elif [ "${1-}" == "burn-iso" ]; then
shift
exit_when_iso
validateConfigPath
.log $L_5NOTICE " > Burn Iso"
local device_path
device_path=$(get_device_path_by_serial "$1")
# TODO: error when it's mounted already
sudo dd bs=4M if="${LOCAL_CONFIG_PATH}/result/iso/${HOSTNAME_INSTALLER}.iso" of="${device_path}" status=progress oflag=sync
sudo sync
elif [ "${1-}" == "burn-image" ]; then
shift
exit_when_iso
validateConfigPath
.log $L_5NOTICE " > Burn Image"
local device_path
device_path=$(get_device_path_by_serial "$1")
# zstdcat "${LOCAL_CONFIG_PATH}/result/sd-image/${HOSTNAME_IMAGE}.img.zst" | sudo dd bs=4M iflag=fullblock of="${device_path}" status=progress oflag=sync
# TODO: error when it's mounted already
sudo dd bs=4M if="${LOCAL_CONFIG_PATH}/result/sd-image/${HOSTNAME_IMAGE}.img" of="${device_path}" status=progress oflag=sync
sudo sync
elif [ "${1-}" == "is-uefi-mode" ]; then
shift
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_installer_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
check_uefi_mode "$dest"
elif [ "${1-}" == "install" ]; then
shift
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_when_empty "${1-}")")
dest="${ARG_DEST:-$DEFAULT_DESTINATION}"
install "$hostname" "$dest"
shutdown_or_reboot "$dest"
elif [ "${1-}" == "install-anywhere" ]; then
shift
validateConfigPath
.log $L_3ERROR "TODO: not yet implemented: install-anywhere using nixos-anywhere"
# hostname=$(empty_when_localhost "$(validate_hostname_or_choose_when_empty "${1-}")")
# TODO nixos-anywhere
elif [ "${1-}" == "unmount" ]; then
shift
ARG_IGNORE_UNMOUNT=false
dest="${ARG_DEST:-$DEFAULT_DESTINATION}"
unmount_and_export_pool "$dest"
elif [ "${1-}" == "restart-sway" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
restart_sway "$dest"
elif [ "${1-}" == "reboot" ]; then
shift
ARG_REBOOT_AFTER=true
ARG_SHUTDOWN_AFTER=false
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_installer_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
ssh_tty_param="-t" # force interactive
shutdown_or_reboot "$dest"
elif [[ ${1-} == "shutdown" ]] || [[ ${1-} == "poweroff" ]]; then
shift
ARG_SHUTDOWN_AFTER=true
ARG_REBOOT_AFTER=false
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_installer_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
ssh_tty_param="-t" # force interactive
shutdown_or_reboot "$dest"
elif [ "${1-}" == "update" ]; then
shift
exit_when_iso
validateConfigPath
flake_update
elif [ "${1-}" == "build" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "build" "$hostname" "$dest"
elif [ "${1-}" == "build-vm" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "build-vm" "$hostname" "$dest"
elif [ "${1-}" == "build-vm-with-bootloader" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "build-vm-with-bootloader" "$hostname" "$dest"
elif [ "${1-}" == "test" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "test" "$hostname" "$dest"
shutdown_or_reboot "$dest"
elif [ "${1-}" == "boot" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "boot" "$hostname" "$dest"
shutdown_or_reboot "$dest"
elif [ "${1-}" == "switch" ]; then
shift
exit_when_iso
validateConfigPath
hostname=$(empty_when_localhost "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$hostname")
rebuild "switch" "$hostname" "$dest"
elif [ "${1-}" == "list" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
list_generations "$dest"
elif [ "${1-}" == "compare-generations" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
show_difference_between_generations "$dest"
elif [ "${1-}" == "delete" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
delete_previous_generations "$dest"
elif [ "${1-}" == "delete-all" ]; then
shift
exit_when_iso
dest=$(convert_hostname_in_destination "$ARG_USE_ROOT_USERNAME" "$(validate_hostname_or_choose_with_localhost_first_when_empty "${1-}")")
delete_all_previous_generations "$dest"
else
usage
fi
}
_main "${@}"
1 Like