#!/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