feat(membershipd): --bind flag governs HTTP + embedded NATS interface
Add a --bind flag (default 127.0.0.1) to membershipd that controls which network interface both the control-plane HTTP API and the embedded NATS data plane listen on. Use 0.0.0.0 to expose the stack to the LAN so remote peers (phones, other PCs) can connect; keep the default for a loopback-only dev stack. embeddednats gains StartHost(storeDir, host, port) for explicit interface control; Start stays a backward-compatible wrapper (host "" = nats default 0.0.0.0) so the playground and tests are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
|
bind = flag.String("bind", "127.0.0.1", "network interface to bind the HTTP API and the embedded NATS to; use 0.0.0.0 to accept LAN/remote peers")
|
||||||
natsURL = flag.String("nats-url", "", "external NATS url; empty starts an embedded server")
|
natsURL = flag.String("nats-url", "", "external NATS url; empty starts an embedded server")
|
||||||
httpPort = flag.String("http-port", "8470", "HTTP port for the control-plane API")
|
httpPort = flag.String("http-port", "8470", "HTTP port for the control-plane API")
|
||||||
dbPath = flag.String("db", "./local_files/unibus.db", "SQLite database path")
|
dbPath = flag.String("db", "./local_files/unibus.db", "SQLite database path")
|
||||||
@@ -40,7 +41,10 @@ func main() {
|
|||||||
natsClientURL := *natsURL
|
natsClientURL := *natsURL
|
||||||
if natsClientURL == "" {
|
if natsClientURL == "" {
|
||||||
var err error
|
var err error
|
||||||
ns, err = embeddednats.Start(*natsStore, *natsPort)
|
// Bind the embedded NATS to the same interface as the HTTP API so a single
|
||||||
|
// --bind flag governs reachability: 127.0.0.1 keeps the whole stack
|
||||||
|
// loopback-only; 0.0.0.0 exposes both planes to the LAN.
|
||||||
|
ns, err = embeddednats.StartHost(*natsStore, *bind, *natsPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("start embedded nats: %v", err)
|
log.Fatalf("start embedded nats: %v", err)
|
||||||
}
|
}
|
||||||
@@ -65,7 +69,7 @@ func main() {
|
|||||||
log.Printf("blob store: %s", *storeDir)
|
log.Printf("blob store: %s", *storeDir)
|
||||||
|
|
||||||
srv := membership.NewServer(store, blobs)
|
srv := membership.NewServer(store, blobs)
|
||||||
addr := "127.0.0.1:" + *httpPort
|
addr := *bind + ":" + *httpPort
|
||||||
httpSrv := &http.Server{Addr: addr, Handler: srv}
|
httpSrv := &http.Server{Addr: addr, Handler: srv}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -13,13 +13,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Start launches an embedded nats-server with JetStream enabled, listening on
|
// Start launches an embedded nats-server with JetStream enabled, listening on
|
||||||
// the given port and persisting JetStream state under storeDir. It blocks until
|
// the given port and persisting JetStream state under storeDir. The listen host
|
||||||
// the server is ready to accept connections (up to 5s) and returns the running
|
// is left at the nats-server default ("0.0.0.0", all interfaces). It blocks
|
||||||
// server. The caller is responsible for calling Shutdown on it.
|
// until the server is ready to accept connections (up to 5s) and returns the
|
||||||
|
// running server. The caller is responsible for calling Shutdown on it.
|
||||||
|
//
|
||||||
|
// Start is a thin backward-compatible wrapper over StartHost; callers that need
|
||||||
|
// to control the bind interface (loopback vs LAN) should use StartHost directly.
|
||||||
func Start(storeDir string, port int) (*server.Server, error) {
|
func Start(storeDir string, port int) (*server.Server, error) {
|
||||||
|
return StartHost(storeDir, "", port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartHost is Start with explicit control over the bind interface. host selects
|
||||||
|
// which network interface the data plane listens on: pass "127.0.0.1" to keep
|
||||||
|
// NATS loopback-only (the safe default for a single-host dev stack) or "0.0.0.0"
|
||||||
|
// to expose it to the LAN so remote peers (phones, other PCs) can connect. An
|
||||||
|
// empty host falls back to the nats-server default ("0.0.0.0", all interfaces).
|
||||||
|
func StartHost(storeDir, host string, port int) (*server.Server, error) {
|
||||||
opts := &server.Options{
|
opts := &server.Options{
|
||||||
JetStream: true,
|
JetStream: true,
|
||||||
StoreDir: storeDir,
|
StoreDir: storeDir,
|
||||||
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
DontListen: false,
|
DontListen: false,
|
||||||
// Keep the embedded server quiet by default; the host app logs the URLs.
|
// Keep the embedded server quiet by default; the host app logs the URLs.
|
||||||
|
|||||||
Reference in New Issue
Block a user