Cloudflare Workers のプレビュー URL を自動で無効化する
Cloudflare Workers のプレビュー URL は、PR をマージしても自動で無効化されません。バージョンの削除ではアクセスを止められないため、Subdomain API の previews_enabled を GitHub Actions で自動制御する方法を実装しました。
目次
Cloudflare Pages は 2020 年にリリースされた静的サイトホスティングサービスですが、2024 年に Workers が静的アセット配信に対応したことで状況が変わりました。Cloudflare はWorkers への移行を推奨する方針を打ち出し、Workers では
wrangler versions upload でプレビューバージョン1をアップロードでき、PR ごとにプレビュー URL で動作確認が可能です。
しかし、Workers のプレビューバージョンには構造的な課題があります。PR をマージしてブランチを削除しても、プレビューバージョンは自動削除されず、URL を知っていれば誰でもアクセスできてしまいます。Pages にはデプロイの削除 API が公開されていますが、Workers の Standard API にバージョンの DELETE エンドポイントはありません。この問題は 2025年8月ころ
Cloudflare Community でも報告されています。
このブログも Cloudflare Workers でホスティングしており、同じ問題が発生しました。Vercel であればプレビューデプロイに認証をかけられますが、Workers のプレビューバージョンにはそのような認証機能がありません。個人ブログなので実害はないかもしれませんが、昨今のセキュリティ事情を考えると、放置するのも気持ちが悪いです。「まぁ試しにやってみるか」くらいの気持ちで調べ始めたところ、
Subdomain API の
previews_enabled でプレビュー URL を一括無効化できることが分かり、GitHub Actions で本番デプロイ後に自動で無効化するしくみを実装しました。
なぜ Pages ではなく Workers なのか
「プレビューの管理が面倒なら Pages を使えばよいのでは?」と思うかもしれません。実際、Pages であればプレビューデプロイの削除は簡単で、GitHub Actions で自動化する方法も Zenn で紹介されています。
wrangler-actionを使ってCloudflare Pagesを自動デプロイするzenn.dev
ただ、Cloudflare に勤めていて Hono(軽量な Web フレームワーク)の作者でもある Yusuke Wada 氏は、X で以下のように説明しています。
これからは理由がない限りCloudflare PagesではなくCloudflare Workersを使ってください。
Pagesと同じくアセットへのアクセスは無料です
Pagesではできない機能が使えます > Durable Objects/Workers Logs etc.
フロントエンドフレームワークが動きます

