---
title: "Plugins"
description: "Hono and Elysia plugins, request context, and the append-style XFF trust model."
---

> Documentation Index
> Fetch the complete documentation index at: https://logbun-docs.abshahin.workers.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

Plugins attach request context (`userAgent`, optional `ipAddress`) to `auditLog.fire` / `auditLog.fireAsync`.

They expose **both**:

| Method | Behavior |
|--------|----------|
| `auditLog.fire` | Never-throws fire-and-forget |
| `auditLog.fireAsync` | Awaitable enqueue / WAL; may reject |

Optional `getTenantId` fills `tenantId` when the handler omits it (does not override an explicit `input.tenantId`). Resolve from an authenticated session or verified JWT.

Usage: [Hono](/guides/hono), [Elysia](/guides/elysia).

## IP trust model

Plugins default `trustedProxyCount` to `0` (safe): `X-Forwarded-For` and `X-Real-IP` are ignored and `ipAddress` stays undefined unless the handler passes it.

Logbun implements **append-style** XFF (nginx `$proxy_add_x_forwarded_for`, AWS ALB): each trusted hop **appends** the TCP client it saw. The last hop is that TCP client, not the proxy’s own identity.

| `trustedProxyCount` | Behavior |
|---------------------|----------|
| `0` (default) | Ignore `X-Forwarded-For` and `X-Real-IP`. `ipAddress` is undefined. |
| `≥ 1` | Parse XFF (comma-separated, trimmed). Client = `parts[parts.length - trustedProxyCount]` when `parts.length >= N`. A short list (`length < N`) stays undefined. |

Example: client `203.0.113.50` sent a spoofed `X-Forwarded-For: 1.1.1.1`. One trusted proxy appended the real TCP client → `1.1.1.1, 203.0.113.50`. With `trustedProxyCount: 1` Logbun returns `203.0.113.50` (the hop the proxy added), **not** `1.1.1.1`.

This is **not** Express `app.set('trust proxy', N)` / skip-N identities. In that model the rightmost N entries are treated as the proxies themselves, so the client index is `length - 1 - N` and the same header with N=1 would return the spoofed `1.1.1.1`.

`X-Real-IP` is a **last-resort** fallback only when the XFF header is **missing** (`null` / `undefined` / empty string). A whitespace-only XFF value is present, so there is no `X-Real-IP` fallback; after trim it usually has fewer than N hops and stays undefined. The header is spoofable unless the edge overwrites it.

Set `trustedProxyCount` to the number of reverse proxies **you control** that append to XFF. Do not trust XFF on the open internet without a trusted edge.

Implementation: `extractClientIp` in `src/utils/client-ip.ts` (not a root export).

## Exports

From `logbun/plugins/hono`: `createAuditMiddleware`, `AuditMiddlewareOptions`, `HonoAuditLog`, `LogbunHonoVariables`.

From `logbun/plugins/elysia`: `auditPlugin`, `AuditPluginOptions`, `extractWaitUntil`.

Source: https://logbun-docs.abshahin.workers.dev/reference/plugins/index.mdx
