#!/bin/bash # Aether HF Space entrypoint # # Steps: # 1. Restore SQLite db from HF Dataset (if backup exists) # 2. Start backup cron (every AETHER_BACKUP_INTERVAL_MIN minutes) # 3. Start auto-update cron (every AETHER_AUTO_UPDATE_INTERVAL_HOURS hours) # 4. Run a non-blocking auto-update check at startup (HF free Spaces sleep, so cron alone is not reliable) # 5. Trap SIGTERM/SIGINT to flush a final backup before exit # 6. exec aether-gateway in the foreground set -euo pipefail log() { printf '[%s] aether-entrypoint: %s\n' "$(date -u +%FT%TZ)" "$*" } # ---------- step 1: restore ---------- log "step 1: restore SQLite db from HF Dataset (if exists)" if [[ -n "${HF_TOKEN:-}" && -n "${AETHER_BACKUP_REPO:-}" ]]; then python3 /usr/local/bin/aether_restore.py || \ log "restore failed (will start with fresh db)" else log "HF_TOKEN or AETHER_BACKUP_REPO unset; skip restore" fi mkdir -p "${AETHER_BACKUP_DIR}" # ---------- step 2: backup cron ---------- log "step 2: setup backup cron (every ${AETHER_BACKUP_INTERVAL_MIN}m)" mkdir -p /var/log/aether /etc/cron.d cat > /etc/cron.d/aether-backup <> /var/log/aether/backup.log 2>&1 EOFCRON chmod 0644 /etc/cron.d/aether-backup touch /var/log/aether/backup.log # ---------- step 3: auto-update cron ---------- if [[ "${AETHER_AUTO_UPDATE:-true}" == "true" ]]; then log "step 3: setup auto-update cron (every ${AETHER_AUTO_UPDATE_INTERVAL_HOURS}h)" cat > /etc/cron.d/aether-auto-update <> /var/log/aether/auto-update.log 2>&1 EOFCRON chmod 0644 /etc/cron.d/aether-auto-update touch /var/log/aether/auto-update.log log "step 4: start non-blocking auto-update check" ( /usr/local/bin/aether-auto-update.sh || true ) >> /var/log/aether/auto-update.log 2>&1 & else log "auto-update disabled" fi cron # ---------- step 5: trap shutdown for final backup ---------- shutdown_backup() { log "received signal, flushing final backup" /usr/local/bin/aether-backup.sh || log "final backup failed" if [[ -n "${AETHER_PID:-}" ]] && kill -0 "$AETHER_PID" 2>/dev/null; then kill -TERM "$AETHER_PID" || true wait "$AETHER_PID" || true fi exit 0 } trap shutdown_backup TERM INT # ---------- step 6: launch aether-gateway ---------- log "step 5: launch aether-gateway on port ${APP_PORT}" cd /opt/aether # distroless layout: /opt/aether/current -> /opt/aether/releases/image # binary: /opt/aether/current/bin/aether-gateway exec_bin="/opt/aether/current/bin/aether-gateway" if [[ ! -x "$exec_bin" ]]; then log "ERROR: $exec_bin not found or not executable" ls -la /opt/aether/current/bin/ || true exit 1 fi "$exec_bin" & AETHER_PID=$! log "aether-gateway started (pid=${AETHER_PID})" wait "$AETHER_PID" EXIT_CODE=$? log "aether-gateway exited (code=${EXIT_CODE})" shutdown_backup exit $EXIT_CODE