How to Set Up Bun.serve with TLS/SSL Configuration for Secure HTTPS Servers

To enable HTTPS in Bun.serve, pass a tls property in the server options object containing cert and key fields, or provide an array of TLS configurations for multi-domain SNI support.

Bun.serve creates a high-performance HTTP server in the oven-sh/bun runtime. Adding TLS/SSL configuration transforms it into a secure HTTPS server capable of handling encrypted traffic, client certificate authentication, and Server Name Indication (SNI) for multi-domain hosting. The implementation relies on native OpenSSL bindings and exposes these features through the tls option defined in packages/bun-types/serve.d.ts.

Basic HTTPS Configuration

The minimal configuration requires two fields: cert for the PEM-encoded certificate chain and key for the private key. According to the TypeScript definitions in packages/bun-types/bun.d.ts, these accept BunFile objects, strings, or BufferSource instances.

const server = Bun.serve({
  fetch(req) {
    return new Response("🔒 Secure connection established");
  },
  
  tls: {
    cert: Bun.file("server.crt"),
    key: Bun.file("server.key"),
  }
});

console.log(`Listening on https://${server.hostname}:${server.port}`);

The underlying implementation in src/js/node/_http_server.ts handles the creation of the TLS listener when this configuration is present.

Multi-Domain SNI Support

For servers hosting multiple domains on a single IP address, supply an array of TLSOptions objects. Each configuration must include a serverName field to match the client's SNI request, as implemented in src/bun.js/api/server/SSLConfig.bindv2.ts.

const server = Bun.serve({
  fetch(req) {
    return new Response(`Hello from ${new URL(req.url).hostname}`);
  },
  
  tls: [
    {
      serverName: "example.com",
      cert: Bun.file("example.com.crt"),
      key: Bun.file("example.com.key"),
    },
    {
      serverName: "api.example.org",
      cert: Bun.file("api.example.org.crt"),
      key: Bun.file("api.example.org.key"),
      ca: [Bun.file("intermediate.pem"), Bun.file("root.pem")],
    }
  ]
});

When the array format is used, Bun automatically selects the appropriate certificate based on the hostname provided in the ClientHello message.

Advanced TLS Options

The tls object supports several advanced security parameters defined in packages/bun-types/bun.d.ts (lines 373-455):

  • ca – Overrides the default Mozilla CA bundle with custom trusted certificates
  • requestCert – Enables mutual TLS by requesting client certificates
  • rejectUnauthorized – When false, accepts self-signed or invalid client certificates (default: true)
  • dhParamsFile – Specifies custom Diffie-Hellman parameters for key exchange
  • passphrase – Decrypts password-protected private keys
  • lowMemoryMode – Reduces OpenSSL memory usage at the cost of performance
tls: {
  cert: Bun.file("server.crt"),
  key: Bun.file("server.key"),
  ca: Bun.file("custom-ca.pem"),
  requestCert: true,
  rejectUnauthorized: false, // Allow self-signed certs for testing
  dhParamsFile: Bun.file("dhparams.pem"),
  passphrase: "secret-key-password"
}

Common Configuration Pitfalls

Missing serverName in SNI arrays – When providing an array of TLS configurations, omitting the serverName field causes Bun to fall back to the first certificate for all connections.

Certificate chain ordering – The cert field must include the server certificate followed by intermediate certificates in the correct order. Mismatched cert/key pairs when using multiple entries will cause handshake failures.

CA bundle replacement – Supplying the ca option completely replaces the built-in Mozilla certificate store. You must explicitly include all necessary root and intermediate certificates.

Port assignment – Bun.serve defaults to port 0 (OS-assigned). For HTTPS servers, explicitly set port: 443 or your desired port to avoid confusion.

Summary

  • Add a tls object to Bun.serve options containing cert and key to enable HTTPS
  • Use an array of TLS configurations with serverName fields for multi-domain SNI support
  • Reference implementation files: packages/bun-types/serve.d.ts (API), packages/bun-types/bun.d.ts (TLSOptions), and src/bun.js/api/server/SSLConfig.bindv2.ts (native bindings)
  • Enable mutual TLS with requestCert: true and control client validation with rejectUnauthorized
  • Override default CA trust stores using the ca field, but include all required certificates

Frequently Asked Questions

How do I enable HTTPS in Bun.serve?

Pass a tls configuration object in the Bun.serve options containing your cert (certificate chain) and key (private key). Both fields accept Bun.file() references, strings, or buffers. The server automatically starts in HTTPS mode when this property is present.

Can I host multiple domains with different SSL certificates on one Bun server?

Yes. Provide an array of TLS configuration objects instead of a single object. Each element must include a serverName field matching the domain name. Bun uses the Server Name Indication (SNI) extension to select the appropriate certificate during the TLS handshake.

What file formats does Bun.serve support for TLS certificates?

Bun accepts standard PEM-encoded certificates and keys. You can load these using Bun.file("path/to/cert.pem"), provide them as strings containing the PEM content, or pass BufferSource objects. Encrypted private keys are supported when you provide the passphrase option.

How do I configure mutual TLS (mTLS) authentication?

Set requestCert: true in your TLS options to require clients to present certificates. Combine this with rejectUnauthorized: true (the default) to validate client certificates against your specified ca bundle. This enforces bidirectional authentication between client and server.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →