#!/bin/sh # Start Server Up onder een gewone gebruiker in plaats van als root. # # Waarom dit niet gewoon `user:` in compose is: Docker maakt het `su-data`-volume # als root aan. Een container die meteen als uid 1000 start kan daar niet in # schrijven en komt niet eens tot de configuratie. Dit script begint dus als # root, zet klaar wat klaargezet moet worden, en zakt daarna pas af. # # En waarom `setpriv` en niet `gosu`: een proces dat met setuid afzakt verliest # zijn capabilities. Server Up moet daarna nog steeds bestanden kunnen chownen # (bij het verhuizen van mappen en het terugzetten van backups) en appdata van # andere gebruikers kunnen lezen (bij het maken van backups). `setpriv` kan die # rechten als *ambient* capability meegeven, zodat ze de overgang overleven. # # SU_UID leeg of 0 → alles blijft zoals het was: draaien als root. set -e log() { printf ' %s\n' "$1" >&2; } SU_UID="${SU_UID:-0}" SU_GID="${SU_GID:-$SU_UID}" case "$SU_UID:$SU_GID" in *[!0-9:]*) log "SU_UID/SU_GID moeten getallen zijn ('$SU_UID:$SU_GID'); ik negeer ze." exec "$@" ;; esac # ── Als root draaien: het gedrag van vóór deze versie ──────────────────────── if [ "$SU_UID" = "0" ] || [ -z "$SU_UID" ]; then exec "$@" fi # Zelf al niet-root? Dan is er niets om af te zakken en missen we de rechten om # iets klaar te zetten. Gewoon doorgaan is beter dan weigeren. if [ "$(id -u)" != "0" ]; then log "Draait al als uid $(id -u); SU_UID wordt genegeerd." exec "$@" fi # ── Een naam bij het nummer ────────────────────────────────────────────────── # git en ssh willen een echte gebruiker in /etc/passwd met een $HOME, anders # komt er "No such device or address" uit een clone. if ! getent group "$SU_GID" >/dev/null 2>&1; then groupadd --gid "$SU_GID" serverup 2>/dev/null || true fi if ! getent passwd "$SU_UID" >/dev/null 2>&1; then useradd --uid "$SU_UID" --gid "$SU_GID" --no-create-home \ --home-dir /data --shell /usr/sbin/nologin serverup 2>/dev/null || true fi GEBRUIKER="$(getent passwd "$SU_UID" | cut -d: -f1)" GEBRUIKER="${GEBRUIKER:-$SU_UID}" # ── Wat van ons is, overnemen ──────────────────────────────────────────────── # /data is het volume met de configuratie, het auditlog en de git-cache. chown -R "$SU_UID:$SU_GID" /data 2>/dev/null || log "Kon /data niet overnemen." cp -n /root/.gitconfig /data/.gitconfig 2>/dev/null || true chown "$SU_UID:$SU_GID" /data/.gitconfig 2>/dev/null || true # De stacks en de backups maakt Server Up zelf aan, dus die mogen van hem zijn. # # appdata NIET. Die mappen zijn van de apps: postgres draait als 999, een # linuxserver-image als de PUID die jij hebt ingevuld. Er een chown overheen # halen breekt precies die containers. Server Up leest ze via CAP_DAC_OVERRIDE. if [ -n "$BASE_DIR" ]; then for sub in stacks backups; do [ -d "$BASE_DIR/$sub" ] || continue chown -R "$SU_UID:$SU_GID" "$BASE_DIR/$sub" 2>/dev/null \ || log "Kon $BASE_DIR/$sub niet overnemen." done fi # ── Bij de docker-socket kunnen ────────────────────────────────────────────── # De gid daarvan verschilt per host, dus die lezen we hier uit in plaats van hem # in compose te moeten hardcoderen. De gebruiker wordt lid van die groep, want # `setpriv --groups` en `--init-groups` sluiten elkaar uit — via /etc/group # krijgen we allebei. # Overschrijfbaar voor rootless Docker en Podman, die de socket elders zetten. SOCK="${SU_DOCKER_SOCK:-/var/run/docker.sock}" if [ -S "$SOCK" ]; then SOCK_GID="$(stat -c %g "$SOCK" 2>/dev/null || echo '')" if [ -n "$SOCK_GID" ] && [ "$SOCK_GID" != "$SU_GID" ]; then SOCK_GROEP="$(getent group "$SOCK_GID" | cut -d: -f1)" if [ -z "$SOCK_GROEP" ]; then SOCK_GROEP=dockersock groupadd --gid "$SOCK_GID" "$SOCK_GROEP" 2>/dev/null || true fi usermod -aG "$SOCK_GROEP" "$GEBRUIKER" 2>/dev/null \ || log "Kon $GEBRUIKER niet in groep $SOCK_GROEP zetten." fi else log "Geen docker-socket op $SOCK; Server Up kan straks niets starten." fi # ── Afzakken ───────────────────────────────────────────────────────────────── # chown → eigenaarschap meenemen bij het verhuizen van mappen en het # terugzetten van backups # dac_override, fowner → appdata lezen die van een andere gebruiker is # # Alle drie zitten al in de standaardset van Docker; er komt hier dus geen # enkel recht bij dat de container niet al had. Wat weggaat is de rest van root. CAPS="chown,dac_override,fowner" if ! command -v setpriv >/dev/null 2>&1; then log "setpriv ontbreekt in dit image; ik draai als root verder." exec "$@" fi log "Server Up draait als $GEBRUIKER ($SU_UID:$SU_GID)." export HOME=/data exec setpriv --reuid "$SU_UID" --regid "$SU_GID" --init-groups \ --inh-caps "+$CAPS" --ambient-caps "+$CAPS" "$@"