Both existing crontab entries (trim-feeds, anniversaries) and backup-db.sh referenced a run-cron.sh that was never actually created/committed - cron has been executing it daily (04:00/08:00) with exit 127 since at least today, silently, because no local mail delivery is configured for the cron user's failure notifications. Recreates it per README's documented curl pattern (bearer token via CRON_SECRET, --resolve for the origin TLS cert quirk) and adds logging to docker/cron.log so future failures are visible without relying on cron's mail notification. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
60 lines
1.7 KiB
Bash
60 lines
1.7 KiB
Bash
#!/bin/sh
|
|
# Triggers a PawFeed cron route from the NAS crontab.
|
|
#
|
|
# Usage: run-cron.sh /api/cron/<name>
|
|
#
|
|
# Reads CRON_SECRET from docker/.env (sibling to this script) and hits the app
|
|
# via the DDNS hostname with --resolve to localhost, because the origin TLS
|
|
# cert (Nginx Proxy Manager) is only valid for pawfeed.neodk.ipv64.de — a plain
|
|
# curl against pawfeed.org fails with an SSL hostname mismatch from the NAS
|
|
# itself (Cloudflare only terminates TLS for pawfeed.org at the edge, browsers
|
|
# only). See README.md "Common Pitfalls".
|
|
#
|
|
# Every run is logged to docker/cron.log (with HTTP status + response body) so
|
|
# failures are visible even though this NAS has no local mail delivery set up
|
|
# for the cron user — a missing/renamed script or a non-2xx response would
|
|
# otherwise fail silently.
|
|
set -eu
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
ENV_FILE="$SCRIPT_DIR/.env"
|
|
LOG_FILE="$SCRIPT_DIR/cron.log"
|
|
HOST="pawfeed.neodk.ipv64.de"
|
|
|
|
log() {
|
|
printf '%s [run-cron] %s\n' "$(date -Iseconds)" "$1" >> "$LOG_FILE"
|
|
}
|
|
|
|
ROUTE="${1:?usage: run-cron.sh /api/cron/<name>}"
|
|
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
log "ERROR: $ENV_FILE not found"
|
|
exit 1
|
|
fi
|
|
|
|
CRON_SECRET="$(grep -E '^CRON_SECRET=' "$ENV_FILE" | head -n1 | cut -d= -f2-)"
|
|
if [ -z "$CRON_SECRET" ]; then
|
|
log "ERROR: CRON_SECRET not set in $ENV_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
RESPONSE_FILE="$(mktemp)"
|
|
trap 'rm -f "$RESPONSE_FILE"' EXIT
|
|
|
|
STATUS=$(curl -s -o "$RESPONSE_FILE" -w '%{http_code}' \
|
|
--resolve "$HOST:443:127.0.0.1" \
|
|
--max-time 60 \
|
|
-H "Authorization: Bearer $CRON_SECRET" \
|
|
"https://$HOST$ROUTE") || STATUS=000
|
|
|
|
BODY="$(cat "$RESPONSE_FILE" 2>/dev/null || true)"
|
|
log "$ROUTE -> HTTP $STATUS: $BODY"
|
|
|
|
case "$STATUS" in
|
|
2??) exit 0 ;;
|
|
*)
|
|
log "ERROR: $ROUTE returned HTTP $STATUS"
|
|
exit 1
|
|
;;
|
|
esac
|