Skip to main content
Sockets define the network endpoints where your workerd instance listens for incoming connections. Each socket routes requests to a designated service.

Basic socket configuration

Sockets are defined in the sockets list of your configuration:
using Workerd = import "/workerd/workerd.capnp";

const config :Workerd.Config = (
  services = [
    (name = "main", worker = .mainWorker),
  ],

  sockets = [
    ( name = "http",
      address = "*:8080",
      http = (),
      service = "main"
    ),
  ]
);

Socket fields

name
Text
required
Unique name for the socket. Used with command-line overrides:
  • --socket-addr <name>=<addr>: Override the address
  • --socket-fd <name>=<fd>: Use an inherited file descriptor
name = "http",
address
Text
Address and port to listen on. Optional if you plan to specify it on the command line.Examples:
  • "*:80": All interfaces, port 80
  • "1.2.3.4": Specific IPv4 address, default port
  • "1.2.3.4:8080": Specific IPv4 address and port
  • "1234:5678::abcd": IPv6 address, default port
  • "[1234:5678::abcd]:8080": IPv6 address and port
  • "unix:/path/to/socket": Unix domain socket
  • "unix-abstract:name": Linux abstract Unix socket
  • "example.com:8080": DNS hostname (resolves and listens on all addresses)
address = "*:8080",
service
ServiceDesignator
required
Service name that handles requests on this socket.
service = "main",

Protocol configuration

Sockets support HTTP and HTTPS protocols:

HTTP

For unencrypted HTTP connections:
sockets = [
  ( name = "http",
    address = "*:8080",
    http = (),
    service = "main"
  ),
]

HTTPS

For TLS-encrypted connections:
sockets = [
  ( name = "https",
    address = "*:8443",
    https = (
      options = (),
      tlsOptions = (
        keypair = (
          privateKey = embed "key.pem",
          certificateChain = embed "cert.pem",
        ),
      ),
    ),
    service = "main"
  ),
]

HTTP options

HTTP options configure request/response behavior, particularly for proxy scenarios:
style
Style
default:"host"
HTTP style:
  • host: Normal HTTP (path in request line, separate Host header)
  • proxy: HTTP proxy protocol (full URL in request line)
http = (style = proxy),
forwardedProtoHeader
Text
Header name containing the original protocol ("http" or "https"). Useful when behind a reverse proxy that performs TLS termination.Common values: "X-Forwarded-Proto", "X-Real-Proto"
http = (
  forwardedProtoHeader = "X-Forwarded-Proto",
),
cfBlobHeader
Text
Header name for encoding/parsing the request.cf object as JSON. If not set, request.cf is discarded on send and undefined on receipt.
http = (
  cfBlobHeader = "CF-Blob",
),
injectRequestHeaders
List(Header)
Headers automatically injected into all incoming requests. Existing headers with the same name are removed.
http = (
  injectRequestHeaders = [
    (name = "X-Server", value = "workerd"),
    (name = "X-Custom", value = "value"),
  ],
),
injectResponseHeaders
List(Header)
Headers automatically injected into all outgoing responses.
http = (
  injectResponseHeaders = [
    (name = "X-Powered-By", value = "workerd"),
    (name = "Strict-Transport-Security", value = "max-age=31536000"),
  ],
),
capnpConnectHost
Text
Host+port for Cap’n Proto RPC connections. CONNECT requests for this host are treated as requests to form a Cap’n Proto RPC connection, exposing a WorkerdBootstrap interface.
http = (
  capnpConnectHost = "capnp.internal:9000",
),

TLS options

TLS configuration for encrypted connections:
keypair
Keypair
Private key and certificate chain. Optional for clients, required for servers.
tlsOptions = (
  keypair = (
    privateKey = embed "server-key.pem",
    certificateChain = embed "server-cert.pem",
  ),
),
  • privateKey: PEM format, supports PKCS8, traditional RSA, and DSA keys
  • certificateChain: PEM format, concatenate multiple certificates starting with the leaf
