Bezpečný deploy na Cloudflare

API token pro jeden účet, mimo kód - krok za krokem pro Next.js i Express, včetně starých chunků po deployi

Návod, podle kterého zvládnete postupovat i bez hlubší znalosti Cloudflare: jak vytvořit token se správnými oprávněními, udržet ho mimo nasazený kód, zamknout deploy na jeden účet, ověřit, že to funguje, a nasadit bez rozbití stránek, které mají návštěvníci otevřené.

Vladimír NeporAutorIng. Vladimír Nepor
Publikováno
Bezpečný deploy: API token je v .env.deploy, obal v bashi ho načte jen pro jeden příkaz a wrangler.jsonc zamkne deploy na jeden účet Cloudflare. Build token nikdy nevidí..env.deployCLOUDFLARE_API_TOKEN=•••••••token tohoto projektuchmod 600 · .gitignore✕ build ho nikdy nečtenpm run deploybash -c 'set -a; . …'exec wrangler deploytoken jen protento jeden příkazCloudflare"account_id": "a1b2…"jen jeden účetwrangler.jsonc03 · TOKENToken pro jeden účetminimum oprávnění + filtr IPkapitola →04 · PROJEKTToken mimo buildaccount_id + .env.deploy + skriptykapitola →05 · OVĚŘENÍKontrola před deployemwhoami + kontrola buildukapitola →06 · DEPLOYDeploy bez rozbitých stránekzachování starých chunkůkapitola →
Obsah návodu

00 · Přehled

Bezpečný deploy v kostce

Návod nastaví deploy na Cloudflare Workers tak, aby se API token nikdy nedostal do nasazeného kódu, každý deploy šel právě do jednoho účtu a návštěvníkům se po deployi nerozbily otevřené stránky. Každý příkaz jde zkopírovat jedním kliknutím.

Zvolte svou technologii

Většina kroků je stejná pro každý projekt. Kde se Next.js a Express liší, ukazuje návod záložky jako tyto. Volba platí pro celou stránku a zapamatuje se.

  • Riziko: build OpenNext zkopíruje všechny hodnoty z .env do Workeru, takže token z něj běží v produkci.
  • Projděte: všechny kapitoly, včetně starých chunků v kapitole 06.
  • Statický export (output: "export") na Workers Static Assets: kapitoly 03 až 05 jako u Workeru a k tomu staré chunky.

Celé nastavení v kostce

  1. Jeden token na projekt - token pro jeden účet jen s oprávněními, která projekt používá, omezený na vaši IP adresu
  2. Zamčený účet - "account_id" ve wrangler.jsonc, takže deploy nemůže skončit v jiném účtu
  3. Token mimo kód - token je v .env.deploy, který nečte žádný framework ani wrangler dev; nikdy v .env
  4. Načíst jen pro jeden příkaz - npm skripty soubor načtou ve vlastním bashi; npm run -s wr -- nahrazuje npx wrangler
  5. Ověřit a nasadit - kontrola účtu a výstupu buildu, deploy a (Next.js) zachování starých JS chunků, aby otevřené stránky fungovaly dál

Co potřebujete vyřešit?

OtázkaKde najdete odpověď
Proč je token v .env nebo wrangler login problém?Proč →
Co potřebuji, než začnu?Než začnete →
Jaká oprávnění má token mít?Vytvoření tokenu →
Jak upravit soubory projektu?Nastavení projektu →
Jak ověřím, že token není v buildu?Ověření →
Po deployi otevřené stránky padají na ChunkLoadError.Staré chunky →
Token už máme v .env. Co teď?Přechod ze starého nastavení →
Dostávám 403, okno OAuth nebo „not authenticated“.Řešení problémů →
Rozsah

Stav k říjnu 2026: Wrangler 4, @opennextjs/cloudflare 1.x, účtové API tokeny. Nastavení běží v produkci na tomto webu (Next.js na OpenNext, D1, R2, Workers Cache) i na našich Workerech s Expressem. Příkazy potřebují bash: Linux, macOS nebo WSL ve Windows.

01 · Proč

Co je špatně na wrangler login a tokenu v .env

