mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2026-08-13 12:33:07 +02:00
Make the CLN dev-fixture rune creation self-healing
Address review F5 on #1625: create-rune.sh was a one-shot poststart script — if the RPC wasn't ready within its poll or createrune failed, it exited without ever writing rtl.rune, and since the cln healthcheck gates on that file and rtl waits on service_healthy, a failed pass deadlocked the whole stack until 'down -v'. Drive rune creation from the healthcheck instead: the script is now a quick, idempotent single attempt, and the healthcheck runs it on every interval, so a transient RPC-startup race just retries and self-heals. Moved the script out of lightning-poststart.d to /opt and updated the healthcheck, compose comment and README accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
99cb60d2a7
commit
9c3cd983b4
4 changed files with 46 additions and 49 deletions
|
|
@ -115,12 +115,15 @@ before she can route to carol. The seed waits for this; anything you script your
|
|||
should too.
|
||||
|
||||
**Core Lightning auth uses a rune.** RTL talks to `cln` over clnrest and authenticates
|
||||
with a rune, not a macaroon. On first start `cln/poststart.d/create-rune.sh` runs inside
|
||||
the node (once the RPC is up), creates a master rune, and writes it as
|
||||
`LIGHTNING_RUNE="…"` to `rtl.rune` in the shared `cln_data` volume; RTL reads it via the
|
||||
`runePath` in its config. The `cln` healthcheck only passes once that file exists, so RTL
|
||||
waits for it. `--clnrest-host=0.0.0.0` is required for RTL (another container) to reach
|
||||
clnrest; the default `127.0.0.1` would only be reachable from inside the node.
|
||||
with a rune, not a macaroon. `cln/create-rune.sh` — run from the `cln` healthcheck —
|
||||
creates a master rune once the RPC is up and writes it as `LIGHTNING_RUNE="…"` to
|
||||
`rtl.rune` in the shared `cln_data` volume; RTL reads it via the `runePath` in its config.
|
||||
The healthcheck reports unhealthy until that file exists, so RTL (which waits on
|
||||
`service_healthy`) starts only once the rune is ready. Because it runs on every
|
||||
healthcheck tick (idempotent), a transient RPC-startup race just retries and self-heals
|
||||
rather than wedging the stack. `--clnrest-host=0.0.0.0` is required for RTL (another
|
||||
container) to reach clnrest; the default `127.0.0.1` would only be reachable from inside
|
||||
the node.
|
||||
|
||||
## Not included
|
||||
|
||||
|
|
|
|||
26
docker/cln/create-rune.sh
Executable file
26
docker/cln/create-rune.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Ensure the RTL rune exists. One quick, idempotent attempt:
|
||||
# - already have it -> succeed
|
||||
# - RPC up, createrune works -> write it, succeed
|
||||
# - RPC not ready / failure -> fail, so the caller retries
|
||||
#
|
||||
# This is invoked from the cln healthcheck (not a one-shot poststart hook) so a
|
||||
# transient RPC-startup race self-heals on the next healthcheck tick instead of
|
||||
# permanently wedging the stack. Stores the rune as LIGHTNING_RUNE="<rune>", the
|
||||
# format RTL reads via its runePath. POSIX sh compatible.
|
||||
set -u
|
||||
|
||||
RUNE_FILE="${LIGHTNINGD_DATA}/rtl.rune"
|
||||
|
||||
[ -f "${RUNE_FILE}" ] && exit 0
|
||||
|
||||
lightning-cli --network="${LIGHTNINGD_NETWORK}" getinfo >/dev/null 2>&1 || exit 1
|
||||
|
||||
rune=$(lightning-cli --network="${LIGHTNINGD_NETWORK}" createrune 2>/dev/null \
|
||||
| grep -o '"rune"[[:space:]]*:[[:space:]]*"[^"]*"' \
|
||||
| sed -e 's/.*"rune"[[:space:]]*:[[:space:]]*"//' -e 's/"$//')
|
||||
|
||||
[ -n "${rune}" ] || exit 1
|
||||
|
||||
printf 'LIGHTNING_RUNE="%s"\n' "${rune}" > "${RUNE_FILE}"
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Runs from Core Lightning's lightning-poststart.d. Creates a master rune (once)
|
||||
# and stores it in the format RTL expects: a file containing
|
||||
# LIGHTNING_RUNE="<rune>"
|
||||
# which RTL reads via its runePath.
|
||||
#
|
||||
# The image entrypoint can invoke poststart scripts before the RPC socket is
|
||||
# ready (it watches the datadir with a race that loses on a fresh node), so poll
|
||||
# for `getinfo` before calling createrune. Idempotent: keeps the same rune across
|
||||
# restarts so RTL's stored auth stays valid.
|
||||
|
||||
RUNE_FILE="${LIGHTNINGD_DATA}/rtl.rune"
|
||||
|
||||
[ -f "${RUNE_FILE}" ] && exit 0
|
||||
|
||||
# Wait (up to ~120s) for the RPC to accept commands.
|
||||
for _ in $(seq 1 120); do
|
||||
if lightning-cli --network="${LIGHTNINGD_NETWORK}" getinfo >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
rune=$(lightning-cli --network="${LIGHTNINGD_NETWORK}" createrune 2>/dev/null \
|
||||
| grep -o '"rune"[[:space:]]*:[[:space:]]*"[^"]*"' \
|
||||
| sed -e 's/.*"rune"[[:space:]]*:[[:space:]]*"//' -e 's/"$//')
|
||||
|
||||
if [ -z "${rune}" ]; then
|
||||
echo "create-rune.sh: failed to create rune" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'LIGHTNING_RUNE="%s"\n' "${rune}" > "${RUNE_FILE}"
|
||||
echo "create-rune.sh: wrote rune to ${RUNE_FILE}"
|
||||
|
|
@ -145,9 +145,9 @@ services:
|
|||
|
||||
# Core Lightning node. Unlike the LND nodes it talks to RTL over clnrest (the
|
||||
# built-in REST plugin) using rune auth, so it needs --clnrest-* options and a
|
||||
# rune written where RTL can read it. The entrypoint runs scripts dropped in
|
||||
# lightning-poststart.d once the RPC socket is up; create-rune.sh generates the
|
||||
# rune there and writes it to /root/.lightning/rtl.rune (RTL mounts that read-only).
|
||||
# rune written where RTL can read it. create-rune.sh (run from the healthcheck)
|
||||
# creates the rune and writes it to /root/.lightning/rtl.rune (RTL mounts that
|
||||
# read-only); the healthcheck is unhealthy until it exists, so rtl waits for it.
|
||||
# --clnrest-host=0.0.0.0 is required so the rtl container can reach it; the default
|
||||
# 127.0.0.1 would only be reachable from inside this container. Protocol stays https
|
||||
# (clnrest default, self-signed) — RTL connects with rejectUnauthorized:false.
|
||||
|
|
@ -175,13 +175,16 @@ services:
|
|||
- "${CLN_REST_PORT:-3010}:3010"
|
||||
volumes:
|
||||
- cln_data:/root/.lightning
|
||||
- ./cln/poststart.d:/root/.lightning/lightning-poststart.d:ro
|
||||
- ./cln/create-rune.sh:/opt/create-rune.sh:ro
|
||||
healthcheck:
|
||||
# Healthy only once the RPC is up AND the rune file has been written, so the
|
||||
# rtl service (which reads the rune at startup) can wait on this.
|
||||
test: ["CMD-SHELL", "lightning-cli --network=regtest getinfo >/dev/null 2>&1 && test -f /root/.lightning/rtl.rune"]
|
||||
# create-rune.sh ensures the rune exists (idempotent, one quick attempt) and
|
||||
# this reports healthy only once it does. Driving it from the healthcheck — which
|
||||
# retries on its interval — means a transient RPC-startup race self-heals instead
|
||||
# of a one-shot script permanently wedging the stack. rtl waits on this via
|
||||
# depends_on: condition: service_healthy before reading the rune at startup.
|
||||
test: ["CMD-SHELL", "sh /opt/create-rune.sh && test -f /root/.lightning/rtl.rune"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
timeout: 10s
|
||||
retries: 40
|
||||
|
||||
# RTL rewrites its config file on startup, so it cannot be given the tracked
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue