- scripts/Invoke-CloudflareApi.ps1: control de tunnel/DNS via API - scripts/Install-CoolifyAutostart.ps1 + scripts/host/: autostart de LXC 102 + tunnel tras corte - scripts/Apply-ChatwootEnterprisePatch.ps1: parche enterprise (autodetecta creds) - Deploy-SoloLeveling.ps1: deploy build-on-server verificado - docs/runbooks/cloudflare-tunnel.md y autostart-coolify.md - docs/casos/chatwoot-enterprise-patch.md (credenciales redactadas) - docs/AGENTS-coolify-apps.md + issues y reportes - deploy_skill/references/coolify-4.1.2-notes.md: hallazgos verificados (seccion 7) - package.json para verify-online.mjs del coolify-deploy skill - .gitignore: excluye .claude/ y .opencode/ (config local de herramientas)
82 lines
3.2 KiB
Bash
82 lines
3.2 KiB
Bash
#!/usr/bin/env bash
|
|
# coolify-autostart.sh
|
|
# -----------------------------------------------------------------------------
|
|
# Ensures the Coolify stack survives a power outage: on every host boot it
|
|
# starts LXC 102 (if not already up via onboot), waits for Docker inside the
|
|
# LXC, and makes sure the core Coolify containers + the Cloudflare tunnel are
|
|
# running. Idempotent and self-healing: safe to run any number of times.
|
|
#
|
|
# Installed by scripts/Install-CoolifyAutostart.ps1 to /usr/local/bin/ and
|
|
# invoked by the systemd unit coolify-autostart.service on multi-user.target.
|
|
# -----------------------------------------------------------------------------
|
|
set -uo pipefail
|
|
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
|
|
LXC_ID="${COOLIFY_LXC:-102}"
|
|
LOG="/var/log/coolify-autostart.log"
|
|
MAX_WAIT="${COOLIFY_MAX_WAIT:-180}" # seconds to wait for docker inside the LXC
|
|
|
|
# Dependencies first, then the app, proxy and tunnel. These all normally come
|
|
# up on their own via Docker restart policies; this loop only heals the ones
|
|
# that didn't (e.g. restart=no, or a wedged start).
|
|
CORE_CONTAINERS=(coolify-db coolify-redis coolify-realtime coolify coolify-proxy cloudflared)
|
|
|
|
log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }
|
|
|
|
log "=== coolify-autostart start (LXC ${LXC_ID}) ==="
|
|
|
|
# 1. Ensure the LXC is running -------------------------------------------------
|
|
status="$(pct status "$LXC_ID" 2>/dev/null | awk '{print $2}')"
|
|
if [ "$status" != "running" ]; then
|
|
log "LXC ${LXC_ID} status='${status:-unknown}' -> starting"
|
|
if pct start "$LXC_ID"; then
|
|
log "pct start issued"
|
|
else
|
|
log "ERROR: pct start ${LXC_ID} failed"
|
|
fi
|
|
else
|
|
log "LXC ${LXC_ID} already running"
|
|
fi
|
|
|
|
# 2. Wait for the Docker daemon inside the LXC to respond ----------------------
|
|
waited=0
|
|
until pct exec "$LXC_ID" -- docker info >/dev/null 2>&1; do
|
|
if [ "$waited" -ge "$MAX_WAIT" ]; then
|
|
log "ERROR: docker not ready after ${MAX_WAIT}s -> aborting"
|
|
exit 1
|
|
fi
|
|
sleep 5
|
|
waited=$((waited + 5))
|
|
done
|
|
log "docker ready after ${waited}s"
|
|
|
|
# 3. Ensure the core Coolify containers + tunnel container are running ---------
|
|
for c in "${CORE_CONTAINERS[@]}"; do
|
|
st="$(pct exec "$LXC_ID" -- docker inspect -f '{{.State.Running}}' "$c" 2>/dev/null || echo missing)"
|
|
case "$st" in
|
|
true) log "container ${c}: running" ;;
|
|
missing) log "WARN container ${c}: not found (skipping)" ;;
|
|
*)
|
|
log "container ${c}: running=${st} -> starting"
|
|
if pct exec "$LXC_ID" -- docker start "$c" >/dev/null 2>&1; then
|
|
log "started ${c}"
|
|
else
|
|
log "ERROR: could not start ${c}"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 4. Ensure the systemd cloudflared tunnel inside the LXC is up ----------------
|
|
# (second connector to the same tunnel; belt-and-suspenders alongside the
|
|
# cloudflared Docker container above.)
|
|
if pct exec "$LXC_ID" -- systemctl is-enabled cloudflared >/dev/null 2>&1; then
|
|
if pct exec "$LXC_ID" -- systemctl start cloudflared >/dev/null 2>&1; then
|
|
log "cloudflared.service ensured up"
|
|
else
|
|
log "WARN: cloudflared.service start returned non-zero"
|
|
fi
|
|
fi
|
|
|
|
log "=== coolify-autostart done ==="
|