requireClientCerts
Bool
default:false
Require clients to present certificates signed by trusted CAs. Typically used with trustBrowserCas = false and a specific private CA in trustedCertificates.
tlsOptions = (
  requireClientCerts = true,
  trustBrowserCas = false,
  trustedCertificates = [embed "client-ca.pem"],
),
trustBrowserCas
Bool
default:false
Trust certificates signed by browser-trusted CAs. Set true for public internet, false for internal networks.
tlsOptions = (trustBrowserCas = true),
trustedCertificates
List(Text)
Additional CA certificates to trust, in PEM format.
tlsOptions = (
  trustedCertificates = [
    embed "internal-ca-1.pem",
    embed "internal-ca-2.pem",
  ],
),
minVersion
Version
default:"goodDefault"
Minimum TLS version allowed:
  • goodDefault: Chosen by maintainers, may change
  • ssl3, tls1Dot0, tls1Dot1: Legacy versions
  • tls1Dot2, tls1Dot3: Modern versions
tlsOptions = (minVersion = tls1Dot2),
Only override this if you have specific backwards-compatibility needs.
cipherList
Text
OpenSSL cipher list string. The default is based on Mozilla’s “intermediate” recommendations and changes with cryptanalysis developments.Only specify your own if:
  • You need extreme backwards-compatibility
  • You need to quickly disable a recently-broken algorithm
tlsOptions = (
  cipherList = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256",
),

Multiple sockets

You can define multiple sockets listening on different addresses or ports:
using Workerd = import "/workerd/workerd.capnp";

const config :Workerd.Config = (
  services = [
    (name = "main", worker = .mainWorker),
    (name = "admin", worker = .adminWorker),
  ],

  sockets = [
    # Public HTTP
    ( name = "http",
      address = "*:8080",
      http = (),
      service = "main"
    ),

    # Public HTTPS
    ( name = "https",
      address = "*:8443",
      https = (
        options = (),
        tlsOptions = (
          keypair = (
            privateKey = embed "server-key.pem",
            certificateChain = embed "server-cert.pem",
          ),
          trustBrowserCas = true,
        ),
      ),
      service = "main"
    ),

    # Internal admin interface
    ( name = "admin",
      address = "127.0.0.1:9000",
      http = (),
      service = "admin"
    ),
  ]
);

Command-line overrides

You can override socket addresses from the command line:
# Override socket address
workerd serve config.capnp --socket-addr http=*:3000

# Use inherited file descriptor (e.g., from systemd)
workerd serve config.capnp --socket-fd http=3 --socket-fd https=4

# Multiple overrides
workerd serve config.capnp \
  --socket-addr http=127.0.0.1:8080 \
  --socket-addr https=127.0.0.1:8443

Systemd integration

workerd works well with systemd socket activation:
# /etc/systemd/system/workerd.service
[Unit]
Description=workerd runtime
Requires=workerd.socket

[Service]
ExecStart=/usr/bin/workerd serve /etc/workerd/config.capnp \
  --socket-fd http=3 --socket-fd https=4
Sockets=workerd.socket
User=nobody
Group=nogroup
Restart=always
# /etc/systemd/system/workerd.socket
[Unit]
Description=sockets for workerd
PartOf=workerd.service

[Socket]
ListenStream=0.0.0.0:80
ListenStream=0.0.0.0:443

[Install]
WantedBy=sockets.target
This allows systemd to open privileged ports while workerd runs as an unprivileged user.

Complete example

using Workerd = import "/workerd/workerd.capnp";

const config :Workerd.Config = (
  services = [
    (name = "main", worker = .mainWorker),
  ],

  sockets = [
    ( name = "https",
      address = "*:8443",
      https = (
        options = (
          forwardedProtoHeader = "X-Forwarded-Proto",
          injectResponseHeaders = [
            (name = "Strict-Transport-Security", value = "max-age=31536000"),
          ],
        ),
        tlsOptions = (
          keypair = (
            privateKey = embed "server-key.pem",
            certificateChain = embed "server-cert.pem",
          ),
          trustBrowserCas = true,
          minVersion = tls1Dot2,
        ),
      ),
      service = "main"
    ),
  ]
);

const mainWorker :Workerd.Worker = (
  serviceWorkerScript = embed "worker.js",
  compatibilityDate = "2023-02-28",
);

Next steps

Services

Configure services to handle requests

Workers

Set up worker services

Build docs developers (and LLMs) love