#!/bin/sh

umask 022
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
export PATH
set -e
trap '[ $? -eq 0 ] || warn "$0 did not complete successfully."' EXIT
trap 'exit 1' INT HUP TERM

# Stage-0 bootstrap: NFS is not yet mounted, so /home/admin does not exist.
# On the web tree, aitken.conf and common.sh sit one level up from this script
# (admin/aitken.conf, admin/common.sh).  setup.sh is always fetched and run
# from the web tree for stage-0; it is not sourced directly from the repo.
_dir="$(cd "$(dirname "$0")" && pwd)"
. "${_dir}/../aitken.conf"
. "${_dir}/../common.sh"


#
# Validate hostname
#
[ -n "$1" ] || die "Usage: $0 <fqdn>"
hostname="$1"
validate_fqdn "$hostname"
# shellcheck disable=SC2086
require_known_domain "$hostname" $VALID_DOMAINS

log ""
log "Setting up a new Ubuntu 26.04 host (${hostname})."
log "Press Enter to continue, or ^C to abort."
read -r _x


#
# Remove throwaway installer user
#
# The Ubuntu installer forces user creation and does not allow setting a UID,
# which would conflict with the NFS-mounted /home.  A throwaway user named
# 'setup' is created during install and removed here.
#
log "Removing throwaway installer user..."
id setup > /dev/null 2>&1 && userdel -r setup || true


#
# Update hostname and /etc/hosts
#
# hostnamectl is idempotent.  The /etc/hosts update replaces the 127.0.1.1
# line's short hostname with the FQDN so that tools resolving the local
# hostname get the fully-qualified name.
#
log "Configuring hostname..."
backup_file /etc/hostname
hostnamectl set-hostname "$hostname"
_short="${hostname%%.*}"
backup_file /etc/hosts
if grep -q "^127\.0\.1\.1" /etc/hosts; then
    sed -i "s/^127\.0\.1\.1.*/127.0.1.1 ${hostname} ${_short}/" /etc/hosts
fi


#
# Configure DNS resolvers
#
# Creates a netplan overlay that sets our resolvers authoritatively, overriding
# whatever was configured during the OS install.  The primary interface is
# detected via the default route rather than hardcoded.
# netplan(5) requires 0600 on YAML config files.
#
log "Configuring DNS resolvers..."
_iface=$(ip route show default | sed 's/.* dev \([^ ]*\).*/\1/' | head -1)
[ -n "$_iface" ] || die "Cannot detect primary network interface"
printf 'network:\n  version: 2\n  ethernets:\n    %s:\n      nameservers:\n        addresses: [%s]\n        search: [%s]\n' \
    "$_iface" \
    "$(printf '%s' "$DNS_RESOLVERS" | tr ' ' ',')" \
    "$(printf '%s' "$DNS_SEARCH"    | tr ' ' ',')" \
    > /etc/netplan/99-aitken-dns.yaml
chmod 0600 /etc/netplan/99-aitken-dns.yaml
netplan apply
syslog "DNS configured: interface=${_iface} resolvers=${DNS_RESOLVERS} search=${DNS_SEARCH}"


#
# Update system packages
#
log "Updating system packages..."
apt-get update -q
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -q


#
# Mount NFS filesystems
#
# vers=3 forces NFSv3 to avoid NFSv4 UID/GID mapping issues with TrueNAS Core.
# _netdev tells systemd to wait for network; hard retries on transient failures.
# See README.md for background.
#
log "Installing NFS client and mounting filesystems..."
DEBIAN_FRONTEND=noninteractive apt-get install -y -q nfs-common

ensure_dir /media/pics  root root 755
ensure_dir /media/videos root root 755

backup_file /etc/fstab
printf '%s\n' "$NFS_MOUNTS" | while IFS=' 	' read -r _export _mnt; do
    [ -z "$_export" ] && continue
    append_once "${_export}" /etc/fstab \
        "${_export} ${_mnt} nfs vers=3,hard,_netdev,rw 0 0"
