281 lines
7.6 KiB
Bash
Executable File
281 lines
7.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Change into script dir.
|
|
cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null || exit
|
|
nixosDir=$(pwd)
|
|
|
|
# Defaults
|
|
defaultHostname="nixos"
|
|
defaultSwap="8G"
|
|
defaultName="grmrgecko"
|
|
defaultDescription="James Coleman"
|
|
defaultGitName="GRMrGecko"
|
|
defaultGitEmail="grmrgecko@gmail.com"
|
|
|
|
# A simple function to print an array.
|
|
CHOICE=0
|
|
chooseOpts() {
|
|
local opts i
|
|
CHOICE=-1
|
|
opts=("$@")
|
|
# Keep an index to properly index the options.
|
|
i=0
|
|
echo
|
|
# For each option, print it and increment the index.
|
|
for opt in "${opts[@]}"; do
|
|
echo "$i) $opt"
|
|
i=$((i+1))
|
|
done
|
|
# Ask for their choice.
|
|
echo
|
|
echo -n "Enter choice: "
|
|
read -r CHOICE
|
|
# Check inputted index range.
|
|
if ((CHOICE >= ${#opts[@]} || CHOICE < 0)); then
|
|
echo "Invalid range"
|
|
chooseOpts "$@"
|
|
fi
|
|
}
|
|
|
|
# A looping function to choose Y or N.
|
|
chooseYN() {
|
|
# Determine the default based on upper case Y or N in prompt.
|
|
local default=""
|
|
if [[ "$1" =~ \[.*([YN]).*\] ]]; then
|
|
default=${BASH_REMATCH[1]}
|
|
fi
|
|
|
|
# Loop for the choice.
|
|
while true; do
|
|
# Prompt for choice.
|
|
echo -n "$1: "
|
|
read -r CHOICE
|
|
|
|
# If choice is empty, set choice to the default.
|
|
[[ -z $CHOICE ]] && CHOICE=$default
|
|
|
|
# If choice does not equal Y or N, continue.
|
|
# Otherwise set the global CHOICE variable to lowercase y or n.
|
|
# Lowercase allows for easy logic in code that calls this function.
|
|
if [[ "$CHOICE" =~ ^[yY]$ ]]; then
|
|
CHOICE="y"
|
|
elif [[ "$CHOICE" =~ ^[nN]$ ]]; then
|
|
CHOICE="n"
|
|
else
|
|
continue
|
|
fi
|
|
break
|
|
done
|
|
}
|
|
|
|
remoteAddr=""
|
|
echo "If you are configuring a remote machine, ensure you have ssh access with keys."
|
|
echo -n "Configuring [local machine]: "
|
|
read -r CHOICE
|
|
if [[ -n $CHOICE ]]; then
|
|
remoteAddr="$CHOICE"
|
|
fi
|
|
sshCmd=""
|
|
if [[ -n $remoteAddr ]]; then
|
|
if ssh "$remoteAddr" /usr/bin/env true; then
|
|
sshCmd="ssh $remoteAddr"
|
|
else
|
|
echo "Unable to confirm connection to remote $remoteAddr"
|
|
fi
|
|
fi
|
|
|
|
# Determine video drivers based on PCI devices.
|
|
videoDrivers="unknown"
|
|
pciRaw=$($sshCmd lspci | grep -E 'VGA')
|
|
if [[ "$pciRaw" =~ QXL ]]; then
|
|
videoDrivers="qxl"
|
|
elif [[ "$pciRaw" =~ NVIDIA ]]; then
|
|
videoDrivers="nvidia"
|
|
elif [[ "$pciRaw" =~ AMD ]]; then
|
|
videoDrivers="amdgpu"
|
|
fi
|
|
|
|
# Get the packages souce, rather its unstable or stable.
|
|
PACKAGESOPTS=(
|
|
"stable"
|
|
"unstable"
|
|
)
|
|
echo "Packages source"
|
|
chooseOpts "${PACKAGESOPTS[@]}"
|
|
PACKAGES=${PACKAGESOPTS[$CHOICE]}
|
|
|
|
# Get the profile for this system.
|
|
PROFILEOPTS=()
|
|
# Build profile list from profiles directory.
|
|
for profile in ./profiles/*.nix; do
|
|
PROFILEOPTS+=("$(basename "${profile%.*}")")
|
|
done
|
|
echo "Choose your profile"
|
|
chooseOpts "${PROFILEOPTS[@]}"
|
|
PROFILE=${PROFILEOPTS[$CHOICE]}
|
|
|
|
# Get the hostname.
|
|
echo -n "Choose hostname [$defaultHostname]: "
|
|
read -r hostName
|
|
[[ -z $hostName ]] && hostName=$defaultHostname
|
|
|
|
# Determine default disk.
|
|
diskDefault=""
|
|
[[ -e /dev/sda ]] && diskDefault="/dev/sda"
|
|
[[ -e /dev/vda ]] && diskDefault="/dev/vda"
|
|
echo
|
|
echo "Select a disk from the list below:"
|
|
# List disks to allow a choice to be made without stopping
|
|
# configuration and verifying available disks.
|
|
$sshCmd lsblk -o PATH,ID-LINK,SIZE -t
|
|
echo
|
|
echo -n "Choose disk (/dev/disk/by-id/{ID-LINK}) [$diskDefault]: "
|
|
read -r disk
|
|
# If selected disk is none, use the default disk determined above.
|
|
[[ -z $disk ]] && disk=$diskDefault
|
|
|
|
# Get the swap size.
|
|
echo -n "Swap size [$defaultSwap]: "
|
|
read -r swapSize
|
|
[[ -z $swapSize ]] && swapSize=$defaultSwap
|
|
|
|
# Determine if we should LUKS encrypt the disk.
|
|
luks="false"
|
|
chooseYN "Use LUKS Encryption? [N/y]"
|
|
if [[ "$CHOICE" == "y" ]]; then
|
|
luks="true"
|
|
# Get a password from the user, with confirmation to ensure
|
|
# we are not setting a typo.
|
|
while true; do
|
|
echo -n "Enter your luks encryption passphrase: "
|
|
read -r -s luksPasswd
|
|
echo
|
|
echo -n "Confirm your luks encryption passphrase: "
|
|
read -r -s confirmLuksPasswd
|
|
echo
|
|
if [[ "$luksPasswd" == "$confirmLuksPasswd" ]]; then
|
|
break
|
|
fi
|
|
echo "Passwords do not match, try again."
|
|
done
|
|
# Save the password to the tmpfs for disko to pick up during partitioning.
|
|
echo -n "$luksPasswd" | $sshCmd dd of=/tmp/secret.key
|
|
fi
|
|
|
|
# Get username for the main user.
|
|
echo -n "Main user name [$defaultName]: "
|
|
read -r name
|
|
[[ -z $name ]] && name=$defaultName
|
|
|
|
# Get description for the main user.
|
|
echo -n "Main user description [$defaultDescription]: "
|
|
read -r description
|
|
[[ -z $description ]] && description=$defaultDescription
|
|
|
|
# Determine password for main user, verifying no typos.
|
|
while true; do
|
|
echo -n "Enter password for main user: "
|
|
read -r -s mainPasswd
|
|
echo
|
|
echo -n "Confirm your password for main user: "
|
|
read -r -s confirmMainPasswd
|
|
echo
|
|
if [[ "$mainPasswd" == "$confirmMainPasswd" ]]; then
|
|
break
|
|
fi
|
|
echo "Passwords do not match, try again."
|
|
done
|
|
# Use mkpasswd to create a hashed password with the lastest
|
|
# linux password hashing algorithm.
|
|
password=$($sshCmd mkpasswd "\"$mainPasswd\"")
|
|
|
|
# Determine SSH keys to allow into the system.
|
|
sshKeys=()
|
|
while true; do
|
|
echo "To exit loop, press enter."
|
|
echo -n "Add ssh key (Github Username or ssh key): "
|
|
read -r keyToAdd
|
|
|
|
# If empty, exit loop as all keys were selected.
|
|
[[ -z $keyToAdd ]] && break
|
|
|
|
# If matches an ssh public key, add to list.
|
|
if [[ "$keyToAdd" =~ ^ssh-.* ]]; then
|
|
echo "Added key: $keyToAdd"
|
|
sshKeys+=("$keyToAdd")
|
|
continue
|
|
fi
|
|
|
|
# If is an username, check github for all keys and add them.
|
|
if [[ "$keyToAdd" =~ ([a-zA-Z0-9]+) ]]; then
|
|
githubUsername=${BASH_REMATCH[1]}
|
|
while read -r key; do
|
|
if [[ $key == "Not Found" ]]; then
|
|
echo "Github user provided not found"
|
|
continue
|
|
fi
|
|
echo "Adding key: $key"
|
|
sshKeys+=("$key")
|
|
done < <(curl -s -q "https://github.com/$githubUsername.keys")
|
|
fi
|
|
done
|
|
|
|
# Determine if we want to autologin to the main user,
|
|
# this may be desirable on full disk encrypted machines.
|
|
autoLogin="false"
|
|
chooseYN "Autologin to main user? [N/y]"
|
|
if [[ "$CHOICE" == "y" ]]; then
|
|
autoLogin="true"
|
|
fi
|
|
|
|
# Get git name.
|
|
echo -n "Git name [$defaultGitName]: "
|
|
read -r gitName
|
|
[[ -z $gitName ]] && gitName=$defaultGitName
|
|
|
|
# Get git email.
|
|
echo -n "Git email [$defaultGitEmail]: "
|
|
read -r gitEmail
|
|
[[ -z $gitEmail ]] && gitEmail=$defaultGitEmail
|
|
|
|
# Generate settings.nix file with above choosen options.
|
|
echo "Generating settings.nix:"
|
|
cat <<EOF | tee "$nixosDir/settings.nix"
|
|
rec {
|
|
system = "x86_64-linux";
|
|
timezone = "America/Chicago";
|
|
locale = "en_US.UTF-8";
|
|
packages = "${PACKAGES}";
|
|
profile = "${PROFILE}";
|
|
hostId = "$(tr -dc a-f0-9 </dev/urandom | head -c 8)";
|
|
hostName = "${hostName}";
|
|
videoDrivers = "${videoDrivers}";
|
|
disk = {
|
|
device = "${disk}";
|
|
swapSize = "${swapSize}";
|
|
luks = ${luks};
|
|
};
|
|
user = {
|
|
name = "${name}";
|
|
description = "${description}";
|
|
hashedPassword = "${password}";
|
|
openssh.authorizedKeys.keys = [$(printf ' "%s"' "${sshKeys[@]}") ];
|
|
autoLogin = ${autoLogin};
|
|
};
|
|
root = {
|
|
hashedPassword = user.hashedPassword;
|
|
openssh.authorizedKeys.keys = user.openssh.authorizedKeys.keys;
|
|
};
|
|
git = {
|
|
name = "${gitName}";
|
|
email = "${gitEmail}";
|
|
};
|
|
networkmanager.profiles = {};
|
|
}
|
|
EOF
|
|
|
|
# Generate hardware-configuration.nix without filesystems as we use the disko partitoning flake.
|
|
echo
|
|
echo "Generating hardware-configuration.nix"
|
|
$sshCmd nixos-generate-config --no-filesystems --show-hardware-config | tee "$nixosDir/hardware-configuration.nix"
|