Běžné nastavení, tedy wrangler login nebo token v .env, funguje, ale má slabá místa. Snadno se nasadí do špatného účtu a token se může dostat tam, kam nepatří: do produkčního kódu nebo na dosah vašeho kódu a jeho závislostí.

wrangler login otevře všechny účty

npx wrangler login vás přihlásí přes OAuth jako osobu. Wrangler pak má přístup ke všem účtům, jejichž jste členem: k vlastnímu i ke všem klientským. Stačí jeden příkaz spuštěný ve špatné složce nebo projekt bez pevně daného účtu a deploy, dotaz do D1 nebo smazání bucketu skončí jinde, než má. Token vytvořený pro jeden účet tohle udělat nemůže.

Kam se dostane token z .env

Wrangler si .env načte sám, takže dát token tam vypadá přirozeně. Jenže soubor čtou i další nástroje a co se stane dál, záleží na technologii:

Nahoře: token v .env načte build OpenNext, zapíše ho do next-env.mjs a skončí v produkčním Workeru. Dole: token v .env.deploy načte jen obal pro wrangler CLI, build ho nečte a Worker žádný token neobsahuje.✕ Token v .env.envCLOUDFLARE_API_TOKEN=…Build OpenNextčte všechny .env*Produkční Workertoken v process.env✓ Token v .env.deploy.env.deployCLOUDFLARE_API_TOKEN=…Obal v bashijen pro wranglerCloudflare APIdeploy do jednoho účtuBuild čte jen .env, .env.local, .env.<mode>: ve Workeru žádný token není
Stejný token, dva soubory. Jen spodní cesta ho udrží mimo nasazený Worker.
KdeJak se token dostane do nasazeného kódu
Build OpenNextzapíše všechny hodnoty z .env, .env.local, .env.<mode> a .env.<mode>.local do .open-next/cloudflare/next-env.mjs a za běhu je nahraje do process.env
Next.js standalone.next/standalone obsahuje kopii .env
DockerCOPY . . bez .env* v .dockerignore zkopíruje soubor do image
Prohlížečproměnné s prefixem NEXT_PUBLIC_ a hodnoty v next.config → env skončí ve veřejném JavaScriptu

U OpenNext je tedy token z .env v produkčním Workeru a přes process.env ho přečte váš kód i každá závislost.

Proč na tom záleží

Kdo se dostane k deploy tokenu (přes kód Workeru, jeho prostředí, logy nebo napadenou závislost), může nasazovat, číst databáze a mazat úložiště ve vašem účtu. Token platí, dokud ho v dashboardu nesmažete, i když ho mezitím z .env odstraníte.

02 · Než začnete

Co budete potřebovat

Deset minut a těchto pár věcí. Pokud něco chybí, vyřešte to nejdřív, další kroky na tom stojí.

  • Projekt s konfigurací Wrangleru: wrangler.jsonc, wrangler.json nebo wrangler.toml v kořeni projektu.
  • bash: Linux a macOS ho mají. Ve Windows pracujte ve WSL (Ubuntu), na samotné příkazy stačí i Git Bash.
  • Přístup do dashboardu Cloudflare cílového účtu s právem vytvářet API tokeny.
  • Projekt v gitu, ať přesně vidíte, co se změnilo.

Jaký projekt máte?

V projektu vidíteTyp projektuZáložka a co projít
@opennextjs/cloudflare v package.jsonNext.js na OpenNextNext.js, všechny kapitoly včetně starých chunků
wrangler.jsonc s "main", bez Next.jsWorker (Express, Hono…)Workery, všechny kapitoly, staré chunky jen s frontendovým buildem s hashi
"assets" bez "main", statický build (Next.js output: "export", Vite)statický webWorkery. Do výstupu se token dostane jen přes NEXT_PUBLIC_ / VITE_, takže stačí zamčený účet, .env.deploy a vlastní token. Staré chunky platí také (CHUNKS_DIR).
Dockerfile + containers v konfiguraciCloudflare ContainersWorkery a navíc .env* do .dockerignore
Express na vlastním serveru (bez Wrangleru)není Workerserver žádný token Cloudflare nepotřebuje, držte ho jen na stroji, ze kterého nasazujete

