Public Access
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
52 lines
2.2 KiB
Bash
Executable File
52 lines
2.2 KiB
Bash
Executable File
#!/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"
|