From f551b4fe136bee6a42966f26ccf0aba1e3c04bb6 Mon Sep 17 00:00:00 2001 From: pablomendezroyo Date: Thu, 26 Feb 2026 10:50:35 +0100 Subject: [PATCH 1/2] Add localhost configuration support and related tests - Implement setLocalhostConfig function to modify config for localhost usage. - Update getWireguardCredentials to handle --localhost flag. - Add tests for setLocalhostConfig to ensure correct functionality. --- api/src/createLocalConfigFile.ts | 8 ++-- .../executables/getWireguardCredentials.ts | 12 +++-- api/src/setLocalhostConfig.ts | 9 ++++ api/test/createLocalConfigFile.test.ts | 4 +- api/test/setLocalhostConfig.test.ts | 44 +++++++++++++++++++ 5 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 api/src/setLocalhostConfig.ts create mode 100644 api/test/setLocalhostConfig.test.ts diff --git a/api/src/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts index 91247048..9fcf92e5 100644 --- a/api/src/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -43,7 +43,7 @@ async function getLocalIpWithRetries(retries: number): Promise { async function getLocalIp(): Promise { const dappmanagerHostnames = params.DAPPMANAGER_HOSTNAMES; const getLocalIpUrls = dappmanagerHostnames.map( - (hostname) => `http://${hostname}${params.GET_INTERNAL_IP_ENDPOINT}` + (hostname) => `http://${hostname}${params.GET_INTERNAL_IP_ENDPOINT}`, ); let errorMessages: string[] = []; @@ -57,7 +57,7 @@ async function getLocalIp(): Promise { return localIp; } catch (e) { errorMessages.push( - `Local IP could not be fetched from ${url}: ${e.message}` + `Local IP could not be fetched from ${url}: ${e.message}`, ); } } @@ -66,12 +66,12 @@ async function getLocalIp(): Promise { export function setLocalEndpoint( configFile: string, - localEndpoint: string + localEndpoint: string, ): string { return configFile .split("\n") .map((row) => - row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row + row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row, ) .join("\n"); } diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts index eb5cd472..31b8229c 100644 --- a/api/src/executables/getWireguardCredentials.ts +++ b/api/src/executables/getWireguardCredentials.ts @@ -11,6 +11,7 @@ import { createLocalConfigFile, getRemoteConfigFilePath, } from "../createLocalConfigFile"; +import { setLocalhostConfig } from "../setLocalhostConfig"; import fs from "fs"; (async function (): Promise { @@ -23,20 +24,25 @@ import fs from "fs"; const isQr = process.argv.includes("--qr"); const isLocal = process.argv.includes("--local"); + const isLocalhost = process.argv.includes("--localhost"); const configName = isLocal ? "local" : "remote"; const configFormat = isQr ? "qr" : "text"; console.log( - `Preparing ${configName} ${configFormat} Wireguard credentials; use CTRL + C to stop` + `Preparing ${configName} ${configFormat} Wireguard credentials; use CTRL + C to stop`, ); - const config = isLocal + const baseConfig = isLocal ? await createLocalConfigFile(params.MASTER_ADMIN) : fs.readFileSync( getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"), - "utf-8" + "utf-8", ); + // Mostly required to connect from within the same machine, + // especially when DAppNode is installed on macOS. + const config = isLocalhost ? setLocalhostConfig(baseConfig) : baseConfig; + const str = isQr ? // If rendering the QR fails, show error and the raw remoteTextCreds await renderQrCode(config).catch((e) => { diff --git a/api/src/setLocalhostConfig.ts b/api/src/setLocalhostConfig.ts new file mode 100644 index 00000000..a933add9 --- /dev/null +++ b/api/src/setLocalhostConfig.ts @@ -0,0 +1,9 @@ +export function setLocalhostConfig(configFile: string): string { + return configFile + .split("\n") + .filter((row) => !row.includes("ListenPort")) + .map((row) => + row.match(/^Endpoint\s*=/) ? "Endpoint = localhost:51820" : row, + ) + .join("\n"); +} diff --git a/api/test/createLocalConfigFile.test.ts b/api/test/createLocalConfigFile.test.ts index 82ca376e..fc7da7ce 100644 --- a/api/test/createLocalConfigFile.test.ts +++ b/api/test/createLocalConfigFile.test.ts @@ -28,6 +28,8 @@ AllowedIPs = 0.0.0.0/0`; const localEndpoint = `192.168.1.45:51820`; - expect(setLocalEndpoint(remoteConfig, localEndpoint)).to.deep.equal(expextedLocalConfig); + expect(setLocalEndpoint(remoteConfig, localEndpoint)).to.deep.equal( + expextedLocalConfig, + ); }); }); diff --git a/api/test/setLocalhostConfig.test.ts b/api/test/setLocalhostConfig.test.ts new file mode 100644 index 00000000..0f65acfe --- /dev/null +++ b/api/test/setLocalhostConfig.test.ts @@ -0,0 +1,44 @@ +import "mocha"; +import { expect } from "chai"; +import { setLocalhostConfig } from "../src/setLocalhostConfig"; + +describe("setLocalhostConfig", function () { + it("removes ListenPort and sets localhost endpoint", function () { + const remoteConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +ListenPort = 51820 +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = ff0239facf453517.dyndns.dappnode.io:51820 +AllowedIPs = 0.0.0.0/0`; + + const expectedLocalhostConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = localhost:51820 +AllowedIPs = 0.0.0.0/0`; + + expect(setLocalhostConfig(remoteConfig)).to.deep.equal( + expectedLocalhostConfig, + ); + }); + + it("replaces endpoint when spacing around equal sign varies", function () { + const remoteConfig = `[Peer] +Endpoint = ff0239facf453517.dyndns.dappnode.io:51820`; + + const expectedLocalhostConfig = `[Peer] +Endpoint = localhost:51820`; + + expect(setLocalhostConfig(remoteConfig)).to.deep.equal( + expectedLocalhostConfig, + ); + }); +}); From 6bab1e4841e598553e708e52e943a085d366df92 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Fri, 27 Feb 2026 10:39:25 +0100 Subject: [PATCH 2/2] Remove listenhost fom client interface completely --- api/src/setLocalhostConfig.ts | 1 - api/test/setLocalhostConfig.test.ts | 3 +-- root/defaults/peer.conf | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/api/src/setLocalhostConfig.ts b/api/src/setLocalhostConfig.ts index a933add9..b703cca8 100644 --- a/api/src/setLocalhostConfig.ts +++ b/api/src/setLocalhostConfig.ts @@ -1,7 +1,6 @@ export function setLocalhostConfig(configFile: string): string { return configFile .split("\n") - .filter((row) => !row.includes("ListenPort")) .map((row) => row.match(/^Endpoint\s*=/) ? "Endpoint = localhost:51820" : row, ) diff --git a/api/test/setLocalhostConfig.test.ts b/api/test/setLocalhostConfig.test.ts index 0f65acfe..8087ff17 100644 --- a/api/test/setLocalhostConfig.test.ts +++ b/api/test/setLocalhostConfig.test.ts @@ -3,11 +3,10 @@ import { expect } from "chai"; import { setLocalhostConfig } from "../src/setLocalhostConfig"; describe("setLocalhostConfig", function () { - it("removes ListenPort and sets localhost endpoint", function () { + it("sets localhost endpoint", function () { const remoteConfig = `[Interface] Address = AX032NVGI2RIB4 PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= -ListenPort = 51820 DNS = 172.33.1.2 [Peer] diff --git a/root/defaults/peer.conf b/root/defaults/peer.conf index d987dba9..525b2bd8 100644 --- a/root/defaults/peer.conf +++ b/root/defaults/peer.conf @@ -1,7 +1,6 @@ [Interface] Address = ${CLIENT_IP} PrivateKey = $(cat /config/${PEER_ID}/privatekey-${PEER_ID}) -ListenPort = 51820 DNS = ${PEERDNS} [Peer]