03 · Token

Vytvořte token pro jeden projekt

Pro každý projekt vytvořte samostatný token. Když budete mít podezření na únik, smažete jeden token a ostatní projekty běží dál. Cloudflare ukáže hodnotu tokenu jen jednou, takže mějte projekt otevřený a připravený token vložit.

Krok 1: Otevřete formulář tokenu ve správném účtu

V dashboardu se přepněte do účtu projektu a otevřete Manage Account → Account API Tokens → Create Token → Custom token. Účtový token patří účtu a do jiného účtu se nikdy nedostane. Funguje i uživatelský token (My Profile → API Tokens), jen ho musíte na jeden účet omezit sami (krok 3).

Krok 2: Pojmenujte token a přidejte jen oprávnění, která projekt používá

Název: např. my-app deploy. Pak pro každý potřebný řádek klikněte na Add more. Podívejte se na bindingy ve svém wrangler.jsonc: d1_databases znamená D1, r2_buckets R2, kv_namespaces KV.

Workers Scripts pokrývá deploy, secrets, Durable Objects i logy. Pokud deploy později spadne na chybějící oprávnění (Queues, Containers, Images), přidejte jen to jedno.

Oprávnění (typ → položka → úroveň)Kdy
Account → Workers Scripts → Editvždy
Account → Account Settings → Readvždy
Account → D1 → Editd1_databases v konfiguraci
Account → Workers R2 Storage → Editr2_buckets (i incremental cache OpenNext)
Account → Workers KV Storage → Editkv_namespaces
Zone → Workers Routes → Editjen s routes v konfiguraci, a Zone Resources omezte na tu jednu zónu
Nezačínejte šablonou „Edit Cloudflare Workers“

Šablona je pohodlná, ale dává mnohem víc, než deploy potřebuje: kromě Workers Scripts i KV, R2, Tail, údaje o uživateli a Workers Routes na všech vašich zónách. Začněte volbou Custom token a přidejte jen řádky z tabulky výše.

Krok 3: Omezte token na jeden účet

Jen ve formuláři uživatelského tokenu: v sekci Account Resources nechte Include a místo All accounts vyberte účet projektu. Je to nejdůležitější pole celého formuláře. Formulář účtového tokenu ho nemá, protože token je k účtu vázaný.

Krok 4: Povolte token jen z vaší IP adresy

V sekci Client IP Address Filtering nechte Allow a zadejte svou veřejnou adresu. Uniklý token je pak jinde k ničemu. Adresy zjistíte takto:

Terminál
# your public IPv4 address
curl -4 -s https://ifconfig.me; echo

# your public IPv6 address (no output = you have none, skip it)
curl -6 -s --max-time 5 https://ifconfig.me; echo

Pokud máte i IPv6, přidejte ji přes Add more (adresu nebo její rozsah /64). Jinak se Wrangler může připojit přes IPv6 a dostane chybu 403. Seznam jde upravit i později, třeba když vám poskytovatel adresu změní.

Krok 5: Nastavte platnost, vytvořte token a zkopírujte ho

TTL je nepovinné; rozumná výchozí volba je rok, pak token přegenerujete. Klikněte na Continue to summary → Create Token a hodnotu zkopírujte. Neposílejte ji chatem ani e-mailem, v další kapitole ji vložíte rovnou do projektu. Zkopírujte si i Account ID: na Account home klikněte na tři tečky vedle názvu účtu a zvolte Copy account ID. Account ID není tajné.

04 · Projekt

Nastavení projektu

Pět drobných úprav v projektu. Všechno jsou soubory, které commitujete, kromě .env.deploy, který zůstává jen ve vašem počítači.

Krok 1: Zapište Account ID do wrangler.jsonc

Přidejte "account_id" hned pod "name". Od teď každý deploy i wrangler příkaz tohoto projektu míří jen do tohoto účtu. Pokud má projekt víc konfigurací Wrangleru (např. samostatný statický Worker), přidejte ho do každé.

wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-app",
  // Locked to one account: a deploy or any wrangler command cannot land in another account.
  // The API token lives in .env.deploy (see package.json scripts "deploy" and "wr").
  "account_id": "<ACCOUNT_ID>",
  // ... the rest of your config stays as it is
}

Krok 2: Vložte token do .env.deploy

Vytvořte soubor v kořeni projektu a vložte do něj token. Next.js, OpenNext i Vite načítají jen .env, .env.local, .env.<mode> a .env.<mode>.local, wrangler dev jen .dev.vars nebo .env. Soubor .env.deploy sám od sebe nečte nic.

.env.deploy
# Only for deploys and the wrangler CLI. Next.js, OpenNext and Vite never read this file.
CLOUDFLARE_API_TOKEN="<API_TOKEN>"
Terminál
# only you can read the file
chmod 600 .env.deploy

# must print a .gitignore rule; if it prints nothing, add one
git check-ignore -v .env.deploy || echo '.env*' >> .gitignore
Terminál
# Docker only: keep all env files out of the image
echo '.env*' >> .dockerignore

Krok 3: Odstraňte proměnné Cloudflare ze všech ostatních env souborů

Smažte řádky CLOUDFLARE_API_TOKEN a CLOUDFLARE_ACCOUNT_ID z .env, .env.local, .env.production, .dev.vars a podobných. První příkaz níže nesmí nic vypsat.

Terminál
# Which env files still contain Cloudflare variables? (prints names, never values)
grep -l 'CLOUDFLARE_' .env .env.* .dev.vars 2>/dev/null | grep -v '^.env.deploy$'

# Show the variable names in .env without their values
sed 's/=.*/=<redacted>/' .env

Proč i Account ID, když není tajné? U příkazů pro Workery vyhrává account_id ve wrangler.jsonc (ověřeno na Wrangleru 4.98 i 4.149), ale příkazy wrangler pages … dávají přednost proměnné a wrangler dev ji předá vašemu kódu jako binding. Jedno místo pro účet obojímu předejde.

Krok 4: Nechte token načítat npm skripty

Každý skript spustí vlastní bash, načte do něj .env.deploy a provede jeden příkaz. Token ve vašem terminálu nezůstane. V package.json nahraďte odpovídající skripty:

package.json
"scripts": {
  "dev":     "bash -c 'set -a; . ./.env.deploy; set +a; exec next dev \"$@\"' dev",
  "cfbuild": "bash -c 'set -a; . ./.env.deploy; set +a; exec opennextjs-cloudflare build'",
  "preview": "bash -c 'set -a; . ./.env.deploy; set +a; opennextjs-cloudflare build && exec opennextjs-cloudflare preview'",
  "deploy":  "bash -c 'set -a; . ./.env.deploy; set +a; opennextjs-cloudflare build && scripts/keep-old-chunks.sh merge && opennextjs-cloudflare deploy && scripts/keep-old-chunks.sh save'",
  "wr":      "bash -c 'set -a; . ./.env.deploy; set +a; exec wrangler \"$@\"' wr"
}
  • OpenNext hodnoty z prostředí shellu do buildu nezapisuje, takže načíst token pro cfbuild a deploy je bezpečné.
  • dev potřebuje token jen tehdy, když má některý binding "remote": true (pak čte produkční data). Bez obalu by otevřel okno OAuth.
  • scripts/keep-old-chunks.sh, který volá deploy, je v kapitole 06.

Krok 5: Místo npx wrangler používejte npm run -s wr --

Vše za -- dostane Wrangler. Nahraďte npx wrangler i v README, dokumentaci a skriptech, ať nikdo nespustí příkaz bez tokenu.

Terminál
# instead of:  npx wrangler <command>
npm run -s wr -- whoami
npm run -s wr -- tail
npm run -s wr -- d1 execute <DB_NAME> --remote --command "SELECT 1"
npm run -s wr -- r2 object get <BUCKET>/<KEY> --remote

Proč ne vlastní --env-file Wrangleru? Funguje jen za názvem příkazu (wrangler whoami --env-file=…), před ním Wrangler vypíše jen nápovědu. Obal je jednodušší a stejný pro všechny příkazy.

