Files
automations/deployments/ergo/deploy.sh
T
57_WolveandClaude Opus 5 134736c082 fix(ergo): findings from reviewing the first live deploy
Seven confirmed findings from an observed-vs-expected review of a real deploy
transcript against the code (four other proposed findings were refuted and no
change was made for them).

- Caddyfile reformatted so `caddy fmt` is clean, removing the warning Caddy
  printed on every validate and every start. Two causes, not one: `caddy fmt`
  indents with TABS, and it deletes a blank line whose following line begins
  with `{` -- which is why the warning pointed at line 17, the blank before the
  global options block. The check is a whole-file byte comparison, so the line
  number was only the first difference and the entire file had to be
  reformatted. Verified whitespace-only outside the heredoc, whose body is left
  byte-identical: Caddy strips padding derived from the closing marker's
  indentation, so re-indenting it would change what the page serves.
- deploy.sh no longer upgrades Caddy behind the operator's back. A bare
  `docker compose pull` refreshed the floating `caddy:2-alpine` on every re-run
  and `up -d` then recreated it, doing exactly what CADDY_AUTOUPDATE=0 promises
  not to, with none of update.sh's health check or rollback. Pulls are now
  per service: the pinned Ergo tag always, Caddy only when absent or opted in.
- deploy.sh seeds the ACME_EMAIL and NETWORK_NAME prompts from .env, so pressing
  Enter through a re-run no longer renames the network to the hostname in the
  summary while .env keeps the real one.
- The Caddy restart guard compares the container's identity across `up -d`. A
  container compose created or recreated has already read the new Caddyfile;
  only one left running still holds the old config, and `svc_state` cannot tell
  those apart.
- Container logs are now rotated (json-file, 10m x 3) on every service. Alpine's
  docker package ships no daemon.json, so the default is unbounded, and the
  60-second health probe alone writes a log line per run.
- ergoctl notes that LUSERS counts its own probe connection, which is why a
  server with nobody on it reports one invisible user.

Verified: seven local suites pass, the embedded archive round-trips, line
endings are LF, and the reformatted Caddyfile is a verified fixed point of the
formatter (semantically identical token-for-token to the previous one).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 15:38:13 -05:00

1436 lines
92 KiB
Bash

