@cerefox/memory 1.19.6 → 1.21.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.
@@ -15,8 +15,9 @@
15
15
  href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&display=swap"
16
16
  />
17
17
  <title>Cerefox</title>
18
- <script type="module" crossorigin src="/app/assets/index-lS0yMSGS.js"></script>
19
- <link rel="stylesheet" crossorigin href="/app/assets/index-01k5C3sG.css">
18
+ <script type="module" crossorigin src="/app/assets/index-Dd1nIOAB.js"></script>
19
+ <link rel="modulepreload" crossorigin href="/app/assets/rolldown-runtime-COiEfhsA.js">
20
+ <link rel="stylesheet" crossorigin href="/app/assets/index-CV1iy1p2.css">
20
21
  </head>
21
22
  <body>
22
23
  <div id="root"></div>
@@ -18,7 +18,7 @@
18
18
  * doesn't touch `supabase/functions/` leaves it alone).
19
19
  */
20
20
 
21
- export const EF_VERSION = "1.19.6";
21
+ export const EF_VERSION = "1.21.0";
22
22
 
23
23
  /**
24
24
  * The Cerefox RELEASE version — what `cerefox --version` reports and what npm
@@ -36,7 +36,7 @@ export const EF_VERSION = "1.19.6";
36
36
  * is imported by the Deno Edge Functions, which cannot reach into the npm
37
37
  * package.
38
38
  */
39
- export const CEREFOX_VERSION = "1.19.6";
39
+ export const CEREFOX_VERSION = "1.21.0";
40
40
 
