2026-03-26 18:10:49 -04:00
|
|
|
#!/bin/bash
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────
|
2026-04-15 14:54:20 +02:00
|
|
|
# SF Container Entrypoint
|
2026-03-26 18:10:49 -04:00
|
|
|
#
|
|
|
|
|
# Responsibilities:
|
|
|
|
|
# 1. UID/GID remapping — match host user via PUID/PGID
|
|
|
|
|
# 2. Pre-create critical files — prevent Docker bind-mount
|
|
|
|
|
# from creating directories where files are expected
|
|
|
|
|
# 3. Sentinel-based bootstrap — one-time first-boot setup
|
|
|
|
|
# 4. Signal forwarding — exec into the final process
|
|
|
|
|
# ──────────────────────────────────────────────
|
|
|
|
|
|
2026-04-15 18:33:47 +02:00
|
|
|
SF_USER="sf"
|
2026-04-15 14:54:20 +02:00
|
|
|
SF_HOME="/home/${SF_USER}"
|
2026-04-15 18:33:47 +02:00
|
|
|
SF_DIR="${SF_HOME}/.sf"
|
2026-03-26 18:10:49 -04:00
|
|
|
|
|
|
|
|
# ── 1. UID/GID Remapping ────────────────────────────────
|
|
|
|
|
# Accept PUID/PGID from the environment so the container
|
|
|
|
|
# can run with the same UID/GID as the host user, avoiding
|
|
|
|
|
# permission headaches on bind-mounted volumes.
|
|
|
|
|
|
|
|
|
|
PUID="${PUID:-1000}"
|
|
|
|
|
PGID="${PGID:-1000}"
|
|
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
CURRENT_UID=$(id -u "${SF_USER}")
|
|
|
|
|
CURRENT_GID=$(id -g "${SF_USER}")
|
2026-03-26 18:10:49 -04:00
|
|
|
|
|
|
|
|
REMAPPED=0
|
|
|
|
|
|
|
|
|
|
if [ "${PGID}" != "${CURRENT_GID}" ]; then
|
2026-04-15 14:54:20 +02:00
|
|
|
groupmod -o -g "${PGID}" "${SF_USER}"
|
2026-03-26 18:10:49 -04:00
|
|
|
REMAPPED=1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "${PUID}" != "${CURRENT_UID}" ]; then
|
2026-04-15 14:54:20 +02:00
|
|
|
usermod -o -u "${PUID}" "${SF_USER}"
|
2026-03-26 18:10:49 -04:00
|
|
|
REMAPPED=1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Fix ownership only when UID/GID actually changed
|
|
|
|
|
if [ "${REMAPPED}" -eq 1 ]; then
|
2026-04-15 14:54:20 +02:00
|
|
|
chown -R "${PUID}:${PGID}" "${SF_HOME}"
|
2026-03-26 18:10:49 -04:00
|
|
|
chown "${PUID}:${PGID}" /workspace
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ── 2. Pre-create Critical Files ────────────────────────
|
|
|
|
|
# Docker bind-mounts will create a *directory* if the target
|
|
|
|
|
# path doesn't exist. We need these to be files, so touch
|
|
|
|
|
# them before Docker gets a chance to mangle things.
|
|
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
mkdir -p "${SF_DIR}"
|
2026-03-26 18:10:49 -04:00
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
if [ ! -f "${SF_DIR}/settings.json" ]; then
|
|
|
|
|
echo '{}' > "${SF_DIR}/settings.json"
|
2026-03-26 18:10:49 -04:00
|
|
|
fi
|
|
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
chown "${PUID}:${PGID}" "${SF_DIR}" "${SF_DIR}/settings.json"
|
2026-03-26 18:10:49 -04:00
|
|
|
|
|
|
|
|
# ── 3. Sentinel-based Bootstrap ─────────────────────────
|
|
|
|
|
# Run first-boot setup exactly once. Subsequent container
|
|
|
|
|
# starts (or restarts) skip this entirely.
|
|
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
SENTINEL="${SF_DIR}/.bootstrapped"
|
2026-03-26 18:10:49 -04:00
|
|
|
|
|
|
|
|
if [ ! -f "${SENTINEL}" ]; then
|
|
|
|
|
if [ -x /usr/local/bin/bootstrap.sh ]; then
|
2026-04-15 18:33:47 +02:00
|
|
|
# Run bootstrap as the sf user so files get correct ownership
|
2026-04-15 14:54:20 +02:00
|
|
|
gosu "${SF_USER}" /usr/local/bin/bootstrap.sh
|
2026-03-26 18:10:49 -04:00
|
|
|
fi
|
|
|
|
|
touch "${SENTINEL}"
|
|
|
|
|
chown "${PUID}:${PGID}" "${SENTINEL}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# ── 4. Drop Privileges & Exec ──────────────────────────
|
|
|
|
|
# Replace this shell process with the final command running
|
2026-04-15 18:33:47 +02:00
|
|
|
# as the sf user. exec + gosu = proper PID 1 = proper
|
2026-03-26 18:10:49 -04:00
|
|
|
# signal forwarding (SIGTERM, SIGINT, etc.).
|
|
|
|
|
|
2026-04-15 14:54:20 +02:00
|
|
|
exec gosu "${SF_USER}" "$@"
|