# Server Options

> Provide additional options to customize listening server.

When starting a new server, in addition to main `fetch` handler, you can provide additional options to customize listening server.

```js
import { serve } from "srvx";

serve({
  // Generic options
  port: 3000,
  hostname: "localhost",

  // Runtime specific options
  node: {},
  bun: {},
  deno: {},

  // Main server handler
  fetch: () => new Response("👋 Hello there!"),
});
```

There are two kind of options:

- Generic options: Top level options are intended to have exactly same functionality regardless of runtime
- Runtime specific: Allow customizing more runtime specific options

## Generic Options

### `port`

The port server should be listening to.

Default is value of `PORT` environment variable or `3000`.

<tip>

You can set the port to `0` to use a random port.

</tip>

### `hostname`

The hostname (IP or resolvable host) server listener should bound to.

When not provided, server will **listen to all network interfaces** by default.

<important>

If you are running a server that should not be exposed to the network, use `localhost`.

</important>

### `reusePort`

Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.

<note>

Despite Node.js built-in behavior that has `exclusive` flag enabled by default, srvx uses non-exclusive mode for consistency.

</note>

### `silent`

If enabled, no server listening message will be printed (enabled by default when `TEST` environment variable is set).

### `protocol`

The protocol to use for the server.

Possible values are `http` or `https`.

If `protocol` is not set, Server will use `http` as the default protocol or `https` if both `tls.cert` and `tls.key` options are provided.

### `tls`

TLS server options.

**Example:**

```js
import { serve } from "srvx";

serve({
  tls: { cert: "./server.crt", key: "./server.key" },
  fetch: () => new Response("👋 Hello there!"),
});
```

**Options:**

- `cert`: Path or inline content for the certificate in PEM format (required).
- `key`: Path or inline content for the private key in PEM format (required).
- `passphrase`: Passphrase for the private key (optional).

<tip>

You can pass inline `cert` and `key` values in PEM format starting with `-----BEGIN `.

</tip>

Client certificates (mutual TLS) are available through the [`mtls()` plugin](/guide/tls#mutual-tls-mtls).

<read-more to="/guide/tls" title="TLS & mutual TLS">



</read-more>

### `onError`

Runtime agnostic error handler.

<note>

This handler will take over the built-in error handlers of Deno and Bun.

</note>

**Example:**

```js
import { serve } from "srvx";

serve({
  fetch: () => new Response("👋 Hello there!"),
  onError(error) {
    return new Response(`<pre>${error}\n${error.stack}</pre>`, {
      headers: { "Content-Type": "text/html" },
    });
  },
});
```

### `maxRequestBodySize`

Maximum allowed size **in bytes** for the request body. Defaults to `undefined` (no limit).

As the body is read, its accumulated length is tracked and, once it exceeds the limit, reading is aborted and rejects with a `413`-style error. The error carries `statusCode: 413`, `status: 413` and `code: "ERR_BODY_TOO_LARGE"`, so a handler (or [`onError`](#onerror)) can map it to an HTTP `413 Payload Too Large` response.

The limit covers both buffered reads (`request.text()` / `request.json()`) and the streamed body (`request.body`, and therefore `request.arrayBuffer()` / `.blob()` / `.bytes()` / `.formData()`).

**Example:**

```js
import { serve } from "srvx";

serve({
  maxRequestBodySize: 1024 * 1024, // 1 MiB
  fetch: async (request) => {
    try {
      return Response.json(await request.json());
    } catch (error) {
      if (error.code === "ERR_BODY_TOO_LARGE") {
        return new Response("Payload Too Large", { status: 413 });
      }
      throw error;
    }
  },
});
```

<note>

Runtime support:

- **Node**: enforced by srvx (the request body stream is size-limited).
- **Bun**: forwarded to Bun's native [`maxRequestBodySize`](https://bun.sh/docs/api/http), enforced by Bun (responds with `413` before the handler runs).
- **Deno**: enforced by srvx (`Deno.serve` has no native option).

</note>

### `trustProxy`

Whether to trust `X-Forwarded-*` headers (`X-Forwarded-Proto`, `X-Forwarded-Host`, `X-Forwarded-For`, and the HTTP/2 `:scheme`) when deriving `request.url` and `request.ip`. Defaults to `false`.

Any client can send `X-Forwarded-Proto: https`, `X-Forwarded-Host` or `X-Forwarded-For`, so trusting them lets a request masquerade as `https:`, forge its host, or spoof its client IP. Only enable this when a proxy you control sits in front and overwrites the headers.

- `false` (default): ignore the headers; use the real connection protocol, the on-the-wire `Host` header and the socket peer address.
- `true`: always trust the headers.
- `"loopback"`: trust them only when the proxy connects from a loopback address (`127.0.0.0/8` or `::1`).
- `string[]`: trust them only when the proxy's address is in the list.

**Example:**

```js
import { serve } from "srvx";

serve({
  // Behind a reverse proxy you control (e.g. Nginx, a load balancer):
  trustProxy: true,
  fetch: (request) => new Response(new URL(request.url).protocol),
});
```

<note>

Applies to the Node, AWS Lambda, Bun and Deno adapters.

</note>

## Runtime Specific Options

### Node.js

**Example:**

```js
import { serve } from "srvx";

serve({
  node: {
    maxHeadersize: 16384 * 2, // Double default
    ipv6Only: true, // Disable dual-stack support
    // http2: false // Disable http2 support (enabled by default in TLS mode)
  },
  fetch: () => new Response("👋 Hello there!"),
});
```

<read-more>

See Node.js documentation for [ServerOptions](https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener) and [ListenOptions](https://nodejs.org/api/net.html#serverlistenoptions-callback) for all available options.

</read-more>

### Bun

**Example:**

```js
import { serve } from "srvx";

serve({
  bun: {
    error(error) {
      return new Response(`<pre>${error}\n${error.stack}</pre>`, {
        headers: { "Content-Type": "text/html" },
      });
    },
  },
  fetch: () => new Response("👋 Hello there!"),
});
```

<read-more to="https://bun.sh/docs/api/http">

See Bun HTTP documentation for all available options.

</read-more>

### Deno

**Example:**

```js
import { serve } from "srvx";

serve({
  deno: {
    onError(error) {
      return new Response(`<pre>${error}\n${error.stack}</pre>`, {
        headers: { "Content-Type": "text/html" },
      });
    },
  },
  fetch: () => new Response("👋 Hello there!"),
});
```

<read-more to="https://docs.deno.com/api/deno/~/Deno.ServeOptions">

See Deno serve documentation for all available options.

</read-more>