Tajemství, která aplikace potřebuje za běhu

API klíče, které serverový kód čte za běhu (platby, e-maily, mapy na serveru), do .env také nepatří. V produkci jsou to secrets Workeru. Pozor: secret put vytvoří novou verzi Workeru v produkci.

Terminál
# Runtime secrets of the app (third-party API keys etc.), never in .env.
# The value is read from .env and piped in, so it never shows up on screen or in the shell history.
grep '^MY_SECRET=' .env | cut -d= -f2- | npm run -s wr -- secret put MY_SECRET

# check (prints names only), then delete the line from .env
npm run -s wr -- secret list

OpenNext za běhu zkopíruje secrets Workeru do process.env a mají přednost před hodnotami z buildu. Kód zůstává stejný: process.env.MY_SECRET.

05 · Ověření

Kontrola před prvním deployem

Tři kontroly před prvním deployem. Každá trvá pár sekund, a když neprojde, řekne vám přesně, co je špatně.

Krok 1: Wrangler vidí token a správný účet

Terminál
npm run -s wr -- whoami
# → "You are logged in with an Account API Token" (or "User API Token")
#   and the account you expect

Vidíte jiný účet nebo chybu? Zkontrolujte hodnotu tokenu v .env.deploy a že příkaz spouštíte v kořeni projektu. U uživatelského tokenu se vypíše i Unable to retrieve email… User Details Read: je to jen informace, žádné oprávnění přidávat není třeba.

Krok 2: Bez obalu Wrangler přihlášený není

Terminál
npx wrangler whoami
# → "You are not authenticated. Please run `wrangler login`."
#   That is correct: without the wrapper there is no token. Do NOT run wrangler login.

Pokud hlásí přihlášení, je aktivní stará relace OAuth (spusťte npx wrangler logout) nebo je token pořád v .env či ve vašem shellu (otevřete nový terminál a vraťte se ke kroku 3 kapitoly 04).

Krok 3: Výstup buildu neobsahuje token

Sestavte projekt lokálně (nic se nenasadí) a prohledejte výstup. Kontroly vypisují jen názvy, nikdy samotný token.

Terminál
npm run cfbuild

# OpenNext: no Cloudflare variable in the Worker bundle (must print 0)
grep -c CLOUDFLARE_ .open-next/cloudflare/next-env.mjs

# Any project: no value from .env.deploy anywhere in the build output.
# Prints file names only, never the values. Empty output = OK.
while IFS='=' read -r k v; do v=${v//\"/}; [ -n "$v" ] && [ "${k#\#}" = "$k" ] && \
  grep -rlF -- "$v" .open-next .next dist build 2>/dev/null | sed "s|^|$k found in: |"; done < .env.deploy

Něco nalezeno? Některá proměnná Cloudflare je pořád v .env souboru, který build čte. Odstraňte ji a sestavte znovu.

06 · Deploy

Deploy, rollback, CI a staré chunky

Se skripty z kapitoly 04 je deploy jediný příkaz. Kapitola dál popisuje rollback, CI a u Next.js a statických webů i to, jak po deployi udržet funkční stránky, které mají návštěvníci otevřené.

Deploy

Terminál
npm run deploy
# 1. build  2. add old chunks  3. deploy  4. archive the deployed chunks
# Step 4 runs only when the deploy succeeded.

První deploy vypíše no archive yet, to je v pořádku. Od druhého uvidíte added N old files. Jak archiv funguje, je popsané níže.

Rollback

Statické soubory jsou součástí každé verze Workeru, takže rollback vrátí i soubory té verze. Nový build není potřeba.

Terminál
npm run -s wr -- deployments list   # recent versions
npm run -s wr -- rollback           # back to the previous version

Deploy z CI

V GitHub Actions nebo GitLabu uložte token jako tajnou proměnnou (secret) a předejte ho jen krokům, které ho potřebují. Nikdy před buildem negenerujte .env z tajných proměnných CI, tím byste vrátili původní problém. Runnery hostované GitHubem mění IP adresy, takže filtr IP tam nefunguje: použijte samostatný token pro CI s krátkým TTL, nebo vlastní runner s pevnou adresou.

.github/workflows/deploy.yml (kroky)
# GitHub Actions: the token goes only to the steps that need it, never into a .env file
- run: npm ci
- run: npx opennextjs-cloudflare build
  env:
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}   # only if bindings use "remote": true
- run: scripts/keep-old-chunks.sh merge
  env:
    OLD_ASSETS_DIR: ${{ runner.temp }}/old-assets             # restore it with actions/cache
