okengine 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/manifest.v1.schema.json +9 -1
- package/package.json +3 -3
- package/site/content/docs/console/runs.mdx +10 -0
- package/site/content/docs/console/traces.mdx +4 -0
- package/site/content/docs/elements/ai.mdx +54 -32
- package/site/content/docs/elements/channel.mdx +105 -14
- package/site/content/docs/elements/clock.mdx +1 -0
- package/site/content/docs/elements/flow.mdx +42 -8
- package/site/content/docs/get-started/basic-usage.mdx +5 -1
- package/site/content/docs/get-started/installation.mdx +9 -5
- package/site/content/docs/meta.json +2 -0
- package/site/content/docs/plugins/otp.mdx +58 -46
- package/site/content/docs/providers/azure-redis.mdx +85 -0
- package/site/content/docs/providers/cockroachdb.mdx +86 -0
- package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
- package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
- package/site/content/docs/providers/elasticache.mdx +92 -0
- package/site/content/docs/providers/index.mdx +101 -0
- package/site/content/docs/providers/memorystore.mdx +89 -0
- package/site/content/docs/providers/meta.json +20 -0
- package/site/content/docs/providers/neon.mdx +115 -0
- package/site/content/docs/providers/redis-cloud.mdx +93 -0
- package/site/content/docs/providers/supabase.mdx +117 -0
- package/site/content/docs/providers/upstash.mdx +91 -0
- package/site/content/docs/providers/yugabytedb.mdx +95 -0
- package/site/content/docs/recipes/caddy.mdx +128 -0
- package/site/content/docs/recipes/cockroachdb.mdx +127 -0
- package/site/content/docs/recipes/dragonfly.mdx +125 -0
- package/site/content/docs/recipes/index.mdx +146 -0
- package/site/content/docs/recipes/llama-cpp.mdx +153 -0
- package/site/content/docs/recipes/mailpit.mdx +136 -0
- package/site/content/docs/recipes/meilisearch.mdx +139 -0
- package/site/content/docs/recipes/meta.json +31 -0
- package/site/content/docs/recipes/ollama.mdx +142 -0
- package/site/content/docs/recipes/openbao.mdx +141 -0
- package/site/content/docs/recipes/pgdog.mdx +137 -0
- package/site/content/docs/recipes/postgres.mdx +136 -0
- package/site/content/docs/recipes/redis.mdx +130 -0
- package/site/content/docs/recipes/rustfs.mdx +148 -0
- package/site/content/docs/recipes/sglang.mdx +105 -0
- package/site/content/docs/recipes/supabase-docker.mdx +145 -0
- package/site/content/docs/recipes/timescale.mdx +129 -0
- package/site/content/docs/recipes/traefik.mdx +136 -0
- package/site/content/docs/recipes/valkey.mdx +121 -0
- package/site/content/docs/recipes/vllm.mdx +106 -0
- package/site/content/docs/recipes/yugabytedb.mdx +135 -0
- package/site/content/docs/reference/cli.md +42 -6
- package/site/content/docs/reference/configuration.mdx +5 -3
- package/site/content/docs/reference/environment-variables.mdx +12 -12
- package/site/content/docs/reference/fx.mdx +38 -4
- package/src/auth/otp-capability.ts +14 -14
- package/src/cli/ai-setup/ai-setup.test.ts +32 -12
- package/src/cli/ai-setup/apply.ts +65 -23
- package/src/cli/ai-setup/catalog.ts +1316 -35
- package/src/cli/ai-setup/detect-ollama.ts +47 -0
- package/src/cli/ai-setup/index.ts +44 -7
- package/src/cli/ai-setup/prompts.ts +430 -486
- package/src/cli/ai-setup/recommend.test.ts +150 -50
- package/src/cli/ai-setup/recommend.ts +118 -101
- package/src/cli/ask-seed.test.ts +68 -0
- package/src/cli/ask-seed.ts +79 -0
- package/src/cli/db-seed-redact.test.ts +25 -0
- package/src/cli/db-seed.ts +36 -7
- package/src/cli/db.test.ts +1 -1
- package/src/cli/db.ts +2 -2
- package/src/cli/dev-controls.test.ts +107 -0
- package/src/cli/dev-controls.ts +354 -0
- package/src/cli/dev-schema-sync.ts +12 -4
- package/src/cli/dev.test.ts +50 -30
- package/src/cli/dev.ts +607 -66
- package/src/cli/drizzle-env.test.ts +40 -6
- package/src/cli/drizzle-env.ts +22 -1
- package/src/cli/ensure-drizzle-config.ts +6 -4
- package/src/cli/hero-meta.test.ts +13 -1
- package/src/cli/hero-meta.ts +28 -6
- package/src/cli/index.ts +5 -0
- package/src/cli/registry.ts +24 -0
- package/src/cli/replay.test.ts +105 -0
- package/src/cli/replay.ts +206 -0
- package/src/compiler/extract.ts +3 -3
- package/src/config/index.ts +3 -3
- package/src/console/server/claim.ts +3 -1
- package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
- package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
- package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/overview/slo.ts +31 -3
- package/src/console/ui/overview/types.ts +6 -0
- package/src/console/ui/runs/errors.test.ts +53 -0
- package/src/console/ui/runs/errors.ts +88 -0
- package/src/console/ui/runs/index.ts +8 -0
- package/src/console/ui/runs/search.ts +16 -0
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
- package/src/docker/ai-model-status.test.ts +101 -0
- package/src/docker/ai-model-status.ts +276 -0
- package/src/docker/compose-health.test.ts +115 -0
- package/src/docker/compose-health.ts +234 -0
- package/src/docker/compose.ts +24 -8
- package/src/docker/derive.ts +35 -9
- package/src/docker/docker.test.ts +304 -12
- package/src/docker/helpers.ts +56 -0
- package/src/docker/index.ts +52 -0
- package/src/docker/ollama-pull.ts +232 -0
- package/src/docker/recipes/cockroach.ts +24 -0
- package/src/docker/recipes/index.ts +32 -0
- package/src/docker/recipes/llama-cpp.ts +273 -0
- package/src/docker/recipes/ollama.ts +19 -23
- package/src/docker/recipes/pgdog.ts +4 -1
- package/src/docker/recipes/postgres.ts +5 -18
- package/src/docker/recipes/sglang.ts +55 -0
- package/src/docker/recipes/supabase.ts +21 -0
- package/src/docker/recipes/timescale.ts +18 -0
- package/src/docker/recipes/vllm.ts +44 -0
- package/src/docker/recipes/yugabyte.ts +23 -0
- package/src/docker/stack-id.test.ts +22 -0
- package/src/docker/stack-id.ts +38 -4
- package/src/docker/types.ts +15 -0
- package/src/drivers/ai-ollama.integration.test.ts +7 -4
- package/src/drivers/signal-engine.ts +10 -0
- package/src/drivers/signal-postgres.ts +24 -2
- package/src/drivers/signal-types.ts +10 -0
- package/src/elements/channel/fallback.test.ts +91 -0
- package/src/elements/channel/hard-bounce.test.ts +82 -0
- package/src/elements/channel/injection.test.ts +153 -0
- package/src/elements/channel/locale-ar.test.ts +102 -0
- package/src/elements/channel/otp-delivery.ts +5 -2
- package/src/elements/channel/receipts-ledger.test.ts +100 -0
- package/src/elements/channel/runtime.ts +24 -1
- package/src/elements/channel/test-helpers.ts +60 -0
- package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
- package/src/elements/store/cache.ts +1 -1
- package/src/elements/store/emit-drizzle.ts +43 -9
- package/src/elements/store/runtime.ts +1 -1
- package/src/elements/store/schema-decl.test.ts +2 -0
- package/src/elements/store/schema-decl.ts +15 -0
- package/src/elements/store/seed.ts +1 -1
- package/src/index.ts +1 -0
- package/src/kernel/app.ts +118 -11
- package/src/kernel/boot-bind/signal.ts +6 -2
- package/src/kernel/boot-bind/store.ts +2 -1
- package/src/kernel/boot.test.ts +6 -5
- package/src/kernel/boot.ts +8 -3
- package/src/kernel/compensate.test.ts +131 -0
- package/src/kernel/correlation.test.ts +108 -0
- package/src/kernel/effect-timing.test.ts +82 -0
- package/src/kernel/flow.ts +38 -0
- package/src/kernel/fx-runs.test.ts +49 -0
- package/src/kernel/fx.test.ts +14 -0
- package/src/kernel/fx.ts +111 -1
- package/src/manifest/types.ts +8 -2
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +3 -3
- package/src/plugins/auth-methods.test.ts +1 -1
- package/src/plugins/index.ts +2 -2
- package/src/plugins/otp.test.ts +21 -19
- package/src/plugins/otp.ts +36 -34
- package/src/plugins/taqnyat.live.test.ts +3 -3
- package/src/runs/collect.ts +3 -0
- package/src/runs/export-otlp.ts +64 -0
- package/src/runs/index.ts +16 -0
- package/src/runs/parquet.ts +9 -0
- package/src/runs/types.ts +5 -0
- package/src/runs/window.test.ts +68 -0
- package/src/runs/window.ts +148 -0
- package/src/runtime/boot-warn.test.ts +45 -0
- package/src/runtime/boot-warn.ts +17 -0
- package/src/runtime/dev-request-log.ts +5 -5
- package/src/term.test.ts +95 -10
- package/src/term.ts +369 -14
- package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
- package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "OpenBao"
|
|
3
|
+
description: "Durable single-node vault — Raft under /openbao/file, OKE_VAULT_URL / OKE_VAULT_TOKEN, host unseal key SPOF."
|
|
4
|
+
icon: "KeyRound"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
OpenBao is the docker/prod Vault driver target — a real secrets service with Raft
|
|
9
|
+
storage, **not** an in-memory `-dev` server. Templates pin
|
|
10
|
+
`vault: "openbao/openbao:2.6.1"` and `drivers.vault.docker/prod: "openbao"`.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Never run OpenBao `-dev` in docker/prod. Data belongs on the Raft volume; init + unseal stay on
|
|
14
|
+
the host under `.oke/openbao/`.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin driver + image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
drivers: {
|
|
26
|
+
vault: { local: "env", docker: "openbao", test: "memory", prod: "openbao" },
|
|
27
|
+
},
|
|
28
|
+
images: {
|
|
29
|
+
vault: "openbao/openbao:2.6.1",
|
|
30
|
+
},
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
</Step>
|
|
34
|
+
|
|
35
|
+
<Step>
|
|
36
|
+
### First boot is automatic
|
|
37
|
+
|
|
38
|
+
`oke dev --docker` initializes OpenBao (Shamir 1-of-1), unseals it, writes a
|
|
39
|
+
least-privilege policy for **declared** secrets only, and mints an app token. You do not
|
|
40
|
+
run raw `bao` commands.
|
|
41
|
+
|
|
42
|
+
</Step>
|
|
43
|
+
|
|
44
|
+
<Step>
|
|
45
|
+
### App sees only the least-privilege token
|
|
46
|
+
|
|
47
|
+
```bash title="docker/.env.docker"
|
|
48
|
+
OKE_VAULT_URL=http://127.0.0.1:8200
|
|
49
|
+
OKE_VAULT_TOKEN=… # app token — not the root token
|
|
50
|
+
OKE_VAULT_MOUNT=secret # KV v2 mount (default)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
</Step>
|
|
54
|
+
|
|
55
|
+
</Steps>
|
|
56
|
+
|
|
57
|
+
## Required env
|
|
58
|
+
|
|
59
|
+
| Variable | Who holds it | Meaning |
|
|
60
|
+
| ------------------ | ------------------- | ---------------------------------------- |
|
|
61
|
+
| `OKE_VAULT_URL` | App / stack | OpenBao base URL |
|
|
62
|
+
| `OKE_VAULT_TOKEN` | App (`.env.docker`) | Least-privilege app token |
|
|
63
|
+
| `OKE_VAULT_MOUNT` | Optional | KV v2 mount path (default `"secret"`) |
|
|
64
|
+
| `BAO_LOCAL_CONFIG` | Container (recipe) | Listener + Raft JSON — set by the recipe |
|
|
65
|
+
|
|
66
|
+
Host-only material (mode `0600`, gitignored) — **not** in compose YAML:
|
|
67
|
+
|
|
68
|
+
| File | Holds |
|
|
69
|
+
| ------------------------- | ---------------------------------------- |
|
|
70
|
+
| `.oke/openbao/unseal.key` | Single unseal share |
|
|
71
|
+
| `.oke/openbao/root.token` | Root token (CLI policy sync / mint only) |
|
|
72
|
+
| `.oke/openbao/app.token` | Same least-privilege token the app uses |
|
|
73
|
+
|
|
74
|
+
## Data and backup
|
|
75
|
+
|
|
76
|
+
| Volume | Path | What it stores |
|
|
77
|
+
| ------------ | --------------- | ---------------------------- |
|
|
78
|
+
| `vault-data` | `/openbao/file` | Raft storage (node id `oke`) |
|
|
79
|
+
|
|
80
|
+
Recipe note: Raft path is `/openbao/file` (the stock entrypoint chowns that directory).
|
|
81
|
+
Healthcheck hits `/v1/sys/init` — **200 even while sealed**; bootstrap owns unseal.
|
|
82
|
+
|
|
83
|
+
**Backup means two things:**
|
|
84
|
+
|
|
85
|
+
1. The Raft volume (`/openbao/file`) — encrypted secret store
|
|
86
|
+
2. `.oke/openbao/unseal.key` on the host — without it the volume is unrecoverable
|
|
87
|
+
|
|
88
|
+
## Production note
|
|
89
|
+
|
|
90
|
+
<Callout title="Single point of failure — read this once" type="warn">
|
|
91
|
+
Back up `.oke/openbao/unseal.key` to a separate safe location. Losing it means losing every secret
|
|
92
|
+
permanently, with no recovery. Restated from [Vault ·
|
|
93
|
+
OpenBao](/docs/elements/vault#openbao-in-docker-and-prod).
|
|
94
|
+
</Callout>
|
|
95
|
+
|
|
96
|
+
Self-hosted single-node, Shamir 1-of-1, no cloud KMS — by design. If OpenBao is
|
|
97
|
+
initialized but the key is gone, boot fails with an explicit permanent-loss error; it
|
|
98
|
+
never silently starts empty.
|
|
99
|
+
|
|
100
|
+
## What the recipe configures
|
|
101
|
+
|
|
102
|
+
| Field | Value |
|
|
103
|
+
| -------------- | -------------------------------------------------------------------------------------- |
|
|
104
|
+
| Container port | `8200` |
|
|
105
|
+
| Command | `server` (with `BAO_LOCAL_CONFIG`) |
|
|
106
|
+
| TLS | Disabled on the listener for compose (`tls_disable: true`) — rely on network isolation |
|
|
107
|
+
| Healthcheck | `wget` `/v1/sys/init`, every 5s, 12 retries |
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
<Accordions>
|
|
112
|
+
<Accordion title="openbao vault: GET … failed (… ) — sealed or unauthorized?">
|
|
113
|
+
|
|
114
|
+
`OpenBaoUnavailableError` — vault sealed, wrong token, or unreachable. Re-run
|
|
115
|
+
`oke dev --docker` so bootstrap unseals with the host key. If the vault is initialized
|
|
116
|
+
but `.oke/openbao/unseal.key` is missing, restore the key from backup.
|
|
117
|
+
|
|
118
|
+
</Accordion>
|
|
119
|
+
<Accordion title="Permanent-loss / initialized but key missing">
|
|
120
|
+
|
|
121
|
+
Starting empty would look like “no secrets.” The CLI refuses that path. Restore
|
|
122
|
+
`unseal.key` or treat the Raft volume as destroyed and re-init only if you accept wiping
|
|
123
|
+
secrets.
|
|
124
|
+
|
|
125
|
+
</Accordion>
|
|
126
|
+
</Accordions>
|
|
127
|
+
|
|
128
|
+
## Learn more
|
|
129
|
+
|
|
130
|
+
- [Vault · OpenBao in docker and prod](/docs/elements/vault#openbao-in-docker-and-prod) —
|
|
131
|
+
full bootstrap, key table, SPOF callout
|
|
132
|
+
- [Errors](/docs/reference/errors) — `OpenBaoUnavailableError`, `OpenBaoBootstrapError`
|
|
133
|
+
- [CLI · oke vault](/docs/reference/cli) — `set` / `list` / `import`
|
|
134
|
+
|
|
135
|
+
## Next
|
|
136
|
+
|
|
137
|
+
<Cards>
|
|
138
|
+
<Card title="Vault" description="Resolution chain and rotation." href="/docs/elements/vault" />
|
|
139
|
+
<Card title="Mailpit" description="Local email catcher." href="/docs/recipes/mailpit" />
|
|
140
|
+
<Card title="RustFS" description="S3-compatible files." href="/docs/recipes/rustfs" />
|
|
141
|
+
</Cards>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "PgDog"
|
|
3
|
+
description: "Postgres wire-protocol pooler — transaction mode on :6432, generated pgdog.toml / users.toml, DATABASE_URL rewrite."
|
|
4
|
+
icon: "Package"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Bun.SQL defaults to **10** connections per process. Scale to several app instances and
|
|
9
|
+
`N × pool` can exceed Postgres `max_connections`. PgDog sits in front of `store.sql` as a
|
|
10
|
+
transaction-pooling proxy — same wire protocol, no app code changes.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Pin `pgdog` alongside `store.sql` and `DATABASE_URL` automatically points at the pooler on `:6432`
|
|
14
|
+
instead of Postgres directly — Bun.SQL and Drizzle see no difference.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin both images
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
images: {
|
|
26
|
+
"store.sql": "postgres:18-alpine",
|
|
27
|
+
pgdog: "ghcr.io/pgdogdev/pgdog:v0.1.51",
|
|
28
|
+
},
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
</Step>
|
|
32
|
+
|
|
33
|
+
<Step>
|
|
34
|
+
### Derive compose
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
oke docker
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Writes `./pgdog.toml` (listen + one primary database) and `./users.toml` (same
|
|
41
|
+
user/password/database as Postgres). The pooler waits on `store-sql` health before start.
|
|
42
|
+
|
|
43
|
+
</Step>
|
|
44
|
+
|
|
45
|
+
<Step>
|
|
46
|
+
### Confirm the rewrite
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
echo "$DATABASE_URL"
|
|
50
|
+
# …@host:6432/db ← pooler, not :5432
|
|
51
|
+
echo "$OKE_STORE_SQL_URL" # still the direct Postgres URL when you need it
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
</Step>
|
|
55
|
+
|
|
56
|
+
</Steps>
|
|
57
|
+
|
|
58
|
+
## Required env
|
|
59
|
+
|
|
60
|
+
| Variable | Role |
|
|
61
|
+
| ---------------------------------------- | ---------------------------------------------------------------- |
|
|
62
|
+
| `OKE_STORE_SQL_USER` / `PASSWORD` / `DB` | Copied into `users.toml` for client + server auth |
|
|
63
|
+
| `DATABASE_URL` | Rewritten to the pooler URL (`:6432`) when PgDog is in the stack |
|
|
64
|
+
| `OKE_PGDOG_URL` | Same value as pooled `DATABASE_URL` when both are present |
|
|
65
|
+
| `OKE_STORE_SQL_URL` | Direct Postgres host — bypass the pooler for admin / migrations |
|
|
66
|
+
|
|
67
|
+
PgDog itself has no separate credential env — it mounts the generated TOML files read-only.
|
|
68
|
+
|
|
69
|
+
## Data and backup
|
|
70
|
+
|
|
71
|
+
| Mount | What it is |
|
|
72
|
+
| ----------------------------------- | ------------------------------------------------------------------ |
|
|
73
|
+
| `./pgdog.toml:/pgdog/pgdog.toml:ro` | Generated listen + `[[databases]]` (host `store-sql`, port `5432`) |
|
|
74
|
+
| `./users.toml:/pgdog/users.toml:ro` | Generated `[[users]]` credentials |
|
|
75
|
+
|
|
76
|
+
**No database state lives in the PgDog container.** Backing up PgDog means keeping those
|
|
77
|
+
two config files (they are regenerated by `oke docker`). Durable data stays on the
|
|
78
|
+
[Postgres](/docs/recipes/postgres) volume / dump.
|
|
79
|
+
|
|
80
|
+
## Production note
|
|
81
|
+
|
|
82
|
+
Pooling mode is `transaction` — set explicitly (also PgDog's upstream default). Naive
|
|
83
|
+
poolers can leak session state (`SET`, RLS vars, `LISTEN`/`NOTIFY`) across clients;
|
|
84
|
+
PgDog re-applies that state per transaction.
|
|
85
|
+
|
|
86
|
+
**Do not stack** PgDog in front of a managed pooler (Neon `-pooler`, Supabase Supavisor
|
|
87
|
+
`:6543`). Pick one pooler. Use `OKE_STORE_SQL_URL` (direct) for migrations and anything
|
|
88
|
+
that needs session features.
|
|
89
|
+
|
|
90
|
+
Read-replica routing (`BEGIN READ ONLY` → replica) is documented readiness in PgDog —
|
|
91
|
+
not wired into the generated stack yet.
|
|
92
|
+
|
|
93
|
+
## What the recipe configures
|
|
94
|
+
|
|
95
|
+
| Field | Value |
|
|
96
|
+
| -------------- | ------------------------------------------------------- |
|
|
97
|
+
| Container port | `6432` |
|
|
98
|
+
| `dependsOn` | `store-sql` healthy |
|
|
99
|
+
| Healthcheck | `pg_isready -h 127.0.0.1 -p 6432`, every 5s, 12 retries |
|
|
100
|
+
| Connection URL | `postgres://user:pass@host:6432/db` |
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
<Accordions>
|
|
105
|
+
<Accordion title="pgdog unhealthy — pg_isready on :6432 fails">
|
|
106
|
+
|
|
107
|
+
Usually the backend is not ready, or `users.toml` credentials do not match Postgres.
|
|
108
|
+
Confirm `store-sql` is healthy first, then re-run `oke docker` so TOML matches
|
|
109
|
+
`OKE_STORE_SQL_*`. Logs often show auth failures against `store-sql:5432`.
|
|
110
|
+
|
|
111
|
+
</Accordion>
|
|
112
|
+
<Accordion title="Session features break through the pooler">
|
|
113
|
+
|
|
114
|
+
Transaction mode does not preserve session-scoped state the way a direct connection
|
|
115
|
+
does. Point migrations / `LISTEN` / session `SET` at `OKE_STORE_SQL_URL` (direct
|
|
116
|
+
Postgres), keep `DATABASE_URL` on the pooler for app traffic.
|
|
117
|
+
|
|
118
|
+
</Accordion>
|
|
119
|
+
</Accordions>
|
|
120
|
+
|
|
121
|
+
## Learn more
|
|
122
|
+
|
|
123
|
+
- [Docker · PgDog pooling](/docs/deployment/docker#pgdog-pooling) — compose `-f` layer order
|
|
124
|
+
- [Postgres](/docs/recipes/postgres) — the backend PgDog fronts
|
|
125
|
+
- [Store · SQL](/docs/elements/store#sql) — “Connection pooling is infrastructure”
|
|
126
|
+
|
|
127
|
+
## Next
|
|
128
|
+
|
|
129
|
+
<Cards>
|
|
130
|
+
<Card title="Postgres" description="The backend PgDog fronts." href="/docs/recipes/postgres" />
|
|
131
|
+
<Card
|
|
132
|
+
title="Supabase"
|
|
133
|
+
description="Also Postgres wire — same pooler applies."
|
|
134
|
+
href="/docs/recipes/supabase-docker"
|
|
135
|
+
/>
|
|
136
|
+
<Card title="Caddy" description="TLS at the edge, once you need it." href="/docs/recipes/caddy" />
|
|
137
|
+
</Cards>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Postgres"
|
|
3
|
+
description: "Default store.sql image — POSTGRES_* env, PGDATA path, and when DATABASE_URL points at PgDog instead."
|
|
4
|
+
icon: "Database"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Postgres is the default `store.sql` image in docker and prod. `oke docker` matches
|
|
9
|
+
any image whose reference contains `postgres` or `pgvector` (after more specific
|
|
10
|
+
recipes), then derives env, healthcheck, and connection URL.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
The driver id stays `postgres` no matter which Postgres-wire image you pin — vendor choice lives
|
|
14
|
+
in `images["store.sql"]`, not in `drivers.store.sql`.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin the image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
images: {
|
|
26
|
+
"store.sql": "postgres:18-alpine", // any Postgres / pgvector image
|
|
27
|
+
},
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
</Step>
|
|
31
|
+
|
|
32
|
+
<Step>
|
|
33
|
+
### Bring the stack up
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
oke dev --docker
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`oke docker` writes `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` into
|
|
40
|
+
`docker/.env.docker` as `${OKE_STORE_SQL_USER}` / `${OKE_STORE_SQL_PASSWORD}` /
|
|
41
|
+
`${OKE_STORE_SQL_DB}` refs — never literal secrets in compose YAML.
|
|
42
|
+
|
|
43
|
+
</Step>
|
|
44
|
+
|
|
45
|
+
<Step>
|
|
46
|
+
### Connect
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# App reads this (also accepts OKE_STORE_SQL_URL)
|
|
50
|
+
echo "$DATABASE_URL"
|
|
51
|
+
# postgres://oke:…@127.0.0.1:5432/oke
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
When PgDog is pinned, `DATABASE_URL` points at `:6432` instead — see
|
|
55
|
+
[PgDog](/docs/recipes/pgdog).
|
|
56
|
+
|
|
57
|
+
</Step>
|
|
58
|
+
|
|
59
|
+
</Steps>
|
|
60
|
+
|
|
61
|
+
## Required env
|
|
62
|
+
|
|
63
|
+
| Variable | Who sets it | Meaning |
|
|
64
|
+
| ------------------------ | ---------------------- | ------------------------------------ |
|
|
65
|
+
| `OKE_STORE_SQL_USER` | `oke docker` → compose | Injected as `POSTGRES_USER` |
|
|
66
|
+
| `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | Injected as `POSTGRES_PASSWORD` |
|
|
67
|
+
| `OKE_STORE_SQL_DB` | `oke docker` → compose | Injected as `POSTGRES_DB` |
|
|
68
|
+
| `DATABASE_URL` | stack env for the app | What Bun.SQL / Drizzle actually open |
|
|
69
|
+
| `PGDATA` | stack default | `/var/lib/postgresql/data/pgdata` |
|
|
70
|
+
| `POSTGRES_INITDB_ARGS` | stack default | `--data-checksums` |
|
|
71
|
+
|
|
72
|
+
## Data and backup
|
|
73
|
+
|
|
74
|
+
| Path | What lives there |
|
|
75
|
+
| --------------------------------------------- | ---------------------------------------------------- |
|
|
76
|
+
| `$PGDATA` (`/var/lib/postgresql/data/pgdata`) | Cluster data directory |
|
|
77
|
+
| Image `VOLUME` `/var/lib/postgresql/data` | Official image mount — Docker attaches a volume here |
|
|
78
|
+
|
|
79
|
+
The recipe does **not** declare a named compose volume. Persistence rides the image's
|
|
80
|
+
`VOLUME` (anonymous unless you add a named mount in `compose.override.yml`).
|
|
81
|
+
|
|
82
|
+
**Backup means:** `pg_dump` / `pg_dumpall`, or a Docker volume backup of
|
|
83
|
+
`/var/lib/postgresql/data`. Losing that volume loses the cluster.
|
|
84
|
+
|
|
85
|
+
## Production note
|
|
86
|
+
|
|
87
|
+
For multi-replica apps, keep SQL on a shared Postgres — Clock CronStore and durable
|
|
88
|
+
journal need one backend. See [Clock](/docs/elements/clock#what-the-runtime-guarantees) ·
|
|
89
|
+
[Docker](/docs/deployment/docker#share-backing-services).
|
|
90
|
+
|
|
91
|
+
Scale out with [PgDog](/docs/recipes/pgdog) so `N × Bun.SQL pool` does not exhaust
|
|
92
|
+
`max_connections`. Do not also stack a managed provider's pooler on the same URL.
|
|
93
|
+
|
|
94
|
+
## What the recipe configures
|
|
95
|
+
|
|
96
|
+
| Field | Value |
|
|
97
|
+
| -------------- | ---------------------------------------------------- |
|
|
98
|
+
| Container port | `5432` |
|
|
99
|
+
| Healthcheck | `pg_isready -U $POSTGRES_USER`, every 5s, 10 retries |
|
|
100
|
+
| Connection URL | `postgres://user:pass@host:5432/db` |
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
<Accordions>
|
|
105
|
+
<Accordion title="oke boot: postgres driver needs DATABASE_URL">
|
|
106
|
+
|
|
107
|
+
The `postgres` driver fails boot when neither `DATABASE_URL` nor `OKE_STORE_SQL_URL` is
|
|
108
|
+
set. Re-run `oke dev --docker` so the stack writes `docker/.env.docker`, or export
|
|
109
|
+
`DATABASE_URL` yourself when pointing at a managed host.
|
|
110
|
+
|
|
111
|
+
</Accordion>
|
|
112
|
+
<Accordion title="pg_isready fails / store-sql unhealthy">
|
|
113
|
+
|
|
114
|
+
Wrong `POSTGRES_USER` or the container is still initializing. Check
|
|
115
|
+
`docker compose … logs store-sql` for `database system is ready to accept connections`.
|
|
116
|
+
|
|
117
|
+
Credential refs must resolve in `.env.docker` — empty `${OKE_STORE_SQL_PASSWORD}` leaves
|
|
118
|
+
Postgres refusing auth.
|
|
119
|
+
|
|
120
|
+
</Accordion>
|
|
121
|
+
</Accordions>
|
|
122
|
+
|
|
123
|
+
## Learn more
|
|
124
|
+
|
|
125
|
+
- [PgDog](/docs/recipes/pgdog) — transaction pooling in front of this recipe
|
|
126
|
+
- [Store · SQL](/docs/elements/store#sql) — schema push / generate / migrate
|
|
127
|
+
- [Environment variables](/docs/reference/environment-variables) — `DATABASE_URL` precedence
|
|
128
|
+
- [Neon](/docs/providers/neon) · [Supabase](/docs/providers/supabase) — managed alternatives
|
|
129
|
+
|
|
130
|
+
## Next
|
|
131
|
+
|
|
132
|
+
<Cards>
|
|
133
|
+
<Card title="PgDog" description="Add pooling in front of Postgres." href="/docs/recipes/pgdog" />
|
|
134
|
+
<Card title="Neon" description="A managed alternative." href="/docs/providers/neon" />
|
|
135
|
+
<Card title="Redis" description="The default store.kv image." href="/docs/recipes/redis" />
|
|
136
|
+
</Cards>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Redis"
|
|
3
|
+
description: "Default store.kv image — OKE_STORE_KV_PASSWORD, maxmemory policy, ephemeral data, REDIS_URL."
|
|
4
|
+
icon: "Zap"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Redis is the default `store.kv` image in docker and prod. `oke docker` matches image
|
|
9
|
+
references containing `redis` or `keydb` and derives a password-required server — no
|
|
10
|
+
unauthenticated instance.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
The driver id stays `redis` for every Redis-wire image — Redis, Valkey, Dragonfly, or a managed
|
|
14
|
+
provider. Vendor choice lives in `images["store.kv"]`, never in `drivers.store.kv`.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin the image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
images: {
|
|
26
|
+
"store.kv": "redis:8-alpine",
|
|
27
|
+
},
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
</Step>
|
|
31
|
+
|
|
32
|
+
<Step>
|
|
33
|
+
### Required password
|
|
34
|
+
|
|
35
|
+
```bash title="docker/.env.docker (written by oke docker)"
|
|
36
|
+
OKE_STORE_KV_PASSWORD=…
|
|
37
|
+
REDIS_URL=redis://:…@127.0.0.1:6379
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The recipe runs:
|
|
41
|
+
|
|
42
|
+
`redis-server --requirepass "$OKE_STORE_KV_PASSWORD" --maxmemory … --maxmemory-policy …`
|
|
43
|
+
|
|
44
|
+
</Step>
|
|
45
|
+
|
|
46
|
+
<Step>
|
|
47
|
+
### Optional memory caps
|
|
48
|
+
|
|
49
|
+
| Variable | Default in recipe | Meaning |
|
|
50
|
+
| ------------------------------- | ------------------------------------------------------- | -------- |
|
|
51
|
+
| `OKE_STORE_KV_MAXMEMORY` | `0` (unlimited) in command; stack often sets `256mb` | Max RSS |
|
|
52
|
+
| `OKE_STORE_KV_MAXMEMORY_POLICY` | `noeviction` in command; stack often sets `allkeys-lru` | Eviction |
|
|
53
|
+
|
|
54
|
+
</Step>
|
|
55
|
+
|
|
56
|
+
</Steps>
|
|
57
|
+
|
|
58
|
+
## Required env
|
|
59
|
+
|
|
60
|
+
| Variable | Required? | Meaning |
|
|
61
|
+
| ------------------------------- | ------------- | ------------------------------------------------------------------ |
|
|
62
|
+
| `OKE_STORE_KV_PASSWORD` | **Yes** | `--requirepass` — empty password is not a valid production posture |
|
|
63
|
+
| `REDIS_URL` | **Yes** (app) | What the `redis` driver opens (`OKE_STORE_KV_URL` also works) |
|
|
64
|
+
| `OKE_STORE_KV_MAXMEMORY` | Optional | Cap memory |
|
|
65
|
+
| `OKE_STORE_KV_MAXMEMORY_POLICY` | Optional | Eviction when at cap |
|
|
66
|
+
|
|
67
|
+
## Data and backup
|
|
68
|
+
|
|
69
|
+
The Redis recipe declares **no named volume**. Process memory is the source of truth;
|
|
70
|
+
a container recreate loses keys unless you add persistence yourself
|
|
71
|
+
(`compose.override.yml` + Redis AOF/RDB).
|
|
72
|
+
|
|
73
|
+
**Backup means (default recipe):** treat KV as a cache — rebuild from SQL / files, or
|
|
74
|
+
add an explicit volume + `SAVE`/`BGSAVE` policy before you rely on durability.
|
|
75
|
+
|
|
76
|
+
## Production note
|
|
77
|
+
|
|
78
|
+
<Callout title="License note" type="warn">
|
|
79
|
+
Redis ≥8 is dual-licensed RSALv2 / SSPLv1 / AGPLv3. Those terms restrict offering Redis itself as
|
|
80
|
+
a managed service to third parties — running it for your own app is unaffected. Prefer
|
|
81
|
+
[Valkey](/docs/recipes/valkey) when the managed-service restriction matters.
|
|
82
|
+
</Callout>
|
|
83
|
+
|
|
84
|
+
Multi-replica Gate rate counters and Signal need a **shared** Redis URL — an in-process
|
|
85
|
+
`memory` driver is per instance. Same shared-store idea as
|
|
86
|
+
[Clock](/docs/elements/clock#what-the-runtime-guarantees) for cron exclusivity.
|
|
87
|
+
|
|
88
|
+
## What the recipe configures
|
|
89
|
+
|
|
90
|
+
| Field | Value |
|
|
91
|
+
| -------------- | ---------------------------------------------------- |
|
|
92
|
+
| Container port | `6379` |
|
|
93
|
+
| Healthcheck | `redis-cli -a <password> ping`, every 5s, 10 retries |
|
|
94
|
+
| Connection URL | `redis://:pass@host:6379` |
|
|
95
|
+
|
|
96
|
+
## Troubleshooting
|
|
97
|
+
|
|
98
|
+
<Accordions>
|
|
99
|
+
<Accordion title="oke boot: redis driver needs REDIS_URL">
|
|
100
|
+
|
|
101
|
+
Missing `REDIS_URL` fails boot loudly — never a silent fallback to `memory`. Re-run
|
|
102
|
+
`oke dev --docker` or export `REDIS_URL` when using a managed host. In docker mode the
|
|
103
|
+
message asks whether `oke dev -d` wrote `docker/.env.docker`.
|
|
104
|
+
|
|
105
|
+
</Accordion>
|
|
106
|
+
<Accordion title="NOAUTH Authentication required">
|
|
107
|
+
|
|
108
|
+
`REDIS_URL` is missing the password, or it does not match `OKE_STORE_KV_PASSWORD`.
|
|
109
|
+
Format must be `redis://:PASSWORD@host:6379` (colon before the password, empty username).
|
|
110
|
+
|
|
111
|
+
</Accordion>
|
|
112
|
+
</Accordions>
|
|
113
|
+
|
|
114
|
+
## Learn more
|
|
115
|
+
|
|
116
|
+
- [Store · KV](/docs/elements/store#kv) — TTL physics, per-driver behavior, license table
|
|
117
|
+
- [Valkey](/docs/recipes/valkey) · [Dragonfly](/docs/recipes/dragonfly) — Redis-wire peers
|
|
118
|
+
- [Environment variables](/docs/reference/environment-variables) — `REDIS_URL` precedence
|
|
119
|
+
|
|
120
|
+
## Next
|
|
121
|
+
|
|
122
|
+
<Cards>
|
|
123
|
+
<Card title="Valkey" description="Permissive-licensed alternative." href="/docs/recipes/valkey" />
|
|
124
|
+
<Card title="Redis Cloud" description="Managed Redis." href="/docs/providers/redis-cloud" />
|
|
125
|
+
<Card
|
|
126
|
+
title="Upstash"
|
|
127
|
+
description="Serverless Redis-protocol option."
|
|
128
|
+
href="/docs/providers/upstash"
|
|
129
|
+
/>
|
|
130
|
+
</Cards>
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "RustFS"
|
|
3
|
+
description: "S3-compatible object store — S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY, /data volume, console on :9001."
|
|
4
|
+
icon: "HardDrive"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
RustFS is the default docker `store.files` image — an Apache-2.0 S3-compatible object
|
|
9
|
+
store (MinIO alternative). Driver id stays `s3`; Bun binds `Bun.S3Client` against the
|
|
10
|
+
endpoint.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Protocol name is `s3` — vendor choice is the image pin (`rustfs/rustfs:…`) plus `S3_ENDPOINT`.
|
|
14
|
+
Never invent a `rustfs` driver id.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin driver + image (templates already do)
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
drivers: {
|
|
26
|
+
store: {
|
|
27
|
+
files: { local: "fs", docker: "s3", test: "memory", prod: "s3" },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
images: {
|
|
31
|
+
"store.files": "rustfs/rustfs:1.0.0-beta.11",
|
|
32
|
+
},
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
</Step>
|
|
36
|
+
|
|
37
|
+
<Step>
|
|
38
|
+
### Credentials and endpoint
|
|
39
|
+
|
|
40
|
+
```bash title="docker/.env.docker (written by oke docker)"
|
|
41
|
+
S3_ACCESS_KEY_ID=…
|
|
42
|
+
S3_SECRET_ACCESS_KEY=…
|
|
43
|
+
S3_BUCKET=oke
|
|
44
|
+
S3_ENDPOINT=http://127.0.0.1:9000
|
|
45
|
+
S3_URL=http://…@127.0.0.1:9000/oke
|
|
46
|
+
S3_REGION=us-east-1
|
|
47
|
+
S3_CONSOLE_URL=http://127.0.0.1:9001
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Recipe maps:
|
|
51
|
+
|
|
52
|
+
- `RUSTFS_ACCESS_KEY=${S3_ACCESS_KEY_ID}`
|
|
53
|
+
- `RUSTFS_SECRET_KEY=${S3_SECRET_ACCESS_KEY}`
|
|
54
|
+
- `RUSTFS_CONSOLE_ENABLE=true`
|
|
55
|
+
- `RUSTFS_ADDRESS=:9000`
|
|
56
|
+
- command: `/data`
|
|
57
|
+
|
|
58
|
+
</Step>
|
|
59
|
+
|
|
60
|
+
<Step>
|
|
61
|
+
### Put an object
|
|
62
|
+
|
|
63
|
+
Any flow using `fx.store` files (`put` / `get`) against the `s3` driver talks to this
|
|
64
|
+
endpoint. Open `S3_CONSOLE_URL` for a browser console on port **9001**.
|
|
65
|
+
|
|
66
|
+
</Step>
|
|
67
|
+
|
|
68
|
+
</Steps>
|
|
69
|
+
|
|
70
|
+
## Required env
|
|
71
|
+
|
|
72
|
+
| Variable | Required? | Meaning |
|
|
73
|
+
| ---------------------- | ----------------- | ------------------------------------------ |
|
|
74
|
+
| `S3_ACCESS_KEY_ID` | **Yes** | Access key → `RUSTFS_ACCESS_KEY` |
|
|
75
|
+
| `S3_SECRET_ACCESS_KEY` | **Yes** | Secret key → `RUSTFS_SECRET_KEY` |
|
|
76
|
+
| `S3_BUCKET` | **Yes** (app) | Bucket name the driver opens |
|
|
77
|
+
| `S3_ENDPOINT` | **Yes** (non-AWS) | Origin `http://host:9000` |
|
|
78
|
+
| `S3_REGION` | Optional | Default `us-east-1` in stack env |
|
|
79
|
+
| `S3_SESSION_TOKEN` | Optional | Temporary creds |
|
|
80
|
+
| `S3_CONSOLE_URL` | Written by stack | UI on `:9001` — not required by the driver |
|
|
81
|
+
| `S3_URL` | Written by stack | Credentialed URL form |
|
|
82
|
+
|
|
83
|
+
## Data and backup
|
|
84
|
+
|
|
85
|
+
| Volume | Path | What it stores |
|
|
86
|
+
| ------------------ | ------- | ------------------------------ |
|
|
87
|
+
| `store-files-data` | `/data` | Object bytes + RustFS metadata |
|
|
88
|
+
|
|
89
|
+
**Backup means:** snapshot that named volume (or `aws s3 sync` against the API).
|
|
90
|
+
Deleting the volume deletes every object.
|
|
91
|
+
|
|
92
|
+
Credentials live in `.env.docker`, not in `/data` — rotate keys without wiping objects.
|
|
93
|
+
Losing both volume and keys means full restore from backup only.
|
|
94
|
+
|
|
95
|
+
## Production note
|
|
96
|
+
|
|
97
|
+
For cloud prod, point the same `s3` driver at real S3 / R2 / GCS interop by changing
|
|
98
|
+
`S3_ENDPOINT` + keys — keep the driver id. Self-hosted RustFS on a single node is a
|
|
99
|
+
durability SPOF: put the `/data` volume on reliable disks and back it up.
|
|
100
|
+
|
|
101
|
+
Do not publish `:9000` / `:9001` on the public internet without TLS and network policy —
|
|
102
|
+
the recipe enables the console for local ops.
|
|
103
|
+
|
|
104
|
+
## What the recipe configures
|
|
105
|
+
|
|
106
|
+
| Field | Value |
|
|
107
|
+
| -------------- | ----------------------------------------------------------------------- |
|
|
108
|
+
| API port | `9000` |
|
|
109
|
+
| Extra port | `9001` → console |
|
|
110
|
+
| Healthcheck | `curl -f http://127.0.0.1:9000/health`, every 5s, 12 retries, 10s start |
|
|
111
|
+
| Connection URL | `http://user:pass@host:9000/bucket` |
|
|
112
|
+
|
|
113
|
+
## Troubleshooting
|
|
114
|
+
|
|
115
|
+
<Accordions>
|
|
116
|
+
<Accordion title="oke boot: redis / meilisearch / S3 URL missing — S3_BUCKET">
|
|
117
|
+
|
|
118
|
+
Files on the `s3` driver need `S3_BUCKET` (or `OKE_STORE_FILES_DB`). Without it the
|
|
119
|
+
facet cannot open. Re-run `oke dev --docker` so stack env fills `S3_*`, or export them
|
|
120
|
+
for a managed bucket.
|
|
121
|
+
|
|
122
|
+
</Accordion>
|
|
123
|
+
<Accordion title="Access Denied / signature errors against :9000">
|
|
124
|
+
|
|
125
|
+
`S3_ACCESS_KEY_ID` / `S3_SECRET_ACCESS_KEY` do not match `RUSTFS_*` inside the
|
|
126
|
+
container, or `S3_ENDPOINT` points at the wrong host/port. Align `.env.docker` with the
|
|
127
|
+
running service; confirm health at `/health` before debugging client signatures.
|
|
128
|
+
|
|
129
|
+
</Accordion>
|
|
130
|
+
</Accordions>
|
|
131
|
+
|
|
132
|
+
## Learn more
|
|
133
|
+
|
|
134
|
+
- [Store · Files](/docs/elements/store#files) — facet API and drivers
|
|
135
|
+
- [Environment variables](/docs/reference/environment-variables) — full `S3_*` map
|
|
136
|
+
- [Installation](/docs/get-started/installation) — docker env cheat sheet
|
|
137
|
+
|
|
138
|
+
## Next
|
|
139
|
+
|
|
140
|
+
<Cards>
|
|
141
|
+
<Card
|
|
142
|
+
title="Mailpit"
|
|
143
|
+
description="SMTP catcher for the same stack."
|
|
144
|
+
href="/docs/recipes/mailpit"
|
|
145
|
+
/>
|
|
146
|
+
<Card title="OpenBao" description="Vault for secrets." href="/docs/recipes/openbao" />
|
|
147
|
+
<Card title="Store" description="Files facet details." href="/docs/elements/store" />
|
|
148
|
+
</Cards>
|