Luigit
repositories / bugabinga.net

bugabinga.net

personal infrastructure for bugabinga!

owned by admin

services/pufferpanel/deploy/setup-user.sh

Raw
#!/usr/bin/env bash
set -euo pipefail

[[ "${EUID}" -eq 0 && "$#" -eq 1 && "$1" =~ ^[a-z_][a-z0-9_-]*$ ]] || {
  echo "usage: setup-user.sh PUBLIC_PROXY_USER (as root)" >&2
  exit 2
}

user=pufferpanel
public_proxy_user="$1"
home_dir=/home/pufferpanel
command -v semanage >/dev/null
command -v restorecon >/dev/null
command -v podman >/dev/null

if ! id -u "${user}" >/dev/null 2>&1; then
  useradd --create-home --user-group --home-dir "${home_dir}" --shell /usr/sbin/nologin "${user}"
fi
uid="$(id -u "${user}")"
[[ "${uid}" -ge 1000 && "$(getent passwd "${user}" | cut -d: -f6)" == "${home_dir}" && "$(id -gn "${user}")" == "${user}" ]] || {
  echo "refusing incompatible existing pufferpanel account" >&2
  exit 1
}
for ranges in /etc/subuid /etc/subgid; do
  awk -F: -v user="${user}" '$1 == user && $3 >= 65536 { found = 1 } END { exit !found }' "${ranges}" || {
    echo "missing subordinate ID range in ${ranges}; configure before deployment" >&2
    exit 1
  }
done

directories=(
  "${home_dir}" "${home_dir}/.config" "${home_dir}/.config/containers"
  "${home_dir}/.config/containers/systemd" "${home_dir}/.local" "${home_dir}/.local/share"
  "${home_dir}/.local/share/containers"
  /data/pufferpanel /data/pufferpanel/config /data/pufferpanel/data /data/pufferpanel/logs /data/pufferpanel/theme
  /data/pufferpanel-ingress
)

for directory in "${directories[@]}"; do
  [[ ! -L "${directory}" ]] || {
    echo "refusing symlinked deployment directory: ${directory}" >&2
    exit 1
  }
  install -d -o "${user}" -g "${user}" -m 0750 "${directory}"
done
id -u "${public_proxy_user}" >/dev/null
install -d -o "${user}" -g "${user}" -m 0770 /data/pufferpanel-ingress
setfacl -m "u:${public_proxy_user}:rx,d:u:${public_proxy_user}:rw" /data/pufferpanel-ingress
# Game containers share server data, so use shared SELinux labels, not a private MCS category.
semanage fcontext -a -t container_file_t '/data/pufferpanel(/.*)?' 2>/dev/null ||
  semanage fcontext -m -t container_file_t '/data/pufferpanel(/.*)?'
semanage fcontext -a -t container_file_t '/data/pufferpanel-ingress(/.*)?' 2>/dev/null ||
  semanage fcontext -m -t container_file_t '/data/pufferpanel-ingress(/.*)?'
restorecon -RF /data/pufferpanel /data/pufferpanel-ingress

loginctl enable-linger "${user}"
systemctl start "user@${uid}.service"
runtime="/run/user/${uid}"
for _ in $(seq 1 25); do
  [[ -S "${runtime}/bus" ]] && break
  sleep 0.2
done
[[ -S "${runtime}/bus" ]] || {
  echo "pufferpanel user bus did not start" >&2
  exit 1
}
runuser -u "${user}" -- env \
  HOME="${home_dir}" USER="${user}" LOGNAME="${user}" \
  XDG_RUNTIME_DIR="${runtime}" DBUS_SESSION_BUS_ADDRESS="unix:path=${runtime}/bus" \
  systemctl --user enable --now podman.socket podman-auto-update.timer