All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 16m58s
`+chown,dac_override,fowner` kwam door elke stringtest heen maar werd door setpriv geweigerd met "bad capability string", waarna de container niet meer opstartte. Alleen de CI-stap in een echte container zag dit. - CAPS is nu +chown,+dac_override,+fowner - de test laat de echte setpriv over de string oordelen in plaats van hem te vergelijken met een verwachte tekst; met de oude waarde faalt hij Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
115 lines
5.3 KiB
Bash
Executable file
115 lines
5.3 KiB
Bash
Executable file
#!/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.
|
|
#
|
|
# Elke capability krijgt zijn eigen teken: setpriv leest "+a,b" niet als "+a,+b"
|
|
# maar weigert het met "bad capability string".
|
|
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" "$@"
|