From 60a7a5cf4279e53808714675608b275740a11d78 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Sun, 1 Mar 2026 10:26:19 +0100 Subject: [PATCH] config+doc: add support for Bitcoin Core cookie files --- README.md | 24 ++++++++++++++++++++++-- config.js | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9c9ecca..da83498 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,34 @@ The server can be configured through environment variables or by modifying the d ### Bitcoin Core Configuration -Configure the Bitcoin Core RPC connection: +Configure the Bitcoin Core RPC connection using either a cookie file or username/password. +#### Cookie file authentication (recommended) + +When Bitcoin Core is started without explicit `rpcuser`/`rpcpassword` settings, it +generates a `.cookie` file in its data directory. Point the server at this file: + +``` +BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC URL +BITCOIN_RPC_COOKIE_FILE=~/.bitcoin/.cookie # Path to cookie file ``` -BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC host + +The cookie file is re-read at server startup. If Bitcoin Core restarts (and +generates a new cookie), the server must be restarted as well. + +#### Username/password authentication + +Alternatively, configure explicit RPC credentials: + +``` +BITCOIN_RPC_URL=http://127.0.0.1:38332 # Bitcoin Core RPC URL BITCOIN_RPC_USER=user # Bitcoin Core RPC username BITCOIN_RPC_PASS=password # Bitcoin Core RPC password ``` +If `BITCOIN_RPC_COOKIE_FILE` is set, it takes priority over `BITCOIN_RPC_USER` +and `BITCOIN_RPC_PASS`. + ### Layer 2 Configuration Configure Layer 2 CLI paths and RPC connections: diff --git a/config.js b/config.js index 6145a72..55952f3 100644 --- a/config.js +++ b/config.js @@ -1,4 +1,4 @@ -const { access, constants } = require('fs/promises'); +const { access, constants, readFile } = require('fs/promises'); const path = require('path'); const axios = require('axios'); const { makeRpcCallBTC } = require('./utils/bitcoin-rpc'); @@ -43,6 +43,31 @@ async function verifyExecutable(filePath, name) { } } +// Read Bitcoin Core cookie file and return { user, password } +async function readCookieFile(cookieFile) { + const expandedPath = cookieFile.replace(/^~/, process.env.HOME); + const resolvedPath = path.resolve(expandedPath); + try { + const contents = (await readFile(resolvedPath, 'utf-8')).trim(); + const separatorIndex = contents.indexOf(':'); + if (separatorIndex === -1) { + throw new Error(`Invalid cookie file format in ${resolvedPath}: expected "user:password"`); + } + return { + user: contents.substring(0, separatorIndex), + password: contents.substring(separatorIndex + 1) + }; + } catch (error) { + if (error.code === 'ENOENT') { + throw new Error(`Bitcoin Core cookie file not found at ${resolvedPath}. Is Bitcoin Core running?`); + } + if (error.code === 'EACCES') { + throw new Error(`Permission denied reading cookie file at ${resolvedPath}.`); + } + throw error; + } +} + // Verify Bitcoin Core RPC connection async function verifyBitcoinRpc(config) { try { @@ -52,7 +77,10 @@ async function verifyBitcoinRpc(config) { if (error.code === 'ECONNREFUSED') { throw new Error(`Could not connect to Bitcoin Core at ${config.bitcoin.host}:${config.bitcoin.port}`); } else if (error.response && error.response.status === 401) { - throw new Error('Bitcoin Core RPC authentication failed. Check your username and password.'); + const hint = config.bitcoin.cookieFile + ? 'Check your cookie file path.' + : 'Check your username and password.'; + throw new Error(`Bitcoin Core RPC authentication failed. ${hint}`); } throw new Error(`Bitcoin Core RPC verification failed: ${error.message}`); } @@ -89,6 +117,15 @@ async function verifyBitNamesConnection(config) { // Verify all CLI tools are available async function verifyConfig(config) { try { + // If cookie file is configured, read credentials from it + if (config.bitcoin.cookieFile) { + console.log('Reading Bitcoin Core cookie file...'); + const cookie = await readCookieFile(config.bitcoin.cookieFile); + config.bitcoin.user = cookie.user; + config.bitcoin.password = cookie.password; + console.log('Cookie file read successfully'); + } + // First verify Bitcoin Core connection console.log('Verifying Bitcoin Core RPC connection...'); await verifyBitcoinRpc(config); @@ -122,7 +159,8 @@ const config = { bitcoin: { url: process.env.BITCOIN_RPC_URL || defaultConfig.bitcoin.url, user: process.env.BITCOIN_RPC_USER || defaultConfig.bitcoin.user, - password: process.env.BITCOIN_RPC_PASS || defaultConfig.bitcoin.password + password: process.env.BITCOIN_RPC_PASS || defaultConfig.bitcoin.password, + cookieFile: process.env.BITCOIN_RPC_COOKIE_FILE || null }, thunder: { cliPath: process.env.THUNDER_CLI_PATH || defaultConfig.thunder.cliPath,