Site: published by CI after a push to main and after a release (#79)
CI / build (pull_request) Successful in 1m20s
Site / build (pull_request) Successful in 11s

The Site workflow's last step, and the release workflow after publishing,
ask the web server over SSH to rebuild the site. The key CI holds is tied
on the server to one forced command (restrict,command=...), so CI sends no
command and a leaked key can only refresh the site. The server, the user,
the key and the server's host key are Gitea secrets; with none of them set
the step does nothing.

scripts/site_refresh.sh is what both workflows run;
scripts/site_deploy_keygen.sh makes the key and prints where each half goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-07 14:34:02 +02:00
co-authored by Claude Opus 5.5
parent 55c9ad2eb4
commit 12c88c98d3
6 changed files with 220 additions and 6 deletions
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Asks the web server to rebuild the site (issue #79, docs/milestones/W1.md). Run by CI after a push
# to main that changed the site, and after a release is published (the home page and Downloads
# name the latest release when they are built).
#
# It only connects: the server's authorized_keys line forces the one command this key may run, so
# nothing sent from here chooses what happens there. From the environment (Gitea secrets):
# SITE_DEPLOY_KEY the private key (scripts/site_deploy_keygen.sh makes it)
# SITE_DEPLOY_HOST the server, or server:port
# SITE_DEPLOY_USER the user there
# SITE_DEPLOY_KNOWN_HOSTS the server's host key, as a known_hosts line: nothing else is trusted
# With none of them set it does nothing (a fork, or before the key is installed); with only some, it fails.
set -euo pipefail
set_count=0
for v in SITE_DEPLOY_KEY SITE_DEPLOY_HOST SITE_DEPLOY_USER SITE_DEPLOY_KNOWN_HOSTS; do
[ -z "${!v:-}" ] || set_count=$((set_count + 1))
done
if [ "$set_count" = 0 ]; then
echo "site refresh: no SITE_DEPLOY_* secrets here, nothing done"
exit 0
fi
if [ "$set_count" != 4 ]; then
echo "site refresh: SITE_DEPLOY_KEY, _HOST, _USER and _KNOWN_HOSTS are needed, and only $set_count of them are set" >&2
exit 1
fi
if ! command -v ssh >/dev/null; then
apt-get update -qq
apt-get install -y -qq --no-install-recommends openssh-client >/dev/null
fi
host="$SITE_DEPLOY_HOST" port=22
case "$host" in
*:*) port="${host##*:}" host="${host%:*}" ;;
esac
# The key and the host key exist as files only while this runs, in a container that goes with the job.
umask 077
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
printf '%s\n' "$SITE_DEPLOY_KEY" > "$tmp/key"
printf '%s\n' "$SITE_DEPLOY_KNOWN_HOSTS" > "$tmp/known_hosts"
# -F none: no configuration but this line. -T and no command: the server's forced command runs.
ssh -F none -T -p "$port" -i "$tmp/key" \
-o IdentitiesOnly=yes -o BatchMode=yes \
-o StrictHostKeyChecking=yes -o UserKnownHostsFile="$tmp/known_hosts" -o GlobalKnownHostsFile=/dev/null \
-o ConnectTimeout=20 -o ServerAliveInterval=15 -o ServerAliveCountMax=8 \
"$SITE_DEPLOY_USER@$host"
echo "site refresh: done"