Skip to content

Networking

IdentityScribe runs a single HTTP server for all traffic: REST, GraphQL, MCP, monitoring, and the built-in UI. You control what listens where using named sockets.

Socket Model

How HTTP sockets bind to channels

HTTP Sockets
@default :8080
auto
admin :9090
optional
Channels
REST API
GraphQL
MCP
Monitoring
Default binding
Override via socket =

All channels bind to the same server. By default, everything uses the @default socket on port 8080.

The primary socket is configured at the http {} root:

http {
port = 8080
port = ${?SCRIBE_HTTP_PORT}
# "auto" → localhost in dev, 0.0.0.0 in production
host = auto
host = ${?SCRIBE_HTTP_HOST}
}

Define additional sockets under http.sockets.* for network separation:

http.sockets.internal {
port = 9001
port = ${?SCRIBE_INTERNAL_PORT}
host = "localhost"
}

Named sockets inherit all settings from http {}. Only override what differs.

Channels reference sockets by name. Unspecified channels use @default.

channels.rest {
enabled = true
socket = ${?SCRIBE_REST_SOCKET} # default: @default
}
monitoring {
socket = ${?SCRIBE_MONITORING_SOCKET} # default for all monitoring
prometheus.socket = ${?SCRIBE_PROMETHEUS_SOCKET} # per-endpoint override
observe.socket = ${?SCRIBE_OBSERVE_SOCKET}
health.socket = ${?SCRIBE_HEALTH_SOCKET}
}

Channels can bind to multiple sockets:

monitoring.socket = ["@default", "internal"]

Everything on one port:

http {
port = 8080
host = "0.0.0.0"
}

Public APIs on one port, monitoring on another:

http {
port = 8080
host = "0.0.0.0"
sockets.internal {
port = 9001
host = "localhost"
}
}
monitoring.socket = "internal"

The bundled monitoring stack (monitoring/docker, monitoring/helm) uses this pattern.

During development, expose monitoring on both sockets to avoid 404 confusion:

http {
port = 8080
sockets.monitoring { port = 9001 }
}
monitoring {
socket = "monitoring"
observe.socket = ["@default", "monitoring"]
health.socket = ["@default", "monitoring"]
prometheus.socket = ["@default", "monitoring"]
}

The config/dev-local.conf uses this pattern.

Site UI socket topology (1/2/3 socket examples)

Section titled “Site UI socket topology (1/2/3 socket examples)”

When site.ui.enabled is true, startup enforces this fail-closed contract:

  • channels.rest.enabled = true
  • monitoring.enabled = true and monitoring.observe.enabled = true
  • every socket in site.socket must also be present in both channels.rest.socket and monitoring.observe.socket
channels.rest.enabled = true
site.socket = "@default"
channels.rest.socket = "@default"
monitoring.observe.socket = "@default"

Valid: UI and REST stay on public (@default), while monitoring endpoints can also be exposed on internal.

http {
port = 8080 # public
sockets.internal {
port = 9001
host = "localhost"
}
}
channels.rest.enabled = true
site.socket = "@default"
channels.rest.socket = "@default"
monitoring.observe.socket = ["@default", "internal"]
monitoring.prometheus.socket = "internal"
monitoring.health.socket = "internal"

Invalid: UI on public, but observe only on internal (startup fails).

site.socket = "@default"
channels.rest.socket = "@default"
monitoring.observe.socket = "internal" # missing @default

3) Three sockets (public + internal + site)

Section titled “3) Three sockets (public + internal + site)”

Remediation for invalid cases:

# Option A: move UI to a socket that already has REST+Observe
site.socket = "@default"
# Option B: keep UI socket and explicitly add it to both dependencies
channels.rest.socket = ["@default", "site"]
monitoring.observe.socket = ["internal", "site"]
http {
port = 443
ssl {
enabled = true
cert = "/path/to/server.pem"
key = "/path/to/server.key"
}
}

Or via environment variables:

Terminal window
SCRIBE_HTTP_SSL_ENABLED=true
SCRIBE_HTTP_SSL_CERT=/path/to/server.pem
SCRIBE_HTTP_SSL_KEY=/path/to/server.key

Require client certificates for API access:

http {
port = 8443
ssl {
enabled = true
cert = "/path/to/server.pem"
key = "/path/to/server.key"
ca = "/path/to/client-ca.pem"
client-auth = "REQUIRED"
}
}

client-auth options: NONE (default), OPTIONAL, REQUIRED.