关于 craft-cloud
面向在 Craft Cloud 上部署 Craft CMS 项目的参考技能,Craft Cloud 是 Pixel & Tonic 的无服务器托管平台。内容涵盖专属配置、部署流程、兼容性限制,以及从自托管环境迁移。
主要功能
- 01说明 `craft-cloud.yaml` 配置
- 02介绍 Build → Migrate → Release 流程
- 03讲解 Cloud 文件系统和数据库限制
- 04梳理缓存与图像转换
- 05指导从自托管环境迁移
适用场景
- 01配置 Craft Cloud 项目
- 02检查插件的 Cloud 兼容性
- 03排查部署或缓存问题
- 04规划迁移到 Craft Cloud
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ michtio/ craftcms-claude-skills --skill craft-cloud安装后在 Claude Code 中输入/craft-cloud确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/assets-and-transforms.mdcaching-and-edge.mdcommands-and-cron.mdconfig-file.mddatabase.mddeploy-pipeline.mddomains.mdextension.mdheadless.mdlimitations.mdlocal-dev.mdmigration.mdplugin-development.md详细介绍
Craft Cloud — Craft CMS 的无服务器托管
Craft Cloud 参考指南。Craft Cloud 是 Pixel & Tonic 为 Craft CMS 提供的无服务器托管平台。本指南涵盖 craft-cloud.yaml 配置文件、Build → Migrate → Release 部署流水线、craftcms/cloud 扩展、边缘图像转换与静态缓存、Cloud 文件系统、插件的 Cloud 兼容性要求,以及从自托管迁移到 Cloud。
本技能专门针对 Craft Cloud — 介绍 Cloud 与在 Forge、Servd 或裸机上自行运行 Craft 的不同之处。有关 Servd,请参阅 servd 技能。有关通用 Craft 部署(构建产物、项目配置同步、传统主机上的原子部署),请参阅 craftcms 技能中的 deployment.md。
配套技能 — 按需加载
craftcms— 当 Cloud 相关主题涉及插件或模块的 PHP 工作时(例如服务中的App::isEphemeral()检查、资源包限制、针对 15 分钟上限设计队列任务)。craft-site— 当 Cloud 相关主题涉及前端模板时(缓存页面中的 ESI 岛、边缘图像转换的使用、静态缓存的{% expires %}退出机制)。ddev— 用于本地开发环境一致性方案(匹配 PHP/DB 版本,在本地模拟临时文件系统)。craft-php-guidelines— 编辑插件 PHP 以添加 Cloud 兼容性检查时。
文档
编写本技能时使用的权威来源:
- Craft Cloud 文档首页:https://craftcms.com/docs/cloud/
- 配置参考:https://craftcms.com/docs/cloud/config
- 部署流水线:https://craftcms.com/docs/cloud/deployment
- 构建:https://craftcms.com/docs/cloud/builds
- 兼容性与限制:https://craftcms.com/docs/cloud/compatibility
- 资源与转换:https://craftcms.com/docs/cloud/assets
- 静态缓存:https://craftcms.com/docs/cloud/static-caching
- 无头应用:https://craftcms.com/docs/cloud/headless-apps
- 请求签名:https://craftcms.com/docs/cloud/request-signing
- 插件开发:https://craftcms.com/docs/cloud/plugin-development
- Cloud 扩展源码:https://github.com/craftcms/cloud
每个参考文件中都包含对应声明的 URL。最后一次根据文档及 craftcms/cloud-extension-yii2@main 进行核实的日期为 2026-05-28;无头应用/请求签名、产物 URL、环境、配额及备份内容根据 craftcms/docs@main 核实的日期为 2026-09-02。
Cloud 与自托管的差异
快速了解各项差异。自托管环境中的习惯可能会让你在以下方面产生误判。
| 关注事项 | 自托管 | Cloud |
|---|---|---|
| 配置文件 | .env、config/general.php、config/db.php、你的 Web 服务器配置 | 仓库根目录下的 craft-cloud.yaml 用于平台设置;运行时环境变量在 Craft Console UI 中设置(而非 .env) |
| 部署 | 按你自己的配置操作(Forge、GitHub Actions、rsync) | Git 推送 → 自动执行 构建 → 迁移 → 发布(构建上限为 15 分钟) |
| 文件系统 | 本地磁盘或你自己的 S3/R2 配置 | 临时性 Lambda 文件系统;使用 App::isEphemeral() 限制写入;用户资源必须使用 Cloud 捆绑的 S3 支持型文件系统 |
| 数据库 | 你安装的任何数据库 | 仅支持 MySQL 8.0 或 Postgres 15——不支持 MariaDB,不支持 tablePrefix,不得修改 db.php,不得覆盖 CRAFT_DB_* |
| 应用/组件配置 | 可随意在 config/app.php 中覆盖组件 | 扩展拥有多个组件(response、session、cache、mutex、queue、assetManager)以及数据库连接——在 app.*.php 中覆盖这些组件会破坏配置,而且无法在本地复现(该扩展仅在 Cloud 上运行) |
| 无头模式/API 消费者 | 你的 GraphQL 端点、你的速率限制 | 机器人检测会降低自动化流量的优先级——SSG 构建/ISR 会收到 429/503,除非请求经过签名(RFC 9421、$CRAFT_CLOUD_SIGNING_KEY)并使用退避策略重试 |
| 队列任务 | 你运行工作进程(systemd、supervisor、cron) | 由 Cloud 自动处理——不要安排运行器;每个任务最长运行 15 分钟 |
| Cron | crontab -e,任意频率 | 仅限 Craft Console UI;最低频率为每小时一次 |
| 图像变换 | ImageOptimize / Imager-X / 原生功能 | 通过 Cloudflare Images 执行边缘变换——无需修改模板,但 ImageOptimize 不兼容 |
| 页面缓存 | Blitz 或类似工具 | 通过 craft-cloud.yaml 中的 cache.rules 配置边缘静态缓存;基于标签自动失效 |
| 缓存页面中的动态片段 | 针对各缓存驱动的变通方案 | 一流支持的 cloud.esi(...) Twig 助手 |
| 日志 | storage/logs/ 中的文件 | 仅支持 Craft::info/warning/error()——没有文件尾随 UI;Console 命令输出是事实上的查看入口 |
| 邮件 | sendmail 或任意适配器 | 没有内置邮件功能——请自行接入 SMTP/Postmark/SES/Resend |
| SSH | ssh user@server | 不支持——仅提供 Console 命令运行器(上限为 255 个字符、15 分钟) |
| 服务器重写规则 | .htaccess/nginx 配置 | craft-cloud.yaml 中的 redirects: 和 rewrites: 键 |
| 自定义域名 | DNS 提供商 + 证书 | DNS + 所有权 TXT + CNAME 指向 edge.craft.cloud;通过 Cloudflare 自动配置 SSL |
| 预览环境 | 你的 CI | 仅支持按分支创建——文档未说明支持按 PR 创建预览环境 |
常见陷阱(跨领域)
- 在没有
App::isEphemeral()检查的情况下写入磁盘。 Lambda 的文件系统是临时的,请求之间的写入会丢失。插件、服务和迁移都需要检查并使用 Path 服务(Craft::$app->getPath()->getTempPath()/getStoragePath()/getCachePath())进行临时写入。请参阅references/extension.md(App::isEphemeral)和references/plugin-development.md。 - 在
config/app.php/app.web.php/app.console.php中重新配置由 Cloud 管理的应用组件。craftcms/cloud扩展会扩展response组件(规范化标头、gzip、将二进制内容卸载到 S3,均在EVENT_AFTER_PREPARE上附加),并替换session、cache、mutex、queue和assetManager,还会自动接入数据库连接。在应用配置中重新定义或扩展其中任何组件都会与这些配置冲突,并可能导致每个请求都返回 HTTP 500(且绕过边缘缓存)。数据库也包括在内:不要配置db.php,也不要设置CRAFT_DB_*环境变量。若要添加响应逻辑(例如Content-Language标头),请从模块运行时将其附加到response实例上——Craft::$app->getResponse()->on(\yii\web\Response::EVENT_AFTER_PREPARE, …)——绝不要重新定义response组件。**也绝不要在本地验证这些更改:**该扩展只在 Cloud 上运行(在 DDEV 上Helper::isCraftCloud()为 false),因此本地 HTTP 200 并不能证明任何事情——应将app.*.php视为只能在生产环境验证。请参阅references/database.md和references/extension.md。 - 使用
tablePrefix。 Cloud 不支持此项。迁移前请运行php craft db/drop-table-prefix。请参阅references/migration.md。 - 选择 MariaDB。 Cloud 仅支持 MySQL 8.0 和 Postgres 15。
- 自行安排队列运行器。 Cloud 会自动处理队列任务——添加队列运行器的定时命令是多余的,还可能引发冲突。
- 在迁移中清空整个缓存。 在迁移阶段调用
Craft::$app->getCache()->flush()(或执行任何全局清除)会与共享缓存上仍在运行的旧版本争用资源;如果未配置 Redis/Valkey,该缓存会是单个 MySQL 表,因此清空缓存可能导致死锁(MySQL 1205),并耗尽部署的 CLI 时间上限。只使已更改的内容失效。请参阅references/deploy-pipeline.md(Never flush the whole cache from a migration)和references/extension.md(Cache, queue, and session wiring)。 - 在元素保存钩子中同步执行外部 HTTP 请求。 这会阻塞每次保存;在重新保存或执行
cloud/up期间,还会将网络延迟计入部署的 CLI 时间上限。请改为将调用加入队列。请参阅references/plugin-development.md。 - 尝试将 cron 安排得比每小时更频繁。 Cloud 的 UI 强制设置至少为一小时。请围绕这一频率下限设计定期任务,或将工作移至由其他事件触发的队列任务中。
- 在可缓存模板中使用
{{ csrfInput() }}。 这会强制设置 cookie,破坏边缘静态缓存。请改用csrfInput()函数,它会渲染与asyncCsrfInputs兼容的异步输入(在 Cloud 上强制启用)。 - 期望已登录用户在可缓存路由中看到由
currentUser控制的 UI。 Cloud 不会针对已登录请求自动绕过边缘缓存——某个 URL 的访客版本一旦被缓存,编辑者也会收到该版本(cf-cache-status: HIT),因此服务器渲染的编辑链接/仅会员可见的区块会悄然消失。请在嵌套的cache:→rules:键下,通过会话 cookie(cookies: [CraftSessionId])而不是session:来区分缓存键。请参阅references/caching-and-edge.md。 - 在仓库中使用
.htaccess规则或 nginx 配置。 这些配置不会生效——请改为在craft-cloud.yaml中配置redirects:/rewrites:。请参阅references/config-file.md。 - 写入日志文件。 文件系统不具备持久性。请使用
Craft::info/warning/error(),日志记录器会自动将日志路由到 Cloud 的日志目标。请参阅references/extension.md。 - 假设可以通过 SSH 访问。 Cloud 不提供 SSH 访问。Console 命令运行器是执行命令的唯一方式,参数上限为 255 个字符,超时时间为 15 分钟。
- 使用分叉的 Git 仓库。 Cloud 无法从分叉仓库部署——必须使用上游仓库。
- 期望为每个 PR 提供预览环境。 Cloud 仅支持每个分支一个环境;不会为每个拉取请求自动创建临时环境。
- 使用默认的
sendmail适配器。 该适配器无法发送邮件。请明确配置 SMTP/Postmark/SES/Resend。请参阅references/limitations.md(Mail)。 - 在 Cloud 上使用 ImageOptimize。 Cloud 通过 Cloudflare Images 在边缘处理变换——ImageOptimize 会重复处理工作,并可能造成冲突。请参阅
references/assets-and-transforms.md。 - 未签名的自动化流量(SSG 构建、ISR 重新验证、CI)收到
429/503。 Cloud 的机器人检测会正确地将无头内容获取识别为机器人流量。请使用环境变量$CRAFT_CLOUD_SIGNING_KEY(RFC 9421)为服务器端请求签名,并且在收到429/503时根据Retry-After进行退避重试——签名可以绕过机器人策略,但不能绕过容量限制。绝不要在客户端公开此密钥。请参阅references/headless.md。 - 在非生产环境中,
robots.txt屏蔽所有内容,或首次请求速度很慢。 Cloud 会向所有未标记为 Production 的环境注入Disallow: /,并会让非生产环境的函数在闲置约 15 分钟后休眠。这两种情况都是设计如此——排查问题前请先检查 Production Environment 设置。请参阅references/limitations.md(Environments)。 - 更改 Console 环境变量后,期望立即生效。 变量更改仅在下一次部署时生效。请参阅
references/deploy-pipeline.md。
参考文件
请阅读任务所需的相关参考文件。通常需要多个文件。
任务示例:
- “在 Cloud 上创建新的 Craft 项目” →
config-file.md+deploy-pipeline.md+extension.md - “为 PHP 和 Node 版本配置
craft-cloud.yaml” →config-file.md - “在
craft-cloud.yaml中添加重定向” →config-file.md(重定向和重写) - “部署期间会发生什么?” →
deploy-pipeline.md - “设置构建时环境变量” →
deploy-pipeline.md(构建时与运行时变量) - “Cloud 上有哪些环境变量是保留变量/不应设置?” →
deploy-pipeline.md(保留的运行时变量) - “
php craft cloud/up会做什么?” →extension.md(cloud/up 内部机制) - “在缓存页面中添加 ESI 岛” →
caching-and-edge.md - “边缘静态缓存规则” →
caching-and-edge.md - “将用户资源从自托管环境迁移到 Cloud” →
assets-and-transforms.md+migration.md - “让这个插件兼容 Cloud” →
plugin-development.md - “为什么插件在 Cloud 上写入文件会悄无声息地失败?” →
plugin-development.md(临时文件系统)+extension.md(App::isEphemeral) - “设置自定义域名” →
domains.md - “安排定期运行的命令” →
commands-and-cron.md(最短间隔为每小时) - “在 Cloud 上运行一次性命令” →
commands-and-cron.md(控制台命令运行器) - “在 Cloud 上配置 SMTP” →
limitations.md(邮件)+craftcms/email.md - “设置本地 DDEV,使其与 Cloud 环境一致” →
local-dev.md - “将自托管的 Craft 站点迁移到 Cloud” →
migration.md - “哪些插件可在 Cloud 上运行?” →
limitations.md(插件兼容性 — 社区知识) - “我的 Next.js/Nuxt/Astro 构建从 Cloud 收到 429 错误” →
headless.md - “为发送到 Cloud 的程序化请求签名” →
headless.md(请求签名) - “从模板链接已构建的 JS/CSS” →
deploy-pipeline.md(制品 URL) - “在 Cloud 上使用私有 Composer 包” →
deploy-pipeline.md(私有 Composer 包) - “robots.txt 阻止了我的站点” →
limitations.md(环境)
仅加载任务所需的参考文件。
| 参考资料 | 范围 | 约行数 |
|---|---|---|
references/config-file.md | craft-cloud.yaml 完整键参考:php-version、node-version、node-path、npm-script、artifact-path(取消发布 webroot 的注意事项)、app-path、webroot、cache: → rules:、redirects、rewrites | 156 |
references/deploy-pipeline.md | Build → Migrate → Release 流程、On Push 与 Manual 触发器、15 分钟构建上限、构建时系统变量(CRAFT_CLOUD_*、GIT_SHA)、Console 中的运行时环境变量(更改后需要重新部署)、不得设置的保留/注入变量(CRAFT_SECURITY_KEY、CRAFT_APP_ID、CRAFT_OMIT_SCRIPT_NAME_IN_URLS、CRAFT_DB_*、REDIS_*,等等)、工件 URL(cloud.artifactUrl()、@artifactBaseUrl、不进行缓存破坏、manifest/svg() CDN 读取、白标 CDN 重写)、私有 Composer 包(Composer Auth)、迁移失败时的回滚语义 | 210 |
references/headless.md | Headless 应用与请求签名:针对 SSG/ISR 流量的机器人检测和 429/503 响应、使用 $CRAFT_CLOUD_SIGNING_KEY 的 RFC 9421 HMAC 签名(有效期 5 分钟、URL 必须完全匹配、网关验证失败时会静默回退)、Retry-After + 退避重试约定(仅适用于读取操作,耗尽后抛出异常)、Next.js/Nuxt/Astro 集成、在 Craft 中通过 getRequestSigner() 进行签名 | 107 |
references/extension.md | craftcms/cloud 包:Yii2 模块引导、App::isEphemeral()、Path 服务用法、cloud.esi() Twig 助手、cloud/up 内部机制(已通过源码验证)、资产包 CDN 发布器、二进制响应自动上传、日志目标 | 201 |
references/assets-and-transforms.md | Cloud 文件系统类型(必须使用 assets/ 子路径)、通过 aws s3 sync 迁移、边缘图像转换(70MB/100MP/12,000px 限制,AVIF 上限为 1,600px,拉伸模式限制)、无需更改模板端代码 | 87 |
references/database.md | 仅支持 MySQL 8.0/Postgres 15(不支持 MariaDB)、禁止使用 tablePrefix、php craft db/drop-table-prefix、自动连接的数据库连接、每夜备份 + 按需备份(保留 30 天,上限 200GB,不属于 Cloud 的持久性架构)、恢复命令 | 111 |
references/caching-and-edge.md | 静态缓存规则(将嵌套的 cache: 改为 rules:、pattern + query-string + cookies、采用首个匹配规则)、默认忽略的跟踪参数(自定义规则会替换该列表)、已登录用户与缓存的访客副本(cookies: [CraftSessionId])、禁用缓存的方法({% expires %}、setNoCacheHeaders())、flash-guard 模式、Commerce 购物车注意事项、强制启用 asyncCsrfInputs、用于动态区域的 cloud.esi(...)(仅限标量变量,不支持嵌套)、基于标签的自动失效 | 347 |
references/domains.md | DNS 设置(_cf-custom-hostname TXT、指向 edge.craft.cloud 的 CNAME、apex A 记录、Orange-to-Orange Cloudflare)、预览 URL 格式、自动 SSL、不自动添加 www、额外域名定价 | 104 |
references/commands-and-cron.md | Console 命令运行器(无 SSH,上限 255 个字符,上限 15 分钟,不进行 shell 插值)、计划命令(最短间隔为每小时一次,每个环境最多 5 个)、队列任务自动处理(不要安排运行器)、每个任务上限 15 分钟、通过批处理任务处理长时间工作 | 143 |
references/plugin-development.md | Cloud 兼容插件检查清单:资产包限制、App::isEphemeral() 条件判断、Path 服务、使用 Craft::info() 记录日志、队列任务预算、无 Cookie 设计、csrfInput() 函数(CSRF 令牌泄露警告)、sendContentAsFile() 自动处理、优先选择资产、最低要求 Craft 4.6+ | 234 |
references/migration.md | 从可自托管环境切换到 Cloud:审计(表前缀、MariaDB、文件写入、.htaccess、第三方 S3 插件)、php craft db/drop-table-prefix、通过 aws s3 sync 迁移资产、DNS 切换顺序、项目配置同步 | 132 |
references/local-dev.md | 用于模拟 Cloud 的 DDEV 配方:匹配 craft-cloud.yaml 中的 PHP 版本、数据库引擎 + 版本、Cloud 扩展的自检测及在本地无操作、用于测试保护逻辑的可选 CRAFT_EPHEMERAL、S3 模拟提示 | 145 |
references/limitations.md | 文档记录的不支持功能(MariaDB、tablePrefix、.htaccess、SSH、sendmail、生产环境中的 devMode、包括前端上传在内的 6MB 响应上限、16KB 标头上限、60 秒请求超时、200MB 上传上限、不支持克隆环境、不支持更改区域、不支持按 PR 预览、禁用 CP 数据库备份工具、分叉仓库无法部署)+ 环境事实(非生产环境的 robots.txt 为 Disallow、函数休眠、共享资产存储桶、删除即彻底删除)+ 扁平化的重复标头、无效的 resourceBase* + 明确标注为未经 Pixel & Tonic 背书的社区插件兼容性矩阵(ImageOptimize、Imager-X、Blitz、Typesense 等)+ 邮件策略 + 日志记录缺口 | 239 |