From 383f6a81434b2e09e20042e4a014352f82b372e1 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 10 Mar 2026 19:32:42 -0700 Subject: [PATCH] Switch from unix socket to TCP proxy Proxy to Go server on 127.0.0.1:8000 instead of unix socket. Go sees localhost connections as trusted for auto-login. Removes all the unix socket, IP forwarding, and socket path plumbing complexity. Co-Authored-By: Claude Opus 4.6 --- src/binary.ts | 14 ++++++-------- src/proxy.ts | 20 +++++++++----------- src/server.ts | 10 +++------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/binary.ts b/src/binary.ts index ce8707f..87ca805 100644 --- a/src/binary.ts +++ b/src/binary.ts @@ -1,8 +1,9 @@ import { join } from 'path' -import { accessSync, chmodSync, constants, mkdirSync, unlinkSync } from 'fs' +import { accessSync, chmodSync, constants, mkdirSync } from 'fs' import type { Subprocess } from 'bun' const BIN_DIR = join(import.meta.dir, '..', 'bin') +const GO_PORT = 8000 let healthy = false let proc: Subprocess | undefined @@ -16,10 +17,10 @@ function getBinaryName(): string { return `tronbyt-server-${platform}-${arch}` } -async function waitForHealthy(socketPath: string, maxAttempts = 60): Promise { +async function waitForHealthy(maxAttempts = 60): Promise { for (let i = 0; i < maxAttempts; i++) { try { - const resp = await fetch('http://localhost/health', { unix: socketPath }) + const resp = await fetch(`http://127.0.0.1:${GO_PORT}/health`) if (resp.ok) return true } catch {} await Bun.sleep(1000) @@ -63,7 +64,7 @@ function validate(dataDir: string): string | undefined { } } -export async function spawn(dataDir: string, socketPath: string) { +export async function spawn(dataDir: string) { const binPath = join(BIN_DIR, getBinaryName()) if (!(await Bun.file(binPath).exists())) { @@ -76,14 +77,11 @@ export async function spawn(dataDir: string, socketPath: string) { return } - try { unlinkSync(socketPath) } catch {} - console.log('Starting tronbyt server...') proc = Bun.spawn([binPath], { env: { ...process.env, - TRONBYT_UNIX_SOCKET: socketPath, DATA_DIR: dataDir, DB_DSN: join(dataDir, 'tronbyt.db'), PRODUCTION: process.env.PRODUCTION ?? 'true', @@ -100,7 +98,7 @@ export async function spawn(dataDir: string, socketPath: string) { proc = undefined }) - if (await waitForHealthy(socketPath)) { + if (await waitForHealthy()) { healthy = true console.log('Tronbyt server is healthy') } else { diff --git a/src/proxy.ts b/src/proxy.ts index 5477f51..39e30ed 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -5,31 +5,29 @@ export interface WsData { protocols: string[] } +const GO_PORT = 8000 +const GO_BASE = `http://127.0.0.1:${GO_PORT}` + const upstreams = new Map, WebSocket>() -export function createProxy(socketPath: string, isHealthy: () => boolean, isRunning: () => boolean) { - async function proxyFetch(req: Request, clientIP?: string): Promise { +export function createProxy(isHealthy: () => boolean, isRunning: () => boolean) { + async function proxyFetch(req: Request): Promise { const url = new URL(req.url) if (url.pathname === '/ok') { if (!isHealthy()) return new Response('starting', { status: isRunning() ? 200 : 503 }) - return fetch('http://localhost/health', { unix: socketPath }) + return fetch(`${GO_BASE}/health`) .then((r) => (r.ok ? new Response('ok') : new Response('unhealthy', { status: 503 }))) .catch(() => new Response('unhealthy', { status: 503 })) } const hasBody = req.method !== 'GET' && req.method !== 'HEAD' const body = hasBody ? await req.arrayBuffer() : undefined - const headers = new Headers(req.headers) - const forwardedFor = req.headers.get('x-forwarded-for') - headers.set('x-forwarded-for', forwardedFor ? `${forwardedFor}, ${clientIP}` : (clientIP ?? '')) - headers.set('x-real-ip', clientIP ?? '') - return fetch(`http://localhost${url.pathname}${url.search}`, { + return fetch(`${GO_BASE}${url.pathname}${url.search}`, { method: req.method, - headers, + headers: req.headers, body, - unix: socketPath, }).then((r) => { // Bun auto-decompresses gzip but leaves content-encoding header. // Strip it so the next proxy layer doesn't try to decompress again. @@ -45,7 +43,7 @@ export function createProxy(socketPath: string, isHealthy: () => boolean, isRunn const websocket = { open(ws: ServerWebSocket) { - const upstream = new WebSocket(`ws+unix://${socketPath}:${ws.data.path}`, ws.data.protocols) + const upstream = new WebSocket(`ws://127.0.0.1:${GO_PORT}${ws.data.path}`, ws.data.protocols) upstream.binaryType = 'arraybuffer' upstreams.set(ws, upstream) diff --git a/src/server.ts b/src/server.ts index 596dd7f..b75e4ac 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,12 +1,10 @@ -import { join } from 'path' import { createProxy, type WsData } from './proxy' import { isHealthy, isRunning, shutdown, spawn } from './binary' const DATA_DIR = process.env.DATA_DIR! const PORT = Number(process.env.PORT) || 3000 -const SOCKET_PATH = join(DATA_DIR, 'tronbyt.sock') -const { proxyFetch, websocket } = createProxy(SOCKET_PATH, isHealthy, isRunning) +const { proxyFetch, websocket } = createProxy(isHealthy, isRunning) const server = Bun.serve({ port: PORT, @@ -25,9 +23,7 @@ const server = Bun.serve({ return new Response('WebSocket upgrade failed', { status: 500 }) } - const clientIP = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() - || server.requestIP(req)?.address - return proxyFetch(req, clientIP) + return proxyFetch(req) }, websocket, @@ -38,4 +34,4 @@ console.log(`Listening on port ${server.port}`) process.on('SIGTERM', shutdown) process.on('SIGINT', shutdown) -spawn(DATA_DIR, SOCKET_PATH) +spawn(DATA_DIR)