bx-sites-deployment 是 bx-sites(ortus-boxlang/bx-sites)的部署参考,说明如何部署、打包或发布一个已构建的 bx-sites 站点。site/ 是纯静态站点,可托管在任何能提供静态文件的地方,bxSites deploy 会直接把它送到目标位置。部署前需先构建(或让 deploy 代为构建),构建细节见 bx-sites-build。
一、deploy 命令的三种调用形式
- bxSites deploy --entry=production [--verbose]:使用命名的 deployments/<name>.json 条目。--entry=<name> 会分派到 deployments/<name>.json 所声明的目标;除 local/github-pages 外,每个目标都需要这种方式(配置项多于几个标志能承载的量)。
- bxSites deploy --target=local|github-pages [flags] [--verbose]:仅用标志、不需要 deployments/ 文件,是仅有的两个最简单目标的简写——local(--destination=<path>)和 github-pages([--branch] [--remote] [--message],默认值与 gh-deploy 相同)。
- bxSites deploy [--verbose]:依次部署每一个 deployments/*.json 条目,共用一次构建(不按目标重复构建)。某个目标失败不会阻止其余目标;仅当至少一个失败时命令以非零退出,摘要会报告数量(如 Deployed to 2/3 target(s) (1 failed))。 --verbose 会在构建及每个目标开始/结束时打印进度行,而不只是最终摘要。
二、密钥处理 密钥始终来自环境变量,绝不在 deployments/*.json 中写字面值。每个以 EnvVar 结尾的字段都命名存放真实密钥的环境变量,在部署时实时解析,因此 JSON 文件本身始终可安全提交。唯一例外是已单独管理的凭据文件路径(如 SSH 密钥、下载的 GCP 服务账号 JSON)——这类是普通字段,因为要排除在版本控制之外的是文件本身而非其路径。本地这些环境变量可来自 .env 文件(BoxLang 会自动加载);在 CI 中则设为真实的 runner 密钥。
三、各目标配置 local:无需 deployments/ 条目,是唯一不需要的目标。示例:bxSites deploy --target=local --destination=/path/to/somewhere github-pages:与 gh-deploy 相同的推送,也可从统一命令调用,同样无需 deployments/ 条目。示例:bxSites deploy --target=github-pages [--branch=gh-pages] [--remote=origin] [--message="..."] s3:真实 AWS S3 或任何 S3 兼容服务。非 AWS 需设置 endpoint,多数非 AWS 提供商需 forcePathStyle: true。示例字段包括 target、bucket、region、prefix、accessKeyIdEnvVar、secretAccessKeyEnvVar;自定义 endpoint 加 forcePathStyle: true 也覆盖 Cloudflare R2(https://<accountid>.r2.cloudflarestorage.com)、Backblaze B2、MinIO/Wasabi。可选的 acl(如 "public-read")在存在时作为 x-amz-acl 头发送。 azure:字段为 target、account、container、accountKeyEnvVar。用 SAS 令牌、账户密钥或完整连接字符串三者之一认证——sasTokenEnvVar、connectionStringEnvVar 或 accountKeyEnvVar(若同时设置则按此优先级)。可选 prefix 为每个上传的 blob 名加前缀(如 "docs/")。 gcs:字段为 target、bucket、serviceAccountKeyPath(下载的服务账号 JSON 密钥,来自 Google Cloud Console → IAM & Admin → Service Accounts → Keys)。 firebase:字段为 target、siteId、serviceAccountKeyPath。 ftp / sftp:示例字段为 target、host、username、remotePath、key。SFTP 接受密码(passwordEnvVar)或 SSH 密钥(key 为私钥文件路径,可选 passphraseEnvVar 为该密钥的密码);FTP 需要 passwordEnvVar。两者都保留站点的文件夹结构。其他可选字段:port(FTP 21,SFTP 22)、passive(FTP,true)、proxyServer、timeout(秒,30)以及 SFTP 的 fingerprint。 rsync:字段为 target、host、username、remotePath、identityFile。通过 SSH 使用真实 rsync 二进制,只传输变更内容,对完整重建比 FTP/SFTP 更快。要求运行 bxSites 的机器上有 rsync 和 ssh。 netlify:字段为 target、siteId、authTokenEnvVar。 vercel:字段为 target、projectId、authTokenEnvVar。 cloudflare-pages:字段为 target、accountId、projectName、apiTokenEnvVar。Cloudflare 没有用于直接上传部署的公开 REST API(只有 wrangler),此目标逆向工程了 Wrangler 自身的上传流程,且需要多数默认 JVM 不附带的 BLAKE3 哈希实现。视为最粗糙的目标;依赖前请先验证真实部署。
四、publish——bxSites Cloud bxSites Cloud 是专为 bxSites 站点构建的托管 SaaS,bxSites publish 通过其自有 publish API 直接构建并发布到那里,与 deploy 的可插拔目标(都发布到你自有的基础设施)不同。用法:export BXSITES_CLOUD_TOKEN="cb_..." 后执行 bxSites publish;配置中 cloud 块含 siteId(目标站点 UUID)和 apiUrl(https://cloud.bxsites.app 或自托管实例)。API 令牌绝不写入 bxsites.yaml——publish 从 BXSITES_CLOUD_TOKEN 或显式 --token=cb_... 标志读取(两者都设置时后者优先),因此该文件始终可安全提交。成功时打印站点的实时 URL;对以下情况会以具体、可操作的错误而非堆栈跟踪失败:无/不完整的 cloud 块、无可用令牌、401/403(令牌错误/未授权)、404(cloud.siteId 错误),或其他情况(400/413/500/网络故障,附带实际状态/正文)。bxSites Cloud 也是 bx-sites-ai-features 所述面向 AI 的功能(已发布站点的 MCP 服务器)和 bx-sites-content-blocks 所述 ::: contact-form ::: 块的实际服务方——两者仅用开源模块即可免费渲染/构建,但发布后要真正工作需付费 Cloud 计划。
五、package——改为普通归档 bxSites package 或 bxSites package --output=dist/my-site.zip:先构建,然后把 site/ 自身的内容(不是包裹的 site/ 文件夹)打包成一个文件——用于附加到 GitHub release、只接受 zip 上传的主机,或上述可插拔列表未覆盖的任何目标。--output 默认为 <projectRoot>/site.zip;父目录会自动创建。
六、GitHub Actions:多版本发布 bx-sites 附带一个即用型 .github/workflows/pages.yml 模式,把 main 和 development 作为同一站点的两个独立在线版本发布到 GitHub Pages:安装 BoxLang + bx-markdown(及项目所需其他内容);将仓库注册为模块以便 boxlang bxSites build 解析;在除 main 外的任何分支上,把 baseURL 指向 .../<branch-name>/ 仅供该次构建;运行 boxlang bxSites build;把 site/ 推送到 gh-pages——main 到站点根,development 到 /development/,各自带 keep_files: true 和自己的 destination_dir 以免互相覆盖。也可手动触发(workflow_dispatch)做一次性重新发布。一次性设置(在工作流至少运行一次后,因为首次运行会创建 gh-pages 分支):Settings → Pages → Build and deployment → Source: "Deploy from a branch" → Branch: gh-pages / (root)。添加第三个分支(如 release/2.0):把它加入 on.push.branches 并给它自己的 if: github.ref_name == '...' 部署步骤,destination_dir: release-2.0。项目 Pages 子路径——https://<user>.github.io/<repo>/(相对于 <user>.github.io 用户站点)需要把 baseURL 设为该完整 URL,以便每个内部链接/资源/导航条目都带上 /<repo>/ 前缀并生成真实的 sitemap.xml(见 bx-sites-configuration)。用户站点或映射到根的自定义域名可让 baseURL 保持默认(/)。
七、限制已部署站点的访问 没有内置访问控制——纯静态 site/ 没有“谁在请求”的概念。robots: false 告诉行为良好的爬虫不要索引它,但这是礼貌请求而非锁——任何拿到 URL 的人仍可访问。真正的访问限制必须在静态文件之前、由提供它们的主机完成:Cloudflare Pages/Access——Cloudflare Access 策略(邮箱允许列表、SSO、一次性 PIN),无需应用代码;Netlify——按站点/部署的内置密码保护,仅靠站点设置;一个微型反向代理(任意主机)——在静态文件前加 HTTP Basic Auth——可挡住搜索引擎和随意访客,但不是真正的按用户身份。这些都不是 bx-sites 功能,而是主机级设置。