docs
Configuration
okuri reads an optional TOML file plus the environment. Point the server at
a file with okuri serve --config okuri.toml or OKURI_CONFIG=okuri.toml.
The file is optional: defaults plus the environment is a supported way to
run.
Precedence is defaults, then file, then environment. The environment wins because it is the layer a scheduler controls, while the file is the layer an image bakes in.
Unknown keys are rejected, so a typo fails at startup instead of silently keeping a default.
The repository ships a fully commented reference at
okuri.example.toml.
[store]
| key | default | env | notes |
|---|---|---|---|
bucket |
none, required | OKURI_S3_BUCKET |
the bucket every queue lives in |
endpoint |
provider default | OKURI_S3_ENDPOINT |
override for MinIO, R2, and other S3-compatible stores |
region |
none | OKURI_S3_REGION |
the region to sign for |
access_key |
none | OKURI_S3_ACCESS_KEY |
leave unset with secret_key to use the provider credential chain |
secret_key |
none | OKURI_S3_SECRET_KEY |
see above |
[server]
| key | default | env |
|---|---|---|
admin_addr |
0.0.0.0:9090 |
OKURI_ADMIN_ADDR |
grpc_addr |
0.0.0.0:8080 |
OKURI_GRPC_ADDR |
drain_deadline_ms |
30000 |
OKURI_DRAIN_DEADLINE_MS |
readiness_probe_interval_ms |
5000 |
OKURI_READINESS_PROBE_INTERVAL_MS |
receive_poll_interval_ms |
500 |
OKURI_RECEIVE_POLL_INTERVAL_MS |
receive_max_wait_ms |
20000 |
OKURI_RECEIVE_MAX_WAIT_MS |
receipt_handle_key |
none, required | OKURI_RECEIPT_HANDLE_KEY |
receipt_handle_verify_keys |
[] |
OKURI_RECEIPT_HANDLE_VERIFY_KEYS |
namespace |
default |
OKURI_NAMESPACE |
api_keys |
none, required | OKURI_API_KEYS |
sqs_credentials |
none, required | OKURI_SQS_CREDENTIALS |
sqs_endpoint |
http://localhost:8080 |
OKURI_SQS_ENDPOINT |
sqs_region |
us-east-1 |
OKURI_SQS_REGION |
sequencer_enabled |
false |
OKURI_SEQUENCER_ENABLED |
sequencer_ttl_ms |
15000 |
OKURI_SEQUENCER_TTL_MS |
sequencer_renew_interval_ms |
5000 |
OKURI_SEQUENCER_RENEW_INTERVAL_MS |
The required keys
Three keys have no default and reject empty values, because these failures are better discovered at startup than at the first request.
receipt_handle_key signs receipt handles: 32 bytes in base64, from
head -c 32 /dev/urandom | base64. Every node in a fleet carries the same
one, so a handle issued by whichever node served the receive is honored by
whichever node the load balancer sends the ack to.
receipt_handle_verify_keys holds keys that no longer sign but are still
honored, which is what makes key rotation possible: put the new key in
receipt_handle_key, leave the old one in the verify list for at least the
longest visibility timeout plus a grace period, then drop it.
api_keys are the bearer keys the native gRPC and HTTP/JSON surfaces
accept, each scoped to a namespace:
[[server.api_keys]]
namespace = "default"
key = "..."
As an environment variable, OKURI_API_KEYS takes comma-separated
namespace:key pairs.
sqs_credentials are the SigV4 credentials the SQS surface accepts,
separate from the API keys and never derived from them:
[[server.sqs_credentials]]
namespace = "default"
access_key_id = "..."
secret = "..."
As an environment variable, OKURI_SQS_CREDENTIALS takes comma-separated
namespace:access-key-id:secret triples.
Namespaces
namespace scopes both storage and signatures. Two deployments pointed at
one bucket under different namespaces share the bucket and nothing else,
even where they use the same queue names: messages, segments, leases,
tombstones, and purge watermarks are all namespace-scoped. Namespace names follow the queue-name rule:
[a-z0-9_-], at most 64 bytes.
SQS addressing
sqs_endpoint is the root of every queue URL the compat surface hands
out. It is the address clients use to reach this node, which is a
different thing from the address this node uses to reach its bucket: a
node behind a load balancer has to advertise the balancer’s address.
sqs_region is the region every ARN names. Both settings exist separately
from [store] for that reason.
Per-queue configuration
Queue-level settings live in the queue’s manifest object in the bucket, not
in the server config: visibility_timeout_ms, retention_ms, and
max_receive_count. They are exposed through SQS GetQueueAttributes and
SetQueueAttributes as well as the native API.
Queue names everywhere follow one rule: non-empty, at most 64 bytes,
[a-z0-9_-] only. The -dlq suffix is reserved, so a queue that wants a
reachable dead-letter queue is limited to 60 bytes of name.