@supacloud/lite 0.33.1 → 0.34.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/CHANGELOG.md +27 -0
- package/README.md +85 -2
- package/deploy/README.md +110 -0
- package/deploy/caddy/Caddyfile +15 -0
- package/deploy/systemd/supacloud-lite.service +32 -0
- package/dist/cli.js +552 -155
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +474 -129
- package/dist/project-runtime.d.ts +2 -0
- package/dist/project-runtime.d.ts.map +1 -1
- package/dist/runtime/auth/proxy.d.ts +28 -0
- package/dist/runtime/auth/proxy.d.ts.map +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/node/bun-server.d.ts +2 -0
- package/dist/runtime/node/bun-server.d.ts.map +1 -1
- package/dist/runtime/node/native/readiness.d.ts +2 -0
- package/dist/runtime/node/native/readiness.d.ts.map +1 -1
- package/dist/runtime/node/production-readiness.d.ts +31 -0
- package/dist/runtime/node/production-readiness.d.ts.map +1 -0
- package/dist/runtime/realtime/engine.d.ts +23 -0
- package/dist/runtime/realtime/engine.d.ts.map +1 -1
- package/dist/runtime/storage/handler.d.ts +6 -0
- package/dist/runtime/storage/handler.d.ts.map +1 -1
- package/package.json +18 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.34.0](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.33.2...supacloud-lite-v0.34.0) (2026-10-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **lite:** add authorized realtime HTTP broadcast ([#2250](https://github.com/vibeunion/supacloud/issues/2250)) ([405747c](https://github.com/vibeunion/supacloud/commit/405747cce8f055c371e8f76c38a862aaf480f94c))
|
|
9
|
+
* **lite:** add production readiness doctor checks ([#2249](https://github.com/vibeunion/supacloud/issues/2249)) ([d9f09f2](https://github.com/vibeunion/supacloud/commit/d9f09f2ff797898af9a68d2c261b9d66e0eea001))
|
|
10
|
+
* **lite:** add restricted same-origin external auth proxy ([#2247](https://github.com/vibeunion/supacloud/issues/2247)) ([10e420e](https://github.com/vibeunion/supacloud/commit/10e420e700f206a8f190e6d51622c980d867fc68))
|
|
11
|
+
* **lite:** add storage status and metrics endpoints ([#2251](https://github.com/vibeunion/supacloud/issues/2251)) ([183b323](https://github.com/vibeunion/supacloud/commit/183b32397006a2b80d9961e7ae26d5779654b064))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Documentation
|
|
15
|
+
|
|
16
|
+
* **lite:** add single-node production deployment assets ([#2248](https://github.com/vibeunion/supacloud/issues/2248)) ([1e36554](https://github.com/vibeunion/supacloud/commit/1e36554cbbdbfecbb1e2a4974af560e8fa62124a))
|
|
17
|
+
|
|
18
|
+
## [0.33.2](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.33.1...supacloud-lite-v0.33.2) (2026-10-25)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* **lite:** preserve shared realtime presence sessions ([#2242](https://github.com/vibeunion/supacloud/issues/2242)) ([b6cff5a](https://github.com/vibeunion/supacloud/commit/b6cff5a4117a093fb7c75034bf09575eddb74bd8))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Miscellaneous Chores
|
|
27
|
+
|
|
28
|
+
* **deps:** refresh the Elysia runtime and dependency matrix ([#2243](https://github.com/vibeunion/supacloud/issues/2243)) ([917ff0f](https://github.com/vibeunion/supacloud/commit/917ff0fa81e3c47d86d18e8c58fff79c0f0f67f5))
|
|
29
|
+
|
|
3
30
|
## [0.33.1](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.33.0...supacloud-lite-v0.33.1) (2026-10-19)
|
|
4
31
|
|
|
5
32
|
|
package/README.md
CHANGED
|
@@ -166,8 +166,23 @@ Lite 支持平铺 SQL 与 `时间戳目录/migration.sql`,执行前检查重
|
|
|
166
166
|
|
|
167
167
|
`/graphql/v1` 使用真正的 `pg_graphql` 扩展和调用者的数据库角色/RLS,不模拟扩展。默认 PGlite 和标准 native 下载包均不包含该扩展;native 可通过 `--postgres-dir` 选择已经安装匹配扩展的 PostgreSQL。配置 `[lite.graphql] enabled = true` 会在运行时启动前验证扩展,`doctor --json` 区分已支持、缺失与尚未验证。
|
|
168
168
|
|
|
169
|
+
`doctor --production` 在能力报告之外检查单机生产阻断项和运维义务:strict 运行时、非内存存储、外部身份同源代理、公开地址、数据库/存储目录隔离、状态目录位置和快照新鲜度。阻断项使命令以非零退出码结束;警告项表示必须由部署方承担的运维责任(例如 S3 对象不在快照内、PGlite 容量验证、TLS 必须由反代终止)。
|
|
170
|
+
|
|
169
171
|
外部 SupAuth 可通过 `createSupAuthLiteIdentity` 复用 `@supacloud/elysia` 的验证和业务侧本地用户映射;本地 Auth 仍是默认模式。外部模式不会把本地令牌降级当成 SupAuth,也不会根据请求头授予权限。
|
|
170
172
|
|
|
173
|
+
如果浏览器应用与身份服务不同源,且身份服务没有为业务域名开放 CORS,可在 Lite 前面启用受限的同源 OAuth 反代:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
supacloud-lite start \
|
|
177
|
+
--external-auth-proxy-issuer https://auth.example.com/auth/v1 \
|
|
178
|
+
--external-auth-proxy-redirect-origin https://app.example.com
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
反代只接受 `/auth/v1/oauth/token`(POST)、`/auth/v1/oauth/userinfo`(GET)和
|
|
182
|
+
`/auth/v1/logout`(GET/POST),不会转发 cookie、`x-forwarded-*` 或任意上游地址。
|
|
183
|
+
授权请求仍由浏览器顶层跳转到身份服务;应用端把 token/userinfo 指向 Lite 同源地址。
|
|
184
|
+
嵌入宿主也可以直接调用 `createExternalAuthProxy()`。
|
|
185
|
+
|
|
171
186
|
完整配置、边界和回归方法见仓库文档 `docs/lite-runtime-compatibility.md`。性能基线可在源码目录运行 `bun run benchmark`,native 模式加 `--native`。
|
|
172
187
|
|
|
173
188
|
### CLI
|
|
@@ -187,7 +202,7 @@ supacloud-lite snapshot create [-o backup.tar.gz]
|
|
|
187
202
|
supacloud-lite snapshot restore <backup.tar.gz> [--force]
|
|
188
203
|
supacloud-lite upgrade [-o pre-upgrade.tar.gz]
|
|
189
204
|
supacloud-lite inspect
|
|
190
|
-
supacloud-lite doctor [--json]
|
|
205
|
+
supacloud-lite doctor [--json] [--production]
|
|
191
206
|
supacloud-lite version
|
|
192
207
|
```
|
|
193
208
|
|
|
@@ -374,6 +389,19 @@ S3 模式的快照只包含数据库中的 Storage 元数据和密钥,不复
|
|
|
374
389
|
|
|
375
390
|
RLS 表的 Realtime DELETE 无法在行删除后安全重放 SELECT policy,因此 V1 只向 `service_role` 订阅者发送这类 DELETE 事件。普通用户仍可收到通过逐行 RLS 校验的 INSERT/UPDATE 事件。
|
|
376
391
|
|
|
392
|
+
Realtime 也支持服务端 HTTP 广播:
|
|
393
|
+
|
|
394
|
+
```http
|
|
395
|
+
POST /realtime/v1/api/broadcast
|
|
396
|
+
apikey: <project-anon-key>
|
|
397
|
+
authorization: Bearer <access-token>
|
|
398
|
+
content-type: application/json
|
|
399
|
+
|
|
400
|
+
{"messages":[{"topic":"room:42","event":"notice","payload":{"text":"hello"},"private":false}]}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
请求沿用 Realtime 的 `messages` 数组格式,单次最多 100 条,每条 `event` 最多 256 字节、`topic` 最多 256 字节、`payload` 最多 1 MiB。`private: true` 会按 `realtime.messages` 的 INSERT policy 校验调用者;整个批次先完成校验再发送,任一主题无写权限时返回 `403`,不会部分广播。成功返回 `202 {"message":"Broadcast sent"}`。该端点只做实时投递,不持久化消息;需要离线补偿时仍应使用数据库表或 outbox。
|
|
404
|
+
|
|
377
405
|
### Capability doctor 与 PowerSync profile
|
|
378
406
|
|
|
379
407
|
`doctor` 输出 Lite 自己的稳定能力契约,不复制完整 Management API:
|
|
@@ -508,6 +536,10 @@ Lite 的缓存调用是进程内数据库操作,不具备标准版跨进程 HT
|
|
|
508
536
|
|
|
509
537
|
V1 不在一个进程内复用多个 PGlite 项目。需要多个项目时,为每个项目配置独立的工作目录、端口和 `.supacloud-lite` 状态目录,并用进程管理器分别启动。这样可保持数据库、JWT、Storage 和 Realtime 的故障域隔离。
|
|
510
538
|
|
|
539
|
+
### 生产部署
|
|
540
|
+
|
|
541
|
+
`deploy/` 提供单机生产部署模板:systemd 用户/目录/状态目录约定、Caddy TLS 反代、外部 SupAuth 同源代理、快照维护窗口、S3 对象单独备份和回滚步骤。Lite 不自带 TLS、HA 或控制面;必须保持单进程单状态目录,并由 Caddy/Nginx 终止 TLS。生产前至少应完成容量测试、恢复演练和未认证请求失败关闭验证。
|
|
542
|
+
|
|
511
543
|
### 资源边界
|
|
512
544
|
|
|
513
545
|
PGlite 是 WebAssembly PostgreSQL,不是 SQLite。它换来了 PostgreSQL SQL、角色、RLS 和 Supabase 迁移兼容性,但内存占用通常高于 PocketBase/SQLite。生产部署前应按真实 schema、并发和 Realtime 负载做容量测试。
|
|
@@ -531,6 +563,8 @@ await running.close()
|
|
|
531
563
|
|
|
532
564
|
图片变换目前提供 Bun.Image 的兼容子集:`width`、`height`、`resize=fill|contain`,以及 `format=origin|jpeg|png|webp` 和 JPEG/WebP `quality`。`resize=cover` 需要裁剪能力,当前 Bun 运行时没有对应 API,因此会明确返回不支持错误,不会错误地把图片拉伸成 `cover`。
|
|
533
565
|
|
|
566
|
+
Storage 还提供两个运维端点:`GET /storage/v1/status` 无需项目 API key,返回服务名称、版本和健康状态;`GET /storage/v1/metrics` 需要 `service_role`,以 Prometheus 文本格式输出 bucket 数、对象元数据行数和声明对象总字节数。指标只统计 Lite 自己的 `storage` schema,不代表远端 S3 bucket 的真实用量或后台清理延迟。
|
|
567
|
+
|
|
534
568
|
也可以使用 `createLiteBackend()` 直接创建内存或自定义目录的嵌入式后端,并把它的 `fetch` 传给自定义宿主。
|
|
535
569
|
|
|
536
570
|
### 来源与许可
|
|
@@ -662,7 +696,7 @@ supacloud-lite snapshot create [-o backup.tar.gz]
|
|
|
662
696
|
supacloud-lite snapshot restore <backup.tar.gz> [--force]
|
|
663
697
|
supacloud-lite upgrade [-o pre-upgrade.tar.gz]
|
|
664
698
|
supacloud-lite inspect
|
|
665
|
-
supacloud-lite doctor [--json]
|
|
699
|
+
supacloud-lite doctor [--json] [--production]
|
|
666
700
|
supacloud-lite version
|
|
667
701
|
```
|
|
668
702
|
|
|
@@ -853,6 +887,30 @@ GraphQL fails startup when missing; `doctor --json` reports actual or unverified
|
|
|
853
887
|
capability. External SupAuth can reuse the shared Elysia verifier through
|
|
854
888
|
`createSupAuthLiteIdentity` and an explicit application-owned local user mapping.
|
|
855
889
|
|
|
890
|
+
When the browser application and the identity service have different origins and
|
|
891
|
+
the identity service does not allow the application origin via CORS, Lite can
|
|
892
|
+
serve a restricted same-origin OAuth proxy:
|
|
893
|
+
|
|
894
|
+
```sh
|
|
895
|
+
supacloud-lite start \
|
|
896
|
+
--external-auth-proxy-issuer https://auth.example.com/auth/v1 \
|
|
897
|
+
--external-auth-proxy-redirect-origin https://app.example.com
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
The proxy accepts only `/auth/v1/oauth/token` (POST),
|
|
901
|
+
`/auth/v1/oauth/userinfo` (GET) and `/auth/v1/logout` (GET/POST). It never
|
|
902
|
+
forwards cookies, `x-forwarded-*`, or arbitrary upstream URLs. Authorization
|
|
903
|
+
remains a top-level navigation to the identity service; the application points
|
|
904
|
+
token/userinfo at the Lite same-origin address. Embedded hosts can call
|
|
905
|
+
`createExternalAuthProxy()` directly.
|
|
906
|
+
|
|
907
|
+
`doctor --production` adds single-node production policy checks: strict runtime,
|
|
908
|
+
non-memory storage, external identity proxying, public URLs, database/storage
|
|
909
|
+
path separation, state-directory location and snapshot freshness. Blockers exit
|
|
910
|
+
non-zero; warnings are operational obligations such as backing up S3 objects
|
|
911
|
+
outside the Lite snapshot, capacity-testing PGlite, and terminating TLS at the
|
|
912
|
+
proxy.
|
|
913
|
+
|
|
856
914
|
See repository document `docs/lite-runtime-compatibility.md` for configuration
|
|
857
915
|
and acceptance boundaries. Run `bun run benchmark` (or add `--native`) in the
|
|
858
916
|
source package for a synthetic baseline, not a production performance claim.
|
|
@@ -880,6 +938,19 @@ source package for a synthetic baseline, not a production performance claim.
|
|
|
880
938
|
|
|
881
939
|
Realtime DELETE on RLS tables cannot safely replay SELECT policies after a row is deleted, so V1 only sends such DELETE events to `service_role` subscribers. Regular users can still receive INSERT/UPDATE events that pass row-by-row RLS validation.
|
|
882
940
|
|
|
941
|
+
Realtime also exposes server-side HTTP broadcast:
|
|
942
|
+
|
|
943
|
+
```http
|
|
944
|
+
POST /realtime/v1/api/broadcast
|
|
945
|
+
apikey: <project-anon-key>
|
|
946
|
+
authorization: Bearer <access-token>
|
|
947
|
+
content-type: application/json
|
|
948
|
+
|
|
949
|
+
{"messages":[{"topic":"room:42","event":"notice","payload":{"text":"hello"},"private":false}]}
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
It uses Realtime's `messages` envelope: at most 100 messages per request, each `event` and `topic` at most 256 bytes, and each `payload` at most 1 MiB. `private: true` authorizes the caller through the `realtime.messages` INSERT policy. The whole batch is authorized before any delivery, so one denied topic returns `403` without partially broadcasting. Success returns `202 {"message":"Broadcast sent"}`. This endpoint delivers live events only; use a database table or outbox when messages must survive disconnects.
|
|
953
|
+
|
|
883
954
|
### Capability doctor and PowerSync profile
|
|
884
955
|
|
|
885
956
|
`supacloud-lite doctor --json` reports a stable Lite capability contract without copying the full Management API. PGlite explicitly reports Logical Replication and PowerSync source support as `unsupported`; it never emulates WAL, publications, or slots. Multi-device offline deployments should use central SupaCloud + PowerSync, while a single field workstation can use Lite as a local project server or upload through an application-owned outbox.
|
|
@@ -998,6 +1069,16 @@ Lite's cache calls are in-process database operations and do not have the timeou
|
|
|
998
1069
|
|
|
999
1070
|
V1 does not multiplex multiple PGlite projects within a single process. When multiple projects are needed, configure an independent working directory, port, and `.supacloud-lite` state directory for each project, and start them separately with a process manager. This keeps the database, JWT, Storage, and Realtime failure domains isolated.
|
|
1000
1071
|
|
|
1072
|
+
### Production Deployment
|
|
1073
|
+
|
|
1074
|
+
The `deploy/` directory documents a single-node production contract: systemd
|
|
1075
|
+
service account/state directories, Caddy TLS termination, external SupAuth
|
|
1076
|
+
same-origin proxying, snapshot maintenance windows, separate S3 object backup,
|
|
1077
|
+
and rollback. Lite does not bundle TLS, HA, or a control plane. Keep one process
|
|
1078
|
+
per state directory and terminate TLS at Caddy/Nginx. Before production, run
|
|
1079
|
+
capacity tests, a restore drill, and an unauthenticated-request fail-closed
|
|
1080
|
+
check.
|
|
1081
|
+
|
|
1001
1082
|
### Resource Boundaries
|
|
1002
1083
|
|
|
1003
1084
|
PGlite is WebAssembly PostgreSQL, not SQLite. It trades off for PostgreSQL SQL, roles, RLS, and Supabase migration compatibility, but its memory footprint is typically higher than PocketBase/SQLite. Before production deployment, you should perform capacity testing against the real schema, concurrency, and Realtime load.
|
|
@@ -1021,6 +1102,8 @@ await running.close()
|
|
|
1021
1102
|
|
|
1022
1103
|
Image transforms currently provide a compatible subset of Bun.Image: `width`, `height`, `resize=fill|contain`, as well as `format=origin|jpeg|png|webp` and JPEG/WebP `quality`. `resize=cover` requires cropping capability, which the current Bun runtime does not have a corresponding API for, so it explicitly returns an unsupported error instead of incorrectly stretching the image to `cover`.
|
|
1023
1104
|
|
|
1105
|
+
Storage also exposes two operational endpoints: `GET /storage/v1/status` needs no project API key and returns the service name, version, and health; `GET /storage/v1/metrics` requires `service_role` and returns Prometheus text with bucket count, object metadata rows, and declared object bytes. These metrics cover Lite's `storage` schema only; they do not claim the real usage of a remote S3 bucket or background cleanup latency.
|
|
1106
|
+
|
|
1024
1107
|
You can also use `createLiteBackend()` to directly create an embedded backend with an in-memory or custom directory, and pass its `fetch` to a custom host.
|
|
1025
1108
|
|
|
1026
1109
|
### Provenance and License
|
package/deploy/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# SupaCloud Lite production deployment
|
|
2
|
+
|
|
3
|
+
This directory contains a minimal single-project deployment contract. It is not
|
|
4
|
+
a multi-tenant control plane. Run one Lite process per state directory and put
|
|
5
|
+
TLS plus a reverse proxy in front of it.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
/opt/supacloud-lite/project reviewed migrations, seed and functions (read-only at runtime)
|
|
11
|
+
/var/lib/supacloud-lite database, storage and snapshots (persistent)
|
|
12
|
+
/etc/supacloud-lite/env secrets and runtime configuration (root:root 0600)
|
|
13
|
+
/usr/local/bin/supacloud-lite installed CLI / standalone binary
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The systemd unit sets `SUPACLOUD_LITE_STATE_DIR=/var/lib/supacloud-lite`, so the
|
|
17
|
+
project checkout does not contain mutable data.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
1. Install the pinned Lite release and verify its version.
|
|
22
|
+
2. Create a service account and directories:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
sudo useradd --system --home /var/lib/supacloud-lite --shell /usr/sbin/nologin supacloud-lite
|
|
26
|
+
sudo install -d -o supacloud-lite -g supacloud-lite -m 0750 /var/lib/supacloud-lite
|
|
27
|
+
sudo install -d -o root -g root -m 0755 /opt/supacloud-lite/project /etc/supacloud-lite
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. Put the reviewed project files under `/opt/supacloud-lite/project`.
|
|
31
|
+
4. Create `/etc/supacloud-lite/env` from the project's deployment secret store.
|
|
32
|
+
Keep it `root:root` and `0600`. Supported values include `S3_*` credentials,
|
|
33
|
+
`SUPACLOUD_LITE_S3_PREFIX`, `SUPACLOUD_LITE_STORAGE_BACKEND=s3`, and the
|
|
34
|
+
trusted external identity module setting.
|
|
35
|
+
5. Run migrations and create the first local account **before** starting the
|
|
36
|
+
service:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
sudo -u supacloud-lite env SUPACLOUD_LITE_STATE_DIR=/var/lib/supacloud-lite \
|
|
40
|
+
supacloud-lite migrate --project-dir /opt/supacloud-lite/project
|
|
41
|
+
sudo -u supacloud-lite env SUPACLOUD_LITE_STATE_DIR=/var/lib/supacloud-lite \
|
|
42
|
+
supacloud-lite auth create-user --project-dir /opt/supacloud-lite/project \
|
|
43
|
+
--email operator@example.com --password-stdin --email-confirm < /secure/password.txt
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
6. Install the unit and reload systemd:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
sudo install -m 0644 deploy/systemd/supacloud-lite.service /etc/systemd/system/
|
|
50
|
+
sudo systemctl daemon-reload
|
|
51
|
+
sudo systemctl enable --now supacloud-lite
|
|
52
|
+
curl -fsS http://127.0.0.1:54321/health
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
7. Install the Caddy site from `deploy/caddy/Caddyfile`, replace the hostname,
|
|
56
|
+
and verify HTTPS plus an authenticated API request.
|
|
57
|
+
|
|
58
|
+
## External SupAuth
|
|
59
|
+
|
|
60
|
+
If the browser application and identity service are on different origins and
|
|
61
|
+
the identity service does not allow the application origin via CORS, use the
|
|
62
|
+
restricted same-origin proxy documented in the package README:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
supacloud-lite start \
|
|
66
|
+
--external-auth-proxy-issuer https://auth.example.com/auth/v1 \
|
|
67
|
+
--external-auth-proxy-redirect-origin https://app.example.com
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The proxy handles only OAuth token, userinfo and logout. Authorization remains a
|
|
71
|
+
top-level navigation. Membership and application permissions stay in the
|
|
72
|
+
application-owned data and RLS model; Lite does not grant them from token claims.
|
|
73
|
+
|
|
74
|
+
## Backup, upgrade and restore
|
|
75
|
+
|
|
76
|
+
Lite snapshots require the process to be stopped. Use a maintenance window:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
sudo systemctl stop supacloud-lite
|
|
80
|
+
sudo -u supacloud-lite env SUPACLOUD_LITE_STATE_DIR=/var/lib/supacloud-lite \
|
|
81
|
+
supacloud-lite snapshot create \
|
|
82
|
+
--project-dir /opt/supacloud-lite/project \
|
|
83
|
+
-o /var/lib/supacloud-lite/backups/pre-upgrade.tar.gz
|
|
84
|
+
sudo systemctl start supacloud-lite
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For an upgrade, stop the service, install the pinned candidate, run
|
|
88
|
+
`supacloud-lite upgrade`, start the service, and verify `/health` and a real
|
|
89
|
+
authenticated read. If the upgrade fails, restore the pre-upgrade snapshot with
|
|
90
|
+
`snapshot restore --force` and restart the previous binary.
|
|
91
|
+
|
|
92
|
+
When using S3, snapshots contain database metadata and secrets but **not remote
|
|
93
|
+
objects**. Back up the bucket/prefix separately and restore it before starting
|
|
94
|
+
the service. `db reset` is intentionally rejected in S3 mode.
|
|
95
|
+
|
|
96
|
+
## Production checks
|
|
97
|
+
|
|
98
|
+
Before exposing the service:
|
|
99
|
+
|
|
100
|
+
- keep the process bound to loopback and terminate TLS at the proxy;
|
|
101
|
+
- use `--runtime-mode strict` for functions;
|
|
102
|
+
- set an explicit snapshot retention period and test a restore drill;
|
|
103
|
+
- use S3/MinIO or a durable mounted volume for storage, not an ephemeral disk;
|
|
104
|
+
- use native PostgreSQL when the project needs extensions such as `pg_graphql`;
|
|
105
|
+
- keep one process per state directory; Lite is not a multi-writer cluster;
|
|
106
|
+
- verify unauthenticated API calls fail closed and authenticated reads succeed.
|
|
107
|
+
|
|
108
|
+
`supacloud-lite doctor --json` reports the selected engine, extension inventory,
|
|
109
|
+
identity mode and replication readiness. It is a capability report, not a
|
|
110
|
+
production security certification.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Replace app.example.com with the real public hostname.
|
|
2
|
+
# Lite must remain bound to 127.0.0.1:54321 behind this proxy.
|
|
3
|
+
https://app.example.com {
|
|
4
|
+
encode zstd gzip
|
|
5
|
+
|
|
6
|
+
# Caddy terminates TLS and forwards WebSocket/Realtime upgrades by default.
|
|
7
|
+
reverse_proxy 127.0.0.1:54321
|
|
8
|
+
|
|
9
|
+
header {
|
|
10
|
+
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
|
11
|
+
X-Content-Type-Options "nosniff"
|
|
12
|
+
Referrer-Policy "strict-origin-when-cross-origin"
|
|
13
|
+
-Server
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=SupaCloud Lite (single-project backend)
|
|
3
|
+
Documentation=https://github.com/vibeunion/supacloud/tree/main/packages/supacloud-lite
|
|
4
|
+
After=network-online.target
|
|
5
|
+
Wants=network-online.target
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=simple
|
|
9
|
+
User=supacloud-lite
|
|
10
|
+
Group=supacloud-lite
|
|
11
|
+
WorkingDirectory=/opt/supacloud-lite/project
|
|
12
|
+
EnvironmentFile=/etc/supacloud-lite/env
|
|
13
|
+
Environment=SUPACLOUD_LITE_STATE_DIR=/var/lib/supacloud-lite
|
|
14
|
+
Environment=SUPACLOUD_LITE_HOST=127.0.0.1
|
|
15
|
+
Environment=SUPACLOUD_LITE_PORT=54321
|
|
16
|
+
Environment=SUPACLOUD_LITE_RUNTIME_MODE=strict
|
|
17
|
+
ExecStart=/usr/local/bin/supacloud-lite start --project-dir /opt/supacloud-lite/project
|
|
18
|
+
Restart=on-failure
|
|
19
|
+
RestartSec=3
|
|
20
|
+
# Lite has no bundled TLS termination. Keep it on loopback and terminate TLS in
|
|
21
|
+
# Caddy/Nginx; bind a non-loopback address only when another trusted proxy or
|
|
22
|
+
# network boundary protects it.
|
|
23
|
+
UMask=0077
|
|
24
|
+
NoNewPrivileges=true
|
|
25
|
+
PrivateTmp=true
|
|
26
|
+
ProtectHome=true
|
|
27
|
+
ProtectSystem=strict
|
|
28
|
+
StateDirectory=supacloud-lite
|
|
29
|
+
ReadWritePaths=/var/lib/supacloud-lite
|
|
30
|
+
|
|
31
|
+
[Install]
|
|
32
|
+
WantedBy=multi-user.target
|