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,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>
|