#!/bin/sh # Triggers a PawFeed cron route from the NAS crontab. # # Usage: run-cron.sh /api/cron/ # # 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/}" 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