Skip to content

feat(config): load LND TLS cert from file with env fallback#200

Merged
Danswar merged 3 commits into
developfrom
feat/lightning-cert-from-file
Jun 10, 2026
Merged

feat(config): load LND TLS cert from file with env fallback#200
Danswar merged 3 commits into
developfrom
feat/lightning-cert-from-file

Conversation

@Danswar

@Danswar Danswar commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

On dfxdev we keep hitting recurring Failed to fetch Lightning balance: self-signed certificate errors. The root cause is that the LND TLS certificate is supplied to the app only through the LIGHTNING_API_CERTIFICATE env var, which is a hand-copied snapshot of the cert. Whenever LND regenerates its certificate, that env-var copy goes stale and no longer matches the live cert, so the HTTPS connection to LND fails.

Change

This adds support for a new optional env var LIGHTNING_API_CERTIFICATE_PATH:

  • If LIGHTNING_API_CERTIFICATE_PATH is set and the file is readable, the app reads the certificate straight from that file on disk (fs.readFileSync). Pointing this at the live LND cert means it can never drift again.
  • Otherwise the app falls back to the existing LIGHTNING_API_CERTIFICATE env-var behavior, completely unchanged.
  • If the path is set but the file is missing/unreadable, it silently falls back to the env var (config.ts has no logger).

The certificate is read in src/config/config.ts (the blockchain.lightning.certificate field) via a small readCert() helper. The lightning client TLS logic that consumes this cert is untouched.

Backward compatibility

Fully backward compatible. With no new env var set, behavior is identical to before. Nothing is removed.

Deploy order

Safe to ship code first: with LIGHTNING_API_CERTIFICATE_PATH unset there is zero behavior change. The matching infra change (mounting the live LND cert file into the container and setting the new env var) is a separate PR in the server/infra repo, which can land afterward to actually switch dfxdev over to the file.

Danswar added 2 commits June 9, 2026 16:19
Add support for an optional LIGHTNING_API_CERTIFICATE_PATH env var. When
set and readable, the LND TLS certificate is read from that file on disk
(the live cert), avoiding the recurring 'self-signed certificate' errors
that occur when the hand-copied LIGHTNING_API_CERTIFICATE env var drifts
after LND regenerates its cert.

Fully backward compatible: if the path is unset or unreadable, falls back
to the existing LIGHTNING_API_CERTIFICATE env-var behavior unchanged.
The rest of the repo imports { readFileSync } from 'fs' (app.controller,
monitoring.controller); align readCert with that instead of import * as fs.
@davidleomay

Copy link
Copy Markdown
Collaborator

Suggestion: remove the fallback

Same comment as on the DFX API counterpart (DFXswiss/api#3861) — the silent fallback to LIGHTNING_API_CERTIFICATE masks deploy misconfigurations (missing mount, wrong path) and you won't notice until the live cert rotates and the env var goes stale. Since the infra PR (DFXServer/server#366) guarantees the file is mounted before the app starts, recommend dropping the fallback.

@Danswar

Danswar commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Done — removed the fallback. readCert() now reads LIGHTNING_API_CERTIFICATE_PATH and throws if it's unset/unreadable, so a misconfigured mount surfaces immediately instead of silently using a stale cert.

Since the lds-api code runs on dfxprd too (not in the original dfxdev-only scope), I migrated dfxprd in the infra PR as well so prod keeps a cert source once the env var is gone — DFXServer/server#366.

@davidleomay davidleomay left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Deploy after server PR (DFXServer/server#366).

@Danswar Danswar force-pushed the feat/lightning-cert-from-file branch from ade542d to 838a806 Compare June 10, 2026 15:00
@Danswar

Danswar commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Small refinement after CI: readCert() only throws when LIGHTNING_API_CERTIFICATE_PATH is set but unreadable (your point — no silent fallback on a broken mount). When the path is unset it returns undefined instead of throwing, because Configuration is built eagerly at import and a hard throw broke every test suite that loads config (CI sets no Lightning env). Net effect is the same in real deploys (path is always set via compose); this just keeps non-Lightning environments (tests/CI) bootable. CI green now.

Address review: if LIGHTNING_API_CERTIFICATE_PATH is set, read it or throw.
The LIGHTNING_API_CERTIFICATE env var was the stale copy this change fixes,
so keeping it as a silent fallback only masks a broken mount. Remove it.
@Danswar Danswar force-pushed the feat/lightning-cert-from-file branch from 838a806 to f06a9ef Compare June 10, 2026 15:09
@Danswar Danswar merged commit 716701e into develop Jun 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants