---
title: "Configuration reference"
description: "Fail-closed INI loading, the async HTTP worker model, independent concurrency budgets, middleware configuration, and unsupported settings."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.myswift.rs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration reference

Peregrine reads Swift-style INI files (`swift.conf`, `proxy-server.conf`, and
per-service configuration). Reusing a file does not imply that every Python
option has the same meaning. Treat startup validation and the effective
configuration as part of a deployment gate.

> **Candidate documentation**
>
> The async server semantics on this page describe candidate commit
> `17adf0bfa78b30b2a7eed9f39836e0d63c715d2c`. They have source and isolated-lab
> evidence, and G6 is GREEN; G7 is not accepted. They are not a production
> acceptance claim.

## Startup rules

The loader fails closed when continuing would create an ambiguous security,
routing, or storage state.

| Input | Result |
|---|---|
| unknown pipeline filter | startup failure; there is no dynamic Paste plugin loader |
| `server_runtime=legacy`, `sync`, `blocking`, or `eventlet` | startup failure; production serve is async HTTP/1.1 only |
| invalid storage policy, ring, or hash configuration | exit before binding a service socket |
| malformed numeric filter option | filter construction fails instead of silently selecting another value |
| duplicate or malformed container-sync realm entry | configuration error |
| empty `account_freeze.frozen_accounts` | configuration error |

Some ordinary HTTP-server values retain a documented compatibility default
when absent or unusable. Do not generalize that behavior to policy, pipeline,
or security settings.

## Process, runtime, connection, and request limits

The production path is Hyper HTTP/1.1 on a Tokio multi-thread runtime. An idle
keep-alive connection is a pending task on the reactor; it does not reserve one
OS thread.

The candidate does **not yet map the historical knobs uniformly across all four
servers**. Capacity review must be service-specific:

| Service | Current candidate mapping |
|---|---|
| proxy | numeric `workers` directly selects Tokio runtime threads; unset, `auto`, or `0` uses CPU count × 16 clamped to 16–128. `process_workers` controls OS prefork. `max_connections` and `max_active_requests` are explicit independent admissions; `max_clients` is the legacy request default and also contributes to the connection queue. |
| account / container | numeric `workers > 0` is still adapted as `workers × max_clients`, clamped to 128 Tokio threads; `max_clients` also sizes the connection queue. With no numeric workers, the shared CPU-scaled runtime default applies. These mains do not yet expose the proxy's independent process/connection/request knobs. |
| object | with `servers_per_port = 0`, numeric `workers > 0` is likewise `workers × max_clients`, clamped to 128; with `servers_per_port > 0`, one OS child is supervised per port/worker slot, `workers` is ignored, and each child maps `max_clients` to its capped runtime pool and queue. |

All of these paths use async Hyper/Tokio serving; the legacy sizing formula
does not mean one thread per idle connection. It does mean that the configuration
surface has not completed the independent-budget model across every service.
Treat this as an explicit G3/G7 sizing and observability item, not as a solved
capacity contract.

Proxy-specific settings:

| Setting | Meaning | Default or fallback |
|---|---|---|
| `workers` | proxy Tokio runtime worker threads | CPU count × 16, clamped to 16–128, when unset/non-numeric/`0` |
| `process_workers` | proxy OS prefork process count | 1 |
| `worker_model=process` or `prefork` | treats numeric proxy `workers` as the process count | explicit compatibility mode |
| `worker_model=eventlet` | proxy-only historical alias for OS prefork sizing; it does **not** create greenlets | explicit compatibility mode |
| `max_connections` | proxy accepted-connection admission cap | `0` derives from runtime threads plus connection queue |
| `max_active_requests` | proxy in-flight request cap | `max_clients` |
| `max_clients` | legacy proxy request default and connection-queue input | 1024 |
| `client_timeout` | socket inactivity timeout, in seconds | 60 |
| `reuse_port` | listener `SO_REUSEPORT` | false |

The architectural target is still independent connection admission, active
requests, traffic classes, storage jobs, database jobs, and memory. Do not use a
single thread-count calculation as fleet capacity.

```ini
[app:proxy-server]
server_runtime = async
workers = auto
process_workers = 1
max_connections = 131072
max_active_requests = 2048
client_timeout = 60
```

The values above illustrate the shape only; they are not fleet sizing advice.
Admission limits must be derived from measured file-descriptor, memory, CPU,
device, and backend budgets. See [Concurrency runtime](/concurrency).

## Request and upload bounds

The HTTP layer also carries finite protocol and lifetime bounds: request-line,
header-line/count/total-size limits, `head_deadline`, maximum requests per
connection, progress-aware body-idle timeout, total upload lifetime, client
write timeout, and graceful-shutdown deadline. A progress timeout refreshes
when bytes arrive; an upload lifetime does not.

Do not disable both kinds of upload deadline. Slow progress and an indefinitely
long upload are separate failure modes.

## `[app:proxy-server]`

| Setting | Behavior |
|---|---|
| `account_autocreate` | when enabled, container creation first creates and then rechecks a missing account; inability to make it visible fails closed |
| `allow_account_management` | gates account PUT and DELETE |
| `workers`, `process_workers`, `worker_model` | proxy execution topology described above |
| `max_connections`, `max_active_requests`, `max_clients` | proxy connection/request admission described above |
| ring/policy paths | Swift ring and storage-policy inputs; EC policies require Linux and the `ec` build |
| `pipeline_strict` | rejects pipeline/configuration issues instead of silently accepting them |

## `[filter:s3api]`, `[filter:s3token]`, and auth filters

| Setting | Meaning |
|---|---|
| `location` | region returned by GetBucketLocation |
| `storage_domain` / `storage_domains` | virtual-host bucket domains |
| `dns_compliant_bucket_names` | bucket-name validation policy |
| `allowable_clock_skew` | SigV2/SigV4 timestamp rejection window |
| `enable_extended_subresources` | enables the extended subresource group |
| `anonymous_account` | maps unsigned S3-shaped GET/HEAD to one Swift account; container ACLs still authorize the read |
| `reseller_prefix` | account prefix used by s3token/Keystone mapping |

Credentials and secret-handling guidance is in [Authentication](/authentication).

## Account freeze

The account-freeze filter denies every method for explicitly named accounts,
including the S3 dispatch path.

```ini
[filter:account_freeze]
use = egg:swift#account_freeze
frozen_accounts = AUTH_example
```

An empty list is rejected. Keep incident-specific account names and evidence
out of reusable examples.

## Middleware pipeline

Configured names resolve only to compiled Rust filters or documented named
passthrough slots. Peregrine does not load arbitrary Python/Paste code from
`use = egg:...`. Unknown names fail closed. A matched name is not sufficient
proof of semantic parity; check [Compatibility boundaries](/parity) and the
official-suite evidence for that path.

## Known unsupported or changed options

| Service | Option or behavior | Status |
|---|---|---|
| object | `eventlet_tpool_num_threads` | eventlet-specific; unsupported |
| object | `use_splice` | not an eventlet compatibility path |
| container | legacy `allow_versions` | use configured versioned-writes/S3 versioning paths where validated |
| proxy | arbitrary Paste plugins | unsupported; no dynamic loader |
| all | `server_runtime=legacy` | removed; hard startup error |

If a required key is neither documented nor exercised by a source-level or
live test, treat it as unverified. Run `swift-deploy audit`, configuration
validation, a non-mutating preflight, and the relevant compatibility gate
before rollout.

Source: https://docs.myswift.rs/configuration/index.mdx
