1
0
Fork 0
bootstrapper/bootstrap.sh

253 lines
5.6 KiB
Bash
Raw Normal View History

2022-08-23 21:04:44 +02:00
#!/bin/sh
2024-01-01 22:29:15 +01:00
DOTS_REPO="https://git.snaile.de/luca/dotfiles"
DOTS_BRANCH="main"
STOW_DIR=".local/share/stow"
DOTS_PACKAGE="dots"
2022-08-23 21:04:44 +02:00
2024-01-03 20:51:44 +01:00
USER_GROUPS="wheel,plugdev" # Comma separated list
2024-01-01 22:29:15 +01:00
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
BOLD="$(tput bold)"
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
RESET="$(tput sgr0)"
2022-08-23 21:04:44 +02:00
error() {
2024-01-01 22:29:15 +01:00
printf "%b\n" "${RED}${BOLD}${1}${RESET}" >&2
2022-08-23 21:04:44 +02:00
exit 1
}
2024-01-01 22:29:15 +01:00
prompt() {
message=$1
tty=$2
printf "%b" "${BLUE}${message}${RESET}" >"$tty"
# shellcheck disable=SC3037,SC2046
read -r x
echo "$x"
unset x
2022-08-23 21:04:44 +02:00
}
2024-01-01 22:29:15 +01:00
emphasize() {
printf "%b\n" "${GREEN}${BOLD}${1}${RESET}"
2022-08-23 21:04:44 +02:00
}
2024-01-01 22:29:15 +01:00
info() {
printf "%b\n" "${1}"
}
2024-01-01 22:29:15 +01:00
warn() {
printf "%b\n" "${YELLOW}${BOLD}${1}${RESET}"
2022-08-23 21:04:44 +02:00
}
2024-01-01 22:29:15 +01:00
_loop_wrapper() {
unset n
unset total
file=$1
message=$2
command=$3
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
skip_regex="^(#.*)?$"
total=$(grep -cvP "$skip_regex" "$file")
2024-01-01 22:29:15 +01:00
tput sc
while read -r x; do
echo "$x" | grep -qvP "$skip_regex" || continue
n=$((n + 1))
eval "info \"(${n}/${total}) $message\""
eval "$command"
tput rc
tput el
done <"$file"
}
check_root() {
[ "$(id -u)" != "0" ] &&
error "This script needs root!"
}
setup() {
tput sc
info "Synchronizing XBPS index..."
2024-01-02 20:59:25 +01:00
xbps-install -Sy >/dev/null 2>&1 || error "Failed to synchronize XBPS index!"
2024-01-01 22:29:15 +01:00
tput rc
tput el
info "Installing ntp..."
xbps-install -y ntp >/dev/null 2>&1
tput rc
tput el
info "Synchronizing time..."
ntpdate "pool.ntp.org" >/dev/null 2>&1 || warn "Failed to synchronize time!"
tput rc
tput el
info "Done!"
}
install_packages() {
failed_packages=""
#shellcheck disable=SC2016
_loop_wrapper "$1" \
'Installing ${x}' \
'xbps-install -y "$x" >/dev/null 2>&1 || failed_packages="${failed_packages} ${x}"'
if [ -n "$failed_packages" ]; then
tput rc
tput el
warn "Failed to install:${failed_packages}"
else
info "Done!"
fi
command -v git 1>/dev/null 2>&1 || error "git isn't installed even though it should be!"
command -v stow 1>/dev/null 2>&1 || error "stow isn't installed even though it should be!"
2022-08-23 21:04:44 +02:00
}
2024-01-01 22:29:15 +01:00
install_files() {
(
cd "${SCRIPT_DIR}/files" || exit 1
2024-01-02 20:59:25 +01:00
find . -type f,l -exec install -Dm 644 "{}" "/{}" \;
2024-01-01 22:29:15 +01:00
)
info "Done!"
2022-08-23 21:04:44 +02:00
}
2024-01-01 22:29:15 +01:00
create_user() {
tput sc
2024-01-01 22:29:15 +01:00
failed=false
while ! echo "$username" | grep -q "[a-z_][a-z0-9_-]*$"; do
$failed && warn "Invalid username, try again!"
username=$(prompt "Input Username: " "$(tty)")
failed=true
tput rc
tput el
done
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
if id -u "$username" >/dev/null 2>&1; then
warn "User \"$username\" already exists! Skipping user creation!"
else
info "Creating user \"$username\" with the following groups: \"$USER_GROUPS\"..."
useradd -m -G "$USER_GROUPS" "$username"
failed=false
while [ -z "$pass1" ] || [ "$pass1" != "$pass2" ]; do
$failed && warn "Passwords do not match or are empty, try again!"
tput rc
tput el
pass1=$(prompt "Input Password: " "$(tty)")
tput rc
tput el
pass2=$(prompt "Repeat Password: " "$(tty)")
tput rc
tput el
failed=true
done
echo "$username:$pass1" | chpasswd
fi
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
user_home=$(getent passwd "$username" | cut -d ':' -f 6)
[ -z "$username" ] &&
error "\$username variable is empty, this script is bugged!"
[ -z "$user_home" ] &&
error "\$user_home variable is empty, this script is bugged!"
sudo -u "$username" [ -w "$user_home" ] || error "$username can't write to '$user_home'!"
info "Done!"
}
create_directories() {
#shellcheck disable=SC2016
_loop_wrapper "$1" \
'Creating directory ${x}' \
"mkdir -p $user_home/\${x}"
info "Done!"
}
install_dotfiles() {
tput sc
info "Cloning dotfiles..."
mkdir -p "${user_home}/${STOW_DIR}"
if [ ! -d "${user_home}/${STOW_DIR}/${DOTS_PACKAGE}/.git" ]; then
if ! git -C "${user_home}/${STOW_DIR}" clone -q --recurse-submodules -b "$DOTS_BRANCH" "$DOTS_REPO" "$DOTS_PACKAGE"; then
tput rc
tput el
warn "Failed to clone dotfiles"
return 1
fi
fi
tput rc
tput el
info "Symlinking dotfiles..."
if ! stow -d "$user_home/$STOW_DIR" -t "$user_home" "$DOTS_PACKAGE" 1>/dev/null 2>&1; then
tput rc
tput el
warn "Failed to symlink dotfiles"
return 2
fi
tput rc
tput el
info "Done!"
}
2024-01-04 14:09:46 +01:00
select_keymap() {
2024-01-04 17:06:42 +01:00
map="$(find "${user_home}/.local/share/xkb/compiled" -type f -printf "%f\n" | fzf --header="Select a default keymap:")"
rm "${user_home}/.local/share/xkb/compiled/default"
ln -s "$map" "${user_home}/.local/share/xkb/compiled/default"
2024-01-04 14:09:46 +01:00
}
2024-01-01 22:29:15 +01:00
enable_services() {
tput sc
info "Installing user service service..."
2024-01-03 20:51:44 +01:00
target="/etc/sv/runsvdir-${username}"
mkdir -p "$(dirname "$target")"
2024-01-04 14:00:15 +01:00
sed "s/<U>/$username/" "${SCRIPT_DIR}/runsvdir-user" >"$target/run"
2024-01-01 22:29:15 +01:00
[ ! -L "/var/service/$(basename "$target")" ] &&
ln -s "$target" "/var/service/"
2024-01-03 20:51:44 +01:00
chmod 755 "$target"
2024-01-01 22:29:15 +01:00
tput rc
tput el
#shellcheck disable=SC2016
_loop_wrapper "$1" \
'Enabling ${x} service' \
'[ ! -L /var/service/${x} ] && ln -s "/etc/sv/${x}" "/var/service/"'
info "Done!"
2022-08-23 21:04:44 +02:00
}
finalize() {
2024-01-03 20:51:44 +01:00
gid=$(getent passwd "$username" | cut -d ':' -f 4)
groupname=$(getent group "$gid" | cut -d ':' -f 1)
chown "$username:$groupname" "$user_home"
info "Done!"
}
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
### CONTROL FLOW BEGINS HERE ###
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
check_root
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Preparing Installation --"
setup
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Installing Packages --"
install_packages "${SCRIPT_DIR}/packages.txt"
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Copying Files --"
install_files
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Creating User Account --"
create_user
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Creating Standard Home Directories --"
create_directories "${SCRIPT_DIR}/directories.txt"
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Installing Dotfiles --"
install_dotfiles
2024-01-04 14:09:46 +01:00
select_keymap
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Enabling Services --"
enable_services "${SCRIPT_DIR}/services.txt"
2022-08-23 21:04:44 +02:00
2024-01-01 22:29:15 +01:00
emphasize "-- Finalizing Installation --"
2022-08-23 21:04:44 +02:00
finalize
2024-01-01 22:29:15 +01:00
emphasize "-- Installation Complete --"