backend: harden rootless app lifecycle orchestration
This commit is contained in:
@@ -98,6 +98,11 @@ alloc_port() {
|
||||
# Run as archipelago user — podman sees rootless containers directly.
|
||||
# Use sudo only for chown/mkdir operations.
|
||||
PODMAN="podman"
|
||||
PODMAN_IMAGE_CHECK_TIMEOUT="${PODMAN_IMAGE_CHECK_TIMEOUT:-10}"
|
||||
|
||||
podman_bounded() {
|
||||
timeout --kill-after=2s "${PODMAN_IMAGE_CHECK_TIMEOUT}s" "$PODMAN" "$@"
|
||||
}
|
||||
|
||||
# ── Pre-flight ───────────────────────────────────────────────────────
|
||||
header "╔══════════════════════════════════════════════════╗"
|
||||
@@ -152,7 +157,7 @@ container_image_id() {
|
||||
}
|
||||
|
||||
spec_image_id() {
|
||||
$PODMAN image inspect "$SPEC_IMAGE" --format '{{.Id}}' 2>/dev/null
|
||||
podman_bounded image inspect "$SPEC_IMAGE" --format '{{.Id}}' 2>/dev/null
|
||||
}
|
||||
|
||||
container_network() {
|
||||
@@ -218,6 +223,39 @@ prepare_bind_source() {
|
||||
esac
|
||||
}
|
||||
|
||||
ensure_catatonit() {
|
||||
command -v catatonit >/dev/null 2>&1 && return 0
|
||||
$CHECK_ONLY && { info "catatonit missing (would install)"; return 0; }
|
||||
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
sudo apt-get update >/dev/null 2>&1 || true
|
||||
sudo apt-get install -y catatonit >/dev/null 2>&1 || true
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
sudo dnf install -y catatonit >/dev/null 2>&1 || true
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
sudo apk add catatonit >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
command -v catatonit >/dev/null 2>&1 || { fail "catatonit missing; Portainer compose builds may fail"; return 1; }
|
||||
}
|
||||
|
||||
ensure_portainer_host_paths() {
|
||||
ensure_catatonit
|
||||
if $CHECK_ONLY; then
|
||||
[ -d /var/lib/archipelago/portainer/compose ] || info "Portainer compose dir missing (would create)"
|
||||
[ -e /data ] || info "/data host path missing (would link to /var/lib/archipelago/portainer)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
sudo mkdir -p /var/lib/archipelago/portainer/compose 2>/dev/null || true
|
||||
sudo chown -R 1000:1000 /var/lib/archipelago/portainer 2>/dev/null || true
|
||||
if [ ! -e /data ]; then
|
||||
sudo ln -s /var/lib/archipelago/portainer /data 2>/dev/null || true
|
||||
elif [ -d /data ] && [ ! -L /data ] && [ ! -e /data/compose ]; then
|
||||
sudo ln -s /var/lib/archipelago/portainer/compose /data/compose 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
container_has_mount() {
|
||||
local name="$1" source="$2" target="$3"
|
||||
$PODMAN inspect "$name" --format '{{range .Mounts}}{{println .Source "|" .Destination}}{{end}}' 2>/dev/null \
|
||||
@@ -250,13 +288,7 @@ container_env_val() {
|
||||
URL_ENV_SUFFIXES="_URL _HOST _ENDPOINT"
|
||||
|
||||
image_exists() {
|
||||
# Note: `grep -q` closes stdin after first match → SIGPIPE (exit 141) on podman.
|
||||
# With `set -o pipefail` active in the parent script, that propagates as failure
|
||||
# and spuriously skips local-image containers. Use a full scan + explicit match
|
||||
# check to keep the exit code stable regardless of pipefail.
|
||||
local images
|
||||
images=$($PODMAN images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null)
|
||||
echo "$images" | grep -qF "$1"
|
||||
podman_bounded image exists "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
resolve_spec_image() {
|
||||
@@ -280,7 +312,7 @@ resolve_spec_image() {
|
||||
fi
|
||||
done
|
||||
|
||||
repo=$($PODMAN images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null \
|
||||
repo=$(podman_bounded images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null \
|
||||
| grep -E "/${image_name}:${image_tag}$" \
|
||||
| head -1 || true)
|
||||
if [ -n "$repo" ]; then
|
||||
@@ -377,6 +409,8 @@ reconcile() {
|
||||
return
|
||||
fi
|
||||
|
||||
[ "$name" = "portainer" ] && ensure_portainer_host_paths
|
||||
|
||||
# Filter by tier
|
||||
[ -n "$FILTER_TIER" ] && [ "$SPEC_TIER" != "$FILTER_TIER" ] && return
|
||||
|
||||
@@ -701,7 +735,7 @@ BTCEOF
|
||||
# bitcoin_rw.conf, so clean both files.
|
||||
for conf in "$BITCOIN_CONF" "/var/lib/archipelago/bitcoin/bitcoin_rw.conf"; do
|
||||
if [ -f "$conf" ]; then
|
||||
sudo sed -i '/^server=/d; /^txindex=/d; /^rpcbind=/d; /^rpcallowip=/d; /^rpcport=/d; /^listen=/d; /^bind=/d; /^dbcache=/d' "$conf" 2>/dev/null
|
||||
sudo sed -i '/^server=/d; /^txindex=/d; /^rpcbind=/d; /^rpcallowip=/d; /^rpcport=/d; /^listen=/d; /^bind=/d; /^dbcache=/d; /^rpcthreads=/d; /^rpcworkqueue=/d' "$conf" 2>/dev/null
|
||||
fi
|
||||
done
|
||||
sudo chown -R 100101:100101 /var/lib/archipelago/bitcoin 2>/dev/null
|
||||
|
||||
Reference in New Issue
Block a user