- run: npx opennextjs-cloudflare deploy
  env:
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- run: scripts/keep-old-chunks.sh save
  env:
    OLD_ASSETS_DIR: ${{ runner.temp }}/old-assets

Archiv chunků musí přežít mezi běhy, např. přes actions/cache nad OLD_ASSETS_DIR.

Staré chunky (Next.js a statické weby)

Každý build Next.js dá souborům JS a CSS nové názvy. Stránky, které mají návštěvníci otevřené nebo v cache prohlížeče, ale chtějí ty staré. Pokud je nový deploy neobsahuje, stránka se rozbije. Řešení: držet archiv starých chunků a přidávat ho ke každému deployi. Worker s Expressem bez frontendu s hashi to nepotřebuje.

Stránka otevřená před deployem (verze 1) chce svůj chunk a1.js. Po prostém deployi verze 2 soubor chybí: 404 a ChunkLoadError. Se sloučeným archivem obsahuje verze 2 i staré chunky a stránka funguje dál.Otevřený panelstránka načtená z v1GET a1.jsDeploy v2 bez archivua2.jsb2.jsa1.js✕ 404 → ChunkLoadErrorDeploy v2 + chunky z archivua2.jsb2.jsa1.jsb1.jsz archivu ↓✓ 200 → stránka funguje
Panel otevřený před deployem chce své chunky. Má je jen deploy s archivem.
  • návštěvník má stránku otevřenou a klikne na odkaz (navigace v prohlížeči načítá další chunky staré verze),
  • prohlížeč ukáže HTML z cache (na tomto webu až 10 minut),
  • edge nebo CDN cache drží HTML přes deploy (Workers Cache s cross_version_cache).

Návštěvník vidí prázdnou nebo zamrzlou stránku a konzole hlásí ChunkLoadError nebo 404 pro /_next/static/…. Názvy chunků obsahují hash obsahu, takže se staré a nové soubory nikdy nepřepíšou a je bezpečné držet obojí.

Krok 1: Přidejte skript, který drží staré chunky

Uložte ho jako scripts/keep-old-chunks.sh. merge zkopíruje archivované chunky do čerstvého buildu (nový soubor nikdy nepřepíše), save přidá nasazené chunky do archivu. Archiv leží mimo projekt, v ~/next-deployments-old-assets/<složka projektu>, takže ho čistý checkout ani rm -rf .open-next nesmaže.

scripts/keep-old-chunks.sh
#!/usr/bin/env bash
# Keeps the JS/CSS chunks of earlier builds available after a deploy.
#   merge  before the deploy: copy archived chunks into the fresh build (new files are never overwritten)
#   save   after a successful deploy: add the deployed chunks to the archive
# Archive: $OLD_ASSETS_DIR, default ~/next-deployments-old-assets/<project folder name>
# Chunk folder: $CHUNKS_DIR, default .open-next/assets/_next/static (OpenNext); static export: out/_next/static
set -euo pipefail

BUILD="${CHUNKS_DIR:-.open-next/assets/_next/static}"
ARCHIVE="${OLD_ASSETS_DIR:-$HOME/next-deployments-old-assets/$(basename "$PWD")}/$BUILD"

# Copy files from $1 to $2 that do not exist in $2 yet; the count goes to COPIED.
# Paths keep the leading "./" (build folders may start with "-").
COPIED=0
copy_missing() {
  local src=$1 dst=$2 f
  COPIED=0
  while IFS= read -r -d '' f; do
    if [ ! -e "$dst/$f" ]; then
      mkdir -p -- "$(dirname -- "$dst/$f")"
      cp -p -- "$src/$f" "$dst/$f"
      COPIED=$((COPIED + 1))
    fi
  done < <(cd "$src" && find . -type f -print0)
}

