feat: add independent TLS control for relay public endpoint (#1045)
* feat: add independent TLS control for relay public endpoint Add PASEO_RELAY_PUBLIC_USE_TLS env var and publicUseTls persisted config to separately control TLS for the client→relay pairing offer, falling back to relayUseTls when unset. The daemon→relay connection continues to use PASEO_RELAY_USE_TLS alone. Enables self-hosting behind a TLS-terminating reverse proxy where the internal path is plain ws:// but public clients need wss://. * fix: use public relay TLS in daemon status --------- Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
co-authored by
Mohamed Boudra
parent
ee44b536f5
commit
338a41991d
@@ -1,9 +1,13 @@
|
||||
import { EventEmitter } from "node:events";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
import {
|
||||
type DaemonLaunchRuntime,
|
||||
type DetachedDaemonProcess,
|
||||
resolveLocalDaemonState,
|
||||
startLocalDaemonDetached,
|
||||
startLocalDaemonForeground,
|
||||
} from "./local-daemon.js";
|
||||
@@ -64,6 +68,17 @@ class FakeDaemonRuntime implements DaemonLaunchRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
const tempRoots: string[] = [];
|
||||
|
||||
async function createPaseoHome(config: unknown): Promise<string> {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), "paseo-local-daemon-"));
|
||||
tempRoots.push(root);
|
||||
const paseoHome = path.join(root, ".paseo");
|
||||
await mkdir(paseoHome, { recursive: true });
|
||||
await writeFile(path.join(paseoHome, "config.json"), JSON.stringify(config, null, 2));
|
||||
return paseoHome;
|
||||
}
|
||||
|
||||
function expectSupervisorLaunch(argv: string[]): void {
|
||||
const joined = argv.join(" ");
|
||||
expect(joined).toContain("supervisor-entrypoint");
|
||||
@@ -78,6 +93,12 @@ describe("local daemon launch supervision", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
tempRoots.splice(0).map((root) => rm(root, { recursive: true, force: true })),
|
||||
);
|
||||
});
|
||||
|
||||
test("foreground start spawns supervisor-entrypoint instead of server/index", async () => {
|
||||
const runtime = new FakeDaemonRuntime();
|
||||
|
||||
@@ -131,4 +152,24 @@ describe("local daemon launch supervision", () => {
|
||||
expect(launch?.args).toContain("--relay-use-tls");
|
||||
expect(launch?.options?.env?.PASEO_RELAY_USE_TLS).toBe("true");
|
||||
});
|
||||
|
||||
test("local daemon state keeps public relay TLS separate from daemon relay TLS", async () => {
|
||||
const home = await createPaseoHome({
|
||||
version: 1,
|
||||
daemon: {
|
||||
relay: {
|
||||
endpoint: "10.0.0.5:51185",
|
||||
publicEndpoint: "paseo.example.com",
|
||||
useTls: false,
|
||||
publicUseTls: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const state = resolveLocalDaemonState({ home });
|
||||
|
||||
expect(state.relayEndpoint).toBe("paseo.example.com");
|
||||
expect(state.relayUseTls).toBe(false);
|
||||
expect(state.relayPublicUseTls).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface LocalDaemonState {
|
||||
relayEnabled: boolean;
|
||||
relayEndpoint: string;
|
||||
relayUseTls: boolean;
|
||||
relayPublicUseTls: boolean;
|
||||
logPath: string;
|
||||
pidPath: string;
|
||||
pidInfo: LocalDaemonPidInfo | null;
|
||||
@@ -409,6 +410,7 @@ export function resolveLocalDaemonState(options: { home?: string } = {}): LocalD
|
||||
relayEnabled: config.relayEnabled ?? true,
|
||||
relayEndpoint: config.relayPublicEndpoint ?? config.relayEndpoint ?? "relay.paseo.sh:443",
|
||||
relayUseTls: config.relayUseTls ?? false,
|
||||
relayPublicUseTls: config.relayPublicUseTls ?? config.relayUseTls ?? false,
|
||||
logPath,
|
||||
pidPath,
|
||||
pidInfo,
|
||||
|
||||
@@ -29,6 +29,7 @@ export async function runPairCommand(options: PairOptions): Promise<void> {
|
||||
relayEndpoint: config.relayEndpoint,
|
||||
relayPublicEndpoint: config.relayPublicEndpoint,
|
||||
relayUseTls: config.relayUseTls,
|
||||
relayPublicUseTls: config.relayPublicUseTls,
|
||||
appBaseUrl: config.appBaseUrl,
|
||||
includeQr: true,
|
||||
});
|
||||
|
||||
@@ -316,7 +316,7 @@ async function resolveDaemonNodeLabel(
|
||||
|
||||
function formatRelayStatus(state: ReturnType<typeof resolveLocalDaemonState>): string {
|
||||
if (!state.relayEnabled) return "disabled";
|
||||
const scheme = state.relayUseTls ? "wss" : "ws";
|
||||
const scheme = state.relayPublicUseTls ? "wss" : "ws";
|
||||
return `${scheme}://${state.relayEndpoint}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -492,6 +492,7 @@ export async function runOnboard(options: OnboardOptions): Promise<void> {
|
||||
relayEndpoint: config.relayEndpoint,
|
||||
relayPublicEndpoint: config.relayPublicEndpoint,
|
||||
relayUseTls: config.relayUseTls,
|
||||
relayPublicUseTls: config.relayPublicUseTls,
|
||||
appBaseUrl: config.appBaseUrl,
|
||||
includeQr: true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user