90 lines
4.6 KiB
Bash
90 lines
4.6 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
app_uid="${PUID:-1000}"
|
|
app_gid="${PGID:-1000}"
|
|
|
|
case "$app_uid:$app_gid" in
|
|
*[!0-9:]*|:*|*:) echo "PUID and PGID must be numeric." >&2; exit 1 ;;
|
|
esac
|
|
|
|
data_root="${DATA_DIR:-/data}"
|
|
mkdir -p "$data_root/sites" "$data_root/.uploads" "$data_root/caddy/config" "$data_root/icons" "$data_root/logs" "$data_root/default-site" "$data_root/database" "$data_root/migrations" "$data_root/backups" "$data_root/certificates/custom" "$data_root/certificates/managed" "$data_root/certificates/exports"
|
|
|
|
# Preserve legacy certificate storage before Caddy starts using the unified location.
|
|
if [ -d "$data_root/custom-certificates" ] && [ -z "$(find "$data_root/certificates/custom" -mindepth 1 -print -quit 2>/dev/null)" ]; then cp -a "$data_root/custom-certificates/." "$data_root/certificates/custom/"; fi
|
|
if [ -d "$data_root/caddy/data/caddy" ] && [ -z "$(find "$data_root/certificates/managed" -mindepth 1 -print -quit 2>/dev/null)" ]; then cp -a "$data_root/caddy/data/caddy/." "$data_root/certificates/managed/"; fi
|
|
chown -R "$app_uid:$app_gid" "${DATA_DIR:-/data}"
|
|
chmod 700 "$data_root/database" "$data_root/backups" "$data_root/certificates/custom" "$data_root/certificates/managed"
|
|
|
|
caddyfile="${DATA_DIR:-/data}/caddy/Caddyfile"
|
|
if [ ! -f "$caddyfile" ]; then
|
|
printf '%s\n' '{' ' admin localhost:2019' ' persist_config off' " storage file_system $data_root/certificates/managed" '}' '' ':80 {' ' respond "Site Gateway is ready." 404' '}' > "$caddyfile"
|
|
chown "$app_uid:$app_gid" "$caddyfile"
|
|
fi
|
|
if ! grep -q '^[[:space:]]*storage file_system ' "$caddyfile"; then
|
|
sed -i "/^[[:space:]]*persist_config off/a\\ storage file_system $data_root/certificates/managed" "$caddyfile"
|
|
fi
|
|
|
|
export XDG_DATA_HOME="${DATA_DIR:-/data}/certificates/managed"
|
|
export XDG_CONFIG_HOME="${DATA_DIR:-/data}/caddy/config"
|
|
|
|
# --- Docker socket group access -------------------------------------------------------------
|
|
# A bind-mounted /var/run/docker.sock is typically owned root:docker on the host with mode
|
|
# 0660 -- readable only by root or members of that group. The app drops straight to an
|
|
# unprivileged PUID:PGID with no supplementary groups, so even a correctly mounted socket looks
|
|
# "not detected" to it. The Docker group's GID varies host to host (Unraid, Debian, Synology,
|
|
# etc. all differ), so rather than hardcode one, read it directly off the mounted socket while
|
|
# still root, make sure a local group with that GID exists and the app user is a member of it,
|
|
# then hand su-exec a username instead of a bare uid:gid so it picks up supplementary groups via
|
|
# initgroups() -- the uid:gid form only ever sets the one primary group. Every step here is
|
|
# best-effort: if anything fails, app_exec_target stays the original "$app_uid:$app_gid" and the
|
|
# app starts exactly as it always has, just without Docker integration -- same as an unmounted
|
|
# socket, never worse.
|
|
app_exec_target="$app_uid:$app_gid"
|
|
docker_socket="/var/run/docker.sock"
|
|
if [ -S "$docker_socket" ]; then
|
|
docker_gid="$(stat -c '%g' "$docker_socket" 2>/dev/null || true)"
|
|
if [ -n "$docker_gid" ] && [ "$docker_gid" != "$app_gid" ]; then
|
|
docker_group_name="$(getent group "$docker_gid" 2>/dev/null | cut -d: -f1 || true)"
|
|
if [ -z "$docker_group_name" ]; then
|
|
addgroup -g "$docker_gid" sgdockersock 2>/dev/null || true
|
|
docker_group_name="$(getent group "$docker_gid" 2>/dev/null | cut -d: -f1 || true)"
|
|
fi
|
|
if [ -n "$docker_group_name" ]; then
|
|
app_group_name="$(getent group "$app_gid" 2>/dev/null | cut -d: -f1 || true)"
|
|
if [ -z "$app_group_name" ]; then
|
|
addgroup -g "$app_gid" sgapp 2>/dev/null || true
|
|
app_group_name="$(getent group "$app_gid" 2>/dev/null | cut -d: -f1 || true)"
|
|
fi
|
|
if [ -n "$app_group_name" ] && ! getent passwd "$app_uid" >/dev/null 2>&1; then
|
|
adduser -D -H -u "$app_uid" -G "$app_group_name" sgapp 2>/dev/null || true
|
|
fi
|
|
app_user_name="$(getent passwd "$app_uid" 2>/dev/null | cut -d: -f1 || true)"
|
|
if [ -n "$app_user_name" ]; then
|
|
addgroup "$app_user_name" "$docker_group_name" 2>/dev/null || true
|
|
if id -nG "$app_user_name" 2>/dev/null | grep -qw "$docker_group_name"; then
|
|
app_exec_target="$app_user_name"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
su-exec "$app_uid:$app_gid" caddy run --config "$caddyfile" --adapter caddyfile &
|
|
caddy_pid=$!
|
|
su-exec "$app_exec_target" "$@" &
|
|
app_pid=$!
|
|
|
|
shutdown() {
|
|
kill -TERM "$app_pid" "$caddy_pid" 2>/dev/null || true
|
|
wait "$app_pid" "$caddy_pid" 2>/dev/null || true
|
|
}
|
|
trap shutdown TERM INT
|
|
|
|
wait "$app_pid"
|
|
status=$?
|
|
kill -TERM "$caddy_pid" 2>/dev/null || true
|
|
wait "$caddy_pid" 2>/dev/null || true
|
|
exit "$status"
|