246 lines
5.3 KiB
Bash
Executable File
246 lines
5.3 KiB
Bash
Executable File
#!/bin/sh
|
|
DOTS_REPO="https://git.snaile.de/luca/dotfiles"
|
|
DOTS_BRANCH="main"
|
|
STOW_DIR=".local/share/stow"
|
|
DOTS_PACKAGE="dots"
|
|
|
|
USER_GROUPS="wheel" # Comma separated list
|
|
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)"
|
|
|
|
error() {
|
|
printf "%b\n" "${RED}${BOLD}${1}${RESET}" >&2
|
|
exit 1
|
|
}
|
|
|
|
prompt() {
|
|
message=$1
|
|
tty=$2
|
|
printf "%b" "${BLUE}${message}${RESET}" >"$tty"
|
|
# shellcheck disable=SC3037,SC2046
|
|
read -r x
|
|
echo "$x"
|
|
unset x
|
|
}
|
|
|
|
emphasize() {
|
|
printf "%b\n" "${GREEN}${BOLD}${1}${RESET}"
|
|
}
|
|
|
|
info() {
|
|
printf "%b\n" "${1}"
|
|
}
|
|
|
|
warn() {
|
|
printf "%b\n" "${YELLOW}${BOLD}${1}${RESET}"
|
|
}
|
|
|
|
_loop_wrapper() {
|
|
unset n
|
|
unset total
|
|
file=$1
|
|
message=$2
|
|
command=$3
|
|
|
|
skip_regex="^(#.*)?$"
|
|
total=$(grep -cvP "$skip_regex" "$file")
|
|
|
|
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..."
|
|
xbps-install -Syu >/dev/null 2>&1 || error "Failed to synchronize XBPS index!"
|
|
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!"
|
|
}
|
|
|
|
install_files() {
|
|
(
|
|
cd "${SCRIPT_DIR}/files" || exit 1
|
|
find . -type f -exec install -Dm 644 "{}" "/{}" \;
|
|
)
|
|
info "Done!"
|
|
}
|
|
|
|
create_user() {
|
|
tput sc
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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!"
|
|
}
|
|
|
|
enable_services() {
|
|
tput sc
|
|
info "Installing user service service..."
|
|
target="/etc/sv/runsvdir-${username}/run"
|
|
mkdir -p "$(dirname "$target")"
|
|
sed "s/<U>/$username/" "${SCRIPT_DIR}/userservice.sh" >"$target"
|
|
[ ! -L "/var/service/$(basename "$target")" ] &&
|
|
ln -s "$target" "/var/service/"
|
|
chmod 755 "$target"
|
|
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!"
|
|
}
|
|
|
|
finalize() {
|
|
gid=$(getent passwd "$username" | cut -d ':' -f 4)
|
|
groupname=$(getent group "$gid" | cut -d ':' -f 1)
|
|
chown "$username:$groupname" "$user_home"
|
|
info "Done!"
|
|
}
|
|
|
|
### CONTROL FLOW BEGINS HERE ###
|
|
|
|
check_root
|
|
|
|
emphasize "-- Preparing Installation --"
|
|
setup
|
|
|
|
emphasize "-- Installing Packages --"
|
|
install_packages "${SCRIPT_DIR}/packages.txt"
|
|
|
|
emphasize "-- Copying Files --"
|
|
install_files
|
|
|
|
emphasize "-- Creating User Account --"
|
|
create_user
|
|
|
|
emphasize "-- Creating Standard Home Directories --"
|
|
create_directories "${SCRIPT_DIR}/directories.txt"
|
|
|
|
emphasize "-- Installing Dotfiles --"
|
|
install_dotfiles
|
|
|
|
emphasize "-- Enabling Services --"
|
|
enable_services "${SCRIPT_DIR}/services.txt"
|
|
|
|
emphasize "-- Finalizing Installation --"
|
|
finalize
|
|
|
|
emphasize "-- Installation Complete --"
|