# Delete Windows "Zone.Identifier" files (created when files are copied through Windows Explorer into WSL).
remove_zone_ids() {
  local dir n
  for dir in "$@"; do
    [ -d "$dir" ] || continue
    n=$(find "$dir" -type f -name '*:Zone.Identifier' -print -delete | wc -l)
    [ "$n" -gt 0 ] && echo "keep-old-chunks: deleted $n Zone.Identifier files in $dir"
  done
  return 0
}

[ -d "$BUILD" ] || { echo "keep-old-chunks: $BUILD not found, run the build first" >&2; exit 1; }
remove_zone_ids "$ARCHIVE" "$BUILD"

case "${1:-}" in
  merge)
    if [ -d "$ARCHIVE" ]; then
      copy_missing "$ARCHIVE" "$BUILD"
      echo "keep-old-chunks: added $COPIED old files from $ARCHIVE"
    else
      echo "keep-old-chunks: no archive yet ($ARCHIVE), it starts with this deploy"
    fi
    ;;
  save)
    mkdir -p "$ARCHIVE"
    copy_missing "$BUILD" "$ARCHIVE"
    echo "keep-old-chunks: archived $COPIED new files to $ARCHIVE"
    ;;
  *)
    echo "usage: $0 merge|save" >&2
    exit 2
    ;;
esac
Terminál
chmod +x scripts/keep-old-chunks.sh

Jiné umístění? Nastavte OLD_ASSETS_DIR. Skript z archivu i buildu maže soubory Zone.Identifier z Windows, které vznikají při kopírování přes Průzkumník do WSL.

Krok 2: Zavolejte ho kolem deploye

merge před deployem, save až po úspěšném, aby se do archivu nedostaly soubory, které nikdy nebyly nasazené. Skript deploy pro OpenNext z kapitoly 04 to už dělá. Statický export Next.js jen nastaví CHUNKS_DIR:

package.json (statický export)
# Static Next.js export (output: "export") deployed as Workers Static Assets
"deploy": "next build && CHUNKS_DIR=out/_next/static scripts/keep-old-chunks.sh merge && bash -c 'set -a; . ./.env.deploy; set +a; wrangler deploy' && CHUNKS_DIR=out/_next/static scripts/keep-old-chunks.sh save"

Archiv naroste o pár set kilobajtů na deploy. Kdyby byl někdy velký, smažte v něm nejstarší složky buildů (po pár týdnech je už nikdo nepotřebuje).

07 · Přechod

Přechod z tokenu v .env

Přechod z tokenu v .env. Postupujte v tomto pořadí: web poběží dál a starý token přestane platit až ve chvíli, kdy ho už nic nepotřebuje. Začněte, dokud je starý token ještě v .env, první dva kroky ho čtou odtamtud.

Starý token je v produkci

Build OpenNext ho zapsal do Workeru, který právě běží. Smažte ho až po novém deployi (krok 6), do té doby platí a jde v produkci přečíst.

Krok 1: Zjistěte, jestli stejný token nepoužívají jiné projekty

Token zkopírovaný z projektu do projektu je běžný. Jeho smazání by rozbilo ostatní, takže každý z nich potřebuje nejdřív vlastní token.

Terminál
# Do other projects use the same token? Prints file names only, never the token.
# Anything outside this project = that project must get its own token before you delete this one.
T=$(grep '^CLOUDFLARE_API_TOKEN=' .env | cut -d= -f2- | tr -d '"')
[ -n "$T" ] && grep -lsF -- "$T" ~/projects/*/.env* ~/projects/*/.dev.vars; unset T

Krok 2: Najděte starý token v dashboardu

Účtový token je v Manage Account → Account API Tokens, uživatelský v My Profile → API Tokens. Volání níže vypíše ID tokenu a nastaví mu Last used na teď, takže ho v seznamu poznáte. Čerstvého data se nelekněte.