done

mkdir -p /cdrom
append_once "/dev/sr0" /etc/fstab \
    "/dev/sr0   /cdrom  iso9660  ro,noauto,nofail   0   0"

mount -a -t nfs
df -h

require_nfs_mount /home


#
# Configure admin syslog routing
#
# Route ADMIN_SYSLOG_FACILITY to ADMIN_LOG_FILE so all admin script activity
# lands in one place.  The rsyslog drop-in is generated here (not installed
# from a static file) because it embeds the facility name from aitken.conf.
# The logrotate config is static -- it references ADMIN_LOG_FILE directly.
#
log "Configuring admin syslog routing..."
printf '# aitken.com admin logging -- facility defined in aitken.conf\n%s.*\t%s\n' \
    "$ADMIN_SYSLOG_FACILITY" "$ADMIN_LOG_FILE" \
    > /etc/rsyslog.d/40-aitken-admin.conf
chmod 0644 /etc/rsyslog.d/40-aitken-admin.conf
install_file "${ADMIN_BASE}/system/files/etc/logrotate.d/aitken-admin" \
    /etc/logrotate.d/aitken-admin 0644
systemctl restart rsyslog
syslog "admin syslog routing active: ${ADMIN_SYSLOG_FACILITY}.* -> ${ADMIN_LOG_FILE}"


#
# Install base packages
#
log "Installing base packages..."
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
    qemu-guest-agent \
    vim \
    make \
    wget \
    lsof \
    bat \
    glow \
    shellcheck


#
# Configure Kerberos (Heimdal)
#
# TODO: MIT migration -- when FreeBSD 15.x support is added, switch from
# heimdal-clients to krb5-user and update kadmin syntax accordingly.
#
log "Configuring Kerberos..."
DEBIAN_FRONTEND=noninteractive apt-get install -y -q heimdal-clients libpam-krb5
chmod 4755 /usr/bin/ksu.heimdal

install_file "${ADMIN_BASE}/system/files/etc/krb5.conf" /etc/krb5.conf 0644

if ! kadmin -p "${KERBEROS_ADMIN_PRINCIPAL}" add --random-key --use-defaults \
        "host/${hostname}"; then
    kadmin -p "${KERBEROS_ADMIN_PRINCIPAL}" get "host/${hostname}" > /dev/null \
        || die "kadmin: host/${hostname} add failed and principal does not exist in KDC"
    syslog "Kerberos: host/${hostname} principal already exists, re-extracting keytab"
fi
kadmin -p "${KERBEROS_ADMIN_PRINCIPAL}" ext_keytab "host/${hostname}"


#
# Configure SSH (Kerberos authentication)
#
log "Configuring SSH..."
install_file "${ADMIN_BASE}/system/files/etc/ssh/ssh_config.d/10-aitken-ssh.conf" \
    /etc/ssh/ssh_config.d/10-aitken-ssh.conf 0644
install_file "${ADMIN_BASE}/system/files/etc/ssh/sshd_config.d/10-aitken-sshd.conf" \
    /etc/ssh/sshd_config.d/10-aitken-sshd.conf 0644
install_file "${ADMIN_BASE}/system/files/etc/issue" /etc/issue 0644

systemctl restart ssh


#
# Configure admin user account
#
log "Configuring user accounts..."
id "${ADMIN_USER}" > /dev/null 2>&1 || \
    useradd -u "${ADMIN_UID}" -U -M -s /bin/bash \
            -c "Jeff Aitken" -p '!' "${ADMIN_USER}"
usermod -aG sudo,adm "${ADMIN_USER}"

install_file "${ADMIN_BASE}/system/files/root/.k5login" /root/.k5login 0600


#
# Set MOTD
#
log "Setting MOTD..."
backup_file /etc/motd
sed "s/MYHOSTNAME/${hostname}/g" \
    "${ADMIN_BASE}/system/files/etc/motd.template" > /etc/motd


log ""
log "Setup complete.  Reboot now."
exit 0
