shopseenow / entrypoint.sh
fomext's picture
Upload entrypoint.sh
36e591a verified
Raw
History Blame Contribute Delete
6.13 kB
#!/bin/sh
# ── entrypoint.sh ─────────────────────────────────────────────────────────────
# HF Spaces runs as UID 1000 (not root), so the original docker-entrypoint.sh
# fails — it uses `gosu` to drop root→node, which requires being root.
# We skip it entirely and exec the server directly from /app.
#
# Recovery logic:
# 1. Fix permissions and recreate missing empty PostgreSQL dirs
# 2. Remove stale postmaster.pid from unclean shutdowns
# 3. Probe whether PostgreSQL can start cleanly
# 4. If the cluster is unrecoverable, restore from the latest backup
# 5. Start Paperclip
# ──────────────────────────────────────────────────────────────────────────────
set -e
DB_DIR="/data/paperclip/instances/default/db"
BACKUP_DIR="/data/paperclip/instances/default/data/backups"
DB_PORT=54329
# ── 1. Ensure /data/paperclip is writable ────────────────────────────────────
mkdir -p "${DB_DIR}"
# ── 1a. Fix PostgreSQL data dir permissions ───────────────────────────────────
chmod 0700 "${DB_DIR}"
if [ -d "${DB_DIR}/pg_notify" ]; then
chmod 0700 "${DB_DIR}/pg_notify"
fi
# ── 1b. Remove stale postmaster.pid ──────────────────────────────────────────
# If the Space was killed mid-run, PostgreSQL leaves behind postmaster.pid.
# Paperclip sees it, thinks Postgres is running, tries to connect, and fails.
# Safe to delete β€” PostgreSQL recreates it fresh on startup.
if [ -f "${DB_DIR}/postmaster.pid" ]; then
echo "[entrypoint] Removing stale postmaster.pid (leftover from unclean shutdown)..."
rm -f "${DB_DIR}/postmaster.pid"
echo "[entrypoint] postmaster.pid removed."
fi
# ── 1c. Recreate missing PostgreSQL dirs ─────────────────────────────────────
# These are empty directories β€” safe to recreate if missing after unclean shutdown.
if [ -f "${DB_DIR}/PG_VERSION" ]; then
for dir in pg_notify pg_tblspc pg_replslot pg_twophase pg_snapshots pg_commit_ts pg_logical pg_logical/snapshots pg_logical/mappings; do
if [ ! -d "${DB_DIR}/${dir}" ]; then
echo "[entrypoint] ${dir} missing β€” recreating (cluster data preserved)..."
mkdir -p "${DB_DIR}/${dir}"
chmod 0700 "${DB_DIR}/${dir}"
fi
done
echo "[entrypoint] PostgreSQL directories verified."
fi
# ── 1d. Probe whether PostgreSQL can start β€” restore from backup if not ───────
restore_from_backup() {
echo "[entrypoint] ⚠️ Live PostgreSQL cluster is unrecoverable."
echo "[entrypoint] Looking for latest backup in ${BACKUP_DIR}..."
LATEST_BACKUP=$(ls -t "${BACKUP_DIR}"/*.tar.gz 2>/dev/null | head -n 1 || true)
if [ -z "${LATEST_BACKUP}" ]; then
echo "[entrypoint] ❌ No backup found in ${BACKUP_DIR}. Starting fresh β€” all previous data is lost."
rm -rf "${DB_DIR}"
mkdir -p "${DB_DIR}"
chmod 0700 "${DB_DIR}"
return
fi
echo "[entrypoint] βœ… Found backup: ${LATEST_BACKUP}"
echo "[entrypoint] Wiping corrupted cluster and restoring..."
rm -rf "${DB_DIR}"
mkdir -p "${DB_DIR}"
chmod 0700 "${DB_DIR}"
tar -xzf "${LATEST_BACKUP}" -C "${DB_DIR}" --strip-components=1
chmod 0700 "${DB_DIR}"
echo "[entrypoint] βœ… Restore complete from: $(basename ${LATEST_BACKUP})"
echo "[entrypoint] Note: work done after this backup was taken will be missing."
}
if [ -f "${DB_DIR}/PG_VERSION" ]; then
echo "[entrypoint] Probing PostgreSQL cluster health..."
PG_CTL=$(find /usr -name "pg_ctl" 2>/dev/null | head -n 1 || true)
if [ -n "${PG_CTL}" ]; then
if ! "${PG_CTL}" -D "${DB_DIR}" -o "-p ${DB_PORT}" -w -t 15 start > /tmp/pg_probe.log 2>&1; then
echo "[entrypoint] PostgreSQL probe failed. Logs:"
cat /tmp/pg_probe.log
restore_from_backup
else
echo "[entrypoint] PostgreSQL cluster is healthy. Stopping probe instance..."
"${PG_CTL}" -D "${DB_DIR}" -o "-p ${DB_PORT}" stop > /dev/null 2>&1 || true
fi
else
echo "[entrypoint] pg_ctl not found β€” skipping probe, Paperclip will handle startup."
fi
fi
# ── 2. Write opencode provider config ────────────────────────────────────────
OPENCODE_CONFIG_DIR="${HOME}/.config/opencode"
OPENCODE_STATE_DIR="${HOME}/.local/share/opencode"
mkdir -p "${OPENCODE_CONFIG_DIR}"
cp /app/opencode.json "${OPENCODE_CONFIG_DIR}/config.json"
# ── 3. Write opencode auth file ───────────────────────────────────────────────
mkdir -p "${OPENCODE_STATE_DIR}"
cat > "${OPENCODE_STATE_DIR}/auth.json" <<AUTHEOF
{
"zai-coding-plan": {
"type": "api",
"key": "${ZAI_API_KEY}"
}
}
AUTHEOF
echo "[entrypoint] OpenCode configured β†’ Z.AI Coding Plan (https://api.z.ai/api/coding/paas/v4)"
echo "[entrypoint] Models: glm-5.2 (primary) | glm-4.7 (small/fast)"
# ── 4. Brief pause to let HF storage fully settle before Paperclip starts ────
# Without this, embedded PostgreSQL can get an ECONNREFUSED on the very first
# boot cycle because the storage mount isn't quite ready when Paperclip tries
# its first DB connection (~03:00:54 vs Postgres ready at ~03:01:20).
echo "[entrypoint] Waiting for storage to settle..."
sleep 8
echo "[entrypoint] Starting Paperclip..."
# ── 5. Start the server ───────────────────────────────────────────────────────
cd /app
exec node --import ./server/node_modules/tsx/dist/loader.mjs server/dist/index.js