#!/usr/bin/env bash
#
# deploy.sh -- deploy Ergo (IRC server) behind Caddy (Let's Encrypt) on Alpine,
# Debian or Alma. Single-node; runs as root.
#
# What this does:
# 1. Installs docker + compose (and openssl/jq/curl) if missing; creates the
# `ergo` system user the container runs as.
# 2. Lays down the stack in $STACK_DIR: docker-compose.yml, caddy/etc/Caddyfile,
# update.sh, ergoctl (+ /usr/local/bin/ergoctl wrapper), ergolib.sh.
# 3. Seeds .env on first run, pinning ERGO_TAG to the newest release.
# 4. Generates ircd/ircd.yaml ONCE from the pulled image's own default config
# (server name, network name, listeners, websocket origin, message-history
# backend, admin oper with a random password saved to secrets/admin.pass)
# and validates it with a throwaway `ergo run --smoke` before anything
# starts. Never rewritten.
# 5. Opens 80/443/6697 (+6667 with PLAINTEXT=1) on the host firewall. Both
# containers use host networking, so this firewall really applies.
# 6. Pulls images, validates the Caddyfile, brings the stack up, waits for
# health, copies Caddy's Let's Encrypt cert into ircd/ and rehashes Ergo.
# 7. Schedules update.sh: certsync every 15 min, update check daily.
#
# Idempotent: re-run to apply compose/Caddyfile changes or pull images. It never
# touches ircd/ircd.yaml, secrets/ or caddy/etc/conf.d/; in .env it only refreshes
# ERGO_UID/GID, re-pins a floating ERGO_TAG, and writes back settings you passed
# explicitly on this run (everything else is adopted FROM .env, not overwritten).
#
# Self-contained: docker-compose.yml, docker-compose.postgres.yml, Caddyfile,
# conf.d-readme.caddy, ergo.motd, .env.example, ergolib.sh, update.sh and ergoctl
# are embedded as a base64 tar.gz at the bottom of this file. Rebuild with
# build.sh after editing them.
#
# Usage:
# bash deploy.sh # interactive prompts
# ERGO_DOMAIN=irc.example.com ACME_EMAIL=me@x.com NETWORK_NAME=MyNet \
# SKIP_PROMPTS=1 bash deploy.sh # non-interactive
# HISTORY=postgres bash deploy.sh # FIRST deploy only: persistent history in
# # PostgreSQL (default sqlite; off = RAM only)
# HISTORY_EXPIRE=90d bash deploy.sh # how long messages are kept (default 30d)
# PLAINTEXT=1 bash deploy.sh # FIRST deploy only: also serve plaintext
# # :6667 publicly (+STS). Fixed thereafter.
# ERGO_TAG=v2.19.1 bash deploy.sh # pin a release on the FIRST deploy; after
# # that use: ergoctl update update
# UPDATE_POLICY=security bash deploy.sh # also latest | off
# ERGO_AUTOUPDATE=0 bash deploy.sh # install update.sh but don't schedule the
# # daily update (certsync is still scheduled)
# CERT_WAIT=0 bash deploy.sh # don't wait for the first LE cert
# SKIP_DOCKER_INSTALL=1 bash deploy.sh
set -euo pipefail
: "${STACK_DIR:=/srv/ergo}"
: "${SKIP_DOCKER_INSTALL:=0}"
: "${FORCE:=0}"
: "${SKIP_PROMPTS:=0}"
[[ "$SKIP_PROMPTS" == "1" ]] && FORCE=1
: "${ERGO_DOMAIN:=}"
: "${ACME_EMAIL:=}"
: "${NETWORK_NAME:=}"
: "${ERGO_IMAGE:=ghcr.io/ergochat/ergo}"
: "${ERGO_TAG:=}" # blank = pin the newest release
# Remember which settings the caller actually passed, BEFORE the defaults below
# hide that. On a re-run the rest come from the existing .env instead, so a
# plain `bash deploy.sh` never silently reverts a deployed stack's settings.
# (`|| true` on the trailing `&&`s below: a false test makes the whole list
# return 1, which aborts the script under `set -e` if it ever ends a block.)
EXPLICIT=""
for _k in ERGO_TAG PLAINTEXT HISTORY UPDATE_POLICY FORCE_UPDATE UPDATE_GRACE CADDY_AUTOUPDATE CADDY_TAG; do
[[ -n "${!_k:-}" ]] && EXPLICIT="${EXPLICIT} ${_k}" || true
done
: "${PLAINTEXT:=0}"
: "${HISTORY:=sqlite}" # sqlite | postgres | off (see the README)
# How long messages are kept. Upstream's 1w applies to PERSISTENT storage too --
# it deletes, it is not just a query cutoff -- so persistence with the shipped
# default buys only a week. Retention is a policy (and privacy) decision: raise
# or lower it here, or later with 'ergoctl edit'.
: "${HISTORY_EXPIRE:=30d}"
: "${POSTGRES_TAG:=17-alpine}" # major version is PINNED; update.sh never moves it
: "${POSTGRES_USER:=ergo}"
: "${POSTGRES_DB:=ergo_history}"
: "${POSTGRES_PORT:=5432}"
: "${UPDATE_POLICY:=latest}"
: "${FORCE_UPDATE:=0}"
: "${UPDATE_GRACE:=60}"
: "${CADDY_AUTOUPDATE:=0}"
: "${CADDY_TAG:=2-alpine}"
: "${ERGO_AUTOUPDATE:=1}" # 0 = install update.sh but don't schedule the daily update
: "${CERT_WAIT:=180}" # seconds to wait for Caddy's first Let's Encrypt cert
log() { printf '\033[1;32m[+]\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[!]\033[0m %s\n' "$*" >&2; }
die() { printf '\033[1;31m[x]\033[0m %s\n' "$*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || die "Run as root."
# ---------------------------------------------------------------------------
# Extract the embedded archive; ergolib.sh (shared helpers) comes from it.
# ---------------------------------------------------------------------------
SCRIPT_DIR=$(mktemp -d -t ergo-deploy.XXXXXX)
trap 'rm -rf "$SCRIPT_DIR"' EXIT
extract_archive() {
grep -a -A 9999999 '^__ARCHIVE_BELOW__$' "$0" \
| tail -n +2 \
| base64 -d \
| tar -xz -C "$SCRIPT_DIR"
}
if grep -q -a '^__ARCHIVE_BELOW__$' "$0"; then
log "Extracting embedded deployment files..."
extract_archive
else
die "No embedded archive found. Run build.sh to embed deployment files."
fi
EMBEDDED=(docker-compose.yml docker-compose.postgres.yml Caddyfile conf.d-readme.caddy ergo.motd .env.example ergolib.sh update.sh ergoctl)
for f in "${EMBEDDED[@]}"; do
[[ -f "$SCRIPT_DIR/$f" ]] || die "Embedded archive missing $f"
done
# shellcheck source=ergolib.sh
. "$SCRIPT_DIR/ergolib.sh"
ergo_set_paths
# ---------------------------------------------------------------------------
# Host packages + Docker (deploy-only helpers; ergolib has the rest)
# ---------------------------------------------------------------------------
pkg_install() { # best-effort install across the three families
case "$(osfam)" in
alpine) apk add -q "$@" || true ;;
debian) DEBIAN_FRONTEND=noninteractive apt-get install -y -qq "$@" || true ;;
rhel) dnf install -y -q "$@" || true ;;
esac
}
install_docker() {
if command -v docker >/dev/null 2>&1; then
log "Docker already installed: $(docker --version)"
else
log "Installing Docker (OS: $(osfam))..."
case "$(osfam)" in
alpine) apk add -q docker docker-cli-compose openrc ;;
debian|rhel) command -v curl >/dev/null 2>&1 || pkg_install curl
curl -fsSL https://get.docker.com | sh ;;
*) die "Unsupported OS for auto Docker install. Set SKIP_DOCKER_INSTALL=1 and install Docker yourself." ;;
esac
fi
if command -v rc-update >/dev/null 2>&1; then
rc-update add docker default >/dev/null 2>&1 || true
rc-service docker status >/dev/null 2>&1 || rc-service docker start
elif command -v systemctl >/dev/null 2>&1; then
systemctl enable --now docker >/dev/null 2>&1 || systemctl start docker || true
fi
# dockerd may return before its socket listens (esp. OpenRC); don't race it.
local i
for i in $(seq 1 30); do
docker info >/dev/null 2>&1 && return
sleep 1
done
warn "Docker daemon not ready after 30s; continuing (compose may fail -- check 'docker info')."
}
# The container runs as this host user (no login, no home). It owns ./ircd so
# the DB, config and the copied TLS key are never readable by other local users.
ensure_ergo_user() {
if ! getent passwd ergo >/dev/null 2>&1; then
log "Creating system user 'ergo' (owns $IRCD_DIR; the container runs as it)..."
case "$(osfam)" in
alpine) getent group ergo >/dev/null 2>&1 || addgroup -S ergo
adduser -S -D -H -G ergo -s /sbin/nologin -g "Ergo IRC server" ergo ;;
*) useradd -r -M -s /usr/sbin/nologin -d /nonexistent -c "Ergo IRC server" ergo 2>/dev/null \
|| useradd -r -M -s /sbin/nologin -c "Ergo IRC server" ergo ;;
esac
fi
ERGO_UID="$(id -u ergo)"; ERGO_GID="$(id -g ergo)"
}
open_ports() {
# Host networking: these ports are bound on the host itself, so the INPUT
# firewall genuinely governs them (unlike Docker-published ports).
local ports=(80/tcp 443/tcp 6697/tcp)
[[ "$PLAINTEXT" == "1" ]] && ports+=(6667/tcp)
# ufw and firewalld are additive: unlike the repo's declarative ports.d
# engine they never drop a port that left the list, so turning PLAINTEXT
# back off would leave 6667 open. Revoke it explicitly.
if [[ "$PLAINTEXT" != "1" ]]; then
if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q '^Status: active'; then
ufw status 2>/dev/null | grep -q '^6667/tcp' && { log "Closing 6667/tcp in ufw (PLAINTEXT=0)..."; ufw delete allow 6667/tcp >/dev/null 2>&1 || true; }
elif command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
if firewall-cmd --query-port=6667/tcp --permanent >/dev/null 2>&1; then
log "Closing 6667/tcp in firewalld (PLAINTEXT=0)..."
firewall-cmd -q --remove-port=6667/tcp --permanent || true; firewall-cmd -q --reload || true
fi
fi
fi
if [[ -d /etc/firewall/ports.d && -x /usr/local/sbin/firewall-apply ]]; then
log "Registering ${ports[*]} with the host firewall..."
printf '%s\n' "${ports[@]}" > /etc/firewall/ports.d/ergo.rule
/usr/local/sbin/firewall-apply
elif command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q '^Status: active'; then
log "ufw active -- allowing ${ports[*]}..."
local p; for p in "${ports[@]}"; do ufw allow "$p" >/dev/null; done
elif command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
log "firewalld active -- allowing ${ports[*]}..."
local p; for p in "${ports[@]}"; do firewall-cmd -q --add-port="$p" --permanent; done
firewall-cmd -q --reload
else
warn "No managed host firewall found; make sure ${ports[*]} are reachable (and nothing else is)."
fi
}
# Anything already listening on our host ports (only checked while our own
# containers are not running -- on re-runs they hold the ports themselves).
check_ports_free() {
local listing p busy=""
listing="$(netstat -ltn 2>/dev/null || ss -ltn 2>/dev/null || true)"
[[ -n "$listing" ]] || return 0
for p in 80 443 6697 8097 6667; do
if printf '%s\n' "$listing" | grep -qE "[:.]${p}[[:space:]]"; then busy="${busy} ${p}"; fi
done
[[ -z "$busy" ]] || die "Ports already in use on this host:${busy}. Both containers use host networking, so this stack needs 80/443 (Caddy), 6697/6667/8097 (Ergo) to itself. Another Caddy stack on this box? Move it or this."
}
# ---------------------------------------------------------------------------
# Prompt for required vars, then normalise + validate them
# ---------------------------------------------------------------------------
prompt() { # <VAR> <message> [default]
local varname="$1" message="$2" def="${3:-}"
local -n ref="$varname"
if [[ -z "${ref:-}" ]]; then
if [[ "$SKIP_PROMPTS" == "1" ]]; then
[[ -n "$def" ]] && { ref="$def"; return 0; }
die "$varname required (set it in the environment; running with SKIP_PROMPTS=1)."
fi
if [[ -n "$def" ]]; then read -r -p "$message [$def]: " ref; ref="${ref:-$def}"
else read -r -p "$message: " ref; fi
[[ -n "$ref" ]] || die "$varname required."
fi
}
prompt ERGO_DOMAIN "Public hostname of the IRC server (e.g. irc.example.com)"
ERGO_DOMAIN="$(printf '%s' "$ERGO_DOMAIN" | tr 'A-Z' 'a-z' | sed -E 's#^https?://##; s#[/.]+$##')"
[[ "$ERGO_DOMAIN" =~ ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$ ]] \
|| die "ERGO_DOMAIN '$ERGO_DOMAIN' is not a valid hostname."
# On a re-run these must default to what is DEPLOYED, not to a fresh guess:
# otherwise pressing Enter through the prompts silently renames the network to the
# hostname in the summary while .env keeps the real one. Test for emptiness --
# env_get succeeds even when the key is absent.
_ae_default="$(env_get ACME_EMAIL)"
_nn_default="$(env_get NETWORK_NAME)"
[[ -n "$_nn_default" ]] || _nn_default="$ERGO_DOMAIN"
prompt ACME_EMAIL "Let's Encrypt email" "$_ae_default"
prompt NETWORK_NAME "IRC network name (no spaces)" "$_nn_default"
[[ "$NETWORK_NAME" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ]] \
|| die "NETWORK_NAME '$NETWORK_NAME' must be 1-64 chars of letters, digits, . _ - (no spaces: it is sent as an IRC parameter)."
[[ "$PLAINTEXT" == "0" || "$PLAINTEXT" == "1" ]] || die "PLAINTEXT must be 0 or 1."
case "$UPDATE_POLICY" in latest|security|off) ;; *) die "UPDATE_POLICY must be latest, security or off." ;; esac
case "$HISTORY" in sqlite|postgres|off) ;; *) die "HISTORY must be sqlite, postgres or off." ;; esac
# Re-run guard: server.name is immutable once Ergo has run with it, and the
# cert/websocket origin/Caddy site all derive from ERGO_DOMAIN.
if [[ -f "$IRCD_DIR/ircd.yaml" ]]; then
existing="$(yaml_server_name "$IRCD_DIR/ircd.yaml" || true)"
if [[ -n "$existing" && "$existing" != "$ERGO_DOMAIN" ]]; then
die "This stack is already deployed as '$existing' (ircd/ircd.yaml server.name) but ERGO_DOMAIN=$ERGO_DOMAIN. Ergo cannot rename a running server; re-run with ERGO_DOMAIN=$existing, or stop the stack, move $STACK_DIR away and deploy fresh."
fi
fi
# ---------------------------------------------------------------------------
# Re-run: adopt the deployed settings from .env
#
# Everything below (the firewall rule, the scheduled jobs, the summary) must
# describe the stack as deployed, not this shell's defaults. A setting the
# caller passed explicitly wins and is written back; PLAINTEXT is the exception,
# because the listener it selects lives in ircd.yaml, which is never rewritten.
# ---------------------------------------------------------------------------
if [[ -f "$ENV_FILE" ]]; then
for _k in PLAINTEXT HISTORY UPDATE_POLICY FORCE_UPDATE UPDATE_GRACE CADDY_AUTOUPDATE CADDY_TAG POSTGRES_TAG POSTGRES_USER POSTGRES_DB POSTGRES_PORT; do
_v="$(env_get "$_k")"
[[ -n "$_v" ]] || continue
if [[ " $EXPLICIT " == *" $_k "* ]]; then
[[ "${!_k}" == "$_v" ]] && continue
if [[ "$_k" == "HISTORY" ]]; then
die "This stack was deployed with HISTORY=${_v} and you passed HISTORY=${!_k}. The backend is recorded in ircd/ircd.yaml, which deploy.sh never rewrites, so re-running cannot switch it (and switching does not migrate existing messages). To change it: 'ergoctl history ${!_k}'."
fi
if [[ "$_k" == "PLAINTEXT" ]]; then
die "This stack was deployed with PLAINTEXT=${_v} and you passed PLAINTEXT=${!_k}. The listener is fixed in ircd/ircd.yaml, which deploy.sh never rewrites, so re-running cannot change it. To switch: edit the plaintext listener with 'ergoctl edit' ($( [[ "$_v" == 1 ]] && echo '":6667": -> "127.0.0.1:6667":' || echo '"127.0.0.1:6667": -> ":6667":' ) and server.sts.enabled), set PLAINTEXT=${!_k} in $ENV_FILE, run 'ergoctl restart', then re-run this script to fix the firewall."
fi
log "${_k}: ${_v} -> ${!_k} (updating $ENV_FILE)."
else
printf -v "$_k" '%s' "$_v"
fi
done
[[ "$PLAINTEXT" == "0" || "$PLAINTEXT" == "1" ]] || die "PLAINTEXT in $ENV_FILE must be 0 or 1 (found '$PLAINTEXT')."
case "$UPDATE_POLICY" in latest|security|off) ;; *) die "UPDATE_POLICY in $ENV_FILE must be latest, security or off (found '$UPDATE_POLICY')." ;; esac
fi
# ---------------------------------------------------------------------------
# Host prerequisites
# ---------------------------------------------------------------------------
[[ "$SKIP_DOCKER_INSTALL" == "1" ]] || install_docker
for tool in openssl jq curl; do
command -v "$tool" >/dev/null 2>&1 || { log "Installing $tool..."; pkg_install "$tool"; }
command -v "$tool" >/dev/null 2>&1 || die "$tool is required (certsync/updater); install it and re-run."
done
command -v docker >/dev/null 2>&1 || die "docker not found."
docker compose version >/dev/null 2>&1 || die "docker compose (v2 plugin) not found."
ensure_ergo_user
# Other host-network containers share Ergo's trust boundary (its loopback).
docker info >/dev/null 2>&1 || die "The Docker daemon is not running or not reachable (check 'docker info'). Start it and re-run."
others="$(docker ps -q 2>/dev/null | xargs -r docker inspect -f '{{.Name}} {{.HostConfig.NetworkMode}}' 2>/dev/null \
| awk '$2=="host" && $1!="/ergo" && $1!="/ergo-caddy" {print $1}' | tr '\n' ' ' || true)"
[[ -z "$others" ]] || warn "Other containers use host networking: ${others}-- they can reach Ergo's loopback listeners (see README: Security model)."
if [[ -z "$(dc ps -q 2>/dev/null || true)" ]]; then check_ports_free; fi
open_ports
# ---------------------------------------------------------------------------
# Stack directory + files
# ---------------------------------------------------------------------------
log "Setting up $STACK_DIR..."
install -d -m 0700 "$STACK_DIR" "$SECRETS_DIR" "$BACKUP_DIR" "$TEMPLATES_DIR" "$STATE_DIR"
install -d -m 0700 "$CADDY_DIR" "$CADDY_DIR/data" "$CADDY_DIR/config"
install -d -m 0755 "$CADDY_DIR/etc" "$CADDY_DIR/etc/conf.d"
install -m 0640 "$SCRIPT_DIR/docker-compose.yml" "$STACK_DIR/docker-compose.yml"
install -m 0640 "$SCRIPT_DIR/docker-compose.postgres.yml" "$STACK_DIR/docker-compose.postgres.yml"
# Caddy has no admin API here and bind-mounted file contents are not part of the
# compose config hash, so `up -d` alone would leave a changed Caddyfile unloaded.
# Only an ACTUAL change counts: on a first deploy the destination does not exist
# yet, and restarting Caddy seconds after it started would interrupt the very
# first ACME issuance for nothing.
CADDY_CHANGED=0
if [[ -f "$CADDY_DIR/etc/Caddyfile" ]] && ! cmp -s "$SCRIPT_DIR/Caddyfile" "$CADDY_DIR/etc/Caddyfile"; then
CADDY_CHANGED=1
fi
install -m 0644 "$SCRIPT_DIR/Caddyfile" "$CADDY_DIR/etc/Caddyfile"
[[ -e "$CADDY_DIR/etc/conf.d/00-readme.caddy" ]] || install -m 0644 "$SCRIPT_DIR/conf.d-readme.caddy" "$CADDY_DIR/etc/conf.d/00-readme.caddy"
install -m 0644 "$SCRIPT_DIR/ergolib.sh" "$STACK_DIR/ergolib.sh"
install -m 0750 "$SCRIPT_DIR/update.sh" "$STACK_DIR/update.sh"
install -m 0750 "$SCRIPT_DIR/ergoctl" "$STACK_DIR/ergoctl"
install -d -m 0755 /usr/local/bin
cat > /usr/local/bin/ergoctl <<EOF
#!/bin/sh
# Auto-generated by the Ergo deploy.sh -- runs the stack's admin CLI from anywhere.
exec bash "$STACK_DIR/ergoctl" "\$@"
EOF
chmod 0755 /usr/local/bin/ergoctl
install -d -m 0700 -o "$ERGO_UID" -g "$ERGO_GID" "$IRCD_DIR"
# Pin ERGO_TAG to the newest release so the running version is explicit.
if [[ -z "$ERGO_TAG" && -f "$ENV_FILE" ]]; then ERGO_TAG="$(env_get ERGO_TAG)"; fi
if [[ -z "$ERGO_TAG" || "$ERGO_TAG" == "latest" || "$ERGO_TAG" == "stable" ]]; then
if _t="$(ergo_latest_tag)"; then ERGO_TAG="$_t"; log "Pinned ERGO_TAG=${ERGO_TAG} (newest release)."
else warn "Could not resolve the newest release from GitHub; using tag 'stable' for now (update.sh will pin it)."; ERGO_TAG="stable"; fi
fi
[[ "$ERGO_TAG" == "stable" || "$ERGO_TAG" == v* ]] || ERGO_TAG="v${ERGO_TAG}" # ghcr tags carry the v
if [[ ! -f "$ENV_FILE" ]]; then
log "Seeding $ENV_FILE..."
install -m 0600 "$SCRIPT_DIR/.env.example" "$ENV_FILE"
env_set ERGO_DOMAIN "$ERGO_DOMAIN"
env_set ACME_EMAIL "$ACME_EMAIL"
env_set NETWORK_NAME "$NETWORK_NAME"
env_set ERGO_IMAGE "$ERGO_IMAGE"
env_set ERGO_TAG "$ERGO_TAG"
env_set PLAINTEXT "$PLAINTEXT"
env_set HISTORY "$HISTORY"
env_set UPDATE_POLICY "$UPDATE_POLICY"
env_set FORCE_UPDATE "$FORCE_UPDATE"
env_set UPDATE_GRACE "$UPDATE_GRACE"
env_set CADDY_AUTOUPDATE "$CADDY_AUTOUPDATE"
env_set CADDY_TAG "$CADDY_TAG"
else
log ".env exists; keeping its settings (ERGO_TAG=$(env_get ERGO_TAG))."
[[ "$(ergo_domain)" == "$ERGO_DOMAIN" ]] || die ".env has ERGO_DOMAIN=$(env_get ERGO_DOMAIN) but you passed $ERGO_DOMAIN -- the domain cannot change after the first deploy."
# Persist the settings the caller passed explicitly on this re-run.
for _k in PLAINTEXT UPDATE_POLICY FORCE_UPDATE UPDATE_GRACE CADDY_AUTOUPDATE CADDY_TAG; do
[[ " $EXPLICIT " == *" $_k "* ]] && env_set "$_k" "${!_k}" || true
done
# A floating tag ('stable', from a first deploy that could not reach GitHub)
# would let any pull change the running version with no pre-flight, snapshot
# or rollback. Pin it as soon as we can resolve a real release.
_envtag="$(env_get ERGO_TAG)"
if [[ "$ERGO_TAG" == v[0-9]* && "$ERGO_TAG" != "$_envtag" ]]; then
case "$_envtag" in
# Changing the version of a DEPLOYED stack here would swap the image
# with none of the updater's rails: no pre-flight against the live
# config, no database snapshot, no warning to connected users and no
# rollback if the new build never becomes healthy. Send them there.
v[0-9]*) die "This stack is pinned to ${_envtag} and you passed ERGO_TAG=${ERGO_TAG}. Re-running deploy.sh would swap the image with no pre-flight, no database snapshot and no rollback. Use: TARGET_VERSION=$(normver "$ERGO_TAG") ergoctl update update" ;;
*) env_set ERGO_TAG "$ERGO_TAG"; log "Pinned ERGO_TAG=${ERGO_TAG} (was '${_envtag}', which floats)." ;;
esac
fi
fi
env_set ERGO_UID "$ERGO_UID"
env_set ERGO_GID "$ERGO_GID"
ERGO_TAG="$(ergo_tag)"
IMAGE="$(ergo_image)"
# ---------------------------------------------------------------------------
# Persistent history backend
#
# Ergo's history is ON by default but lives in RAM, so it is lost on every
# restart -- including the ones this stack's updater performs. sqlite persists
# it in a file beside ircd.db with no extra moving parts; postgres adds a
# pinned container for people who want a real database.
# ---------------------------------------------------------------------------
if [[ "$HISTORY" != "off" ]]; then
# Both SQL history backends were added in Ergo 2.18.0.
_v="$(normver "$ERGO_TAG")"
if [[ -n "$_v" ]] && ! ver_ge "$_v" 2.18.0; then
die "HISTORY=$HISTORY needs Ergo 2.18.0 or newer (the SQL history backends were added there), but ERGO_TAG=$ERGO_TAG. Use HISTORY=off or a newer release."
fi
fi
if [[ "$HISTORY" == "postgres" ]]; then
env_set POSTGRES_TAG "$POSTGRES_TAG"
env_set POSTGRES_USER "$POSTGRES_USER"
env_set POSTGRES_DB "$POSTGRES_DB"
env_set POSTGRES_PORT "$POSTGRES_PORT"
# docker compose reads COMPOSE_FILE from .env, so every compose command in
# this stack picks up the overlay without needing extra flags.
env_set COMPOSE_FILE "docker-compose.yml:docker-compose.postgres.yml"
if [[ ! -f "$SECRETS_DIR/postgres.pass" ]]; then
log "Generating the PostgreSQL password (secrets/postgres.pass)..."
( umask 077; ergo_random_password 32 > "$SECRETS_DIR/postgres.pass" )
fi
chmod 0600 "$SECRETS_DIR/postgres.pass"
PG_PASS="$(cat "$SECRETS_DIR/postgres.pass")"
else
env_set COMPOSE_FILE "docker-compose.yml"
fi
missing=()
for var in ERGO_DOMAIN ACME_EMAIL NETWORK_NAME ERGO_TAG ERGO_UID ERGO_GID; do
grep -E "^${var}=.+$" "$ENV_FILE" >/dev/null || missing+=("$var")
done
(( ${#missing[@]} == 0 )) || die "Missing values in $ENV_FILE: ${missing[*]}"
# ---------------------------------------------------------------------------
# Pull images, validate the Caddyfile (static config -- no admin API needed)
# ---------------------------------------------------------------------------
cd "$STACK_DIR"
# Pull per service. ERGO_TAG is an immutable vX.Y.Z, so pulling it is a no-op
# after the first time. caddy's tag FLOATS, and a bare `docker compose pull`
# would adopt a newer Caddy on every re-run and let `up -d` recreate it --
# silently doing what CADDY_AUTOUPDATE=0 promises not to, with none of
# update.sh's health check or rollback. Only pull it when it is missing, or when
# the operator opted in.
log "Pulling $IMAGE..."
docker compose pull ergo
_caddy_tag="$(env_get CADDY_TAG)"; _caddy_tag="${_caddy_tag:-2-alpine}"
if [[ "$CADDY_AUTOUPDATE" == "1" ]] || ! docker image inspect "caddy:${_caddy_tag}" >/dev/null 2>&1; then
log "Pulling caddy:${_caddy_tag}..."
docker compose pull caddy
else
log "Keeping the local caddy:${_caddy_tag} (CADDY_AUTOUPDATE=0; update it with 'ergoctl update caddy')."
fi
if [[ "$HISTORY" == "postgres" ]]; then docker compose pull postgres; fi
log "Validating the Caddyfile..."
# A one-off `compose run` container gets a generated name (compose drops the
# service's container_name for these), so this is safe while ergo-caddy runs.
docker compose run --rm --no-deps -T caddy \
caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null \
|| die "Caddyfile validation failed. Check $CADDY_DIR/etc/Caddyfile and conf.d/*.caddy."
# ---------------------------------------------------------------------------
# First run: generate ircd.yaml from the image's own default config
# ---------------------------------------------------------------------------
render_ircd_yaml() { # <template> <dest>
local plain_listener sts_note netname="" listeners ws
# Cloaked hostnames end in this fake TLD (default "irc"). Use the network's
# first label when it is hostname-shaped; changing it later re-cloaks everyone.
netname="$(printf '%s' "$NETWORK_NAME" | tr 'A-Z' 'a-z' | cut -d. -f1)"
[[ "$netname" =~ ^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$ ]] || netname=""
if [[ "$PLAINTEXT" == "1" ]]; then
plain_listener=' # PLAINTEXT=1: plaintext IRC on ALL interfaces. STS is advertised (server.sts)
# so capable clients pin TLS after first contact. Anything sent here crosses
# the internet unencrypted. Loopback probes (ergoctl, healthcheck) use it too.
":6667":'
else
plain_listener=' # Loopback plaintext: the compose healthcheck and `ergoctl` use it (loopback is
# exempt from ip-limits/bans and treated as secure). To serve plaintext publicly
# instead (not recommended): change this to ":6667", enable server.sts above, set
# PLAINTEXT=1 in ../.env, `ergoctl restart`, then re-run deploy.sh for the firewall.
"127.0.0.1:6667":'
fi
listeners=" listeners:
${plain_listener}
# Public TLS port. fullchain.pem/privkey.pem are Caddy's Let's Encrypt cert,
# kept current by 'update.sh certsync' (self-signed from mkcerts until the
# first sync). Rehash (SIGHUP) reloads them without dropping anyone.
\":6697\":
tls:
cert: fullchain.pem
key: privkey.pem
proxy: false
min-tls-version: 1.2
# IRC over WebSocket for browser clients; TLS is terminated by Caddy on :443
# (wss://${ERGO_DOMAIN}/webirc), which proxies here over loopback with
# X-Forwarded-For -- trusted because 127.0.0.1 is in proxy-allowed-from.
\"127.0.0.1:8097\":
websocket: true
"
ws=" websockets:
# Only pages served from these origins may open a websocket (anchored,
# case-sensitive globs). Add the origin of any web client you host elsewhere.
# Non-browser clients should use :6697 directly.
allowed-origins:
- \"https://${ERGO_DOMAIN}\"
"
MARKER="# Generated by deployments/ergo/deploy.sh on $(date -u +%FT%TZ) from the ${IMAGE} default config.
# Edit freely; apply with 'ergoctl rehash' (or 'ergoctl edit', which validates first).
# server.name, datastore.path, casemapping and enforce-utf8 need 'ergoctl restart'.
# The pristine template is kept in ../templates/ for diffing after upgrades." \
DOMAIN="$ERGO_DOMAIN" NETWORK_NAME="$NETWORK_NAME" HASH="$ADMIN_HASH" PLAINTEXT="$PLAINTEXT" \
NETNAME="$netname" LISTENERS_BLOCK="$listeners" WS_BLOCK="$ws" \
awk '
BEGIN { print ENVIRON["MARKER"]; top=""; sub4=""; oper=""; skip=0 }
{
line=$0
# while replacing a 4-space block, drop its children (8+ spaces) and blanks
if (skip) { if (line ~ /^ / || line ~ /^[ \t]*$/) next; skip=0 }
if (line ~ /^[a-z][a-z-]*:/) { top=line; sub(/:.*/,"",top); sub4=""; oper="" }
if (top=="server") {
if (line ~ /^ [a-z"-]/) { sub4=line; sub(/^ /,"",sub4); sub(/:.*/,"",sub4) }
if (line ~ /^ name:/) { print " name: " ENVIRON["DOMAIN"]; next }
if (line ~ /^ listeners:/) { printf "%s", ENVIRON["LISTENERS_BLOCK"]; skip=1; next }
if (line ~ /^ websockets:/) { printf "%s", ENVIRON["WS_BLOCK"]; skip=1; next }
if (sub4=="sts" && ENVIRON["PLAINTEXT"]=="1" && line ~ /^ enabled: false/) { print " enabled: true"; next }
if (sub4=="ip-cloaking" && ENVIRON["NETNAME"]!="" && line ~ /^ netname:/) { print " netname: \"" ENVIRON["NETNAME"] "\""; next }
}
if (top=="network" && line ~ /^ name:/) { print " name: \"" ENVIRON["NETWORK_NAME"] "\""; next }
if (top=="opers") {
if (line ~ /^ [A-Za-z0-9_.-]+:/) { oper=line; sub(/^ /,"",oper); sub(/:.*/,"",oper) }
if (oper=="admin" && line ~ /^ password:/) { print " password: \"" ENVIRON["HASH"] "\""; next }
}
if (top=="languages" && line ~ /^ path: languages/) { print " path: /ircd-bin/languages"; next }
print line
}' "$1" > "$2"
}
assert_ircd_yaml() { # hard post-conditions -- a silent sed miss would be a public :6667 or a dead admin oper
local f="$1" fail=0
_chk() { if ! grep -qE -- "$1" "$f"; then warn "ircd.yaml check failed: expected $2"; fail=1; fi; }
_nochk() { if grep -qE -- "$1" "$f"; then warn "ircd.yaml check failed: unexpected $2"; fail=1; fi; }
_chk '^ name: '"$ERGO_DOMAIN"'$' "server.name = $ERGO_DOMAIN"
_chk '^ name: "'"$NETWORK_NAME"'"$' "network.name"
_chk '^ ":6697":' "TLS listener :6697"
_chk '^ "127.0.0.1:8097":' "websocket listener"
_chk '^ - "https://'"$ERGO_DOMAIN"'"$' "websocket allowed origin"
_chk '^ password: "\$2[ab]\$' "admin oper bcrypt hash"
_nochk '^ password: "\$2a\$04\$0123456789abcdef' "placeholder oper hash still active (the commented examples are fine)"
_nochk '"\[::1\]:6667"' "[::1] listener (fails on IPv6-less hosts)"
_chk '^ path: /ircd-bin/languages' "languages path"
_nochk '^ path: languages$' "unpatched languages path"
if [[ "$PLAINTEXT" == "1" ]]; then _chk '^ ":6667":' "public plaintext listener"; _nochk '^ "127.0.0.1:6667":' "loopback-only listener with PLAINTEXT=1"
else _chk '^ "127.0.0.1:6667":' "loopback plaintext listener"; _nochk '^ ":6667":' "PUBLIC plaintext listener with PLAINTEXT=0"; fi
# The history backend must be exactly the one asked for -- yaml_set_nested
# targets a specific block, so a wrong result means the template moved.
local got; got="$(history_backend "$f")"
if [[ "$got" != "$HISTORY" ]]; then warn "ircd.yaml check failed: history backend is '$got', expected '$HISTORY'"; fail=1; fi
(( fail == 0 ))
}
CONF="$IRCD_DIR/ircd.yaml"
FIRST_RUN=0
if [[ ! -f "$CONF" ]]; then
FIRST_RUN=1
log "Generating $CONF from the image's default config..."
TEMPLATE="$TEMPLATES_DIR/default.yaml.${ERGO_TAG}"
ergo_extract_template "$IMAGE" "$TEMPLATE" || die "Could not read /ircd-bin/default.yaml from $IMAGE."
chmod 0600 "$TEMPLATE"
# Admin oper: random password (plaintext 0600 on the host, hash in the yaml).
ADMIN_PW="$(ergo_random_password 24)"
ADMIN_HASH="$(ergo_genpasswd "$IMAGE" "$ADMIN_PW")" || die "ergo genpasswd did not return a bcrypt hash."
( umask 077; printf '%s\n' "$ADMIN_PW" > "$ADMIN_PASS_FILE" )
render_ircd_yaml "$TEMPLATE" "$CONF"
# Persistent history. Ergo keeps the in-memory limits (channel-length etc.)
# for the RAM backend; with persistence on, retention is governed by
# history.restrictions.expire-time (1w by default).
if [[ "$HISTORY" != "off" && -n "$HISTORY_EXPIRE" ]]; then
yaml_set_nested "$CONF" history restrictions expire-time "$HISTORY_EXPIRE" \
|| die "Could not set history.restrictions.expire-time."
log "Message retention: ${HISTORY_EXPIRE} (history.restrictions.expire-time)."
fi
case "$HISTORY" in
sqlite)
log "Enabling persistent history (SQLite: ircd/ergo_history.db)..."
yaml_set_nested "$CONF" datastore sqlite enabled true || die "Could not enable datastore.sqlite in the generated config."
yaml_set_nested "$CONF" history persistent enabled true || die "Could not enable history.persistent in the generated config." ;;
postgres)
log "Enabling persistent history (PostgreSQL on 127.0.0.1:${POSTGRES_PORT})..."
yaml_set_nested "$CONF" datastore postgresql enabled true || die "Could not enable datastore.postgresql."
yaml_set_nested "$CONF" datastore postgresql host "\"127.0.0.1\"" || die "Could not set the postgresql host."
yaml_set_nested "$CONF" datastore postgresql port "$POSTGRES_PORT" || die "Could not set the postgresql port."
yaml_set_nested "$CONF" datastore postgresql user "\"${POSTGRES_USER}\"" || die "Could not set the postgresql user."
yaml_set_nested "$CONF" datastore postgresql password "\"${PG_PASS}\"" || die "Could not set the postgresql password."
yaml_set_nested "$CONF" datastore postgresql history-database "\"${POSTGRES_DB}\"" || die "Could not set the postgresql database."
yaml_set_nested "$CONF" history persistent enabled true || die "Could not enable history.persistent." ;;
off)
log "Persistent history disabled (HISTORY=off): messages stay in RAM and are lost on restart." ;;
esac
assert_ircd_yaml "$CONF" || { rm -f "$CONF"; die "Generated ircd.yaml failed its checks (the upstream template layout changed?). Nothing started. Template kept at $TEMPLATE."; }
# MOTD: the bind mount hides the image's ergo.motd, and a missing MOTD is silently
# ignored (clients get ERR_NOMOTD) -- so always ship one.
sed -e "s|__NETWORK_NAME__|${NETWORK_NAME}|g" -e "s|__DOMAIN__|${ERGO_DOMAIN}|g" "$SCRIPT_DIR/ergo.motd" > "$IRCD_DIR/ergo.motd"
chmod 0600 "$CONF"; chmod 0644 "$IRCD_DIR/ergo.motd"
chown -R "$ERGO_UID:$ERGO_GID" "$IRCD_DIR"
log "Validating the generated config (ergo run --smoke in a throwaway container)..."
if ! ergo_validate_config "$IMAGE"; then
tail -n 20 "$VALIDATE_LOG" >&2 || true
rm -f "$CONF"
die "ircd.yaml did not load in $IMAGE. Nothing started; fix the cause above and re-run."
fi
rm -f "$VALIDATE_LOG"
else
log "$CONF exists; leaving it alone."
chown -R "$ERGO_UID:$ERGO_GID" "$IRCD_DIR"
fi
ADMIN_PW="$(head -n1 "$ADMIN_PASS_FILE" 2>/dev/null || echo '<not on file>')"
# Only put the password on screen for a human at a terminal, and only on the run
# that created it. Unattended paths (cloud-init) send stdout to the provider's
# serial console and /var/log/cloud-init-output.log, where a server-admin oper
# credential would sit indefinitely, readable by anyone with console access.
if [[ "$FIRST_RUN" == "1" && -t 1 ]]; then
ADMIN_PW_LINE="/OPER admin ${ADMIN_PW} (also in ${ADMIN_PASS_FILE})"
else
ADMIN_PW_LINE="see ${ADMIN_PASS_FILE}, or run: ergoctl passwd show"
fi
# ---------------------------------------------------------------------------
# Confirm
# ---------------------------------------------------------------------------
if [[ "$FORCE" != "1" ]]; then
cat <<EOF
About to start the Ergo stack from $STACK_DIR (host networking).
Caddy will request a Let's Encrypt cert for ${ERGO_DOMAIN}. DNS for that name must
already point at this host and ports 80/443 must be reachable from the internet.
IRC clients connect on 6697 (TLS)$( [[ "$PLAINTEXT" == "1" ]] && printf ' and 6667 (PLAINTEXT -- credentials in clear)' ).
Continue? [y/N]
EOF
read -r ans
[[ "${ans,,}" == "y" || "${ans,,}" == "yes" ]] || { warn "Aborted."; exit 0; }
fi
# ---------------------------------------------------------------------------
# Up + health
# ---------------------------------------------------------------------------
log "Starting stack..."
# A container compose CREATES or RECREATES has already read the new Caddyfile, so
# only the one it left alone still holds the old config. Compare the container's
# identity across `up -d` to tell those apart -- `svc_state` says "running" in
# both cases.
_caddy_cid_before="$(docker inspect -f '{{.Id}}' ergo-caddy 2>/dev/null || true)"
docker compose up -d --remove-orphans
_caddy_cid_after="$(docker inspect -f '{{.Id}}' ergo-caddy 2>/dev/null || true)"
if (( CADDY_CHANGED )) && [[ -n "$_caddy_cid_before" && "$_caddy_cid_before" == "$_caddy_cid_after" ]] \
&& [[ "$(svc_state caddy)" == running* ]]; then
log "Caddyfile changed; restarting Caddy to load it..."
docker compose restart caddy >/dev/null 2>&1 || warn "Could not restart Caddy; run 'ergoctl caddy-restart'."
fi
log "Waiting for services to become healthy..."
if [[ "$HISTORY" == "postgres" ]]; then
# Ergo refuses to start when its history backend is unreachable, and
# depends_on holds it back until this passes.
if wait_healthy postgres 120; then log "PostgreSQL is ready."
else docker compose logs --tail 20 postgres >&2 || true
die "PostgreSQL did not become healthy; Ergo cannot start without it. See the log above."; fi
fi
wait_healthy caddy 60 || warn "Caddy is not healthy yet (docker compose logs caddy)."
if ! wait_healthy ergo 120; then
docker compose logs --tail 30 ergo >&2 || true
die "Ergo did not become healthy. See the log above."
fi
log "Ergo is up ($(ergo_version_running))."
# ---------------------------------------------------------------------------
# TLS: wait for Caddy's cert, copy it into ircd/, rehash
# ---------------------------------------------------------------------------
log "Waiting up to ${CERT_WAIT}s for Caddy to obtain the Let's Encrypt certificate..."
deadline=$(( $(date +%s) + CERT_WAIT ))
have_cert=0
while (( $(date +%s) < deadline )); do
if ergo_cert_source >/dev/null 2>&1; then have_cert=1; break; fi
sleep 5
done
if [[ "$have_cert" == 1 ]]; then
sleep 2 # let certmagic finish writing the .json sidecar
bash "$STACK_DIR/update.sh" certsync || warn "Cert sync did not complete; the 15-minute job will retry."
else
warn "No certificate from Caddy yet (DNS not pointing here, or 80/443 unreachable?)."
warn "Ergo is serving a SELF-SIGNED cert on 6697 until certsync succeeds (every 15 min). Check: docker compose logs caddy"
fi
# ---------------------------------------------------------------------------
# Schedule certsync (15 min) + the daily update check
# ---------------------------------------------------------------------------
log "Installing scheduled jobs (certsync every 15 min; daily update check, policy=${UPDATE_POLICY})..."
STACK_DIR="$STACK_DIR" UPDATE_POLICY="$UPDATE_POLICY" FORCE_UPDATE="$FORCE_UPDATE" UPDATE_GRACE="$UPDATE_GRACE" \
CADDY_AUTOUPDATE="$CADDY_AUTOUPDATE" SCHEDULE_UPDATES="$ERGO_AUTOUPDATE" \
bash "$STACK_DIR/update.sh" install || warn "Scheduling failed (non-fatal): run '$STACK_DIR/update.sh install' by hand."
echo
log "Stack status:"
docker compose ps
echo
cat <<EOF
================================================================
DEPLOYED -- Ergo IRC server
Network: ${NETWORK_NAME}
Server: ${ERGO_DOMAIN} port 6697 (TLS)$( [[ "$PLAINTEXT" == "1" ]] && printf ', port 6667 (plaintext)' )
WebSocket: wss://${ERGO_DOMAIN}/webirc (landing page: https://${ERGO_DOMAIN})
Stack dir: ${STACK_DIR}
Oper login: ${ADMIN_PW_LINE}
(rotate with: ergoctl passwd rotate)
Config: ${IRCD_DIR}/ircd.yaml MOTD: ${IRCD_DIR}/ergo.motd
ergoctl edit / ergoctl motd (validates, then rehashes)
History: $( case "$HISTORY" in
sqlite) printf 'persistent, SQLite (%s/ergo_history.db)' "$IRCD_DIR" ;;
postgres) printf 'persistent, PostgreSQL (container ergo-postgres, db %s)' "$POSTGRES_DB" ;;
off) printf 'in RAM only -- lost on every restart, including updates' ;;
esac )
$( [[ "$HISTORY" == "off" ]] || printf 'Messages are kept for %s, then deleted (history.restrictions.expire-time).' "$HISTORY_EXPIRE" )
Switch backend: ergoctl history sqlite|postgres|off
Administer (from anywhere on this host):
ergoctl status versions, health, cert, user count
ergoctl users who is on
ergoctl oper add <name> add an operator (prints a generated password)
ergoctl announce <text> NOTICE to everyone
ergoctl kill|ban|defcon ... moderation (see: ergoctl help)
ergoctl cmd <raw IRC line> anything else, as the admin oper
ergoctl logs -f server log (health-probe noise filtered)
ergoctl backup stop-consistent backup of config + database
TLS: Caddy holds the Let's Encrypt cert; 'update.sh certsync' copies it to
Ergo and rehashes (every 15 min, silent when unchanged).
Check with 'ergoctl cert'. While it says SELF-SIGNED, IRC clients will
refuse to connect to 6697 with a certificate error -- that is a pending
issuance, not a broken install. Fix it in this order:
dig +short ${ERGO_DOMAIN} # must return this host's public IP
docker compose logs caddy # shows why ACME failed (80/443 blocked?)
ergoctl cert sync # apply now instead of waiting 15 min
Updates: ergoctl update check current vs latest (+ security advisories)
ergoctl update update update now (health-checked, DB snapshot, rollback)
$( [[ "$ERGO_AUTOUPDATE" == "1" ]] \
&& printf "Daily automatic run, policy '%s' (edit it in %s)." "$UPDATE_POLICY" "$ENV_FILE" \
|| printf "Daily run NOT scheduled (ERGO_AUTOUPDATE=0); enable it with 'ergoctl update install'." )
Restarting Ergo disconnects every user; the daily run warns them first.
Re-running this script is idempotent: it never touches ircd.yaml, secrets/ or
caddy/etc/conf.d/, and it adopts the settings above from .env rather than
resetting them to defaults.
================================================================
EOF
# IMPORTANT: do not put any code below this exit. Everything after the
# __ARCHIVE_BELOW__ marker is the embedded tar.gz payload (base64), appended by
# build.sh.
exit 0
__ARCHIVE_BELOW__
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
++f75/vn++f759/z+f8B5/OhFgAIAgA=