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.
Files changed (175) hide show
  1. package/AGENTS.md +1 -1
  2. package/manifest.v1.schema.json +9 -1
  3. package/package.json +3 -3
  4. package/site/content/docs/console/runs.mdx +10 -0
  5. package/site/content/docs/console/traces.mdx +4 -0
  6. package/site/content/docs/elements/ai.mdx +54 -32
  7. package/site/content/docs/elements/channel.mdx +105 -14
  8. package/site/content/docs/elements/clock.mdx +1 -0
  9. package/site/content/docs/elements/flow.mdx +42 -8
  10. package/site/content/docs/get-started/basic-usage.mdx +5 -1
  11. package/site/content/docs/get-started/installation.mdx +9 -5
  12. package/site/content/docs/meta.json +2 -0
  13. package/site/content/docs/plugins/otp.mdx +58 -46
  14. package/site/content/docs/providers/azure-redis.mdx +85 -0
  15. package/site/content/docs/providers/cockroachdb.mdx +86 -0
  16. package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
  17. package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
  18. package/site/content/docs/providers/elasticache.mdx +92 -0
  19. package/site/content/docs/providers/index.mdx +101 -0
  20. package/site/content/docs/providers/memorystore.mdx +89 -0
  21. package/site/content/docs/providers/meta.json +20 -0
  22. package/site/content/docs/providers/neon.mdx +115 -0
  23. package/site/content/docs/providers/redis-cloud.mdx +93 -0
  24. package/site/content/docs/providers/supabase.mdx +117 -0
  25. package/site/content/docs/providers/upstash.mdx +91 -0
  26. package/site/content/docs/providers/yugabytedb.mdx +95 -0
  27. package/site/content/docs/recipes/caddy.mdx +128 -0
  28. package/site/content/docs/recipes/cockroachdb.mdx +127 -0
  29. package/site/content/docs/recipes/dragonfly.mdx +125 -0
  30. package/site/content/docs/recipes/index.mdx +146 -0
  31. package/site/content/docs/recipes/llama-cpp.mdx +153 -0
  32. package/site/content/docs/recipes/mailpit.mdx +136 -0
  33. package/site/content/docs/recipes/meilisearch.mdx +139 -0
  34. package/site/content/docs/recipes/meta.json +31 -0
  35. package/site/content/docs/recipes/ollama.mdx +142 -0
  36. package/site/content/docs/recipes/openbao.mdx +141 -0
  37. package/site/content/docs/recipes/pgdog.mdx +137 -0
  38. package/site/content/docs/recipes/postgres.mdx +136 -0
  39. package/site/content/docs/recipes/redis.mdx +130 -0
  40. package/site/content/docs/recipes/rustfs.mdx +148 -0
  41. package/site/content/docs/recipes/sglang.mdx +105 -0
  42. package/site/content/docs/recipes/supabase-docker.mdx +145 -0
  43. package/site/content/docs/recipes/timescale.mdx +129 -0
  44. package/site/content/docs/recipes/traefik.mdx +136 -0
  45. package/site/content/docs/recipes/valkey.mdx +121 -0
  46. package/site/content/docs/recipes/vllm.mdx +106 -0
  47. package/site/content/docs/recipes/yugabytedb.mdx +135 -0
  48. package/site/content/docs/reference/cli.md +42 -6
  49. package/site/content/docs/reference/configuration.mdx +5 -3
  50. package/site/content/docs/reference/environment-variables.mdx +12 -12
  51. package/site/content/docs/reference/fx.mdx +38 -4
  52. package/src/auth/otp-capability.ts +14 -14
  53. package/src/cli/ai-setup/ai-setup.test.ts +32 -12
  54. package/src/cli/ai-setup/apply.ts +65 -23
  55. package/src/cli/ai-setup/catalog.ts +1316 -35
  56. package/src/cli/ai-setup/detect-ollama.ts +47 -0
  57. package/src/cli/ai-setup/index.ts +44 -7
  58. package/src/cli/ai-setup/prompts.ts +430 -486
  59. package/src/cli/ai-setup/recommend.test.ts +150 -50
  60. package/src/cli/ai-setup/recommend.ts +118 -101
  61. package/src/cli/ask-seed.test.ts +68 -0
  62. package/src/cli/ask-seed.ts +79 -0
  63. package/src/cli/db-seed-redact.test.ts +25 -0
  64. package/src/cli/db-seed.ts +36 -7
  65. package/src/cli/db.test.ts +1 -1
  66. package/src/cli/db.ts +2 -2
  67. package/src/cli/dev-controls.test.ts +107 -0
  68. package/src/cli/dev-controls.ts +354 -0
  69. package/src/cli/dev-schema-sync.ts +12 -4
  70. package/src/cli/dev.test.ts +50 -30
  71. package/src/cli/dev.ts +607 -66
  72. package/src/cli/drizzle-env.test.ts +40 -6
  73. package/src/cli/drizzle-env.ts +22 -1
  74. package/src/cli/ensure-drizzle-config.ts +6 -4
  75. package/src/cli/hero-meta.test.ts +13 -1
  76. package/src/cli/hero-meta.ts +28 -6
  77. package/src/cli/index.ts +5 -0
  78. package/src/cli/registry.ts +24 -0
  79. package/src/cli/replay.test.ts +105 -0
  80. package/src/cli/replay.ts +206 -0
  81. package/src/compiler/extract.ts +3 -3
  82. package/src/config/index.ts +3 -3
  83. package/src/console/server/claim.ts +3 -1
  84. package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
  85. package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
  86. package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
  87. package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
  88. package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
  89. package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
  90. package/src/console/ui/dist/index.html +1 -1
  91. package/src/console/ui/overview/slo.ts +31 -3
  92. package/src/console/ui/overview/types.ts +6 -0
  93. package/src/console/ui/runs/errors.test.ts +53 -0
  94. package/src/console/ui/runs/errors.ts +88 -0
  95. package/src/console/ui/runs/index.ts +8 -0
  96. package/src/console/ui/runs/search.ts +16 -0
  97. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
  98. package/src/docker/ai-model-status.test.ts +101 -0
  99. package/src/docker/ai-model-status.ts +276 -0
  100. package/src/docker/compose-health.test.ts +115 -0
  101. package/src/docker/compose-health.ts +234 -0
  102. package/src/docker/compose.ts +24 -8
  103. package/src/docker/derive.ts +35 -9
  104. package/src/docker/docker.test.ts +304 -12
  105. package/src/docker/helpers.ts +56 -0
  106. package/src/docker/index.ts +52 -0
  107. package/src/docker/ollama-pull.ts +232 -0
  108. package/src/docker/recipes/cockroach.ts +24 -0
  109. package/src/docker/recipes/index.ts +32 -0
  110. package/src/docker/recipes/llama-cpp.ts +273 -0
  111. package/src/docker/recipes/ollama.ts +19 -23
  112. package/src/docker/recipes/pgdog.ts +4 -1
  113. package/src/docker/recipes/postgres.ts +5 -18
  114. package/src/docker/recipes/sglang.ts +55 -0
  115. package/src/docker/recipes/supabase.ts +21 -0
  116. package/src/docker/recipes/timescale.ts +18 -0
  117. package/src/docker/recipes/vllm.ts +44 -0
  118. package/src/docker/recipes/yugabyte.ts +23 -0
  119. package/src/docker/stack-id.test.ts +22 -0
  120. package/src/docker/stack-id.ts +38 -4
  121. package/src/docker/types.ts +15 -0
  122. package/src/drivers/ai-ollama.integration.test.ts +7 -4
  123. package/src/drivers/signal-engine.ts +10 -0
  124. package/src/drivers/signal-postgres.ts +24 -2
  125. package/src/drivers/signal-types.ts +10 -0
  126. package/src/elements/channel/fallback.test.ts +91 -0
  127. package/src/elements/channel/hard-bounce.test.ts +82 -0
  128. package/src/elements/channel/injection.test.ts +153 -0
  129. package/src/elements/channel/locale-ar.test.ts +102 -0
  130. package/src/elements/channel/otp-delivery.ts +5 -2
  131. package/src/elements/channel/receipts-ledger.test.ts +100 -0
  132. package/src/elements/channel/runtime.ts +24 -1
  133. package/src/elements/channel/test-helpers.ts +60 -0
  134. package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
  135. package/src/elements/store/cache.ts +1 -1
  136. package/src/elements/store/emit-drizzle.ts +43 -9
  137. package/src/elements/store/runtime.ts +1 -1
  138. package/src/elements/store/schema-decl.test.ts +2 -0
  139. package/src/elements/store/schema-decl.ts +15 -0
  140. package/src/elements/store/seed.ts +1 -1
  141. package/src/index.ts +1 -0
  142. package/src/kernel/app.ts +118 -11
  143. package/src/kernel/boot-bind/signal.ts +6 -2
  144. package/src/kernel/boot-bind/store.ts +2 -1
  145. package/src/kernel/boot.test.ts +6 -5
  146. package/src/kernel/boot.ts +8 -3
  147. package/src/kernel/compensate.test.ts +131 -0
  148. package/src/kernel/correlation.test.ts +108 -0
  149. package/src/kernel/effect-timing.test.ts +82 -0
  150. package/src/kernel/flow.ts +38 -0
  151. package/src/kernel/fx-runs.test.ts +49 -0
  152. package/src/kernel/fx.test.ts +14 -0
  153. package/src/kernel/fx.ts +111 -1
  154. package/src/manifest/types.ts +8 -2
  155. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  156. package/src/plugins/auth-methods.security.test.ts +3 -3
  157. package/src/plugins/auth-methods.test.ts +1 -1
  158. package/src/plugins/index.ts +2 -2
  159. package/src/plugins/otp.test.ts +21 -19
  160. package/src/plugins/otp.ts +36 -34
  161. package/src/plugins/taqnyat.live.test.ts +3 -3
  162. package/src/runs/collect.ts +3 -0
  163. package/src/runs/export-otlp.ts +64 -0
  164. package/src/runs/index.ts +16 -0
  165. package/src/runs/parquet.ts +9 -0
  166. package/src/runs/types.ts +5 -0
  167. package/src/runs/window.test.ts +68 -0
  168. package/src/runs/window.ts +148 -0
  169. package/src/runtime/boot-warn.test.ts +45 -0
  170. package/src/runtime/boot-warn.ts +17 -0
  171. package/src/runtime/dev-request-log.ts +5 -5
  172. package/src/term.test.ts +95 -10
  173. package/src/term.ts +369 -14
  174. package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
  175. package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
