Two quick-reference documents, written to be scanned rather than read: - USER-GUIDE.md for people new to IRC -- connecting, claiming a nickname, the dozen commands that matter, scrollback, and a plain-language privacy section (cloaked IP, channels logged for the configured retention, how to turn off DM storage). - ADMIN-CHEATSHEET.md split by where you work: from IRC as an operator (UBAN, KILL, DEFCON, ChanServ, NickServ) and on the host via ergoctl, plus mode tables and a "when things go wrong" section. Both use the same placeholder convention as ergo.motd and are rendered by deploy.sh into $STACK_DIR/docs/ with the network's real name, domain and retention, so they can be handed straight to users and moderators. Refreshed on every run, like the other installed files. Command and mode references were checked against the v2.19.1 sources rather than written from memory: irc/modes/modes.go for every mode letter, and irc/chanserv.go and irc/nickserv.go for the service subcommands and which require an oper capability. build.sh's embed guard caught the docs being added to FILES without being added to deploy.sh's EMBEDDED manifest -- the exact failure it was added to prevent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
2.2 KiB
Bash
71 lines
2.2 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# build.sh -- (re)embed the loose deployment files into deploy.sh as a base64
|
|
# tar.gz payload after __ARCHIVE_BELOW__. Idempotent: strips any existing
|
|
# payload first.
|
|
#
|
|
# Run this after editing ANY embedded file below, then re-stage deploy.sh --
|
|
# the deployed stack uses the EMBEDDED copies, not the loose files.
|
|
|
|
set -euo pipefail
|
|
|
|
DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
SCRIPT="$DIR/deploy.sh"
|
|
MARKER="__ARCHIVE_BELOW__"
|
|
|
|
# README, cloud-init and the build/deploy scripts are NOT embedded. ircd.yaml is
|
|
# generated on the host from the pulled image's own default config.
|
|
FILES=(
|
|
docker-compose.yml
|
|
docker-compose.postgres.yml
|
|
Caddyfile
|
|
conf.d-readme.caddy
|
|
ergo.motd
|
|
USER-GUIDE.md
|
|
ADMIN-CHEATSHEET.md
|
|
.env.example
|
|
ergolib.sh
|
|
update.sh
|
|
ergoctl
|
|
)
|
|
|
|
[[ -f "$SCRIPT" ]] || { echo "deploy.sh not found at $SCRIPT" >&2; exit 1; }
|
|
for f in "${FILES[@]}"; do
|
|
[[ -f "$DIR/$f" ]] || { echo "Missing $DIR/$f" >&2; exit 1; }
|
|
done
|
|
|
|
# Guard: every file deploy.sh reads out of the extracted archive must be in
|
|
# FILES, and must be in deploy.sh's own EMBEDDED manifest. Forgetting either is
|
|
# a deploy-time abort on every host, so catch it here instead.
|
|
missing=0
|
|
while IFS= read -r ref; do
|
|
case " ${FILES[*]} " in *" $ref "*) ;; *) echo "deploy.sh reads \$SCRIPT_DIR/$ref but build.sh does not embed it" >&2; missing=1 ;; esac
|
|
done < <(grep -oE '\$SCRIPT_DIR/[A-Za-z0-9._-]+' "$SCRIPT" | sed 's|^\$SCRIPT_DIR/||' | sort -u)
|
|
for f in "${FILES[@]}"; do
|
|
grep -q "EMBEDDED=(.*$f" "$SCRIPT" || { echo "$f is embedded but missing from deploy.sh's EMBEDDED manifest" >&2; missing=1; }
|
|
done
|
|
(( missing == 0 )) || { echo "Refusing to build a deploy.sh that would abort on the target host." >&2; exit 1; }
|
|
|
|
# Syntax-check the bash payload before embedding it.
|
|
for f in ergolib.sh update.sh ergoctl deploy.sh; do
|
|
bash -n "$DIR/$f" || { echo "bash -n failed: $f" >&2; exit 1; }
|
|
done
|
|
|
|
PAYLOAD=$(tar -czf - -C "$DIR" "${FILES[@]}" | base64)
|
|
|
|
TMP=$(mktemp)
|
|
trap 'rm -f "$TMP"' EXIT
|
|
|
|
sed "/^${MARKER}\$/,\$d" "$SCRIPT" > "$TMP"
|
|
{
|
|
echo "$MARKER"
|
|
echo "$PAYLOAD"
|
|
} >> "$TMP"
|
|
|
|
mv "$TMP" "$SCRIPT"
|
|
chmod +x "$SCRIPT"
|
|
trap - EXIT
|
|
|
|
size=$(wc -c < "$SCRIPT")
|
|
echo "Built $SCRIPT (${size} bytes)"
|