Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
41
scripts/cron/README.md
Normal file
41
scripts/cron/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Explorer maintenance cron
|
||||
|
||||
Automated jobs to prevent 502s, disk full, and nginx downtime on VMID 5000 (explorer.d-bis.org).
|
||||
|
||||
## Install (one-time)
|
||||
|
||||
From the **explorer-monorepo** directory:
|
||||
|
||||
**On Proxmox host that has VMID 5000:**
|
||||
```bash
|
||||
bash scripts/cron/install-explorer-cron.sh
|
||||
```
|
||||
|
||||
**From your machine (SSH to node):**
|
||||
```bash
|
||||
EXPLORER_VM_HOST=root@192.168.11.12 bash scripts/cron/install-explorer-cron.sh
|
||||
```
|
||||
|
||||
## What gets installed (inside VMID 5000)
|
||||
|
||||
| Schedule | Job | Purpose |
|
||||
|----------|-----|--------|
|
||||
| Every 5 min | `/usr/local/bin/explorer-maintain.sh` | If API ≠ 200: restart Blockscout or start from docker-compose. If nginx inactive: start nginx. |
|
||||
| Daily 03:15 | `RUN_PRUNE=1 /usr/local/bin/explorer-maintain.sh` | If disk usage ≥ 90%: safe prune (unused images + build cache only; **no** container prune). |
|
||||
|
||||
Log file: `/var/log/explorer-maintain.log` (inside the VM).
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
# On Proxmox host
|
||||
pct exec 5000 -- crontab -l
|
||||
pct exec 5000 -- tail -20 /var/log/explorer-maintain.log
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
```bash
|
||||
pct exec 5000 -- bash -c '(crontab -l 2>/dev/null | grep -v explorer-maintain | grep -v /usr/local/bin/explorer-maintain.sh) | crontab -'
|
||||
pct exec 5000 -- rm -f /usr/local/bin/explorer-maintain.sh
|
||||
```
|
||||
49
scripts/cron/explorer-maintain.sh
Normal file
49
scripts/cron/explorer-maintain.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runs INSIDE VMID 5000 (explorer). Keeps Blockscout API and nginx up; optional safe disk prune.
|
||||
# Install with: bash scripts/install-explorer-cron.sh
|
||||
# Cron: every 5 min health check + recover; daily safe disk prune.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
LOG="${EXPLORER_MAINTAIN_LOG:-/var/log/explorer-maintain.log}"
|
||||
BLOCKSCOUT_DIR="${BLOCKSCOUT_DIR:-/opt/blockscout}"
|
||||
|
||||
log() { echo "$(date -Iseconds) $*" >> "$LOG" 2>/dev/null || true; }
|
||||
|
||||
# 1) Ensure PostgreSQL is running
|
||||
docker start blockscout-postgres 2>/dev/null || true
|
||||
|
||||
# 2) Blockscout API health: if not 200, restart or start container
|
||||
CODE=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 http://127.0.0.1:4000/api/v2/stats 2>/dev/null || echo "000")
|
||||
if [ "$CODE" != "200" ]; then
|
||||
CONTAINER=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -E "blockscout" | grep -v postgres | head -1 | tr -d '\n\r' || true)
|
||||
if [ -n "$CONTAINER" ]; then
|
||||
log "API not 200 (got $CODE). Restarting container: $CONTAINER"
|
||||
docker restart "$CONTAINER" 2>>"$LOG" || true
|
||||
sleep 15
|
||||
elif [ -f "$BLOCKSCOUT_DIR/docker-compose.yml" ]; then
|
||||
log "API not 200 (got $CODE). Starting Blockscout from $BLOCKSCOUT_DIR"
|
||||
(cd "$BLOCKSCOUT_DIR" && docker-compose up -d blockscout 2>>"$LOG") || true
|
||||
sleep 20
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3) Nginx: ensure running
|
||||
NGINX=$(systemctl is-active nginx 2>/dev/null || echo "inactive")
|
||||
if [ "$NGINX" != "active" ]; then
|
||||
log "Nginx not active. Starting nginx."
|
||||
systemctl start nginx 2>>"$LOG" || true
|
||||
fi
|
||||
|
||||
# 4) Safe disk prune (only if env RUN_PRUNE=1 or first run on Sunday 3am - use cron for daily)
|
||||
# Do NOT prune containers (would remove stopped Blockscout). Prune only unused images and build cache.
|
||||
if [ "${RUN_PRUNE:-0}" = "1" ]; then
|
||||
USED_PCT=$(df / --output=pcent 2>/dev/null | tail -1 | tr -d ' %' || echo "0")
|
||||
if [ -n "$USED_PCT" ] && [ "$USED_PCT" -ge 90 ]; then
|
||||
log "Disk usage ${USED_PCT}%. Running safe prune (images + build cache only)."
|
||||
docker image prune -f 2>>"$LOG" || true
|
||||
docker builder prune -f 2>>"$LOG" || true
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
59
scripts/cron/install-explorer-cron.sh
Normal file
59
scripts/cron/install-explorer-cron.sh
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install cron jobs in VMID 5000 to keep explorer API and nginx healthy and prevent disk full.
|
||||
# Run from repo root on Proxmox host that has VMID 5000, or with EXPLORER_VM_HOST=root@<node>.
|
||||
#
|
||||
# Cron installed inside the VM:
|
||||
# - Every 5 min: health check + restart Blockscout/nginx if needed
|
||||
# - Daily 03:15: safe disk prune (images + build cache only, no container prune)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
[ -f "$REPO_ROOT/../.env" ] && source "$REPO_ROOT/../.env" 2>/dev/null || true
|
||||
VMID="${EXPLORER_VMID:-5000}"
|
||||
EXPLORER_NODE="${EXPLORER_VM_HOST:-${PROXMOX_R630_02:-192.168.11.12}}"
|
||||
if [[ "$EXPLORER_NODE" == *"@"* ]]; then SSH_TARGET="$EXPLORER_NODE"; else SSH_TARGET="root@$EXPLORER_NODE"; fi
|
||||
|
||||
# Remote mode
|
||||
if ! command -v pct &>/dev/null || ! pct list 2>/dev/null | grep -q "^$VMID "; then
|
||||
if [ -n "${EXPLORER_VM_HOST:-}" ] || [ -n "${PROXMOX_R630_02:-}" ]; then
|
||||
echo "Installing cron via SSH on $SSH_TARGET..."
|
||||
scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SCRIPT_DIR/explorer-maintain.sh" "$SSH_TARGET:/tmp/explorer-maintain.sh" 2>/dev/null || true
|
||||
scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SCRIPT_DIR/install-explorer-cron.sh" "$SSH_TARGET:/tmp/install-explorer-cron.sh" 2>/dev/null || true
|
||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SSH_TARGET" "EXPLORER_VM_HOST= bash /tmp/install-explorer-cron.sh"
|
||||
exit $?
|
||||
else
|
||||
echo "Run on Proxmox host that has VMID $VMID, or set EXPLORER_VM_HOST=root@<node-ip>"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
EXEC_PREFIX="pct exec $VMID --"
|
||||
MAINTAIN_SCRIPT="/usr/local/bin/explorer-maintain.sh"
|
||||
|
||||
echo "=============================================="
|
||||
echo "Install explorer maintenance cron (VMID $VMID)"
|
||||
echo "=============================================="
|
||||
|
||||
# Copy script into VM
|
||||
pct push $VMID "$SCRIPT_DIR/explorer-maintain.sh" "$MAINTAIN_SCRIPT"
|
||||
$EXEC_PREFIX chmod +x "$MAINTAIN_SCRIPT"
|
||||
echo "✅ Installed $MAINTAIN_SCRIPT"
|
||||
|
||||
# Install crontab (append to existing)
|
||||
$EXEC_PREFIX bash -c '(crontab -l 2>/dev/null | grep -v explorer-maintain | grep -v /usr/local/bin/explorer-maintain.sh || true; echo "# explorer-maintain"; echo "*/5 * * * * /usr/local/bin/explorer-maintain.sh >> /var/log/explorer-maintain.log 2>&1"; echo "15 3 * * * RUN_PRUNE=1 /usr/local/bin/explorer-maintain.sh >> /var/log/explorer-maintain.log 2>&1") | crontab -'
|
||||
echo "✅ Cron installed:"
|
||||
$EXEC_PREFIX crontab -l 2>/dev/null | grep -E "explorer-maintain|explorer-maintain.sh" || true
|
||||
|
||||
# Ensure log file exists and is writable
|
||||
$EXEC_PREFIX touch /var/log/explorer-maintain.log 2>/dev/null || true
|
||||
$EXEC_PREFIX chmod 644 /var/log/explorer-maintain.log 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo "Done. Schedule:"
|
||||
echo " - Every 5 min: health check + recover Blockscout/nginx"
|
||||
echo " - Daily 03:15: safe disk prune (if usage >= 90%)"
|
||||
echo " Log: pct exec $VMID -- tail -f /var/log/explorer-maintain.log"
|
||||
echo "=============================================="
|
||||
Reference in New Issue
Block a user