@@ -0,0 +1,105 @@
1
+ ---
2
+ title: "SGLang"
3
+ description: "Production-tier self-hosted inference for structured and agent workloads on GPU."
4
+ icon: "Cpu"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ SGLang is for **structured generation and agent-heavy workloads on real GPU
9
+ hardware** when you self-host inference. Prefer a managed provider for most
10
+ production apps. For general multi-user serving, prefer [vLLM](/docs/recipes/vllm).
11
+
12
+ <Callout title="The one rule">
13
+ Pin an explicit runtime tag (never `latest`), publish only on loopback, and pick SGLang only when
14
+ structured / agent throughput is the reason you self-host.
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
+ ai: { docker: "openai-compatible", prod: "openai-compatible", test: "mock" },
27
+ },
28
+ images: {
29
+ ai: "lmsysorg/sglang:v0.5.16-runtime", // never :latest
30
+ },
31
+ ```
32
+
33
+ Or `oke ai setup --provider sglang --yes`.
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Env + GPU
39
+
40
+ ```bash title="docker/.env.docker"
41
+ OKE_AI_URL=http://127.0.0.1:30000/v1
42
+ OKE_AI_MODEL=Qwen/Qwen3-0.6B
43
+ ```
44
+
45
+ Same NVIDIA reservation pattern as vLLM (`ipc: host` + device reservation).
46
+
47
+ </Step>
48
+
49
+ <Step>
50
+ ### Decision matrix
51
+
52
+ | Workload | Recipe |
53
+ | -------------------------------- | -------------------------------------------------------------------------------- |
54
+ | Single-user / dev | [llama.cpp](/docs/recipes/llama-cpp) (default) or [Ollama](/docs/recipes/ollama) |
55
+ | Multi-user GPU serving | [vLLM](/docs/recipes/vllm) |
56
+ | Structured / agent GPU workloads | **SGLang** (this recipe) |
57
+ | Managed cloud | Anthropic / OpenAI / … |
58
+
59
+ </Step>
60
+
61
+ </Steps>
62
+
63
+ ## Security
64
+
65
+ | Control | Requirement |
66
+ | ------------ | ---------------------------------------------- |
67
+ | Host publish | `127.0.0.1:30000:30000` only — never `0.0.0.0` |
68
+ | Image pin | Explicit version tag — never `latest` |
69
+ | Model source | Trusted Hugging Face repos / your own weights |
70
+
71
+ ## What the recipe configures
72
+
73
+ | Field | Value |
74
+ | -------------- | ----------------------------------------------------- |
75
+ | Container port | `30000` |
76
+ | Host publish | `127.0.0.1:30000:30000` |
77
+ | `ipc` | `host` |
78
+ | GPU | `deploy.resources.reservations.devices` (nvidia, all) |
79
+ | Healthcheck | `GET /health`, long start period for model load |
80
+ | Connection URL | `http://host:30000/v1` |
81
+
82
+ ## Troubleshooting
83
+
84
+ <Accordions>
85
+ <Accordion title="GPU not visible / container exits">
86
+
87
+ Install the NVIDIA Container Toolkit. Without a GPU, use
88
+ [llama.cpp](/docs/recipes/llama-cpp) for local smoke tests.
89
+
90
+ </Accordion>
91
+ </Accordions>
92
+
93
+ ## Learn more
94
+
95
+ - [vLLM](/docs/recipes/vllm) — general production GPU serving
96
+ - [llama.cpp](/docs/recipes/llama-cpp) — default local AI
97
+ - [AI](/docs/elements/ai) — drivers and `fx.ask`
98
+
99
+ ## Next
100
+
101
+ <Cards>
102
+ <Card title="vLLM" description="General multi-user GPU serving." href="/docs/recipes/vllm" />
103
+ <Card title="llama.cpp" description="Default local AI." href="/docs/recipes/llama-cpp" />
104
+ <Card title="AI" description="Prompts and guardrails." href="/docs/elements/ai" />
105
+ </Cards>
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: "Supabase"
3
+ description: "Pin supabase/postgres as store.sql — extension bundle (pgvector, …) without Auth, Storage, Realtime, or Studio."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Supabase publishes `supabase/postgres` — plain Postgres with a bundled extension set
9
+ (`pgvector`, `pg_graphql`, `pg_cron`, `wrappers`, and more). `oke docker` matches that
10
+ image ahead of the generic Postgres recipe.
11
+
12
+ <Callout title="Not the full Supabase platform">
13
+ This recipe does **not** start GoTrue, PostgREST, Kong, Realtime, Storage, or Studio. Auth, files,
14
+ and realtime delivery are already covered by [Vault](/docs/elements/vault), [Store ·
15
+ files](/docs/elements/store#files), and [Signal](/docs/elements/signal).
16
+ </Callout>
17
+
18
+ ## Quick start
19
+
20
+ <Steps>
21
+
22
+ <Step>
23
+ ### Pin the image
24
+
25
+ ```typescript title="oke.config.ts"
26
+ images: {
27
+ "store.sql": "supabase/postgres:15.8.1.049", // pin a real tag from Supabase's registry
28
+ },
29
+ ```
30
+
31
+ </Step>
32
+
33
+ <Step>
34
+ ### Same env shape as Postgres
35
+
36
+ `oke docker` injects the same `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`
37
+ refs from `OKE_STORE_SQL_*`. Driver id stays `postgres`.
38
+
39
+ </Step>
40
+
41
+ <Step>
42
+ ### Use pgvector when you need it
43
+
44
+ ```typescript
45
+ drivers: {
46
+ store: {
47
+ index: { local: "memory", docker: "pgvector", prod: "pgvector" },
48
+ },
49
+ },
50
+ ```
51
+
52
+ `CREATE EXTENSION IF NOT EXISTS vector` runs when the `pgvector` index driver opens —
53
+ the extension ships in this image.
54
+
55
+ </Step>
56
+
57
+ </Steps>
58
+
59
+ ## Required env
60
+
61
+ | Variable | Meaning |
62
+ | ------------------------ | ----------------------------------------- |
63
+ | `OKE_STORE_SQL_USER` | → `POSTGRES_USER` |
64
+ | `OKE_STORE_SQL_PASSWORD` | → `POSTGRES_PASSWORD` |
65
+ | `OKE_STORE_SQL_DB` | → `POSTGRES_DB` |
66
+ | `DATABASE_URL` | App connection (`postgres://…:5432/…`) |
67
+ | `PGDATA` | Default `/var/lib/postgresql/data/pgdata` |
68
+
69
+ Identical credential contract to [Postgres](/docs/recipes/postgres) — only the image
70
+ (and its extension bundle) differs.
71
+
72
+ ## Data and backup
73
+
74
+ | Path | What lives there |
75
+ | ----------------------------------------- | ------------------------------------------ |
76
+ | `$PGDATA` | Cluster data, including extension catalogs |
77
+ | Image `VOLUME` `/var/lib/postgresql/data` | Persistence mount |
78
+
79
+ Same backup story as plain Postgres: `pg_dump` or volume backup of
80
+ `/var/lib/postgresql/data`. Losing that volume loses tables **and** which extensions
81
+ were created.
82
+
83
+ ## Production note
84
+
85
+ Want managed Supabase (Auth / Storage / Realtime included)? Use the
86
+ [Supabase provider](/docs/providers/supabase) and set `DATABASE_URL` — do not run this
87
+ image and the cloud project as if they were the same deployment.
88
+
89
+ For self-hosted production, prefer a pinned tag (not `latest`) and the same
90
+ shared-store guidance as [Postgres](/docs/recipes/postgres#production-note). Free-tier
91
+ cloud pausing does not apply to this Docker image — you own uptime.
92
+
93
+ ## What the recipe configures
94
+
95
+ | Field | Value |
96
+ | -------------- | ---------------------------------------------------- |
97
+ | Match | `supabase/postgres` before generic `postgres` |
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='Extension "vector" is not available'>
106
+
107
+ You pinned a plain `postgres:` image, not `supabase/postgres`, or the tag predates the
108
+ bundle. Confirm the image reference contains `supabase/postgres`, then re-derive.
109
+ With the right image, `CREATE EXTENSION vector` succeeds without a separate install.
110
+
111
+ </Accordion>
112
+ <Accordion title="Looking for Studio / the REST API">
113
+
114
+ Those services are not part of this recipe. Use the
115
+ [managed Supabase provider](/docs/providers/supabase) for the full platform, or oke's
116
+ own Vault / Store · files / Signal for those concerns.
117
+
118
+ </Accordion>
119
+ </Accordions>
120
+
121
+ ## Learn more
122
+
123
+ - [Supabase (provider)](/docs/providers/supabase) — managed cloud alternative
124
+ - [Postgres](/docs/recipes/postgres) — generic recipe this one takes precedence over
125
+ - [Store · Index](/docs/elements/store#index) — `pgvector`-backed vector search
126
+
127
+ ## Next
128
+
129
+ <Cards>
130
+ <Card
131
+ title="Supabase"
132
+ description="Managed cloud, same wire protocol."
133
+ href="/docs/providers/supabase"
134
+ />
135
+ <Card
136
+ title="PgDog"
137
+ description="Add pooling in front of this recipe too."
138
+ href="/docs/recipes/pgdog"
139
+ />
140
+ <Card
141
+ title="Postgres"
142
+ description="The plain image this specializes."
143
+ href="/docs/recipes/postgres"
144
+ />
145
+ </Cards>
@@ -0,0 +1,129 @@
1
+ ---
2
+ title: "Timescale"
3
+ description: "Self-hosted TimescaleDB — same POSTGRES_* contract as Postgres, hypertables included, driver stays postgres."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ TimescaleDB is Postgres plus hypertables and time-series tooling. Pin a
9
+ `timescale/timescaledb` image as `store.sql` and `oke docker` uses the Timescale
10
+ recipe — same `POSTGRES_*` contract as plain Postgres. Driver id stays `postgres`.
11
+
12
+ <Callout title="The one rule">
13
+ The driver id stays `postgres` — vendor choice lives in `images["store.sql"]`. Create the
14
+ `timescaledb` extension in SQL when you need hypertables; the image ships it.
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": "timescale/timescaledb:latest-pg17", // pin a real tag
27
+ },
28
+ ```
29
+
30
+ </Step>
31
+
32
+ <Step>
33
+ ### Bring the stack up
34
+
35
+ ```bash
36
+ oke dev --docker
37
+ ```
38
+
39
+ Same credential contract as [Postgres](/docs/recipes/postgres):
40
+ `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` from `OKE_STORE_SQL_*`.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Enable the extension when you need it
46
+
47
+ ```sql
48
+ CREATE EXTENSION IF NOT EXISTS timescaledb;
49
+ ```
50
+
51
+ Then create hypertables with Timescale's usual DDL — Flows still talk through
52
+ `fx.store` / Drizzle like any other Postgres.
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Who sets it | Meaning |
61
+ | ------------------------ | ---------------------- | --------------------------------- |
62
+ | `OKE_STORE_SQL_USER` | `oke docker` → compose | → `POSTGRES_USER` |
63
+ | `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | → `POSTGRES_PASSWORD` |
64
+ | `OKE_STORE_SQL_DB` | `oke docker` → compose | → `POSTGRES_DB` |
65
+ | `DATABASE_URL` | stack env for the app | `postgres://…:5432/…` |
66
+ | `PGDATA` | stack default | `/var/lib/postgresql/data/pgdata` |
67
+
68
+ ## Data and backup
69
+
70
+ | Path | What lives there |
71
+ | ----------------------------------------- | ------------------------------------------ |
72
+ | `$PGDATA` | Cluster data, including Timescale catalogs |
73
+ | Image `VOLUME` `/var/lib/postgresql/data` | Persistence mount |
74
+
75
+ Same backup story as plain Postgres: `pg_dump` / volume backup of
76
+ `/var/lib/postgresql/data`. Losing that volume loses tables and extension state.
77
+
78
+ ## Production note
79
+
80
+ Pin a concrete tag (image + Postgres major). For multi-replica apps, keep one
81
+ shared SQL backend — see
82
+ [Postgres · Production note](/docs/recipes/postgres#production-note).
83
+
84
+ Managed time-series hosts still use `DATABASE_URL` and
85
+ `drivers.store.sql: "postgres"`.
86
+
87
+ ## What the recipe configures
88
+
89
+ | Field | Value |
90
+ | -------------- | --------------------------------------- |
91
+ | Match | `timescale` ahead of generic `postgres` |
92
+ | Container port | `5432` |
93
+ | Healthcheck | `pg_isready -U $POSTGRES_USER` |
94
+ | Connection URL | `postgres://user:pass@host:5432/db` |
95
+
96
+ ## Troubleshooting
97
+
98
+ <Accordions>
99
+ <Accordion title='extension "timescaledb" is not available'>
100
+
101
+ You pinned a plain `postgres:` image. Confirm the reference contains `timescale`,
102
+ re-derive, then `CREATE EXTENSION timescaledb`.
103
+
104
+ </Accordion>
105
+ <Accordion title="oke boot: postgres driver needs DATABASE_URL">
106
+
107
+ Same as Postgres — re-run `oke dev --docker` or export `DATABASE_URL` for a remote
108
+ host.
109
+
110
+ </Accordion>
111
+ </Accordions>
112
+
113
+ ## Learn more
114
+
115
+ - [Postgres](/docs/recipes/postgres) — generic recipe this specialises
116
+ - [Store · SQL](/docs/elements/store#sql) — schema workflows
117
+ - [Environment variables](/docs/reference/environment-variables) — `DATABASE_URL`
118
+
119
+ ## Next
120
+
121
+ <Cards>
122
+ <Card title="Postgres" description="Plain Postgres recipe." href="/docs/recipes/postgres" />
123
+ <Card
124
+ title="Supabase"
125
+ description="Postgres + extension bundle."
126
+ href="/docs/recipes/supabase-docker"
127
+ />
128
+ <Card title="PgDog" description="Transaction pooling in front." href="/docs/recipes/pgdog" />
129
+ </Cards>
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: "Traefik"
3
+ description: "Docker-label auto-discovery proxy — OKE_PROXY_HOST, OKE_PROXY_ACME_EMAIL, socket-proxy, ACME volume."
4
+ icon: "Lock"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Traefik discovers `app` replicas from Docker labels instead of a static upstream, so
9
+ `docker compose up --scale app=N` load-balances without reconfiguring the proxy.
10
+
11
+ <Callout title="The one rule">
12
+ Traefik never mounts the raw Docker socket. A filtered `tecnativa/docker-socket-proxy` companion
13
+ exposes only containers / events / ping / version / networks on the internal compose network.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Pin the proxy
22
+
23
+ ```typescript title="oke.config.ts"
24
+ images: {
25
+ proxy: "traefik:v3.3",
26
+ },
27
+ ```
28
+
29
+ </Step>
30
+
31
+ <Step>
32
+ ### Hostname + ACME email
33
+
34
+ ```bash title="docker/.env.docker"
35
+ OKE_PROXY_HOST=app.example.com
36
+ OKE_PROXY_ACME_EMAIL=admin@example.com
37
+ ```
38
+
39
+ `OKE_PROXY_ACME_EMAIL` defaults to `admin@example.com` if unset — set a real mailbox
40
+ before production ACME.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Scale the app
46
+
47
+ ```bash
48
+ docker compose … up -d --scale app=3
49
+ ```
50
+
51
+ App labels: `traefik.http.routers.app.rule=Host(...)`, TLS cert resolver `letsencrypt`,
52
+ load-balancer port `6530`.
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Required? | Meaning |
61
+ | ----------------------- | -------------------- | ---------------------------------------------- |
62
+ | `OKE_PROXY_HOST` | **Yes** (production) | Host rule + ACME identity; default `localhost` |
63
+ | `OKE_PROXY_ACME_EMAIL` | **Yes** (production) | Let's Encrypt account email |
64
+ | `allowedHosts` (config) | Production | Must include the public hostname |
65
+
66
+ ## Data and backup
67
+
68
+ | Volume | Path | What it stores |
69
+ | ------------------- | ------------------------- | ------------------------------------------------- |
70
+ | `proxy-letsencrypt` | `/letsencrypt` | `acme.json` — certificates + ACME account |
71
+ | Socket proxy only | `/var/run/docker.sock:ro` | **Only** the `socket-proxy` companion mounts this |
72
+
73
+ **Backup means:** preserve the `proxy-letsencrypt` volume (especially `acme.json`). Losing
74
+ it forces re-issuance and can hit Let's Encrypt rate limits. The socket-proxy has no
75
+ durable state.
76
+
77
+ ## Production note
78
+
79
+ Security posture is intentional: Traefik talks to `tcp://socket-proxy:2375` with a
80
+ filtered API (`CONTAINERS`, `EVENTS`, `PING`, `VERSION`, `NETWORKS` only). Never mount
81
+ raw `docker.sock` on Traefik — see [Reverse proxy](/docs/deployment/reverse-proxy).
82
+
83
+ HTTP entrypoint redirects to `websecure`. For a single instance with no scale plans,
84
+ [Caddy](/docs/recipes/caddy) is simpler (no labels, no companion).
85
+
86
+ ## What the recipe configures
87
+
88
+ | Field | Value |
89
+ | ----------- | -------------------------------------------------- |
90
+ | Ports | `80` + `443` |
91
+ | Providers | Docker via socket-proxy, `exposedbydefault=false` |
92
+ | Companion | `tecnativa/docker-socket-proxy:v0.5.0` |
93
+ | Healthcheck | `traefik healthcheck --ping`, every 10s, 5 retries |
94
+
95
+ ## Troubleshooting
96
+
97
+ <Accordions>
98
+ <Accordion title="404 / no backend — Traefik cannot see app">
99
+
100
+ Usually `socket-proxy` is down, or `app` lacks Traefik labels. Confirm
101
+ `depends_on: socket-proxy` and that `compose.proxy.yml` merged the app labels.
102
+
103
+ Logs showing Docker provider connection errors point at the socket-proxy, not Traefik
104
+ config syntax.
105
+
106
+ </Accordion>
107
+ <Accordion title="ACME email rejected / rate limited">
108
+
109
+ Replace the default `admin@example.com` with a real `OKE_PROXY_ACME_EMAIL`. If you wiped
110
+ `proxy-letsencrypt`, you may be rate-limited — restore `acme.json` from backup instead of
111
+ re-issuing repeatedly.
112
+
113
+ </Accordion>
114
+ </Accordions>
115
+
116
+ ## Learn more
117
+
118
+ - [Reverse proxy](/docs/deployment/reverse-proxy) — Docker-socket-proxy security rationale
119
+ - [Docker · Reverse proxy](/docs/deployment/docker#reverse-proxy) — compose layer order
120
+ - [Security](/docs/reference/security) — `allowedHosts`
121
+
122
+ ## Next
123
+
124
+ <Cards>
125
+ <Card title="Caddy" description="Single-instance alternative." href="/docs/recipes/caddy" />
126
+ <Card
127
+ title="PgDog"
128
+ description="Pool Postgres behind the same stack."
129
+ href="/docs/recipes/pgdog"
130
+ />
131
+ <Card
132
+ title="Redis Cloud"
133
+ description="A managed backing store."
134
+ href="/docs/providers/redis-cloud"
135
+ />
136
+ </Cards>
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: "Valkey"
3
+ description: "BSD-licensed Redis-wire fork — same redis driver, OKE_STORE_KV_PASSWORD, valkey-server command."
4
+ icon: "Zap"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Valkey is the Linux Foundation's BSD-3-Clause fork of Redis, forked after Redis's 2024
9
+ license change. Same wire protocol — pin the image and nothing in Flow code moves.
10
+
11
+ <Callout title="The one rule">
12
+ Driver id stays `redis`. Valkey is an image choice, not a driver. `REDIS_URL` and every KV call
13
+ through `fx.store` work exactly as they do against Redis.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Pin the image
22
+
23
+ ```typescript title="oke.config.ts"
24
+ images: {
25
+ "store.kv": "valkey/valkey:8-alpine",
26
+ },
27
+ ```
28
+
29
+ </Step>
30
+
31
+ <Step>
32
+ ### Same password contract as Redis
33
+
34
+ ```bash
35
+ OKE_STORE_KV_PASSWORD=…
36
+ REDIS_URL=redis://:…@127.0.0.1:6379
37
+ ```
38
+
39
+ Command becomes `valkey-server --requirepass "$OKE_STORE_KV_PASSWORD" …` — healthcheck
40
+ uses `valkey-cli`.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Optional memory caps
46
+
47
+ Same knobs as Redis: `OKE_STORE_KV_MAXMEMORY`, `OKE_STORE_KV_MAXMEMORY_POLICY`.
48
+
49
+ </Step>
50
+
51
+ </Steps>
52
+
53
+ ## Required env
54
+
55
+ | Variable | Required? | Meaning |
56
+ | ------------------------------- | ------------- | --------------------------------------------------- |
57
+ | `OKE_STORE_KV_PASSWORD` | **Yes** | `--requirepass` for `valkey-server` |
58
+ | `REDIS_URL` | **Yes** (app) | Still `redis://` scheme — protocol name, not vendor |
59
+ | `OKE_STORE_KV_MAXMEMORY` | Optional | Memory cap |
60
+ | `OKE_STORE_KV_MAXMEMORY_POLICY` | Optional | Eviction policy |
61
+
62
+ ## Data and backup
63
+
64
+ No named volume in the recipe — same ephemeral default as [Redis](/docs/recipes/redis).
65
+ **Backup means:** do not assume durability until you add a volume + persistence config;
66
+ treat the default as a shared cache rebuilt from durable stores.
67
+
68
+ ## Production note
69
+
70
+ Choose Valkey when RSAL/SSPL managed-service terms on Redis ≥8 matter to your legal
71
+ posture — BSD-3-Clause carries no such restriction. Feature parity with Redis 7/8 stays
72
+ close since the fork tracks upstream.
73
+
74
+ DigitalOcean's managed product moved onto Valkey after Aiven stepped back from Redis —
75
+ see [DigitalOcean Managed Caching](/docs/providers/digitalocean-caching).
76
+
77
+ ## What the recipe configures
78
+
79
+ | Field | Value |
80
+ | -------------- | ------------------------------------------------------------------ |
81
+ | Container port | `6379` |
82
+ | Command | `valkey-server --requirepass … --maxmemory … --maxmemory-policy …` |
83
+ | Healthcheck | `valkey-cli -a <password> ping`, every 5s, 10 retries |
84
+ | Connection URL | `redis://:pass@host:6379` |
85
+ | License | BSD-3-Clause |
86
+
87
+ ## Troubleshooting
88
+
89
+ <Accordions>
90
+ <Accordion title="oke boot: redis driver needs REDIS_URL">
91
+
92
+ Same loud failure as Redis — the driver id is still `redis`. Export `REDIS_URL` or let
93
+ `oke dev --docker` write it.
94
+
95
+ </Accordion>
96
+ <Accordion title="Healthcheck uses redis-cli and fails">
97
+
98
+ You still have the Redis recipe matched (image ref contains `redis`). Valkey images must
99
+ match `/valkey/i` so the healthcheck binary is `valkey-cli`. Pin `valkey/valkey:…`
100
+ explicitly.
101
+
102
+ </Accordion>
103
+ </Accordions>
104
+
105
+ ## Learn more
106
+
107
+ - [Store · KV](/docs/elements/store#kv) — full Redis-protocol image license table
108
+ - [Redis](/docs/recipes/redis) · [Dragonfly](/docs/recipes/dragonfly) — the other two peers
109
+ - [DigitalOcean Managed Caching](/docs/providers/digitalocean-caching) — managed Valkey
110
+
111
+ ## Next
112
+
113
+ <Cards>
114
+ <Card
115
+ title="Dragonfly"
116
+ description="Multi-threaded Redis-wire peer."
117
+ href="/docs/recipes/dragonfly"
118
+ />
119
+ <Card title="Redis" description="The mature default." href="/docs/recipes/redis" />
120
+ <Card title="Upstash" description="Managed alternative." href="/docs/providers/upstash" />
121
+ </Cards>