Skip to content

feat: add TCP proxy support for database and cache aliases#161

Open
shige wants to merge 3 commits intovercel-labs:mainfrom
giselles-ai:feat/tcp-proxy-support
Open

feat: add TCP proxy support for database and cache aliases#161
shige wants to merge 3 commits intovercel-labs:mainfrom
giselles-ai:feat/tcp-proxy-support

Conversation

@shige
Copy link
Copy Markdown

@shige shige commented Mar 24, 2026

Summary

Portless only supported HTTP/HTTPS routing by hostname, so raw TCP services (PostgreSQL, MySQL, Redis, etc.) couldn't be exposed through aliases. This PR adds portless alias --tcp <name> <port>, which assigns a dedicated listen port in the 5500-5999 range and proxies traffic to the target. Each alias gets its own port because raw TCP has no Host header for multiplexing.

Changes

  • CLI: portless alias --tcp <name> <port> to register TCP aliases; portless list and portless get return the connect address 127.0.0.1:<listenPort>
  • TCP proxy (tcp-proxy.ts): minimal bidirectional net module proxy between the listen port and the target
  • Route model: extended routes.json with optional type and listenPort fields; existing HTTP entries are unaffected
  • Port allocation: addTcpRoute() uses two-phase locking to avoid holding the file lock during async bind probes, and tracks active listeners in tcp-listeners.json to preserve daemon-held ports across alias updates
  • Daemon: TCP listeners start/stop alongside HTTP routes, bind to 127.0.0.1 only, and are excluded from HTTP routing and hosts sync

Test plan

  • pnpm --filter portless build
  • pnpm --filter portless test
  • pnpm lint && pnpm typecheck && pnpm format:check
  • Manual end-to-end with Docker: PostgreSQL (psql), MySQL (mysql), Redis (redis-cli) all connect through assigned proxy ports

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 24, 2026

@shige is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@shige
Copy link
Copy Markdown
Author

shige commented Mar 24, 2026

Hey, love portless! It's been super handy for local dev!

I've been wanting to use it with databases and caches (PostgreSQL, MySQL, Redis) too. Since those are raw TCP, they can't go through the hostname-based HTTP proxy, so I put together this PR adding portless alias --tcp . It assigns a dedicated listen port and proxies traffic to the target. list and get are also updated to keep the CLI consistent.

This does add some complexity to the daemon for TCP listener lifecycle, but I've tried to handle the common edge cases (bind races, daemon restarts, worktree contexts, etc.).

Happy to iterate if the direction seems reasonable, and totally understand if it's more scope than intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant