fix(ergo): guard a network rename, and persist ACME_EMAIL on a re-run
ergo already defends this bug class deliberately -- it adopts .env settings on
a re-run and dies with a precise remedy for ERGO_DOMAIN, HISTORY, PLAINTEXT
and a floating ERGO_TAG. NETWORK_NAME and ACME_EMAIL were gaps in that
defense, not design choices: both are absent from EXPLICIT and from the
re-run writeback loop, though the header promises it "writes back settings you
passed explicitly on this run".
A plain re-run stays safe, since both are adopted from .env as prompt
defaults. The hole is a value the operator actively supplies. NETWORK_NAME
then splits three ways: the generated docs under $STACK_DIR/docs and (when
exported) the Caddy landing page get the NEW name, ircd.yaml keeps the OLD one
because render_ircd_yaml never rewrites an existing file, and .env is never
updated so the next run reverts the docs too. The summary prints the new name.
Clients keep seeing the old one in NETWORK=.
Add yaml_network_name beside yaml_server_name and die with a remedy pointing
at `ergoctl edit` + `ergoctl rehash`, matching how ERGO_DOMAIN is handled --
a rename ircd.yaml cannot absorb should stop the run, not half-apply. Add
ACME_EMAIL to EXPLICIT and to the writeback loop, since unlike the network
name it genuinely can change on a re-run.
ergolib.sh is embedded, so the payload was regenerated with build.sh; that
rebuild also carries the env_set repair from 947c899.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+734
-723
File diff suppressed because it is too large
Load Diff
@@ -114,13 +114,25 @@ refuse_symlink() { # <path> [what]
|
||||
# ---------------------------------------------------------------------------
|
||||
env_get() { [[ -f "$ENV_FILE" ]] && grep -E "^$1=" "$ENV_FILE" | head -n1 | cut -d= -f2- || true; }
|
||||
env_set() { # <KEY> <value>: update KEY in .env, or append if absent
|
||||
local key="$1" val="$2" esc
|
||||
esc=${val//\\/\\\\}; esc=${esc//|/\\|}; esc=${esc//&/\\&}
|
||||
if grep -qE "^${key}=" "$ENV_FILE" 2>/dev/null; then
|
||||
sed -i -e "s|^${key}=.*|${key}=${esc}|" "$ENV_FILE"
|
||||
else
|
||||
printf '%s=%s\n' "$key" "$val" >> "$ENV_FILE"
|
||||
# The value goes through the ENVIRONMENT, never interpolated into a sed
|
||||
# script. Interpolating it corrupts any value containing & (sed expands it to
|
||||
# the whole match) and aborts the run on one containing the s||| delimiter --
|
||||
# which is reachable for an OIDC secret, a password or a URL query string.
|
||||
local key="$1" val="$2" tmp
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
printf '%s=%s
|
||||
' "$key" "$val" >> "$ENV_FILE"
|
||||
return 0
|
||||
fi
|
||||
tmp="$(mktemp)"
|
||||
_SE_KEY="$key" _SE_VAL="$val" awk '
|
||||
BEGIN { k = ENVIRON["_SE_KEY"]; v = ENVIRON["_SE_VAL"]; seen = 0 }
|
||||
!seen && index($0, k "=") == 1 { print k "=" v; seen = 1; next }
|
||||
{ print }
|
||||
END { if (!seen) print k "=" v }
|
||||
' "$ENV_FILE" > "$tmp"
|
||||
cat "$tmp" > "$ENV_FILE" # rewrite in place: keeps the original mode/owner
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
ergo_domain() { env_get ERGO_DOMAIN | tr 'A-Z' 'a-z' || true; }
|
||||
@@ -434,6 +446,10 @@ yaml_server_name() {
|
||||
awk '/^[a-z]/ {top=$1} top=="server:" && /^ name:/ {sub(/^ name:[ \t]*/,""); gsub(/["\047]/,""); print; exit}' "$1"
|
||||
}
|
||||
|
||||
yaml_network_name() {
|
||||
awk '/^[a-z]/ {top=$1} top=="network:" && /^ name:/ {sub(/^ name:[ \t]*/,""); gsub(/["\047]/,""); print; exit}' "$1"
|
||||
}
|
||||
|
||||
yaml_oper_list() { # <file> -> "name class" per oper
|
||||
awk '
|
||||
/^[a-z]/ { top=$1 }
|
||||
|
||||
Reference in New Issue
Block a user