41
41
  /**
42
42
  * The most recent version whose EF-side SOURCE actually changed (#127).
@@ -45,6 +45,7 @@ Full rule documented in [`docs/specs/polish-and-distribution-design.md` §7](../
45
45
  | `CEREFOX_DATABASE_URL` | `""` | For scripts | Direct Postgres URL for deployment scripts. **Use the Session Pooler** (port `5432`) — Transaction Pooler (`6543`) does not support DDL. Username must include the project-ref suffix (`postgres.<project-ref>`). Append `?sslmode=require`. See [`setup-supabase.md` → Connection pooling (2026)](setup-supabase.md#connection-pooling-2026). |
46
46
  | `CEREFOX_API_KEY` | `""` | Local web server (#229) | **Local API key** (`cfx_lak_…`) for `/api/v1` and `/rest/v1` on the machine running `cerefox web`. Callers on **loopback need no credential**; callers arriving on any other interface must send `Authorization: Bearer <key>`. Unset means the gate is off and the server behaves exactly as it did before v1.12.0 — so upgrading never breaks a working install. Minted by `cerefox api-key generate`; Cerefox Local mints its own at first boot (`cerefox-local api-key`). **Never sent to Supabase**; distinct from `CEREFOX_ACCESS_TOKEN`, which is the *cloud* credential for the Edge Functions. |
47
47
  | `CEREFOX_API_REQUIRE_KEY` | `""` | Local web server (#229) | Set to `1` to demand the API key from **every** caller, loopback included. The one topology that needs it: a same-host reverse proxy, which reconnects from `127.0.0.1`, so every proxied request would otherwise look local and be exempt. `X-Forwarded-For` is deliberately never consulted to recover the original address — it is caller-supplied, so trusting it would let anyone claim to be local. Has no effect when `CEREFOX_API_KEY` is unset (demanding a key that does not exist would lock you out of your own server). |
48
+ | `CEREFOX_ALLOWED_HOSTS` | `""` | Local web server (v1.20.0) | Extra host names a request **without a key** may use to reach the server, comma-separated (`nas.local,cerefox`); `*` allows any. Without it, a keyless request must name the server by an IP address, `localhost` or `host.docker.internal`, which stops a web page from reaching it through DNS rebinding. Requests that present the key are not checked. See [`securing-local-access.md`](securing-local-access.md#web-pages-in-your-browser-v1200). |
48
49
  | `SUPABASE_ACCESS_TOKEN` | *(unset)* | For EF deploys (optional) | Supabase **personal access token** (`sbp_…`, from [supabase.com/dashboard/account/tokens](https://supabase.com/dashboard/account/tokens)), read by the **Supabase CLI** that `cerefox server deploy` shells out to for Edge Function deploys. Optional — without it the CLI falls back to its `supabase login` credential, which on **macOS lives in the Keychain and triggers a password dialog per function deploy** (9 per full deploy; a denied dialog fails that function with `LegacyPlatformAuthRequiredError`). Setting it in `~/.cerefox/.env` avoids the dialogs entirely: Cerefox exports every key from its `.env` to the environment, so the child CLI inherits it. Not a `CEREFOX_` variable — the name is the Supabase CLI's own. **Keep secret** (it grants management access to your Supabase account). |
49
50
 
50
51
  **When each is needed:**
@@ -94,12 +94,43 @@ while making the common case worse for everyone. On a single-user machine,
94
94
  loopback access and key-file access are the same trust boundary, so the gate is
95
95
  drawn at the place where the trust actually changes: the network.
96
96
 
97
- This is also why **the browser never holds a key**. The web UI is a static
98
- file, so a key embedded in the page could be read by anything that can load the
99
- page — precisely the attacker the key exists to stop. A key in an
97
+ This is also why **the browser holds no key on a local install**. The web UI is
98
+ a static file, so a key embedded in the page could be read by anything that can
99
+ load the page — precisely the attacker the key exists to stop. A key in an
100
100
  unauthenticated page is not a secret. The UI works because it is local, not
101
101
  because it holds a credential.
102
102
 
103
+ **When the gate is on for the browser too** (a container published beyond
104
+ loopback, `CEREFOX_API_REQUIRE_KEY=1`, a native server opened from another
105
+ machine), the web UI asks for the key once, keeps it in that browser for that
106
+ address only, and sends it like any other client (v1.20.0+). Nothing is ever
107
+ embedded in the page; the key comes from you. Running Cerefox on another
108
+ machine on your network is covered in [`setup-lan.md`](setup-lan.md).
109
+
110
+ ### Web pages in your browser (v1.20.0+)
111
+
112
+ Trusting the machine has one catch: your browser is on the machine, and it runs
113
+ pages from anywhere. So a request the server lets in **without a key** (from
114
+ loopback, or with the gate off) also has to pass two browser checks:
115
+
116
+ - **No cross-site requests.** A page from another site cannot post to Cerefox:
117
+ the server refuses a request the browser marks as cross-site
118
+ (`Sec-Fetch-Site`), or one whose `Origin` is neither this server nor a page
119
+ served from this machine. Agents, curl and the CLI send neither header, so
120
+ they are not affected.
121
+ - **Only local names.** A keyless request must reach the server by an IP
122
+ address, `localhost`, or `host.docker.internal` (the `Host` header). This stops *DNS rebinding*, where
123
+ a page re-points its own domain name at `127.0.0.1` and reads your store as
124
+ if it were Cerefox. If you reach a gate-off server by a name on purpose (a
125
+ `.local` name, a Docker Compose service name), list it:
126
+
127
+ ```bash
128
+ CEREFOX_ALLOWED_HOSTS=nas.local,cerefox # comma-separated; * turns the check off
129
+ ```
130
+
131
+ Both refusals are a `403` whose message says which rule applied. A request
132
+ that presents the key skips both checks: a foreign page cannot send one.
133
+
103
134
  ## Getting a key
104
135
 
105
136
  ### `cerefox web` (npm install)
@@ -171,9 +202,9 @@ KEY="cfx_lak_$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)"
171
202
  { echo "CEREFOX_API_KEY=$KEY"; echo "CEREFOX_API_REQUIRE_KEY=1"; } >> ~/.cerefox/local/.env
172
203
  cerefox-local restart
173
204
 
174
- # Note: with the gate on, YOUR BROWSER needs the key too. If you use the web UI
175
- # daily, prefer leaving Cerefox published on loopback with the gate off and
176
- # giving your harness host networking instead.
205
+ # Note: with the gate on, YOUR BROWSER needs the key too: the web UI asks for it
206
+ # once (v1.20.0+). If you would rather not, leave Cerefox published on loopback
207
+ # with the gate off and give your harness host networking instead.
177
208
 
178
209
  # 3. Give the same value to your client container, however it takes config.
179
210
  docker run -e CEREFOX_API_KEY="$KEY" … your-harness
@@ -203,8 +234,8 @@ The answer is to stop exempting loopback:
203
234
  CEREFOX_API_REQUIRE_KEY=1
204
235
  ```
205
236
 
206
- Now every caller presents the key, proxy included. Your browser will need it
207
- too, so this mode suits headless deployments rather than daily UI use.
237
+ Now every caller presents the key, proxy included. The web UI asks for it once
238
+ per browser (v1.20.0+).
208
239
 
209
240
  ## What this does not protect
210
241
 
@@ -239,6 +270,21 @@ a Docker network, not loopback. Give it the key (see the recipe above).
239
270
  That is the v1.12.0 bug, not a configuration problem. Run
240
271
  `cerefox-local upgrade` to get v1.12.1 or newer.
241
272
 
273
+ **The web UI asks for an API key.** The server refused the browser, so the gate
274
+ is on for it: paste the key (`cerefox api-key show`, `cerefox-local api-key`, or
275
+ the `CEREFOX_API_KEY` you set). On v1.19.x and older the UI cannot send a key
276
+ at all and a gated server is unusable from a browser; upgrade.
277
+
278
+ **A `403` that says "a page from another site cannot use this server".** A web
279
+ page tried to call Cerefox from another site. If it was a tool of yours, call
280
+ the API from a script or give the tool the key; a browser page from another
281
+ site is exactly what this refuses.
282
+
283
+ **A `403` that says the server "was reached as" some name.** You reached a
284
+ server with no key by a host name. Use `127.0.0.1` or `localhost`, add the name
285
+ to `CEREFOX_ALLOWED_HOSTS` (in `~/.cerefox/local/.env` for Cerefox Local, then
286
+ `cerefox-local restart`), or turn the key on.
287
+
242
288
  **`cerefox-local api-key` says no key was found.** The image predates v1.12.0.
243
289
  Run `cerefox-local upgrade`.
244
290
 
@@ -9,6 +9,16 @@
9
9
 
10
10
  Deploy the Cerefox web UI to Google Cloud Run for a lightweight, serverless hosting option. This guide uses Supabase (free tier) for the database.
11
11
 
12
+ > **v1.20.0 changed the image: it now requires `CEREFOX_API_KEY`.** The repo's
13
+ > `Dockerfile` (the same one the published `cerefox-web` image is built from)
14
+ > refuses to start without it, and turns the API key gate on for every caller.
15
+ > Before v1.20.0 this guide deployed it `--allow-unauthenticated` with no key,
16
+ > which left a Cerefox that can read and change your whole store open to the
17
+ > internet. **If you deployed it that way, add the key (Step 3) before you
18
+ > redeploy**, or the new revision will not start. If Cloud Run IAM or IAP
19
+ > already controls access, `CEREFOX_WEB_NO_KEY=1` starts it without one. The
20
+ > web UI asks for the key once per browser.
21
+
12
22
  > **Note:** The Cerefox web UI is the TypeScript server (`cerefox web` — Hono backend +
13
23
  > React/Mantine SPA); the Python/FastAPI app was removed at v1.0.0. The container `Dockerfile`
14
24
  > builds and serves the TS `cerefox web` server (port 8000).
@@ -56,6 +66,24 @@ gcloud builds submit --tag $IMAGE .
56
66
 
57
67
  ## Step 3 — Deploy to Cloud Run
58
68
 
69
+ Keep the API key in Secret Manager rather than in a plain env var:
70
+
71
+ ```bash
72
+ echo -n "cfx_lak_$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)" | \
73
+ gcloud secrets create cerefox-api-key --data-file=-
74
+ ```
75
+
76
+ Let the service read it. Cloud Run runs as the project's default compute
77
+ service account unless you deployed with `--service-account`; grant that
78
+ account access to this one secret, or the revision cannot start:
79
+
80
+ ```bash
81
+ PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
82
+ gcloud secrets add-iam-policy-binding cerefox-api-key \
83
+ --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
84
+ --role=roles/secretmanager.secretAccessor
85
+ ```
86
+
59
87
  ```bash
60
88
  gcloud run deploy $SERVICE_NAME \
61
89
  --image $IMAGE \
@@ -69,9 +97,13 @@ gcloud run deploy $SERVICE_NAME \
69
97
  CEREFOX_SUPABASE_URL=https://YOUR-REF.supabase.co,\
70
98
  CEREFOX_SUPABASE_KEY=YOUR-SERVICE-ROLE-KEY,\
71
99
  OPENAI_API_KEY=YOUR-OPENAI-KEY,\
72
- CEREFOX_MAX_RESPONSE_BYTES=200000
100
+ CEREFOX_MAX_RESPONSE_BYTES=200000 \
101
+ --set-secrets CEREFOX_API_KEY=cerefox-api-key:latest
73
102
  ```
74
103
 
104
+ Read the key back when the web UI asks for it:
105
+ `gcloud secrets versions access latest --secret cerefox-api-key`.
106
+
75
107
  **Memory**: Cerefox uses cloud embeddings (OpenAI API) — no local model is loaded. `--memory 512Mi` is sufficient for the TS `cerefox web` server alone.
76
108
 
77
109
  **CPU**: `--cpu 1` is sufficient for personal use. Scale up for concurrent users.
@@ -84,7 +116,8 @@ gcloud run deploy $SERVICE_NAME \
84
116
  gcloud run services describe $SERVICE_NAME --region $REGION --format="value(status.url)"
85
117
  ```
86
118
 
87
- Open the printed URL — the Cerefox dashboard should load.
119
+ Open the printed URL followed by `/app/`. The web UI asks for the API key once;
120
+ then the dashboard loads.
88
121
 
89
122
  ---
90
123
 
@@ -95,9 +128,14 @@ After making code changes:
95
128
  ```bash
96
129
  docker build -t $IMAGE .
97
130
  docker push $IMAGE
98
- gcloud run deploy $SERVICE_NAME --image $IMAGE --region $REGION --platform managed
131
+ gcloud run deploy $SERVICE_NAME --image $IMAGE --region $REGION --platform managed \
132
+ --set-secrets CEREFOX_API_KEY=cerefox-api-key:latest
99
133
  ```
100
134
 
135
+ Upgrading a service deployed before v1.20.0 without a key: create the secret
136
+ and grant the service account access to it (Step 3) first, or the new revision
137
+ refuses to start.
138
+
101
139
  Cloud Run performs a zero-downtime rolling update.
102
140
 
103
141
  ---
@@ -112,19 +150,18 @@ all other deployment options. See `docs/guides/operational-cost.md` for a full b
112
150
 
113
151
  ## Securing access
114
152
 
115
- By default `--allow-unauthenticated` makes the URL public. To restrict access:
153
+ `--allow-unauthenticated` makes the URL public; the API key is what protects it
154
+ then. To also restrict who can reach it:
116
155
 
117
156
  ### Option 1 — Cloud Run IAM
118
157
 
119
- Remove `--allow-unauthenticated` and use `gcloud run services add-iam-policy-binding` to add specific Google accounts.
158
+ Remove `--allow-unauthenticated` and use `gcloud run services add-iam-policy-binding` to add specific Google accounts. IAM reads the `Authorization` header itself, so with IAM set `CEREFOX_WEB_NO_KEY=1` instead of a key.
120
159
 
121
160
  ### Option 2 — Cloud Run proxy
122
161
 
123
162
  Use Identity-Aware Proxy (IAP) in front of Cloud Run for Google SSO.
124
163
 
125
- ### Option 3 — Add HTTP basic auth
126
-
127
- Add a Hono middleware to the TS `cerefox web` server that checks `Authorization: Basic ...`
128
- headers, using `CEREFOX_BASIC_AUTH_USER` / `CEREFOX_BASIC_AUTH_PASSWORD` env vars
129
- (implement it against the current TS `cerefox web` server's middleware hook).
164
+ The API key (v1.20.0) replaces the "add HTTP basic auth" option this guide used
165
+ to suggest: both would need the `Authorization` header, and the key is already
166
+ built in.
130
167
 
@@ -0,0 +1,220 @@
1
+ # Running Cerefox on another machine on your network
2
+
3
+ Run Cerefox on an always-on machine on your home or office network (a NAS, a
4
+ mini PC, a home server) and use it from your other machines: agents, the CLI,
5
+ and the web UI in a browser. Requires **v1.20.0 or newer**.
6
+
7
+ There are two ways to do it, and they do not depend on each other:
8
+
9
+ | | What runs on the LAN host | Where the data lives | Image |
10
+ |---|---|---|---|
11
+ | **A. Cerefox Local** | Everything: database, server, web UI | On the LAN host | `ghcr.io/fstamatelopoulos/cerefox-local` |
12
+ | **B. Web container** | The server and web UI | Your Supabase project | `ghcr.io/fstamatelopoulos/cerefox-web` |
13
+
14
+ Pick **A** if you want the data at home and no cloud database. Pick **B** if you
15
+ already run Cerefox on Supabase and want the web UI (and the `/api/v1` API)
16
+ served from your network instead of from your laptop.
17
+
18
+ ## The one rule: the API key gate is on
19
+
20
+ On your laptop, Cerefox trusts connections that start on the same machine and
21
+ needs no key. **On a LAN host that rule cannot apply.** Inside a container every
22
+ caller looks remote, because Docker rewrites the source address of every
23
+ request that comes through a published port, so the container cannot tell your
24
+ laptop apart from any other device on the network. Without a key, anything that
25
+ can reach the port can read, change and delete the whole store.
26
+
27
+ So both setups turn the gate on for every caller (`CEREFOX_API_REQUIRE_KEY=1`)
28
+ and use a key you choose. Make one now and keep it somewhere safe, such as your
29
+ password manager:
30
+
31
+ ```bash
32
+ echo "cfx_lak_$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)"
33
+ ```
34
+
35
+ Every client then presents it as `Authorization: Bearer <key>`. **The web UI
36
+ asks for it once per browser** (see [Using the web UI](#using-the-web-ui)).
37
+
38
+ ## A. Cerefox Local on a LAN host
39
+
40
+ The same all-in-one image the [local install](setup-local.md) uses, run directly
41
+ with Docker instead of through `cerefox-local`.
42
+
43
+ ### With `docker run`
44
+
45
+ ```bash
46
+ docker run -d --name cerefox --restart unless-stopped \
47
+ -p 8000:8000 \
48
+ -v /path/on/host/cerefox-db:/var/lib/postgresql/data \
49
+ -e CEREFOX_API_REQUIRE_KEY=1 \
50
+ -e CEREFOX_API_KEY=cfx_lak_YOUR-KEY \
51
+ -e CEREFOX_EMBEDDER=openai \
52
+ -e OPENAI_API_KEY=YOUR-OPENAI-KEY \
53
+ --memory 2g \
54
+ ghcr.io/fstamatelopoulos/cerefox-local:v1.20.0
55
+ ```
56
+
57
+ - **The data folder** (`/path/on/host/cerefox-db`) holds the database. Deleting
58
+ or recreating the container keeps it, which is how you upgrade.
59
+ - **Publish only port 8000.** Postgres (5432) and PostgREST (3000) stay inside
60
+ the container; do not publish them.
61
+ - **`CEREFOX_API_KEY`** sets the key. Without it the container mints one on
62
+ first boot and keeps it in the data folder; you can read that one with
63
+ `docker exec cerefox cat /var/lib/postgresql/data/.cerefox_api_key`. Setting
64
+ it yourself is easier on hosts whose Docker app gives you no shell.
65
+ - **Embeddings:** `CEREFOX_EMBEDDER=openai` with your key, or
66
+ `CEREFOX_EMBEDDER=local` for the bundled offline model (no API key, needs more
67
+ memory; see [`setup-local.md`](setup-local.md) for the figures).
68
+ - **Memory:** 2 GB is comfortable with OpenAI embeddings.
69
+
70
+ ### With a compose file (or a NAS Docker app)
71
+
72
+ Most NAS Docker apps (Synology Container Manager, QNAP Container Station,
73
+ Unraid, Portainer) accept a compose file as a "project" or "stack". Use one:
74
+ an upgrade is then a one-line change to the image tag.
75
+
76
+ ```yaml
77
+ services:
78
+ cerefox:
79
+ image: ghcr.io/fstamatelopoulos/cerefox-local:v1.20.0
80
+ container_name: cerefox
81
+ restart: unless-stopped
82
+ ports:
83
+ - "8000:8000"
84
+ volumes:
85
+ - /path/on/host/cerefox-db:/var/lib/postgresql/data
86
+ environment:
87
+ CEREFOX_API_REQUIRE_KEY: "1"
88
+ CEREFOX_API_KEY: "cfx_lak_YOUR-KEY"
89
+ CEREFOX_EMBEDDER: openai
90
+ OPENAI_API_KEY: "YOUR-OPENAI-KEY"
91
+ mem_limit: 2g
92
+ ```
93
+
94
+ The compose file holds both keys, so treat it as a secret. Give the project its
95
+ own folder, never the data folder.
96
+
97
+ Set only the variables above. The image's own variables (`PGDATA`,
98
+ `POSTGRES_*`, `CEREFOX_DATABASE_URL`, `CEREFOX_SUPABASE_URL`,
99
+ `CEREFOX_POSTGREST_UPSTREAM`, `PGRST_*`, `CEREFOX_MODELS_DIR`) are defaults
100
+ baked into it; some Docker apps display them, but do not change them.
101
+
102
+ ### If the host cannot pull the image
103
+
104
+ Some NAS Docker apps fail to pull from `ghcr.io` (for example "registry returned
105
+ bad result"). Pull it on another machine and copy it over as a file. Most NAS
106
+ hosts are x86-64, so ask for `linux/amd64` explicitly when the other machine is
107
+ an Apple Silicon Mac:
108
+
109
+ ```bash
110
+ docker pull --platform linux/amd64 ghcr.io/fstamatelopoulos/cerefox-local:v1.20.0
111
+ docker save ghcr.io/fstamatelopoulos/cerefox-local:v1.20.0 -o cerefox-local-v1.20.0-amd64.tar
112
+ ```
113
+
114
+ Then import the `.tar` in the Docker app (usually Image → Add → From file). Keep
115
+ the `image:` line exactly as the imported name and tag, or the app will try to
116
+ pull again.
117
+
118
+ ### Upgrading
119
+
120
+ Change the tag (and import the new `.tar` first if the host cannot pull), then
121
+ recreate the container. The data folder carries the database and, if you let the
122
+ container mint it, the key. Cerefox Local applies pending schema migrations on
123
+ boot.
124
+
125
+ ## B. The web container, with your Supabase backend
126
+
127
+ You need a working Supabase-backed Cerefox first (see
128
+ [`setup-supabase.md`](setup-supabase.md)): the schema, RPCs and Edge Functions
129
+ are deployed by `cerefox server deploy`, not by this image.
130
+
131
+ ```bash
132
+ docker run -d --name cerefox-web --restart unless-stopped \
133
+ -p 8000:8000 \
134
+ -e CEREFOX_SUPABASE_URL=https://YOUR-REF.supabase.co \
135
+ -e CEREFOX_SUPABASE_KEY=YOUR-SECRET-KEY \
136
+ -e OPENAI_API_KEY=YOUR-OPENAI-KEY \
137
+ -e CEREFOX_API_KEY=cfx_lak_YOUR-KEY \
138
+ ghcr.io/fstamatelopoulos/cerefox-web:v1.20.0
139
+ ```
140
+
141
+ - **The image refuses to start without `CEREFOX_API_KEY`** and turns the gate
142
+ on for every caller. It holds your Supabase secret key, so an open container
143
+ on the network would hand out full access to your cloud store.
144
+ - **`CEREFOX_WEB_NO_KEY=1`** starts it without a key. Use it only when
145
+ something in front of the container already controls who can reach it (an
146
+ authenticating proxy, Cloud Run IAM). It logs a warning at every start, and
147
+ sets `CEREFOX_ALLOWED_HOSTS=*` unless you set it, since the container is then
148
+ reached by the proxy's host name.
149
+ - The image runs as an unprivileged user and has a healthcheck that uses the
150
+ key from its own environment.
151
+ - The local offline embedder is not included: it runs only in Cerefox Local.
152
+
153
+ ## Using it from your other machines
154
+
155
+ Use the host's address and the published port, for example
156
+ `http://192.168.1.20:8000`.
157
+
158
+ ```bash
159
+ KEY=cfx_lak_YOUR-KEY; HOST=http://192.168.1.20:8000
160
+ curl -s -o /dev/null -w '%{http_code}\n' "$HOST/api/v1/projects" # 401
161
+ curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $KEY" "$HOST/api/v1/projects" # 200
162
+ ```
163
+
164
+ **Check `/api/v1/projects`, not `/api/v1/version`.** The version route never
165
+ touches the database, so it answers even when the data path is broken. (From
166
+ v1.12.1 to v1.19.5 a gated Cerefox Local container answered `version` while
167
+ every data route failed; fixed in v1.19.6.)
168
+
169
+ The HTTP API is documented in [`api.md`](api.md).
170
+
171
+ ### Using the web UI
172
+
173
+ Open `http://<host>:<port>/app/`. The page loads, the server refuses its first
174
+ call, and the UI asks for the key:
175
+
176
+ - **Paste the key** and press Continue. The UI checks it with the server before
177
+ keeping it, so a mistyped key is refused in the dialog.
178
+ - **"Remember on this browser"** keeps it in the browser's local storage for
179
+ this address. Unticked, it lasts until the tab closes.
180
+ - **The key-off icon** in the header forgets it. So does a key the server stops
181
+ accepting (rotated, or the container recreated with a new one): the UI says
182
+ the saved key was not accepted and asks again.
183
+
184
+ The key is kept per address and port, so other apps on the same host cannot
185
+ read it. It is readable by scripts running in the Cerefox page itself; the page
186
+ renders documents without raw HTML, and the project's tests fail on any change
187
+ that would let a document inject script.
188
+
189
+ ## What this does not protect
190
+
191
+ **Traffic on the wire.** Plain `http://` on your network sends the key, and
192
+ everything else, unencrypted. That is usually acceptable on a home network you
193
+ control; it is not on a shared one. For TLS, put a reverse proxy in front (see
194
+ [`securing-local-access.md`](securing-local-access.md#recipe-a-reverse-proxy-on-the-same-machine));
195
+ the gate stays on, since a proxy makes every request look local.
196
+
197
+ **The internet.** Do not forward the port from your router. These setups are
198
+ for your own network.
199
+
200
+ **Anyone with the key**, or with access to the host's files, the data folder or
201
+ the compose file.
202
+
203
+ ## Troubleshooting
204
+
205
+ **Nothing answers on the port.** Check which host port is actually published in
206
+ your Docker app; the container may be running on a different one than you
207
+ planned.
208
+
209
+ **Every data route returns 500 with the key, but `/version` works.** The image
210
+ is older than v1.19.6. Upgrade.
211
+
212
+ **The web UI shows a white page or keeps failing after the key.** The image is
213
+ older than v1.20.0, which is the first version whose web UI can send a key.
214
+
215
+ **The container exits right away (web container).** Read its log: it refuses
216
+ to start without `CEREFOX_API_KEY` and says so.
217
+
218
+ **A markdown image in a document does not load.** An image whose address is a
219
+ `/api/v1/…` path is fetched by the browser without the key. Links work; images
220
+ from the API do not.
@@ -10,6 +10,10 @@ Cerefox web server. You get the same web UI, CLI, and MCP server as the cloud se
10
10
  > container, fully offline, no API key. See
11
11
  > [Choose your embedder](#choose-your-embedder-openai-vs-fully-local).
12
12
 
13
+ > **On another machine on your network?** To run this image on a NAS or a home
14
+ > server and use it from your other machines (browser included), follow
15
+ > [`setup-lan.md`](setup-lan.md) instead of the installer below.
16
+
13
17
  ## Cloud vs. Local — pick one
14
18
 
15
19
  Cerefox has two independent "worlds". Most people run **one or the other**:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerefox/memory",
3
- "version": "1.19.6",
3
+ "version": "1.21.0",
4
4
  "description": "Cerefox \u2014 user-owned shared memory for AI agents. CLI + stdio MCP server + web UI + ingestion for a knowledge base on your own Supabase project (or fully self-hosted with Cerefox Local).",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/fstamatelopoulos/cerefox",
@@ -58,7 +58,7 @@
58
58
  "onnxruntime-node": "^1.21.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@types/bun": "^1.4.3",
61
+ "@types/bun": "^1.4.4",
62
62
  "@types/cli-progress": "^3.11.5",
63
63
  "@types/node": "^24.19.2",
64
64
  "@types/prompts": "^2.4.9",