summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSt33v <github@f3rr3t.com>2026-03-15 15:48:10 +1100
committerSt33v <github@f3rr3t.com>2026-03-15 15:48:10 +1100
commit96a9cd525e7caf46704ba2240c1c86f6892e3aaf (patch)
tree11f022a651adc766256e00d4dd8bf18f4ab46e35
parent078d16785d7b027aead68f59d1c1b4dd18cd5267 (diff)
Add deployment config and strengthen synopticChart.sh
- Inline DeriveTime from func/deriveTimeString.sh; delete func/ - Add set -euo pipefail, quoting, and stderr for error messages - Archive PDFs to /var/lib/synoptic/archive/raw/ after conversion - Publish PNG to /srv/www/synopticLatest.png - Add systemd units: synoptic.{service,timer}, synoptic-retry.{service,timer} - Timer fires at 02:10, 08:10, 14:10, 20:10 UTC (2h after BOM publish slots) - Add nginx site config for pestrel.com - Add setup.sh (run once on VPS as root) and deploy.sh (run from cr4y) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rwxr-xr-xdeploy.sh16
-rwxr-xr-xfunc/deriveTimeString.sh33
-rw-r--r--index.html5
-rw-r--r--nginx/pestrel.com.conf18
-rwxr-xr-xsetup.sh83
-rwxr-xr-xsynopticChart.sh64
-rw-r--r--systemd/synoptic-retry.service12
-rw-r--r--systemd/synoptic-retry.timer8
-rw-r--r--systemd/synoptic.service13
-rw-r--r--systemd/synoptic.timer9
10 files changed, 202 insertions, 59 deletions
diff --git a/deploy.sh b/deploy.sh
new file mode 100755
index 0000000..bb1badb
--- /dev/null
+++ b/deploy.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+set -euo pipefail
+
+REMOTE=st33v@pestrel.com
+PORT=40022
+
+echo "Deploying synopticChart.sh to ${REMOTE}..."
+scp -P "$PORT" synopticChart.sh "${REMOTE}:/opt/synoptic/synopticChart.sh"
+
+echo "Restarting synoptic.service..."
+if ssh -p "$PORT" "$REMOTE" "sudo systemctl restart synoptic.service"; then
+ echo "SUCCESS: synoptic.service ran cleanly."
+else
+ echo "FAILURE: synoptic.service exited non-zero." >&2
+ exit 1
+fi
diff --git a/func/deriveTimeString.sh b/func/deriveTimeString.sh
deleted file mode 100755
index a09a393..0000000
--- a/func/deriveTimeString.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# BOM releases four synoptic charts per day.
-# They are named according to the UTC dat/time for which they are valid.
-#
-# Filenames follow this template: IDY00030.YYYYMMDDHHMM.[png|pdf]
-#
-# IDY00030 = the asset name (i.e. the Mean Sea Level Pressure synoptic chart)
-# .
-# <datetime string>
-# .
-# <extension> (I want pdf because it contains a Scalable Vectort Graphic (SVG) image)
-
-
-# This function returns the filename for the most recent chart.
-
-DeriveTime() {
- nowDate=$(\date -u +%Y%m%d) # backslash req. to unalias date to raw format
- nowTime=$(\date -u +%H%M) # (I have date aliased to date -R)
-# echo $nowDate$nowTime
-
- if [ $nowTime -ge 1800 ] ; then
- fileTime=1800
- elif [ $nowTime -ge 1200 ] ; then
- fileTime=1200
- elif [ $nowTime -ge 0600 ] ; then
- fileTime=0600
- else
- fileTime=0000
- fi
-
- echo $nowDate$fileTime
-}
-
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f43eedc
--- /dev/null
+++ b/index.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta charset="utf-8"><title>Synoptic</title></head>
+<body><img src="/synopticLatest.png" alt="Latest synoptic"></body>
+</html>
diff --git a/nginx/pestrel.com.conf b/nginx/pestrel.com.conf
new file mode 100644
index 0000000..372c321
--- /dev/null
+++ b/nginx/pestrel.com.conf
@@ -0,0 +1,18 @@
+# Synoptic chart site — pestrel.com
+# Installed to /etc/nginx/conf.d/synoptic.conf by setup.sh
+#
+# Requires /etc/nginx/nginx.conf to include:
+# include /etc/nginx/conf.d/*.conf;
+
+server {
+ listen 80;
+ listen [::]:80;
+ server_name pestrel.com www.pestrel.com;
+
+ root /srv/www;
+ index index.html;
+
+ location / {
+ try_files $uri $uri/ =404;
+ }
+}
diff --git a/setup.sh b/setup.sh
new file mode 100755
index 0000000..14c2eec
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+set -euo pipefail
+
+# Run once on pestrel as root (or with sudo) to install the synoptic service.
+# Usage: sudo ./setup.sh
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "Must run as root or with sudo." >&2
+ exit 1
+fi
+
+SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
+OWNER=st33v
+
+# ---------------------------------------------------------------------------
+# Nginx conflict checks
+# ---------------------------------------------------------------------------
+echo "==> Checking for nginx conflicts..."
+
+CONFLICT=0
+
+if grep -rl "server_name.*pestrel\.com" /etc/nginx/ 2>/dev/null; then
+ echo "WARNING: The above nginx config(s) already reference pestrel.com — check for duplicate server blocks."
+ CONFLICT=1
+fi
+
+if grep -rl "listen.*80.*default_server" /etc/nginx/ 2>/dev/null; then
+ echo "WARNING: The above nginx config(s) define a default_server on port 80 — may intercept traffic intended for this site."
+ CONFLICT=1
+fi
+
+if ! grep -q "include.*conf\.d" /etc/nginx/nginx.conf 2>/dev/null; then
+ echo "WARNING: /etc/nginx/nginx.conf does not appear to include conf.d/*.conf — you may need to add the following line manually:"
+ echo " include /etc/nginx/conf.d/*.conf;"
+ CONFLICT=1
+fi
+
+[ "$CONFLICT" -eq 0 ] && echo " No conflicts detected."
+
+# ---------------------------------------------------------------------------
+# Directories
+# ---------------------------------------------------------------------------
+echo "==> Creating directories..."
+install -d -o "$OWNER" -g "$OWNER" /opt/synoptic
+install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic
+install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic/archive
+install -d -o "$OWNER" -g "$OWNER" /var/lib/synoptic/archive/raw
+install -d -o "$OWNER" -g "$OWNER" /srv/www
+
+# ---------------------------------------------------------------------------
+# Web content
+# ---------------------------------------------------------------------------
+echo "==> Writing index.html..."
+install -o "$OWNER" -g "$OWNER" -m 644 "$SCRIPT_DIR/index.html" /srv/www/index.html
+
+# ---------------------------------------------------------------------------
+# Systemd units
+# ---------------------------------------------------------------------------
+echo "==> Installing systemd unit files..."
+for unit in synoptic.service synoptic.timer synoptic-retry.service synoptic-retry.timer; do
+ install -m 644 "$SCRIPT_DIR/systemd/${unit}" "/etc/systemd/system/${unit}"
+ echo " installed ${unit}"
+done
+
+echo "==> Reloading systemd and enabling timer..."
+systemctl daemon-reload
+systemctl enable --now synoptic.timer
+
+# ---------------------------------------------------------------------------
+# Nginx
+# ---------------------------------------------------------------------------
+echo "==> Installing nginx config..."
+install -m 644 "$SCRIPT_DIR/nginx/pestrel.com.conf" /etc/nginx/conf.d/synoptic.conf
+
+echo "==> Testing nginx config..."
+nginx -t
+
+echo "==> Reloading nginx..."
+systemctl reload nginx
+
+# ---------------------------------------------------------------------------
+echo "==> Done."
+echo " Run 'systemctl list-timers synoptic.timer' to confirm next scheduled run."
diff --git a/synopticChart.sh b/synopticChart.sh
index e7d3726..a515c90 100755
--- a/synopticChart.sh
+++ b/synopticChart.sh
@@ -1,37 +1,49 @@
#!/bin/bash
-# SJP 28 Nov 2021
-# Get synoptic weather charts from BOM and make them into a movie
-# See notes about BOM. they don't like scrapers but permit anon FTP
-# for *personal use*
-# This script will be called froma timer, once every 6 hours, which is
-# how often new charts are published.
-#
-# The timer will take care of scheduing the call to the script
-# todo: check what happens with daylight saving...
+set -euo pipefail
-source func/deriveTimeString.sh
+# SJP 28 Nov 2021 — extended for deployment
+# Download BOM synoptic chart (IDY00030) and publish as PNG.
+# BOM permits anonymous FTP for personal use.
+# Charts are valid at 00, 06, 12, 18 UTC; files appear ~2h later.
+# Deployed to /opt/synoptic/synopticChart.sh on pestrel.com.
-dateTime=$(DeriveTime)
+ARCHIVE_DIR=/var/lib/synoptic/archive
+RAW_DIR=/var/lib/synoptic/archive/raw
+LATEST=/srv/www/synopticLatest.png
+
+# Return the datetime string for the most recently published chart slot.
+# BOM chart slots: 0000, 0600, 1200, 1800 UTC.
+DeriveTime() {
+ local nowDate nowTime fileTime
+ nowDate=$(date -u +%Y%m%d)
+ nowTime=$(date -u +%H%M)
+
+ if [ "$nowTime" -ge 1800 ]; then fileTime=1800
+ elif [ "$nowTime" -ge 1200 ]; then fileTime=1200
+ elif [ "$nowTime" -ge 0600 ]; then fileTime=0600
+ else fileTime=0000
+ fi
-latestChart=IDY00030.${dateTime}.pdf
-#printf "latestChart filename: %s\n" ${latestChart}
+ echo "${nowDate}${fileTime}"
+}
-# -q no config file lookup
-# -f fail early
-# -s silent
-curl -q -fs -o ${latestChart} ftp://ftp.bom.gov.au/anon/gen/fwo/${latestChart}
-curlExit=$?
+dateTime=$(DeriveTime)
+latestChart="IDY00030.${dateTime}.pdf"
+# -q no config file lookup -f fail on error -s silent
+curlExit=0
+curl -q -fs -o "${latestChart}" "ftp://ftp.bom.gov.au/anon/gen/fwo/${latestChart}" \
+ || curlExit=$?
-if [ $curlExit -gt 0 ] ; then
- # Did we find a file? (Maybe it has not been created yet).
- if [ $curlExit -eq 78 ] ; then
- echo "No file at remote site $curlExit"
- # todo create a one-shot timer service
+if [ "$curlExit" -gt 0 ]; then
+ if [ "$curlExit" -eq 78 ]; then
+ echo "No file at remote site: ${latestChart} (curl exit ${curlExit})" >&2
fi
- exit $curlExit
+ exit "$curlExit"
fi
+magick -density 300 "${latestChart}" "${dateTime}.png"
-magick -density 300 ${latestChart} ${dateTime}.png
-
+mv "${latestChart}" "${RAW_DIR}/"
+cp "${dateTime}.png" "${ARCHIVE_DIR}/"
+mv "${dateTime}.png" "${LATEST}"
diff --git a/systemd/synoptic-retry.service b/systemd/synoptic-retry.service
new file mode 100644
index 0000000..ed46d41
--- /dev/null
+++ b/systemd/synoptic-retry.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Retry download and render BOM synoptic chart (after failure)
+
+[Service]
+Type=oneshot
+User=st33v
+WorkingDirectory=/var/lib/synoptic
+ExecStart=/opt/synoptic/synopticChart.sh
+ExecStopPost=/bin/sh -c 'STATUS=SUCCESS; [ "$$EXIT_STATUS" != "0" ] && STATUS=FAILURE; logger -t synoptic-retry -p user.err "synoptic-retry $$STATUS exit=$$EXIT_STATUS"'
+SyslogIdentifier=synoptic-retry
+StandardOutput=journal
+StandardError=journal
diff --git a/systemd/synoptic-retry.timer b/systemd/synoptic-retry.timer
new file mode 100644
index 0000000..fc93089
--- /dev/null
+++ b/systemd/synoptic-retry.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=Retry synoptic chart download 15 minutes after failure
+
+[Timer]
+OnActiveSec=15min
+
+[Install]
+WantedBy=timers.target
diff --git a/systemd/synoptic.service b/systemd/synoptic.service
new file mode 100644
index 0000000..33e7237
--- /dev/null
+++ b/systemd/synoptic.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Download and render BOM synoptic chart
+OnFailure=synoptic-retry.timer
+
+[Service]
+Type=oneshot
+User=st33v
+WorkingDirectory=/var/lib/synoptic
+ExecStart=/opt/synoptic/synopticChart.sh
+ExecStopPost=/bin/sh -c 'STATUS=SUCCESS; [ "$$EXIT_STATUS" != "0" ] && STATUS=FAILURE; logger -t synoptic -p user.err "synoptic $$STATUS exit=$$EXIT_STATUS"'
+SyslogIdentifier=synoptic
+StandardOutput=journal
+StandardError=journal
diff --git a/systemd/synoptic.timer b/systemd/synoptic.timer
new file mode 100644
index 0000000..4884078
--- /dev/null
+++ b/systemd/synoptic.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Run synoptic chart download at 02:10, 08:10, 14:10, 20:10 UTC
+
+[Timer]
+OnCalendar=*-*-* 02,08,14,20:10:00 UTC
+Persistent=true
+
+[Install]
+WantedBy=timers.target