# Server and Security Configuration

Configure server runtime, secure mode, request size limits, tokenization, and rate limiting in Blnk.

This page covers the configuration used to control how the Blnk server listens for requests, protects access to the API, and enables tokenization for sensitive identity fields.

## Server settings

Use the server settings below to configure how Blnk exposes its API and enforces authentication.

<CodeGroup>
```bash blnk.env
BLNK_SERVER_SECURE=false
BLNK_SERVER_SECRET_KEY=
BLNK_SERVER_PORT=5001
BLNK_METRICS_BEARER_TOKEN=
```

```json blnk.json
{
  "server": {
    "secure": false,
    "secret_key": "",
    "port": "5001",
    "metrics_bearer_token": ""
  }
}
```
</CodeGroup>

<ParamField name="BLNK_SERVER_SECURE" default="false">
Enables additional secure-mode protections for the server.
</ParamField>
<ParamField name="BLNK_SERVER_SECRET_KEY">
Secret used for signing and other cryptographic operations.
</ParamField>
<ParamField name="BLNK_SERVER_PORT" default="5001">
The port Blnk listens on for incoming HTTP or HTTPS requests.
</ParamField>
<ParamField name="BLNK_METRICS_BEARER_TOKEN">
Bearer token required to access `/metrics` when set. See [Metrics endpoint](#metrics-endpoint).
</ParamField>

### `BLNK_SERVER_SECURE`

This controls whether API authentication is enforced when you make requests to the server. When set to `false`, Blnk skips authentication checks. 

When set to `true`, requests must authenticate via `X-Blnk-Key` header using one of the following:

- the master key, `BLNK_SERVER_SECRET_KEY`
- a stored API key

### `BLNK_SERVER_SECRET_KEY`

This is required for any secure Blnk deployment. It is used in two places in Blnk:

1. As the master API key for authenticated requests to the server
2. As the HMAC signing secret for outgoing webhooks and hook callbacks.

This means the same secret affects both request authentication and webhook signature validation on systems receiving Blnk webhooks.

<Warning>
Make sure to keep `BLNK_SERVER_SECRET_KEY` out of version control. Store it in a secret manager or inject it through environment variables in production.
</Warning>

### Best practices

1. Set `BLNK_SERVER_SECURE=true` in any real deployment.
2. Use a strong secret for `BLNK_SERVER_SECRET_KEY`, and make sure to store secrets outside version control.
3. Keep the server secret stable within an environment unless you are prepared to update any systems that verify webhook signatures.

### Metrics endpoint

When [monitoring export](/operating/monitoring) is enabled, Blnk serves Prometheus metrics at `GET /metrics` on the API port and on the [worker monitoring port](/operating/monitoring-port). Set `metrics_bearer_token` to require `Authorization: Bearer <token>` on scrape requests.

| `server.secure` | Token set | `/metrics` access |
| :-- | :-- | :-- |
| `false` | no | Open |
| `false` | yes | Bearer required |
| `true` | yes | Bearer required |
| `true` | no | Blocked |

The same rules apply on the worker monitoring port. Auth failures return structured JSON - see [API error codes](/operating/error-codes).

## HTTPS settings

Use these settings to serve the API over HTTPS. TLS is off by default.

<Info>
Honoured again from Blnk Core 0.15.4. Through 0.12.x the flag worked. From 0.13.0 through 0.15.3 it was ignored and the server always served plaintext HTTP. See the [0.15.4 migration guide](/migrations/core/v15-4-migration#serverssl-starts-https).
</Info>

<CodeGroup>
```bash blnk.env
BLNK_SERVER_SSL=false
BLNK_SERVER_SSL_DOMAIN=
BLNK_SERVER_SSL_EMAIL=
BLNK_CERT_STORAGE_PATH=/var/lib/blnk/certs
```

```json blnk.json
{
  "server": {
    "ssl": false,
    "domain": "",
    "ssl_email": "",
    "cert_storage_path": "/var/lib/blnk/certs",
    "port": "5001"
  }
}
```
</CodeGroup>

<ParamField name="BLNK_SERVER_SSL" default="false">
When `true`, Blnk starts an HTTPS listener on `server.port` and obtains a certificate for `server.domain`. When `false`, Blnk serves plaintext HTTP.
</ParamField>
<ParamField name="BLNK_SERVER_SSL_DOMAIN" default="localhost">
Domain used to issue the certificate. Point this hostname at the server before you enable SSL. When empty, Blnk defaults to `localhost`.
</ParamField>
<ParamField name="BLNK_SERVER_SSL_EMAIL">
Email Let's Encrypt uses for certificate expiry notices.
</ParamField>
<ParamField name="BLNK_CERT_STORAGE_PATH" default="/var/lib/blnk/certs">
Directory where issued certificates are stored. The process must be able to write here.
</ParamField>

### How `server.ssl` works

When `ssl` is `false`, Blnk serves plaintext HTTP on `server.port`.

When `ssl` is `true`, Blnk:

1. Starts an HTTPS listener on the same `server.port` (not a separate TLS port).
2. Obtains a certificate for `server.domain` with Let's Encrypt (certmagic).
3. Writes certificates to `cert_storage_path`.
4. Logs the scheme (`https`) on startup so you can confirm TLS is on.
5. Uses the same graceful shutdown path as the HTTP listener.

If a certificate cannot be issued, the server **fails to start**. It does not fall back to plaintext HTTP. A certificate failure names the domains in the error instead of exiting from a background goroutine.

<Warning>
If you left `"ssl": true` in `blnk.json` (or `BLNK_SERVER_SSL=true`) while your clients still use `http://`, those clients will fail the TLS handshake after you upgrade to 0.15.4. Set `ssl` to `false` to keep HTTP, or finish the HTTPS setup before you deploy.
</Warning>

## Tokenization settings

Use tokenization settings to enable encryption and token generation when using the [PII Tokenization](/identities/pii-tokenization) feature.

<CodeGroup>
```bash blnk.env
BLNK_TOKENIZATION_SECRET="blnk-pii-secret"
```

```json blnk.json
{
  "tokenization_secret": "blnk-pii-secret"
}
```
</CodeGroup>

<ParamField name="BLNK_TOKENIZATION_SECRET">
Enables tokenization for sensitive identity fields. Must be exactly 32 bytes long. Used as the cryptographic secret for tokenization operations. Disabled when unset.
</ParamField>

### Tokenization behaviour

Tokenization is only enabled when `BLNK_TOKENIZATION_SECRET` is set and is exactly 32 bytes long. If the secret is missing, tokenization is disabled. If the secret is set but not 32 bytes long, Blnk does not fail startup, but tokenization operations may fail when called.

When enabled, Blnk uses this secret for AES-GCM encryption in standard tokenization and HMAC-based seeding for format-preserving tokenization.

<Note>
**Note:** Store this secret securely and keep it stable for each environment. If you change it after data has already been tokenized, previously tokenized values may no longer detokenize correctly.
</Note>

## Request and payload limits

Use these settings to limit request body size and upload size.

<CodeGroup>
```bash blnk.env
BLNK_SERVER_MAX_REQUEST_BODY_SIZE_MB=5
BLNK_SERVER_MAX_UPLOAD_SIZE_MB=256
```

```json blnk.json
{
  "server": {
    "max_request_body_size_mb": 5,
    "max_upload_size_mb": 256
  }
}
```

</CodeGroup>

<ParamField name="BLNK_SERVER_MAX_REQUEST_BODY_SIZE_MB" default="5">
Max size in MB for JSON request bodies.
</ParamField>
<ParamField name="BLNK_SERVER_MAX_UPLOAD_SIZE_MB" default="256">
Max size in MB for multipart uploads. Applies to [reconciliation upload](/reference/upload-data).
</ParamField>

## How limits are applied

| Request type | Config key | When exceeded |
| :-- | :-- | :-- |
| JSON API requests | `BLNK_SERVER_MAX_REQUEST_BODY_SIZE_MB` | `400` with `GEN_MALFORMED_REQUEST` and message `http: request body too large`. |
| Multipart uploads | `BLNK_SERVER_MAX_UPLOAD_SIZE_MB` | `413` with `GEN_PAYLOAD_TOO_LARGE` on reconciliation file upload. |

<Note>
These size limits are separate from per-endpoint item limits. A request can be within the item-count limit and still exceed the body-size limit. 

For example, a bulk transaction request with the accepted count may exceed 5 MB if each transaction contains large metadata or long field values.
</Note>

## Rate limiting

Use rate limiting settings to protect the API from abuse and to control traffic spikes more predictably.

<CodeGroup>
```bash blnk.env
BLNK_RATE_LIMIT_RPS=5000000
BLNK_RATE_LIMIT_BURST=10000000
BLNK_RATE_LIMIT_CLEANUP_INTERVAL_SEC=10800
```

```json blnk.json
{
  "rate_limit": {
    "requests_per_second": 5000000,
    "burst": 10000000,
    "cleanup_interval_sec": 10800
  }
}
```
</CodeGroup>

<ParamField name="BLNK_RATE_LIMIT_RPS" default="5000000">
Maximum requests allowed per second per client.
</ParamField>
<ParamField name="BLNK_RATE_LIMIT_BURST" default="10000000">
Maximum short burst allowed above the RPS limit.
</ParamField>
<ParamField name="BLNK_RATE_LIMIT_CLEANUP_INTERVAL_SEC" default="10800">
Cleanup interval for expired rate-limit data, in seconds.
</ParamField>

### Rate limiting behaviour

If both `BLNK_RATE_LIMIT_RPS` and `BLNK_RATE_LIMIT_BURST` are unset, Blnk applies its built-in defaults.

If you set only one of those two values, Blnk derives the other automatically:

- if only `BLNK_RATE_LIMIT_RPS` is set, `burst` defaults to `2 * RPS`
- if only `BLNK_RATE_LIMIT_BURST` is set, `requests_per_second` defaults to `burst / 2`

<Tip>
**Tip:** Start with the defaults unless you have a clear traffic policy or abuse-prevention requirement.
</Tip>

<RelatedTopics
  items={[
    { title: "Enable HTTPS", href: "/operating/enable-https" },
    { title: "Secure Blnk", href: "/operating/secure-blnk" },
    { title: "API keys overview", href: "/operating/api-keys/overview" },
    { title: "Webhook security", href: "/webhooks/overview#webhook-security-signature-verification" },
    { title: "0.15.4 migration", href: "/migrations/core/v15-4-migration" },
  ]}
/>