Terminál
# Which token is it? Prints only its ID, never the token.
# The call also sets "Last used" of that token in the dashboard to now: that is how you spot it in the list.
T=$(grep '^CLOUDFLARE_API_TOKEN=' .env | cut -d= -f2- | tr -d '"')

# account token (Manage Account → Account API Tokens)
curl -s -H "Authorization: Bearer $T" "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/tokens/verify" | grep -o '"id":"[^"]*"'

# user token (My Profile → API Tokens)
curl -s -H "Authorization: Bearer $T" "https://api.cloudflare.com/client/v4/user/tokens/verify" | grep -o '"id":"[^"]*"'
unset T

Krok 3: Vytvořte nový token

Podle kapitoly 03, jeden na projekt.

Krok 4: Upravte projekt

account_id, .env.deploy s novým tokenem, vyčištěný .env, skripty (kapitola 04).

Krok 5: Ověřte účet a build

Kapitola 05.

Krok 6: Nasaďte

npm run deploy. Worker, který teď běží, už žádný token neobsahuje.

Krok 7: Smažte starý token

V dashboardu token, který jste našli v kroku 2. U Next.js teprve teď, u prostého Workeru klidně už po kroku 5.

Krok 8: Zrušte přístup přes OAuth

Pokud jste někdy použili wrangler login:

Terminál
npx wrangler logout
# then in the dashboard: My Profile → Access Management → Connected Applications → revoke Wrangler
Byl token někdy v gitu?

Ověřte to příkazem git log --all --oneline -- .env. Pokud něco vypíše, token je v historii repozitáře. Chrání vás smazání tokenu v dashboardu (krok 7), přepis historie je volitelný.

08 · Problémy

Když něco nefunguje

Nejčastější potíže a co s nimi, zhruba v pořadí, v jakém je můžete potkat.

Co vidítePříčinaCo udělat
Okno OAuth: Wrangler wants to access your accountpříkaz běží bez tokenu (přímo npx wrangler …)klikněte na Cancel a spusťte ho znovu přes npm run -s wr --
npm run dev otevře okno OAuthbinding má "remote": true a dev není obalenýobalte dev stejně jako ostatní skripty (kapitola 04)
You are not authenticatedv prostředí není tokenpoužijte npm skript; wrangler login nespouštějte
Unable to retrieve email… User Details Readuživatelský token bez tohoto oprávněníjen informace, nic přidávat netřeba
403 / Authentication errorzměnila se vaše IP adresa, připojujete se přes IPv6 nebo chybí oprávněnízkontrolujte svou IP (krok 4) a seznam IP u tokenu, pak oprávnění
.env.deploy: No such file or directorypříkaz neběží v kořeni projektucd do složky s package.json
Wrangler vypíše jen nápovědu--env-file před názvem příkazupoužijte obal, nebo dejte přepínač za příkaz
Build spadne při čtení D1 / R2binding má "remote": true a build běží bez tokenusestavujte přes npm skript (npm run cfbuild), ne přes npx …
ChunkLoadError po deployideploy neobsahoval staré chunkyzkontrolujte cestu k archivu ve výpisu deploye (staré chunky)
bash: command not found ve Windowsnpm spouští skripty v cmd nebo PowerShellupracujte ve WSL (Ubuntu), nebo nastavte npm script-shell na Git Bash
Shrnutí
  • Jeden projekt = jeden token, jeden účet v account_id a token v .env.deploy.
  • Nikdy token Cloudflare v .env (OpenNext ho zabalí, wrangler dev ho předá vašemu kódu) a nikdy wrangler login.
  • Před prvním deployem zkontrolujte výstup buildu. Po přechodu smažte starý token, až ho nic nepotřebuje, u Next.js až po novém deployi.
  • Next.js a statické weby: staré chunky _next/static držte v archivu mimo projekt a přidávejte je ke každému deployi.

Zdroje

Oficiální dokumentace a další čtení

Nasazujete do více účtů Cloudflare?

Nastavíme tokeny, deploy i celý stack Cloudflare tak, aby nic tajného neskončilo v produkčním kódu.

Rezervovat schůzku