Skip to content

Allow listening on a Unix Domain Socket - #435

Closed
matvore wants to merge 1 commit into
joewalnes:masterfrom
matvore:uds
Closed

Allow listening on a Unix Domain Socket#435
matvore wants to merge 1 commit into
joewalnes:masterfrom
matvore:uds

Conversation

@matvore

@matvore matvore commented Jan 2, 2023

Copy link
Copy Markdown
Contributor

I use this in conjunction with local SSH port forwarding. The benefit is that I can run a server on a remote machine without allowing other users with login access to reach it. The service becomes available on the SSH client on an IP port but on the SSH server only via a private socket.

joewalnes pushed a commit that referenced this pull request Jul 9, 2026
Rebase and rework of #435 (by @matvore), renamed from --uds to
--unixsocket to match this codebase's flag naming (no hyphens:
--staticdir, --cgidir, --reverselookup, etc).

Serves alongside --address/--port by default; given alone (no --port,
--address, or --redirport), no TCP listener is started at all - for
exposing websocketd only to processes on the same host, e.g. behind
an SSH-forwarded or reverse-proxied socket.

Changes from the original PR:
- TCP and Unix listeners now share one serve() helper (also handling
  plain HTTP, TLS, and mutual TLS) instead of duplicating the
  Ssl/SslCaFile branch inline; avoids a merge conflict with the
  mutual-TLS support added after this PR was opened
- GetRemoteInfo returns a stable unix-socket placeholder instead of
  erroring on a Unix peer address (which has no host:port to parse),
  fixed in the shared function itself rather than special-cased at
  the handler.go call site, so every caller benefits
- A stale socket file left behind by an unclean shutdown (a killed
  process never gets to unlink it) is now removed automatically
  before binding, rather than failing with address already in use
- Added unit tests (wantsUnixSocketOnly, GetRemoteInfo) and two
  integration tests (echo round-trip over a real socket, stale-socket
  recovery), plus a QA plan entry and docs (--help, README, man page)

Verified manually end-to-end: real WebSocket handshake + echo over a
Unix socket, unixsocket-only mode confirmed to skip the TCP listener,
and stale-socket cleanup after a simulated SIGKILL crash.

Co-Authored-By: matvore <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M882UWfvyaq5KGvaV37idr

Copy link
Copy Markdown
Owner

Thanks for this — genuinely useful feature. Reworked and rebased as #463: renamed --uds to --unixsocket (to match this codebase's no-hyphen flag naming), unified the TCP/Unix serving path so it composes with the mutual-TLS support added since this was opened, added stale-socket cleanup, and added test coverage. Closing this in favor of that one — you're credited as a co-author on the commit.


Generated by Claude Code

@joewalnes joewalnes closed this Jul 9, 2026
joewalnes pushed a commit that referenced this pull request Jul 10, 2026
Rebase and rework of #435 (by @matvore), renamed from --uds to
--unixsocket to match this codebase's flag naming (no hyphens:
--staticdir, --cgidir, --reverselookup, etc).

Serves alongside --address/--port by default; given alone (no --port,
--address, or --redirport), no TCP listener is started at all - for
exposing websocketd only to processes on the same host, e.g. behind
an SSH-forwarded or reverse-proxied socket.

Changes from the original PR:
- TCP and Unix listeners now share one serve() helper (also handling
  plain HTTP, TLS, and mutual TLS) instead of duplicating the
  Ssl/SslCaFile branch inline; avoids a merge conflict with the
  mutual-TLS support added after this PR was opened
- GetRemoteInfo returns a stable unix-socket placeholder instead of
  erroring on a Unix peer address (which has no host:port to parse),
  fixed in the shared function itself rather than special-cased at
  the handler.go call site, so every caller benefits
- A stale socket file left behind by an unclean shutdown (a killed
  process never gets to unlink it) is now removed automatically
  before binding, rather than failing with address already in use
- Added unit tests (wantsUnixSocketOnly, GetRemoteInfo) and two
  integration tests (echo round-trip over a real socket, stale-socket
  recovery), plus a QA plan entry and docs (--help, README, man page)

Verified manually end-to-end: real WebSocket handshake + echo over a
Unix socket, unixsocket-only mode confirmed to skip the TCP listener,
and stale-socket cleanup after a simulated SIGKILL crash.

Co-Authored-By: matvore <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M882UWfvyaq5KGvaV37idr
joewalnes added a commit that referenced this pull request Jul 10, 2026
* Add --unixsocket to listen on a Unix domain socket

Rebase and rework of #435 (by @matvore), renamed from --uds to
--unixsocket to match this codebase's flag naming (no hyphens:
--staticdir, --cgidir, --reverselookup, etc).

Serves alongside --address/--port by default; given alone (no --port,
--address, or --redirport), no TCP listener is started at all - for
exposing websocketd only to processes on the same host, e.g. behind
an SSH-forwarded or reverse-proxied socket.

Changes from the original PR:
- TCP and Unix listeners now share one serve() helper (also handling
  plain HTTP, TLS, and mutual TLS) instead of duplicating the
  Ssl/SslCaFile branch inline; avoids a merge conflict with the
  mutual-TLS support added after this PR was opened
- GetRemoteInfo returns a stable unix-socket placeholder instead of
  erroring on a Unix peer address (which has no host:port to parse),
  fixed in the shared function itself rather than special-cased at
  the handler.go call site, so every caller benefits
- A stale socket file left behind by an unclean shutdown (a killed
  process never gets to unlink it) is now removed automatically
  before binding, rather than failing with address already in use
- Added unit tests (wantsUnixSocketOnly, GetRemoteInfo) and two
  integration tests (echo round-trip over a real socket, stale-socket
  recovery), plus a QA plan entry and docs (--help, README, man page)

Verified manually end-to-end: real WebSocket handshake + echo over a
Unix socket, unixsocket-only mode confirmed to skip the TCP listener,
and stale-socket cleanup after a simulated SIGKILL crash.

Co-Authored-By: matvore <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M882UWfvyaq5KGvaV37idr

* Fix UDS integration tests on macOS: sun_path 104-byte limit

t.TempDir() on macOS CI nests under a long $TMPDIR plus the test
name and a /001/ subdir, routinely exceeding sockaddr_un.sun_path's
104-byte limit (108 on Linux) and failing bind with EINVAL. Use a
short path under /tmp directly instead.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M882UWfvyaq5KGvaV37idr

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: matvore <[email protected]>
@matvore

matvore commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for accepting this :)

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.

2 participants