これを見てこのブログは Workers を選択しましたが、プレビュー URL の管理でハマりました。
プレビュー URL のしくみ
警告
本記事の内容は 2026 年 2 月時点の API 仕様に基づいています。
Workers のプレビュー URL は、バージョンごとに {version_id}-{script_name}.{subdomain}.workers.dev の形式で発行されます。このルーティングはバージョンの存在そのものではなく、Subdomain API の
previews_enabled という設定で制御されています。
GET /accounts/{account_id}/workers/scripts/{script_name}/subdomain
POST /accounts/{account_id}/workers/scripts/{script_name}/subdomain{
"enabled": true,
"previews_enabled": true
}設定値 | 対象 |
|---|---|
| 本番の workers.dev URL( |
| プレビュー URL( |
この 2 つは独立した設定値です。previews_enabled を false にしても本番 URL には影響しません。公式ドキュメントにも以下の記載があります。
Disabling Preview URLs will disable routing to both versioned and aliased preview URLs.
実際に previews_enabled: false に変更してみたところ、プレビュー URL は HTTP/404 を返すようになり、本番 URL は HTTP/200 のままでした。
URL | 変更前 | 変更後 |
|---|---|---|
プレビュー URL | HTTP/200 | HTTP/404 |
本番 URL( | HTTP/200 | HTTP/200 |
バージョン削除ではプレビュー URL は消えない
最初に試したのはバージョンの削除です。
Workers の API を調べると、Standard API にはバージョンの DELETE エンドポイントが存在しません。試しに DELETE リクエストを送ると 405 Method Not Allowed が返ります。
GET /accounts/{account_id}/workers/scripts/{script_name}/versions
POST /accounts/{account_id}/workers/scripts/{script_name}/versions調べを進めると、Beta API には DELETE エンドポイントがあることが分かりました。
GET /accounts/{account_id}/workers/workers/{worker_id}/versions
POST /accounts/{account_id}/workers/workers/{worker_id}/versions
DELETE /accounts/{account_id}/workers/workers/{worker_id}/versions/{version_id}試しに Beta API でバージョンを削除してみると、HTTP/200 が返るので削除できたように見えます。ところが、削除後もプレビュー URL にはアクセスできてしまいます。
公式ドキュメントを読むと、バージョンは不変かつ追記のみの設計で、もともと「削除する」想定になっていないそうです。wrangler にも
versions delete コマンドは存在しません(upload / deploy / list / view / rollback / secret のみ)。Beta API の DELETE は後付けのエンドポイントで、プレビュー URL のルーティングとは無関係です。
Worker versions are immutable at the API level, meaning they cannot be updated after creation, only re-created with any desired changes. [...] versions are both immutable and append-only.
バージョンを消すのではなく、ルーティングを制御する previews_enabled を使うのが正解でした。
previews_enabled を切り替える
解決策として、Cloudflare Access2 でプレビュー URL に認証をかける方法と、
previews_enabled を CI で切り替える方法があります。
Cloudflare Access は Zero Trust の認証基盤で、プレビュー URL へのアクセスに認証を要求できます。プレビュー URL 自体は有効なまま残りますが、認証を通過しないとアクセスできません。チーム開発ならこちらを使うべきです。
previews_enabled の切り替えは、PR デプロイ前に true、本番デプロイ後に false にするだけのシンプルな方法です。
警告
previews_enabled は Worker 全体の設定です。false にするとすべてのプレビュー URL が無効化されます。複数人で開発していて他の PR のプレビューも同時に使いたい場合は、Cloudflare Access を検討してください。
このブログは私一人で開発しているので、シンプルに切り替え方式を選びました。本番デプロイが実行されるタイミングでプレビュー URL を無効化すれば、他の PR を壊す心配はありません。
GitHub Actions での実装
PR デプロイ時(deploy-preview ジョブ)で wrangler versions upload の前に previews_enabled を true にし、本番デプロイ後に false に戻します。
- name: Enable preview URLs
run: |
SCRIPT_NAME="sui-blog"
API_BASE="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers"
curl -sf -X POST \
"$API_BASE/scripts/$SCRIPT_NAME/subdomain" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true, "previews_enabled": true}'
echo "Preview URLs enabled"
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}本番デプロイ後(deploy-production ジョブ)では、プレビュー URL を無効化します。
- name: Disable preview URLs
continue-on-error: true
run: |
SCRIPT_NAME="sui-blog"
API_BASE="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
"$API_BASE/scripts/$SCRIPT_NAME/subdomain" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true, "previews_enabled": false}')
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo "Preview URLs disabled (HTTP $HTTP_CODE)"
else
echo "::warning::Failed to disable preview URLs (HTTP $HTTP_CODE)"
fi
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}continue-on-error: true を設定しているので、無効化が失敗しても本番デプロイ自体は成功として扱われます。おまけの処理ですので、これが原因でデプロイが止まるのは避けたいところです。
まとめ
- Cloudflare Workers のプレビュー URL は PR をマージしても自動で無効化されず、URL を知っていれば誰でもアクセスできる状態が残る
- Beta API にバージョンの DELETE エンドポイントはあるが、HTTP/200 が返るだけでプレビュー URL のルーティングは無効化されない
- Subdomain API の
previews_enabled: falseで全プレビュー URL を無効化でき、本番 URL には影響しない - GitHub Actions で PR デプロイ前に
true、本番デプロイ後にfalseに切り替えることで、PR 中のみプレビューを公開できる
参考
Version URLsdevelopers.cloudflare.com
workers.devdevelopers.cloudflare.com
Subdomaindevelopers.cloudflare.comVersionsdevelopers.cloudflare.comInfrastructure as Code (IaC)developers.cloudflare.com
Potential Security Concerns with Workers & Pagescommunity.cloudflare.com
Migrate from Pages to Workersdevelopers.cloudflare.com
wrangler-actionを使ってCloudflare Pagesを自動デプロイするzenn.dev
おまけ Workers の DELETE 系エンドポイント一覧
プレビュー URL だけを無効化できる DELETE エンドポイントは存在しません。
エンドポイント | 効果 | プレビュー URL への影響 |
|---|---|---|
| バージョンのメタデータ削除 | 消えない |
| Worker 丸ごと削除 | 本番も消える |
| workers.dev 全無効化( | 本番も消える |
| デプロイ履歴の削除(最新は削除不可) | 消えない |
| カスタムドメインのルート削除 | 無関係 |
正直「わかりづらいな…」と思います。今後の API 設計では、プレビュー URL を個別に管理できるようなエンドポイントが追加されるとうれしいですね!