cloud-sre

Lighthouse の InvalidToken が、実際には Erigon の Forbidden だった

Gnosis の Erigon と Lighthouse の Engine API 接続を直した記録。JWT ミスに見えたが、実際に詰まっていたのは authrpc vhost だった。

Jun 24, 2026
GnosisErigonLighthousearchive-nodeDocker

Gnosis の archive node で、execution layer は Erigon、consensus layer は Lighthouse という構成だった。Erigon 側には次の warning が出続けていた。

flag --externalcl was provided, but no CL requests to engine-api in 22h...

Lighthouse コンテナは起動していたが、ログはこの繰り返しだった。

Failed jwt authorization error: InvalidToken
Execution engine call failed error: Auth(InvalidToken)
HTTP status client error (403 Forbidden) for url (http://gnosis:8551/)

最初は JWT secret の不一致に見える。実際には違った。最後に必要だったのは、Erigon の Engine API に Docker service name を vhost として許可することだった。

--authrpc.vhosts=gnosis,localhost,127.0.0.1

用語の説明

用語意味
Execution layerブロックを実行し、実行層データを保存する client。この構成では Erigon。
Consensus layerPoS の beacon chain を追い、fork choice を進める client。この構成では Lighthouse。
Engine APIconsensus client と execution client の間で使う認証付き API。よく使う port は 8551
JWT secretconsensus client が Engine API に接続するための共有 secret file。
authrpc vhostErigon が認証 RPC で許可する Host の一覧。JWT が正しくても Host が拒否されることがある。
Checkpoint syncLighthouse が最近の finalized checkpoint から起動する同期方式。genesis から追うよりかなり速い。

ログが示していたこと

Erigon は外部 consensus layer を使う形で起動していた。

--externalcl
--authrpc.addr=0.0.0.0
--authrpc.port=8551
--authrpc.jwtsecret=/jwt/jwt.hex

この方向自体は合っている。Erigon README では、Gnosis では Erigon と一緒に consensus layer client が必要だと説明されている。また、consensus client が localhost 以外から接続する場合は --authrpc.addr 0.0.0.0--authrpc.vhosts <CL host> を設定するよう書かれている [1]

Lighthouse 側の endpoint は Docker service name を使っていた。

--execution-endpoint http://gnosis:8551
--execution-jwt /jwt/jwt.hex

この request には二つの要素があった。JWT と HTTP Host だ。このケースでは Host が gnosis:8551 になっていた。

まず JWT を疑った

一番ありそうなのは secret file の不一致なので、まず同じ file が見えているか確認した。

sha256sum /data/jwt/jwt.hex
docker exec gnosis sha256sum /jwt/jwt.hex
docker exec gnosis-lighthouse sha256sum /jwt/jwt.hex

host の file、Erigon container の mount、Lighthouse container の mount は一致していた。

さらに同じ secret から一時 JWT を作り、Erigon の engine_exchangeCapabilities を直接呼んだ。この request は HTTP 200 を返した。ここで範囲がかなり狭まった。Erigon は token を検証できるし、Engine API も到達できる。Lighthouse の InvalidToken は、実際には 403 を包んでいた。

Lighthouse の更新で別の問題も見えた

動いていた Lighthouse image が古かったので、floating tag ではなく明示的な version に固定した。

sigp/lighthouse:v8.2.0

v8.2.0 はその時点の current release で、Lighthouse project も high-priority としていた [2]

この更新で、古い Lighthouse database を開けない問題が出た。

Unable to open database: LoadConfig(ConfigError(InvalidVersionByte(Some(0))))

execution data は Erigon の datadir 側にあり、そこは触っていない。古い Lighthouse datadir は別名で退避し、Gnosis の checkpoint sync を使って Lighthouse を起動し直した。

--checkpoint-sync-url https://checkpoint.gnosischain.com

Gnosis docs はこの checkpoint sync server を案内している。Lighthouse docs でも、checkpoint sync は genesis から同期するより速く、同じ beacon node 機能を提供すると説明されている [3][4]

もう一つ、古い flag を外す必要があった。新しい Lighthouse では次の組み合わせは使えない。

--checkpoint-sync-url ...
--allow-insecure-genesis-sync

checkpoint sync を使うなら、genesis sync 用の古い flag は不要だった。

接続を直した変更

Lighthouse v8.2.0 が起動しても、まだ次の error が残った。

InvalidToken("HTTP status client error (403 Forbidden) for url (http://gnosis:8551/)")

見る点は 403 Forbidden だった。

Lighthouse の endpoint は http://gnosis:8551。これは Docker network 内の service name だ。Erigon は 0.0.0.0:8551 で listen していたが、authrpc vhost に gnosis が入っていなかった。そこで Erigon の起動引数をこう変えた。

--authrpc.addr=0.0.0.0
--authrpc.port=8551
--authrpc.vhosts=gnosis,localhost,127.0.0.1
--authrpc.jwtsecret=/jwt/jwt.hex

その後、同じ /data/erigon と同じ JWT file を使ったまま、Erigon container だけを再起動した。

最終的な形

Erigon 側:

erigon
  --chain=gnosis
  --datadir=/data
  --externalcl
  --authrpc.addr=0.0.0.0
  --authrpc.port=8551
  --authrpc.vhosts=gnosis,localhost,127.0.0.1
  --authrpc.jwtsecret=/jwt/jwt.hex
  --prune.mode=archive

Lighthouse 側:

lighthouse bn
  --network gnosis
  --datadir /data
  --execution-endpoint http://gnosis:8551
  --execution-jwt /jwt/jwt.hex
  --checkpoint-sync-url https://checkpoint.gnosischain.com

確認したこと

Erigon を再起動した後、Erigon のログに次の行が出た。

[GetClientVersionV1] Received request fromClientCode: LH, Lighthouse-v8.2.0...

Lighthouse 側も JWT error ではなく、通常の Engine API flow に変わった。

Execution engine online
Issuing forkchoiceUpdated
Synced ... exec_hash: ... (unverified)
Head is optimistic

直近ログで InvalidToken を数えると 0 だった。

docker logs --since 2m gnosis-lighthouse 2>&1 | grep -c 'InvalidToken'
# 0

この時点の Head is optimistic は問題の切り分けとしては許容できる状態だった。Lighthouse は consensus head に追いついているが、execution layer が対応する payload をまだ検証しきっていない、という意味だ。Erigon 側では Execution stage が進んでいたので、残りは Engine API 認証ではなく execution catch-up だった。

今回の教訓は小さい。Lighthouse が InvalidToken と言っている時も、内側の HTTP status まで見る。Erigon から 403 が返っているなら、JWT file そのものではなく authrpc host allowlist が詰まっていることがある。

参考

[1] Erigon README: Beacon Chain / Consensus Layer

[2] Lighthouse v8.2.0 release notes

[3] Gnosis Chain docs: Lighthouse checkpoint sync

[4] Lighthouse Book: run a node and checkpoint sync