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.
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.
[app:proxy-server]
server_runtime = async
workers = auto
process_workers = 1
max_connections = 131072
max_active_requests = 2048
client_timeout = 60The 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.
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.
Account freeze
The account-freeze filter denies every method for explicitly named accounts, including the S3 dispatch path.
[filter:account_freeze]
use = egg:swift#account_freeze
frozen_accounts = AUTH_exampleAn 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 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.