环境变量
环境变量让您无需把密钥写进代码即可配置应用。变量可按应用设置,也可在整个 Stack 内共享;以加密形式存储,并在下一次部署时注入容器。
添加变量
键名只能包含大写字母、数字和下划线,并以字母或下划线开头(如 DATABASE_URL、_INTERNAL)。小写键名会被以 422 拒绝。
通过控制面板
- 打开应用(Stacks → 对应 Stack → 应用),进入其 Environment 标签页。
- 在 Key-Value 模式下输入键和值。如果该值只在构建镜像时需要,请勾选 Build time。
- 点击 Add Variable。值默认以掩码显示;Reveal 可显示明文,需要在该应用上至少拥有 Developer 角色。
通过 CLI
sh0 env <app> set接受一个 KEY=VALUE 键值对,加 --build 表示构建时变量;list 从不显示变量值。
$ sh0 env my-api set LOG_LEVEL=info
[ok] Set LOG_LEVEL for 'my-api'
$ sh0 env my-api set GREETING_BUILD=hello --build
[ok] Set GREETING_BUILD for 'my-api'
$ sh0 env my-api list
KEY VALUE BUILD CREATED
-------------- ------- ----- -------
LOG_LEVEL ******* no 0s ago
GREETING_BUILD ******* yes 0s ago通过 API
路由为 /api/v1/apps/:id/env-vars(GET、POST)和 /api/v1/apps/:id/env-vars/:env_id(PATCH、DELETE)。响应中的值始终被掩码;在 GET 上加 ?reveal=true 才能读取。
$ curl -s -X POST https://panel.example.com/api/v1/apps/e17d4314-ff61-485a-a509-58b3974c1eee/env-vars \
-H "Authorization: Bearer $SH0_TOKEN" -H "Content-Type: application/json" \
-d '{"key":"DATABASE_URL","value":"postgres://app:[email protected]:5432/appdb"}'
{"data":{"app_id":"e17d4314-ff61-485a-a509-58b3974c1eee","created_at":"2026-10-02T02:49:26.463374291+00:00","id":"68ddf6a1-d9e0-49e4-9893-c320eaa58b62","is_build":false,"key":"DATABASE_URL","value":"*****"}}
$ curl -s -X PATCH https://panel.example.com/api/v1/apps/e17d4314-ff61-485a-a509-58b3974c1eee/env-vars/68ddf6a1-d9e0-49e4-9893-c320eaa58b62 \
-H "Authorization: Bearer $SH0_TOKEN" -H "Content-Type: application/json" \
-d '{"value":"postgres://app:[email protected]:5432/appdb"}'
{"data":{"app_id":"e17d4314-ff61-485a-a509-58b3974c1eee","created_at":"2026-10-02 02:49:26","id":"68ddf6a1-d9e0-49e4-9893-c320eaa58b62","is_build":false,"key":"DATABASE_URL","value":"*****"}}201,应用中会出现两个同名条目。要修改值,请编辑现有变量(PATCH,或在控制面板中点击 Edit)。变更何时生效
保存变量不会重启任何东西。正在运行的容器会保留旧环境,直到下一次部署(在控制面板中或使用 sh0 deploy <app>)。
构建时变量会以 --build-arg 传给 docker build,Dockerfile 必须用 ARG 声明。它们不会出现在运行中的容器里。对于通过上传归档(sh0 push)部署的应用,重新部署会复用上一个镜像:运行时变量会更新,但新的构建时值要等下一次 sh0 push 才生效。
在测试应用重新部署后观察到的结果(构建时变量 GREETING_BUILD 进入了镜像,但不在运行环境中):
$ docker exec <container> env | grep -E '^(LOG_LEVEL|REGION|GREETING_BUILD)='
REGION=eu-central
LOG_LEVEL=info
$ docker exec <container> cat /build-arg.txt
hello批量编辑(.env)
Environment 标签页接受 KEY=VALUE 格式,每行一个;注释(#)和空行会被忽略。两种方式的行为不同:
- Paste .env 后点击 Parse & Add,会把每一行作为新变量添加,其他变量保持不变(已存在的键会出现重复,见上文)。
- .env Editor 后点击 Save All 会用编辑器内容替换该应用的全部变量。对应 API 为
PUT /api/v1/apps/:id/env-vars/bulk,请求体为entries数组:数组中没有的键都会被删除。
Stack 级变量
在 Stack 上设置的变量会被该 Stack 中的所有应用读取。打开 Stack,在 Internal network & shared settings 面板中使用 Shared variables,或调用 API /api/v1/projects/:id/env-vars(在 API 中 Stack 即项目)。提交已存在的键会更新它。Stack 变量的值永远不会被返回,管理员也不例外。
$ curl -s -X POST https://panel.example.com/api/v1/projects/5aee8eea-9f77-4d10-ac21-2fe4a565e666/env-vars \
-H "Authorization: Bearer $SH0_TOKEN" -H "Content-Type: application/json" \
-d '{"key":"REGION","value":"eu-central"}'
{"data":{"created_at":"2026-10-02 02:49:26","id":"e89e5915-e5dd-4878-b1b6-b6df150df54d","is_build":false,"key":"REGION","project_id":"5aee8eea-9f77-4d10-ac21-2fe4a565e666","updated_at":"2026-10-02 02:49:26"}}当同一个键在两层都存在时,以应用为准,部署日志会列出被覆盖的 Stack 变量。在下面的示例中,Stack 设置了 LOG_LEVEL=debug 和 REGION=eu-central,应用设置了 LOG_LEVEL=info:
静态加密
每个值在写入 sh0 数据库之前都会用 AES-256-GCM 加密。密钥为实例主密钥,保存在 master.key 中,并由 master.passphrase(PBKDF2)保护,两者都位于 sh0 数据目录(标准 Linux 安装为 /var/lib/sh0)。
master.key 和 master.passphrase 时,已存储的值(以及加密备份)将无法解密。请在服务器之外保存这两个文件的副本。连接其他服务
sh0 不会展开变量引用:像 $OTHER_VAR 这样的值会原样进入容器。请使用内部主机名写出完整的值:同一 Stack 中的应用可通过 <app-name> 或 <app-name>.internal 互相访问,任何数据库服务器都可通过 <server-name>.internal 访问。
sh0 不会注入的内容
- 没有系统变量。sh0 不会向容器添加任何
SH0_*变量(应用名、域名、提交等)。唯一例外:没有APP_KEY的 Laravel 或 Lumen 应用会在首次部署时生成一个,并保存为应用变量。 - 定时任务中的变量。绑定到应用的定时任务会获得应用及项目的运行时变量,运行在由应用镜像创建的一次性容器中:参见 定时任务。