From c959468128235f875d74ab25f975cee45390d487 Mon Sep 17 00:00:00 2001 From: Daniel Padrino Date: Tue, 9 Jun 2026 16:19:02 -0300 Subject: [PATCH 1/3] feat(config): load LND TLS cert from file with env fallback 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. --- src/config/config.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index f8626ed30..360cc3c83 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,5 +1,6 @@ import { Injectable, Optional } from '@nestjs/common'; import { TypeOrmModuleOptions } from '@nestjs/typeorm'; +import * as fs from 'fs'; export enum Process { SYNC_ONCHAIN_TRANSACTIONS = 'SyncOnchainTransactions', @@ -22,6 +23,22 @@ export function GetConfig(): Configuration { return new Configuration(); } +// Reads the LND TLS certificate from the live file on disk if LIGHTNING_API_CERTIFICATE_PATH is set +// and readable; otherwise falls back to the LIGHTNING_API_CERTIFICATE env var (legacy, may go stale). +function readCert(): string | undefined { + const path = process.env.LIGHTNING_API_CERTIFICATE_PATH; + + if (path) { + try { + return fs.readFileSync(path, 'utf8'); + } catch { + // file missing or unreadable -> fall back to the env var below + } + } + + return process.env.LIGHTNING_API_CERTIFICATE?.split('
').join('\n'); +} + export class Configuration { port = process.env.PORT ?? 3000; environment: Environment = process.env.ENVIRONMENT as Environment; @@ -117,7 +134,7 @@ export class Configuration { wsInvoicesUrl: process.env.LIGHTNING_LND_WS_INVOICES_URL ?? '', wsPaymentsUrl: process.env.LIGHTNING_LND_WS_PAYMENTS_URL ?? '', }, - certificate: process.env.LIGHTNING_API_CERTIFICATE?.split('
').join('\n'), + certificate: readCert(), lnbitsapi: { apiUrl: process.env.LIGHTNING_LNBITSAPI_API_URL ?? '', certificate: process.env.LIGHTNING_LNBITSAPI_CERTIFICATE?.split('
').join('\n') ?? '', From 7167dc2cb2c3186878039482588b29a7447c25c9 Mon Sep 17 00:00:00 2001 From: Daniel Padrino Date: Wed, 10 Jun 2026 09:41:35 -0300 Subject: [PATCH 2/3] Use named readFileSync import in config to match repo convention The rest of the repo imports { readFileSync } from 'fs' (app.controller, monitoring.controller); align readCert with that instead of import * as fs. --- src/config/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index 360cc3c83..04e40fb14 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,6 +1,6 @@ import { Injectable, Optional } from '@nestjs/common'; import { TypeOrmModuleOptions } from '@nestjs/typeorm'; -import * as fs from 'fs'; +import { readFileSync } from 'fs'; export enum Process { SYNC_ONCHAIN_TRANSACTIONS = 'SyncOnchainTransactions', @@ -30,7 +30,7 @@ function readCert(): string | undefined { if (path) { try { - return fs.readFileSync(path, 'utf8'); + return readFileSync(path, 'utf8'); } catch { // file missing or unreadable -> fall back to the env var below } From f06a9ef8fe15e8ba7affec8e41c3a9f46dbd4850 Mon Sep 17 00:00:00 2001 From: Daniel Padrino Date: Wed, 10 Jun 2026 12:09:25 -0300 Subject: [PATCH 3/3] Read LND cert from file only, drop env-var fallback 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. --- src/config/config.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index 04e40fb14..dac6f892d 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -23,20 +23,15 @@ export function GetConfig(): Configuration { return new Configuration(); } -// Reads the LND TLS certificate from the live file on disk if LIGHTNING_API_CERTIFICATE_PATH is set -// and readable; otherwise falls back to the LIGHTNING_API_CERTIFICATE env var (legacy, may go stale). +// Reads the live LND TLS certificate from the file pointed to by LIGHTNING_API_CERTIFICATE_PATH. +// If the path is unset, returns undefined (environments without Lightning, e.g. tests, still boot). +// If the path is set but the file is missing/unreadable, readFileSync throws so a broken mount +// surfaces immediately instead of being masked by a stale fallback. function readCert(): string | undefined { const path = process.env.LIGHTNING_API_CERTIFICATE_PATH; + if (!path) return undefined; - if (path) { - try { - return readFileSync(path, 'utf8'); - } catch { - // file missing or unreadable -> fall back to the env var below - } - } - - return process.env.LIGHTNING_API_CERTIFICATE?.split('
').join('\n'); + return readFileSync(path, 'utf8'); } export class Configuration {