diff --git a/.gitattributes b/.gitattributes index 04e0ea90b3361a..5aec2a5e403b01 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,7 +18,7 @@ *.xml text eol=lf *.yaml text eol=lf *.yml text eol=lf -_redirects text eol=lf +__redirects text eol=lf .editorconfig text eol=lf .gitattributes text eol=lf .prettierignore text eol=lf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7d9549e0fc4c74..199505a1d09f6f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,14 +10,17 @@ /.github/actions/assign-pr/index.js @cloudflare/pcx-technical-writing /.github/styles/cloudflare/spelling-exceptions.txt @cloudflare/pcx-technical-writing /src/components/ @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @marciocloudflare @haleycode @maxvp @GregBrimble @KianNH @WalshyDev -*.js @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @haleycode @maxvp @marciocloudflare @GregBrimble @KianNH @WalshyDev -*.ts @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @haleycode @maxvp @marciocloudflare @GregBrimble @KianNH @WalshyDev +*.js @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @haleycode @GregBrimble @KianNH @WalshyDev +*.ts @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @haleycode @GregBrimble @KianNH @WalshyDev +*.astro @cloudflare/developer-advocacy @kristianfreeman @kodster28 @pedrosousa @haleycode @GregBrimble @KianNH @WalshyDev +/src/schemas/tags.ts @kodster28 @KianNH @joslyn-cf /src/content/workers-ai-models/ @craigsdennis @pedrosousa @cloudflare/pcx-technical-writing -/public/_redirects @GregBrimble @KianNH @pedrosousa @WalshyDev @cloudflare/pcx-technical-writing +/public/__redirects @GregBrimble @KianNH @pedrosousa @WalshyDev @cloudflare/pcx-technical-writing + # AI -/src/content/docs/agents/ @irvinebroque @rita3ko @elithrar @thomasgauvin @threepointone @harshil1712 @megaconfidence @cloudflare/pcx-technical-writing +/src/content/docs/agents/ @irvinebroque @rita3ko @elithrar @thomasgauvin @threepointone @cloudflare/pcx-technical-writing /src/content/docs/ai-gateway/ @kathayl @G4brym @mchenco @daisyfaithauma @cloudflare/pcx-technical-writing /src/content/docs/workers-ai/ @rita3ko @craigsdennis @markdembo @mchenco @daisyfaithauma @cloudflare/pcx-technical-writing /src/content/docs/vectorize/ @elithrar @vy-ton @sejoker @mchenco @cloudflare/pcx-technical-writing @@ -92,10 +95,10 @@ /src/content/docs/calls/ @cloudflare/pcx-technical-writing @cloudflare/calls /src/assets/images/calls/ @cloudflare/pcx-technical-writing @cloudflare/calls /public/calls/ @cloudflare/pcx-technical-writing @cloudflare/calls -/src/content/docs/d1/ @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @cloudflare/pcx-technical-writing +/src/content/docs/d1/ @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @harshil1712 @cloudflare/pcx-technical-writing /src/content/release-notes/d1.yaml @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @cloudflare/pcx-technical-writing -/src/content/partials/d1/ @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @cloudflare/pcx-technical-writing -/src/content/docs/durable-objects/ @elithrar @vy-ton @joshthoward @oxyjun @cloudflare/pcx-technical-writing +/src/content/partials/d1/ @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @harshil1712 @cloudflare/pcx-technical-writing +/src/content/docs/durable-objects/ @elithrar @vy-ton @joshthoward @oxyjun @harshil1712 @cloudflare/pcx-technical-writing /src/content/release-notes/durable-objects.yaml @elithrar @rozenmd @vy-ton @joshthoward @oxyjun @cloudflare/pcx-technical-writing /src/content/docs/email-routing/ @cloudflare/pcx-technical-writing /src/content/docs/hyperdrive/ @elithrar @thomasgauvin @sejoker @oxyjun @cloudflare/pcx-technical-writing @@ -110,9 +113,9 @@ /src/content/release-notes/kv.yaml @elithrar @thomasgauvin @rts-rob @oxyjun @cloudflare/pcx-technical-writing /src/content/partials/kv/ @elithrar @thomasgauvin @rts-rob @oxyjun @cloudflare/pcx-technical-writing /src/content/docs/pub-sub/ @elithrar @dcpena @cloudflare/pcx-technical-writing -/src/content/docs/queues/ @elithrar @toddmantell @maheshwarip @cloudflare/pcx-technical-writing +/src/content/docs/queues/ @elithrar @toddmantell @maheshwarip @harshil1712 @cloudflare/pcx-technical-writing /src/content/release-notes/queues.yaml @elithrar @toddmantell @maheshwarip @cloudflare/pcx-technical-writing -/src/content/docs/r2/ @oxyjun @elithrar @jonesphillip @cloudflare/workers-docs @cloudflare/pcx-technical-writing +/src/content/docs/r2/ @oxyjun @elithrar @jonesphillip @harshil1712 @cloudflare/workers-docs @cloudflare/pcx-technical-writing /src/content/release-notes/r2.yaml @oxyjun @elithrar @cloudflare/workers-docs @cloudflare/pcx-technical-writing /src/content/docs/stream/ @tsmith512 @dcpena @cloudflare/pcx-technical-writing @renandincer @third774 /src/content/release-notes/stream.yaml @tsmith512 @dcpena @cloudflare/pcx-technical-writing @@ -133,13 +136,13 @@ /src/content/docs/workers/reference/security-model.mdx @irvinebroque @GregBrimble @ToriLindsay @cloudflare/pcx-technical-writing /src/content/compatibility-flags/ @irvinebroque @mikenomitch @GregBrimble @cloudflare/pcx-technical-writing /src/content/docs/workers/wrangler/ @cloudflare/wrangler @cloudflare/wrangler-friends @irvinebroque @ToriLindsay @cloudflare/pcx-technical-writing -/src/content/docs/workers/frameworks/ @igorminar @dario-piotrowicz @jculvey @aninibread @GregBrimble @ToriLindsay @cloudflare/pcx-technical-writing -/src/content/docs/pages/framework-guides/ @igorminar @dario-piotrowicz @jculvey @aninibread @GregBrimble @ToriLindsay @cloudflare/pcx-technical-writing +/src/content/docs/workers/frameworks/ @igorminar @cloudflare/wrangler @aninibread @GregBrimble @ToriLindsay @cloudflare/pcx-technical-writing +/src/content/docs/pages/framework-guides/ @igorminar @cloudflare/wrangler @aninibread @GregBrimble @ToriLindsay @cloudflare/pcx-technical-writing /src/content/docs/analytics/analytics-engine/ @irvinebroque @elithrar @cloudflare/pcx-technical-writing /src/content/docs/cloudflare-for-platforms/workers-for-platforms/ @irvinebroque @angelampcosta @GregBrimble @cloudflare/deploy-config @cloudflare/pcx-technical-writing /src/content/docs/workers/observability/ @irvinebroque @mikenomitch @rohinlohe @ToriLindsay @cloudflare/pcx-technical-writing /src/content/docs/workers/static-assets @irvinebroque @GregBrimble @WalshyDev @ToriLindsay @cloudflare/deploy-config @cloudflare/pcx-technical-writing -/src/content/docs/workflows/ @ToriLindsay @elithrar @celso @sidharthachatterjee @cloudflare/pcx-technical-writing +/src/content/docs/workflows/ @elithrar @celso @sidharthachatterjee @cloudflare/pcx-technical-writing # DDoS Protection diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4da57414843a8d..66809b8ac24d44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,11 +1,11 @@ -name: CI +tabname: CI on: pull_request: branches: - production -concurrency: +escconcurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 1 - - uses: actions/setup-node@v4 + tab- uses: actions/setup-node@v4 with: node-version: 22 cache: "npm" @@ -57,3 +57,10 @@ jobs: - name: Tests run: npm run test + + - name: Post PR CI failure comment + if: always() + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx tsx bin/post-pr-ci-failure-comment/index.ts diff --git a/.github/workflows/comment-changed-filenames.yml b/.github/workflows/comment-changed-filenames.yml index 06c59f3f0d98ce..db180eed3ead25 100644 --- a/.github/workflows/comment-changed-filenames.yml +++ b/.github/workflows/comment-changed-filenames.yml @@ -1,4 +1,4 @@ -name: Flag changed filenames +tabname: Flag changed filenames # **What it does**: Adds or removes a comment if a PR renames or removes a file. # **Why we have it**: Highlights when we need redirects covering certain file paths. @@ -13,7 +13,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -jobs: +escjobs: flag_changed_filenames: runs-on: ubuntu-latest steps: @@ -24,7 +24,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - files=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \ + tabfiles=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" | \ jq -r '.[] | select(.status=="renamed" or .status=="removed") | select (.filename | startswith("src/content/docs")) | select(.filename | endswith(".mdx")) | if .status == "renamed" then .previous_filename else .filename end' | \ diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml index 2214d1ca440af9..83f9b6061e5a0f 100644 --- a/.github/workflows/label-pr.yml +++ b/.github/workflows/label-pr.yml @@ -1,4 +1,4 @@ -name: Label PRs +tabname: Label PRs # **What it does**: Uses the files to label PRs with updated doc areas && size estimates. # **Why we have it**: Easier scanning of repo PRs && backend reporting on our team's work. diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4b26bedd18f37c..067c47ffec9c12 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -18,27 +18,3 @@ jobs: - uses: ./.github/actions/assign-pr with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - review_comment: - name: Add review comment - runs-on: ubuntu-latest - steps: - - id: check_if_contributor_is_external - name: Check if contributor is external - run: 'curl --write-out ''%{http_code}'' --silent --output /dev/null -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ env.GH_TOKEN }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/orgs/cloudflare/members/${{ github.event.pull_request.user.login }} | grep -q ''204'' && echo "is_external=false" >> $GITHUB_OUTPUT || echo "is_external=true" >> $GITHUB_OUTPUT' - env: - GH_TOKEN: ${{ secrets.HOLOPIN_LABELER }} - - name: External comment - run: gh pr comment "$NUMBER" --body "Howdy and thanks for contributing to our repo. We review new, external PRs within **2 weeks**. If it's been longer than then without any movement, tag the PR **Assignees** in a comment." - if: steps.check_if_contributor_is_external.outputs.is_external == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.pull_request.number }} - - name: Internal comment - run: gh pr comment "$NUMBER" --body "Howdy and thanks for contributing to our repo. We review internal PRs within **1 week**. If it's something urgent or has been sitting without a comment, start a thread in the *Developer Docs* space internally." - if: steps.check_if_contributor_is_external.outputs.is_external == 'false' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/publish-preview.yml b/.github/workflows/publish-preview.yml index a66f7f0983e286..4a471a508a5b34 100644 --- a/.github/workflows/publish-preview.yml +++ b/.github/workflows/publish-preview.yml @@ -9,6 +9,7 @@ concurrency: jobs: publish: + if: github.repository == 'cloudflare/cloudflare-docs' runs-on: ubuntu-22.04 permissions: contents: read diff --git a/.hyperlint/config.yaml b/.hyperlint/config.yaml index 5ef3576343ec05..529388e6842389 100644 --- a/.hyperlint/config.yaml +++ b/.hyperlint/config.yaml @@ -1,15 +1,16 @@ content_dir: /src/content -authorized_users: - - dcpena - - kodster28 - - KianNH - - marciocloudflare - - pedrosousa - - ranbel - - RebeccaTamachiro -style_guide: +reviewer: + custom_comment: |- + Howdy and thanks for contributing to our repo. The Cloudflare team reviews new, external PRs within **two (2) weeks**. If it's been two weeks or longer without any movement, please tag the PR **Assignees** in a comment. + + We review internal PRs within **1 week**. If it's something urgent or has been sitting without a comment, start a thread in the *Developer Docs* space internally. enabled: true -openapi: - enabled: true - urls: - - https://raw.githubusercontent.com/cloudflare/api-schemas/main/openapi.json + external_link_validation: + check_status_upon_review_failure: neutral + summarize_pull_request: + enabled: true + vale_style_guide: + check_status_upon_review_failure: neutral + enabled: true + limit_num_reviews: 2 + limit_num_comments: 7 diff --git a/.prettierignore b/.prettierignore index dd5da9e52bb9dd..3f158f3d63c576 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,6 @@ dist # generated actions JS .github/**/*/index.js .github/CODEOWNERS -public/_redirects +public/__redirects public/analytics/static/downloads/main.css src/content/workers-ai-models/*.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 2f50be09c286fb..495133435f0f92 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,6 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "typescript.tsdk": "node_modules/typescript/lib", - "cSpell.enableFiletypes": ["mdx"] + "cSpell.enableFiletypes": ["mdx"], + "files.associations": { "__redirects": "plaintext", "_headers": "plaintext" } } diff --git a/astro.config.ts b/astro.config.ts index 3e59ae1d5edd96..8b43468653a27f 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -37,7 +37,21 @@ async function autogenSections() { }); } +async function autogenStyles() { + const styles = ( + await readdir("./src/styles/", { + withFileTypes: true, + recursive: true, + }) + ) + .filter((x) => x.isFile()) + .map((x) => x.parentPath + x.name); + + return styles; +} + const sidebar = await autogenSections(); +const customCss = await autogenStyles(); const runLinkCheck = process.env.RUN_LINK_CHECK || false; @@ -55,6 +69,14 @@ export default defineConfig({ rehypeTitleFigure, ], }, + image: { + service: { + entrypoint: "astro/assets/services/sharp", + config: { + limitInputPixels: false, + }, + }, + }, experimental: { contentIntellisense: true, }, @@ -89,26 +111,15 @@ export default defineConfig({ components: { Footer: "./src/components/overrides/Footer.astro", Head: "./src/components/overrides/Head.astro", + Header: "./src/components/overrides/Header.astro", Hero: "./src/components/overrides/Hero.astro", MarkdownContent: "./src/components/overrides/MarkdownContent.astro", Sidebar: "./src/components/overrides/Sidebar.astro", PageTitle: "./src/components/overrides/PageTitle.astro", - SocialIcons: "./src/components/overrides/SocialIcons.astro", TableOfContents: "./src/components/overrides/TableOfContents.astro", }, sidebar, - customCss: [ - "./src/asides.css", - "./src/badges.css", - "./src/code.css", - "./src/footnotes.css", - "./src/headings.css", - "./src/input.css", - "./src/mermaid.css", - "./src/table.css", - "./src/tailwind.css", - "./src/title.css", - ], + customCss, pagination: false, plugins: [ ...(runLinkCheck @@ -119,7 +130,7 @@ export default defineConfig({ exclude: [ "/api/", "/api/**", - "/changelog/", + "/changelog/**", "/http/resources/**", "{props.*}", "/", @@ -146,9 +157,7 @@ export default defineConfig({ tailwind({ applyBaseStyles: false, }), - liveCode({ - layout: "~/components/live-code/Layout.astro", - }), + liveCode({}), icon(), sitemap({ filter(page) { diff --git a/bin/fetch-ai-models.js b/bin/fetch-ai-models.js index 50e4593bcb1fe7..9e2a7db415a390 100644 --- a/bin/fetch-ai-models.js +++ b/bin/fetch-ai-models.js @@ -3,7 +3,7 @@ import fs from "fs"; fetch("https://ai.cloudflare.com/api/models") .then((res) => res.json()) .then((data) => { - data.models.forEach((model) => { + data.models.map((model) => { const fileName = model.name.split("/")[2]; fs.writeFileSync( `./src/content/workers-ai-models/${fileName}.json`, diff --git a/bin/fetch-warp-releases.js b/bin/fetch-warp-releases.js index c7a4e6258bf8d1..1d337ec08306bc 100644 --- a/bin/fetch-warp-releases.js +++ b/bin/fetch-warp-releases.js @@ -35,7 +35,12 @@ for (let track of tracks) { track = track.replace("noble-intel", "linux"); } - const path = `./src/content/warp-releases/${track}/${item.version}.yaml`; + const folder = `./src/content/warp-releases/${track}`; + const path = `${folder}/${item.version}.yaml`; + + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder, { recursive: true }); + } if (fs.existsSync(path)) { console.log(`${track} ${item.version} already exists.`); @@ -66,13 +71,16 @@ for (let track of tracks) { }); const releaseNotes = tokens.reduce((s, t) => s + t.raw, ""); + const platformName = data.platformName.startsWith("noble-") + ? "Linux" + : data.platformName; fs.writeFileSync( `./src/content/warp-releases/${track}/${item.version}.yaml`, YAML.stringify({ ...item, releaseNotes, - platformName: data.platformName, + platformName, }), "utf-8", ); diff --git a/bin/post-pr-ci-failure-comment/constants.ts b/bin/post-pr-ci-failure-comment/constants.ts new file mode 100644 index 00000000000000..66bc4bbc230947 --- /dev/null +++ b/bin/post-pr-ci-failure-comment/constants.ts @@ -0,0 +1,4 @@ +export const GITHUB_ACTIONS_BOT_ID = 41898282; +export const DOCS_BASE_URL = "https://developers.cloudflare.com"; +export const CONTENT_BASE_PATH = "src/content"; +export const PREVIEW_URL_REGEX = /^\*\*Preview URL:\*\* (.*)$/m; diff --git a/bin/post-pr-ci-failure-comment/index.ts b/bin/post-pr-ci-failure-comment/index.ts new file mode 100644 index 00000000000000..d4fd6fcd53a08c --- /dev/null +++ b/bin/post-pr-ci-failure-comment/index.ts @@ -0,0 +1,101 @@ +import * as core from "@actions/core"; +import * as github from "@actions/github"; +import type { PullRequestEvent } from "@octokit/webhooks-types"; + +import { GITHUB_ACTIONS_BOT_ID } from "./constants"; + +async function run(): Promise { + try { + if (!process.env.GITHUB_TOKEN) { + core.setFailed(`Could not find GITHUB_TOKEN in env`); + process.exit(); + } + + const octokit = github.getOctokit(process.env.GITHUB_TOKEN); + const payload = github.context.payload as PullRequestEvent; + + const { owner, repo } = github.context.repo; + const pullRequestNumber = payload.number; + const runId = github.context.runId; + + const { data: run } = await octokit.rest.actions.listJobsForWorkflowRun({ + owner, + repo, + run_id: runId, + }); + + const job = run.jobs.findLast((job) => job.name === "Compiles"); + + if (!job) { + core.setFailed(`Could not find a job called 'Compiles'`); + process.exit(); + } + + const failedStep = job.steps?.find((step) => step.conclusion === "failure"); + + if (failedStep) { + core.info(`Found failed step ${failedStep.name}`); + } + + const conclusion = failedStep ? "failure" : "success"; + + const { data: comments } = await octokit.rest.issues.listComments({ + owner, + repo, + issue_number: pullRequestNumber, + per_page: 100, + }); + + const existingComment = comments.find( + (comment) => + comment.user?.id === GITHUB_ACTIONS_BOT_ID && + comment.body?.includes("**CI run failed:**"), + ); + + if (existingComment) { + core.info(`Found existing comment with ID ${existingComment.id}`); + } else { + core.info(`No existing comment found`); + } + + const url = `https://github.com/${owner}/${repo}/actions/runs/${runId}/job/${job.id}`; + const comment = `**CI run failed:** [build logs](${url})`; + + if (conclusion === "failure") { + if (existingComment) { + core.info( + `Updating ${existingComment.id} with ${JSON.stringify(comment)}`, + ); + await octokit.rest.issues.updateComment({ + owner, + repo, + comment_id: existingComment.id, + body: comment, + }); + } else { + core.info(`Creating new comment with ${JSON.stringify(comment)}`); + await octokit.rest.issues.createComment({ + owner, + repo, + issue_number: pullRequestNumber, + body: comment, + }); + } + } else if (conclusion === "success" && existingComment) { + core.info(`Removing ${existingComment.id}`); + await octokit.rest.issues.deleteComment({ + owner, + repo, + issue_number: pullRequestNumber, + comment_id: existingComment.id, + }); + } + } catch (error) { + if (error instanceof Error) { + core.setFailed(error.message); + } + process.exit(); + } +} + +run(); diff --git a/bin/validate-redirects.ts b/bin/validate-redirects.ts index 9f4ab9ca608a35..5f59c5cd34748f 100644 --- a/bin/validate-redirects.ts +++ b/bin/validate-redirects.ts @@ -1,7 +1,7 @@ import { readFile } from "fs/promises"; async function main() { - const redirects = await readFile("public/_redirects", { encoding: "utf-8" }); + const redirects = await readFile("public/__redirects", { encoding: "utf-8" }); let numInfiniteRedirects = 0; let numUrlsWithFragment = 0; diff --git a/package-lock.json b/package-lock.json index d3702426b82660..fe09265bd88879 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,88 +9,101 @@ "devDependencies": { "@actions/core": "1.11.1", "@actions/github": "6.0.0", + "@apidevtools/swagger-parser": "10.1.1", "@astrojs/check": "0.9.4", - "@astrojs/react": "4.2.0", + "@astrojs/react": "4.2.1", "@astrojs/rss": "4.0.11", - "@astrojs/sitemap": "3.2.1", - "@astrojs/starlight": "0.31.1", - "@astrojs/starlight-docsearch": "0.5.0", + "@astrojs/sitemap": "3.3.0", + "@astrojs/starlight": "0.32.3", + "@astrojs/starlight-docsearch": "0.6.0", "@astrojs/starlight-tailwind": "3.0.0", "@astrojs/tailwind": "5.1.5", - "@cloudflare/vitest-pool-workers": "0.6.14", - "@cloudflare/workers-types": "4.20250204.0", + "@cloudflare/vitest-pool-workers": "0.8.2", + "@cloudflare/workers-types": "4.20250319.0", "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.40.2", + "@floating-ui/react": "0.27.5", "@iarna/toml": "2.2.5", "@marsidev/react-turnstile": "1.1.0", + "@octokit/webhooks-types": "7.6.1", "@stoplight/json-schema-tree": "4.0.0", "@types/hast": "3.0.4", "@types/he": "1.2.3", - "@types/node": "22.13.2", + "@types/node": "22.13.10", "@types/react": "19.0.7", - "@types/react-dom": "19.0.3", - "@typescript-eslint/parser": "8.25.0", - "algoliasearch": "5.20.2", - "astro": "5.2.1", + "@types/react-dom": "19.0.4", + "@typescript-eslint/parser": "8.27.0", + "algoliasearch": "5.21.0", + "astro": "5.4.1", "astro-breadcrumbs": "3.3.1", "astro-icon": "1.1.5", "astro-live-code": "0.0.5", + "cidr-tools": "11.0.3", "codeowners-utils": "1.0.2", "date-fns": "4.1.0", "dedent": "1.5.3", "dompurify": "3.2.4", "dot-prop": "9.0.0", - "eslint": "9.20.0", + "eslint": "9.22.0", "eslint-plugin-astro": "1.3.1", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.4", "fast-glob": "3.3.3", + "fast-xml-parser": "5.0.9", "github-slugger": "2.0.0", "globals": "16.0.0", + "hast-util-select": "6.0.4", "hastscript": "9.0.1", "he": "1.2.0", - "instantsearch.css": "8.5.1", - "instantsearch.js": "4.77.3", "jsonc-parser": "3.3.1", "lz-string": "1.5.0", "marked": "15.0.7", + "mdast-util-from-markdown": "2.0.2", + "mdast-util-mdx": "3.0.0", "mdast-util-mdx-expression": "2.0.1", - "mermaid": "11.4.1", + "mermaid": "11.5.0", + "micromark-extension-mdxjs": "3.0.0", "node-html-parser": "7.0.1", - "prettier": "3.5.2", + "openapi-types": "12.1.3", + "parse-duration": "2.1.3", + "prettier": "3.5.3", "prettier-plugin-astro": "0.14.1", "prettier-plugin-tailwindcss": "0.6.9", "pretty-bytes": "6.1.1", "react": "19.0.0", "react-dom": "19.0.0", "react-icons": "5.5.0", - "react-markdown": "9.0.3", + "react-instantsearch": "7.15.4", + "react-markdown": "10.1.0", "redirects-in-workers": "0.0.5", "rehype": "13.0.2", "rehype-autolink-headings": "7.1.0", "rehype-external-links": "3.0.0", "rehype-parse": "9.0.1", + "rehype-remark": "10.0.0", "rehype-stringify": "10.0.1", "rehype-title-figure": "0.1.2", "remark": "15.0.1", + "remark-gfm": "4.0.1", + "remark-stringify": "11.0.0", "sharp": "0.33.5", "solarflare-theme": "0.0.4", - "starlight-image-zoom": "0.10.1", - "starlight-links-validator": "0.14.2", + "starlight-image-zoom": "0.11.1", + "starlight-links-validator": "0.14.3", "starlight-package-managers": "0.10.0", "strip-markdown": "6.0.0", "svgo": "3.3.2", "tailwindcss": "3.4.17", "tippy.js": "6.3.7", - "ts-blank-space": "0.6.0", - "tsx": "4.19.2", - "typescript": "5.7.3", - "typescript-eslint": "8.24.1", + "ts-blank-space": "0.6.1", + "tsx": "4.19.3", + "typescript": "5.8.2", + "typescript-eslint": "8.27.0", "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", "vitest": "2.1.6", - "wrangler": "3.109.0" + "wrangler": "4.1.0" }, "engines": { "node": ">=22" @@ -211,41 +224,41 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.20.2.tgz", - "integrity": "sha512-IS8JSFsDD33haaKIIFaL7qj3bEIG9GldZfb3ILW0QF3at7TcrIJYy58hrDvFee5T3p3E2aH/+wqIr0eha8jB/w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.21.0.tgz", + "integrity": "sha512-I239aSmXa3pXDhp3AWGaIfesqJBNFA7drUM8SIfNxMIzvQXUnHRf4rW1o77QXLI/nIClNsb8KOLaB62gO9LnlQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.20.2.tgz", - "integrity": "sha512-k0KxCfcX/HZySqPasKy6GkiiDuebaMh2v/nE0HHg1PbsyeyagLapDi6Ktjkxhz8NlUq6eTJR+ddGJegippKQtQ==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.21.0.tgz", + "integrity": "sha512-OxoUfeG9G4VE4gS7B4q65KkHzdGsQsDwxQfR5J9uKB8poSGuNlHJWsF3ABqCkc5VliAR0m8KMjsQ9o/kOpEGnQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.20.2.tgz", - "integrity": "sha512-xoZcL/Uu49KYDb3feu2n06gALD17p5CslO8Zk3mZ7+uTurK3lgjLws7LNetZ172Ap/GpzPCRXI83d2iDoYQD6Q==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.21.0.tgz", + "integrity": "sha512-iHLgDQFyZNe9M16vipbx6FGOA8NoMswHrfom/QlCGoyh7ntjGvfMb+J2Ss8rRsAlOWluv8h923Ku3QVaB0oWDQ==", "dev": true, "license": "MIT", "engines": { @@ -253,64 +266,64 @@ } }, "node_modules/@algolia/client-insights": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.20.2.tgz", - "integrity": "sha512-fy7aCbo9y7WHt/9G03EYc471Dd5kIaM8PNP4z6AEQYr9a9X8c4inwNs6tePxAEfRHwVQi0CZ7kuVdn6/MjWx1A==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.21.0.tgz", + "integrity": "sha512-y7XBO9Iwb75FLDl95AYcWSLIViJTpR5SUUCyKsYhpP9DgyUqWbISqDLXc96TS9shj+H+7VsTKA9cJK8NUfVN6g==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.20.2.tgz", - "integrity": "sha512-ocL1ZXulfuXzJAwsKw2kMscKMD0rs/f4CFYu6Gjh4mK4um6rGfa1a6u1MSc4swFqRQer0wNP9Pi+kVfKhuKt5A==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.21.0.tgz", + "integrity": "sha512-6KU658lD9Tss4oCX6c/O15tNZxw7vR+WAUG95YtZzYG/KGJHTpy2uckqbMmC2cEK4a86FAq4pH5azSJ7cGMjuw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.20.2.tgz", - "integrity": "sha512-Xjs4Tj1zkLCnmq1ys8RRhLQPy002I6GuT/nbHVdSQmQu4yKCI0gOFbwxHdM6yYPEuE3cJx7A4wSQjCH21mUKsg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.21.0.tgz", + "integrity": "sha512-pG6MyVh1v0X+uwrKHn3U+suHdgJ2C+gug+UGkNHfMELHMsEoWIAQhxMBOFg7hCnWBFjQnuq6qhM3X9X5QO3d9Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.20.2.tgz", - "integrity": "sha512-2cD3RGB5byusLS0DAX1Nvl5MLiv7OoGgQrRs+94dTalqjvK8lGKzxxJhXoVojgx2qcROyIUAIDXFdTqv6NIHaA==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.21.0.tgz", + "integrity": "sha512-nZfgJH4njBK98tFCmCW1VX/ExH4bNOl9DSboxeXGgvhoL0fG1+4DDr/mrLe21OggVCQqHwXBMh6fFInvBeyhiQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" @@ -324,87 +337,87 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.20.2.tgz", - "integrity": "sha512-S593Kmhc98+5zdzGet4GrZEBEBGl4vVtqg/MPfW8dCRf9qDRNYSkhBsIzlhQe9JWiohe9oB9LW5meibwOgRmww==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.21.0.tgz", + "integrity": "sha512-k6MZxLbZphGN5uRri9J/krQQBjUrqNcScPh985XXEFXbSCRvOPKVtjjLdVjGVHXXPOQgKrIZHxIdRNbHS+wVuA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.20.2.tgz", - "integrity": "sha512-bW41aWLYgBv/coJUIT85mkN3kk1VBKsM8tlwB5S/s446Mgc7r8t5TX7kA8kCR2UbwDedOK51i/85/x/rM0ZXbg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.21.0.tgz", + "integrity": "sha512-FiW5nnmyHvaGdorqLClw3PM6keXexAMiwbwJ9xzQr4LcNefLG3ln82NafRPgJO/z0dETAOKjds5aSmEFMiITHQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.20.2.tgz", - "integrity": "sha512-wBMf3J1L5ogvU8p8ifHkknDXWn1zdZ2epkqpt2MkUaZynE3G77rrFU9frcO+Pu1FQJQ5xCDTKcYUUcJCDD00rg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.21.0.tgz", + "integrity": "sha512-+JXavbbliaLmah5QNgc/TDW/+r0ALa+rGhg5Y7+pF6GpNnzO0L+nlUaDNE8QbiJfz54F9BkwFUnJJeRJAuzTFw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-common": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.20.2.tgz", - "integrity": "sha512-w+VMzOkIq2XDGg6Ybzr74RlBZvJQnuIdKpVusQSXCXknvxwAwbO457LmoavhZWl06Lcsk9YDx1X2k0zb+iJQmw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.21.0.tgz", + "integrity": "sha512-Iw+Yj5hOmo/iixHS94vEAQ3zi5GPpJywhfxn1el/zWo4AvPIte/+1h9Ywgw/+3M7YBj4jgAkScxjxQCxzLBsjA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2" + "@algolia/client-common": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.20.2.tgz", - "integrity": "sha512-wpjnbvbi3A13b0DvijE45DRYDvwcP5Ttz7RTMkPWTkF1s6AHuo6O2UcwGyaogMAGa1QOOzFYfp5u4YQwMOQx5g==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.21.0.tgz", + "integrity": "sha512-Z00SRLlIFj3SjYVfsd9Yd3kB3dUwQFAkQG18NunWP7cix2ezXpJqA+xAoEf9vc4QZHdxU3Gm8gHAtRiM2iVaTQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2" + "@algolia/client-common": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.20.2.tgz", - "integrity": "sha512-YuSSdtgUt1dFBTNYUb+2TA5j0Hd0eDXE0bVISjUvTCqmoaGsGLwW+rKI7p1eLQ1r7RESwBAvUwcY1qP2Wl3Lyw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.21.0.tgz", + "integrity": "sha512-WqU0VumUILrIeVYCTGZlyyZoC/tbvhiyPxfGRRO1cSjxN558bnJLlR2BvS0SJ5b75dRNK7HDvtXo2QoP9eLfiA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.20.2" + "@algolia/client-common": "5.21.0" }, "engines": { "node": ">= 14.0.0" @@ -461,6 +474,99 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", + "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.1.tgz", + "integrity": "sha512-u/kozRnsPO/x8QtKYJOqoGtC4kH6yg1lfYkB9Au0WhYB0FNLpyFusttQtvhlwjtG3rOwiRz4D8DnnXa8iEpIKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "11.7.2", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.2" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/@astrojs/check": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.4.tgz", @@ -481,16 +587,16 @@ } }, "node_modules/@astrojs/compiler": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.10.3.tgz", - "integrity": "sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==", + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.10.4.tgz", + "integrity": "sha512-86B3QGagP99MvSNwuJGiYSBHnh8nLvm2Q1IFI15wIUJJsPeQTO3eb2uwBmrqRsXykeR/mBzH8XCgz5AAt1BJrQ==", "dev": true, "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.5.0.tgz", - "integrity": "sha512-CgB5ZaZO1PFG+rbjF3HnA7G6gIBjJ070xb7bUjeu5Gqqufma+t6fpuRWMXnK2iEO3zVyX7e/xplPlqtFKy/lvw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.6.0.tgz", + "integrity": "sha512-XgHIJDQaGlFnTr0sDp1PiJrtqsWzbHP2qkTU+JpQ8SnBewKP2IKOe/wqCkl0CyfyRXRu3TSWu4t/cpYMVfuBNA==", "dev": true, "license": "MIT" }, @@ -606,15 +712,15 @@ } }, "node_modules/@astrojs/react": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.2.0.tgz", - "integrity": "sha512-2OccnYFK+mLuy9GpJqPM3BQGvvemnXNeww+nBVYFuiH04L7YIdfg4Gq0LT7v/BraiuADV5uTl9VhTDL/ZQPAhw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.2.1.tgz", + "integrity": "sha512-g0P6zxG7RPHNcbmMB15dJJ83+ApBVFBcgnf6BnMz/PVXM150Pa1vYKeuTcWhERqLNgmpI2uXuch5MecIhrUlqQ==", "dev": true, "license": "MIT", "dependencies": { "@vitejs/plugin-react": "^4.3.4", "ultrahtml": "^1.5.3", - "vite": "^6.0.9" + "vite": "^6.2.0" }, "engines": { "node": "^18.17.1 || ^20.3.0 || >=22.0.0" @@ -637,22 +743,54 @@ "kleur": "^4.1.5" } }, + "node_modules/@astrojs/rss/node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@astrojs/rss/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/@astrojs/sitemap": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.2.1.tgz", - "integrity": "sha512-uxMfO8f7pALq0ADL6Lk68UV6dNYjJ2xGUzyjjVj60JLBs5a6smtlkBYv3tQ0DzoqwS7c9n4FUx5lgv0yPo/fgA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.3.0.tgz", + "integrity": "sha512-nYE4lKQtk+Kbrw/w0G0TTgT724co0jUsU4tPlHY9au5HmTBKbwiCLwO/15b1/y13aZ4Kr9ZbMeMHlXuwn0ty4Q==", "dev": true, "license": "MIT", "dependencies": { "sitemap": "^8.0.0", "stream-replace-string": "^2.0.0", - "zod": "^3.23.8" + "zod": "^3.24.2" } }, "node_modules/@astrojs/starlight": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.31.1.tgz", - "integrity": "sha512-VIVkHugwgtEqJPiRH8+ouP0UqUfdmpBO9C64R+6QaQ2qmADNkI/BA3/YAJHTBZYlMQQGEEuLJwD9qpaUovi52Q==", + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.32.3.tgz", + "integrity": "sha512-oss5RxvCpuO1FSQyTC0vti5FOjRY0fHiJbGLYbnRsBNVfTzRMKRYMTfNwiduZuVNXML7zhV6QLCFjYpHt0PKuw==", "dev": true, "license": "MIT", "dependencies": { @@ -670,6 +808,7 @@ "hastscript": "^9.0.0", "i18next": "^23.11.5", "js-yaml": "^4.1.0", + "klona": "^2.0.6", "mdast-util-directive": "^3.0.0", "mdast-util-to-markdown": "^2.1.0", "mdast-util-to-string": "^4.0.0", @@ -686,9 +825,9 @@ } }, "node_modules/@astrojs/starlight-docsearch": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@astrojs/starlight-docsearch/-/starlight-docsearch-0.5.0.tgz", - "integrity": "sha512-GaNAnyafW4pCBTPXjL5PLViZ9XRCb85uZgpUCChBXrNjtqEORQxiZ3bH6dsuuYHEaNtGHdR9mC4xFo1PzXdsTg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@astrojs/starlight-docsearch/-/starlight-docsearch-0.6.0.tgz", + "integrity": "sha512-jTW/6SVU98/birzDCrYLVEKrgzdRzLlevGIhG6EDRmieLCAUnsKUk0q856fOJ7RJcuVLTlzg80rkwAgRINpyZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -696,7 +835,7 @@ "@docsearch/js": "^3.6.0" }, "peerDependencies": { - "@astrojs/starlight": ">=0.30.0" + "@astrojs/starlight": ">=0.32.0" } }, "node_modules/@astrojs/starlight-tailwind": { @@ -1123,44 +1262,60 @@ "license": "Apache-2.0" }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", - "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { "mime": "^3.0.0" }, "engines": { - "node": ">=16.13" + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.0.2.tgz", + "integrity": "sha512-nyzYnlZjjV5xT3LizahG1Iu6mnrCaxglJ04rZLpDwlDVDZ7v46lNsfxhV3A/xtfgQuSHmLnc6SVI+KwBpc3Lwg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.14", + "workerd": "^1.20250124.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } } }, "node_modules/@cloudflare/vitest-pool-workers": { - "version": "0.6.14", - "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.6.14.tgz", - "integrity": "sha512-4e3T9iTLOUDwX0bwY+mOFhkZ4Zpps1/l9Q7pmb45sxXywv9phGncMF8hRyULf5l8eqvO8ZDN+2XkVCIEbFyxbw==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.2.tgz", + "integrity": "sha512-j2Gk6//skSawZl10hqbJJtuQyTwMwgx5mWncn8WODHKyOfWRISr9I7v8XVYqju3qD77nUAjtaIRuMNJrz9PtNA==", "dev": true, "license": "MIT", "dependencies": { "birpc": "0.2.14", "cjs-module-lexer": "^1.2.3", "devalue": "^4.3.0", - "esbuild": "0.17.19", - "miniflare": "3.20250204.0", - "semver": "^7.5.1", - "wrangler": "3.108.1", + "esbuild": "0.24.2", + "miniflare": "4.20250317.1", + "semver": "^7.7.1", + "wrangler": "4.2.0", "zod": "^3.22.3" }, "peerDependencies": { - "@vitest/runner": "2.0.x - 2.1.x", - "@vitest/snapshot": "2.0.x - 2.1.x", - "vitest": "2.0.x - 2.1.x" + "@vitest/runner": "2.0.x - 3.0.x", + "@vitest/snapshot": "2.0.x - 3.0.x", + "vitest": "2.0.x - 3.0.x" } }, "node_modules/@cloudflare/vitest-pool-workers/node_modules/miniflare": { - "version": "3.20250204.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250204.0.tgz", - "integrity": "sha512-f7tezEkOvVRVHIVul2EbTyKvWJCXpTDRAOxTxtD4N92+YI8PC2P8AvO4Z30vlN61r5Pje33fTBG8G1fEwSZIqQ==", + "version": "4.20250317.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250317.1.tgz", + "integrity": "sha512-FFReRGco05fkgAB/x9VmxTuQ3KXW4JcpKkpuMZJn+JoZ2dd8hY5J1W9HBI4tSwfQ+hVyd9X7oXbn4BimoD3i8A==", "dev": true, "license": "MIT", "dependencies": { @@ -1170,8 +1325,8 @@ "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", - "undici": "^5.28.4", - "workerd": "1.20250204.0", + "undici": "^5.28.5", + "workerd": "1.20250317.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" @@ -1180,13 +1335,13 @@ "miniflare": "bootstrap.js" }, "engines": { - "node": ">=16.13" + "node": ">=18.0.0" } }, "node_modules/@cloudflare/vitest-pool-workers/node_modules/undici": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", - "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, "license": "MIT", "dependencies": { @@ -1197,35 +1352,34 @@ } }, "node_modules/@cloudflare/vitest-pool-workers/node_modules/wrangler": { - "version": "3.108.1", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.108.1.tgz", - "integrity": "sha512-SuiMv/ys52Cu7r6CVRXJT/GvneXHoB0ef5nGBWghSWyHxUSIm4KavGO6F/hTphn+WmSpHYQt3xNl5hdxk6rJlA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.2.0.tgz", + "integrity": "sha512-wY+jq6tsaBVrxCesJ9NF9R63T+96W6Ht9xEkAdw9JnkstUWM6lGywMOeupYP8Ji8x4roNa98XrT0Gw8qu+QRNQ==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.3.4", - "@esbuild-plugins/node-globals-polyfill": "0.2.3", - "@esbuild-plugins/node-modules-polyfill": "0.2.2", + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.0.2", "blake3-wasm": "2.1.5", - "esbuild": "0.17.19", - "miniflare": "3.20250204.0", + "esbuild": "0.24.2", + "miniflare": "4.20250317.1", "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.1", - "workerd": "1.20250204.0" + "unenv": "2.0.0-rc.14", + "workerd": "1.20250317.0" }, "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=16.17.0" + "node": ">=18.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20250204.0" + "@cloudflare/workers-types": "^4.20250317.0" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -1244,9 +1398,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250204.0.tgz", - "integrity": "sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250317.0.tgz", + "integrity": "sha512-ZnpF+MP/azHJ7sUOW9Ut/5pqeijsEOSmRUpONDXImv/DiHgtCd2BA/He11srp8nG2XeWav3jk+Ob84NKrrXXHg==", "cpu": [ "x64" ], @@ -1261,9 +1415,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250204.0.tgz", - "integrity": "sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250317.0.tgz", + "integrity": "sha512-ypn2/SIK7LAouYx5oB0NNhzb3h+ZdXtDh94VCcsNV81xAVdDXKp6xvTnqY8CWjGfuKWJocbRZVZvU+Lquhuujg==", "cpu": [ "arm64" ], @@ -1278,9 +1432,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250204.0.tgz", - "integrity": "sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250317.0.tgz", + "integrity": "sha512-KfAHN9VHF2NxGjDjj7udLAatZ72GIg4xmN9r2AZ6N1/hsGDlbn+NbVkSJtWjpXBcCoWYxQqtAdpHyO4eb7nIvQ==", "cpu": [ "x64" ], @@ -1295,9 +1449,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250204.0.tgz", - "integrity": "sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250317.0.tgz", + "integrity": "sha512-o7a3poQ4vzw553xGudUWm8yGsfdRWSGxqDEdYyuzT5k3z4qjsYMGsZgW9Yw8x3f1SSpPgYpdLlc8IKg9n7eukA==", "cpu": [ "arm64" ], @@ -1312,9 +1466,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250204.0.tgz", - "integrity": "sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250317.0.tgz", + "integrity": "sha512-tfDSioKY5OKP0nZ7Mkc6bLcwY2fIrROwoq2WjekQ62x91KRbKCJwjkOSvyFJYbshDATK90GutYoblqV80e34jw==", "cpu": [ "x64" ], @@ -1329,9 +1483,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20250204.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250204.0.tgz", - "integrity": "sha512-mWoQbYaP+nYztx9I7q9sgaiNlT54Cypszz0RfzMxYnT5W3NXDuwGcjGB+5B5H5VB8tEC2dYnBRpa70lX94ueaQ==", + "version": "4.20250319.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250319.0.tgz", + "integrity": "sha512-TTg1WZZuWJomzU3g1TvqE/WWI3zpTu1K+RsJvk6zxEgjhONN2PzqUUqKVYOQBk4/p7d+v7h6wz2gX3Ke7Arm7g==", "dev": true, "license": "MIT OR Apache-2.0" }, @@ -1556,34 +1710,27 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild-plugins/node-globals-polyfill": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", - "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "esbuild": "*" - } - }, - "node_modules/@esbuild-plugins/node-modules-polyfill": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", - "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "escape-string-regexp": "^4.0.0", - "rollup-plugin-node-polyfills": "^0.2.1" - }, - "peerDependencies": { - "esbuild": "*" + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", - "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", "cpu": [ "arm" ], @@ -1594,13 +1741,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", - "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", "cpu": [ "arm64" ], @@ -1611,13 +1758,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", - "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", "cpu": [ "x64" ], @@ -1628,13 +1775,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -1645,13 +1792,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", - "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", "cpu": [ "x64" ], @@ -1662,13 +1809,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", - "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", "cpu": [ "arm64" ], @@ -1679,13 +1826,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", - "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", "cpu": [ "x64" ], @@ -1696,13 +1843,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", - "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", "cpu": [ "arm" ], @@ -1713,13 +1860,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", - "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", "cpu": [ "arm64" ], @@ -1730,13 +1877,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", - "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", "cpu": [ "ia32" ], @@ -1747,13 +1894,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", - "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", "cpu": [ "loong64" ], @@ -1764,13 +1911,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", - "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", "cpu": [ "mips64el" ], @@ -1781,13 +1928,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", - "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", "cpu": [ "ppc64" ], @@ -1798,13 +1945,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", - "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", "cpu": [ "riscv64" ], @@ -1815,13 +1962,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", - "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", "cpu": [ "s390x" ], @@ -1832,13 +1979,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -1849,13 +1996,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", "cpu": [ "arm64" ], @@ -1870,9 +2017,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", - "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", "cpu": [ "x64" ], @@ -1883,13 +2030,13 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], @@ -1904,9 +2051,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", - "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", "cpu": [ "x64" ], @@ -1917,13 +2064,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", - "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", "cpu": [ "x64" ], @@ -1934,13 +2081,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", - "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", "cpu": [ "arm64" ], @@ -1951,13 +2098,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", - "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", "cpu": [ "ia32" ], @@ -1968,13 +2115,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", - "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", "cpu": [ "x64" ], @@ -1985,7 +2132,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2031,13 +2178,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -2069,10 +2216,20 @@ "node": "*" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2083,9 +2240,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2144,9 +2301,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.20.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", - "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "dev": true, "license": "MIT", "engines": { @@ -2154,9 +2311,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2164,13 +2321,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.12.0", "levn": "^0.4.1" }, "engines": { @@ -2246,6 +2403,64 @@ "node": ">=14" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.5.tgz", + "integrity": "sha512-BX3jKxo39Ba05pflcQmqPPwc0qdNsdNi/eweAFtoIdrJWNen2sVEWMEac3i6jU55Qfx+lOcdMNKYn2CtWmlnOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.9", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "dev": true, + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -2299,9 +2514,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2863,6 +3078,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true, + "license": "MIT" + }, "node_modules/@marsidev/react-turnstile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@marsidev/react-turnstile/-/react-turnstile-1.1.0.tgz", @@ -3131,6 +3353,13 @@ "@octokit/openapi-types": "^23.0.1" } }, + "node_modules/@octokit/webhooks-types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", + "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", + "dev": true, + "license": "MIT" + }, "node_modules/@oslojs/encoding": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", @@ -3547,67 +3776,67 @@ ] }, "node_modules/@shikijs/core": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.29.1.tgz", - "integrity": "sha512-Mo1gGGkuOYjDu5H8YwzmOuly9vNr8KDVkqj9xiKhhhFS8jisAtDSEWB9hzqRHLVQgFdA310e8XRJcW4tYhRB2A==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.29.2.tgz", + "integrity": "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.29.1", - "@shikijs/engine-oniguruma": "1.29.1", - "@shikijs/types": "1.29.1", + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.29.1.tgz", - "integrity": "sha512-Hpi8k9x77rCQ7F/7zxIOUruNkNidMyBnP5qAGbLFqg4kRrg1HZhkB8btib5EXbQWTtLb5gBHOdBwshk20njD7Q==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.29.2.tgz", + "integrity": "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.29.1", + "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.1.tgz", - "integrity": "sha512-gSt2WhLNgEeLstcweQOSp+C+MhOpTsgdNXRqr3zP6M+BUBZ8Md9OU2BYwUYsALBxHza7hwaIWtFHjQ/aOOychw==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", + "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.29.1", + "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1" } }, "node_modules/@shikijs/langs": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-1.29.1.tgz", - "integrity": "sha512-iERn4HlyuT044/FgrvLOaZgKVKf3PozjKjyV/RZ5GnlyYEAZFcgwHGkYboeBv2IybQG1KVS/e7VGgiAU4JY2Gw==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-1.29.2.tgz", + "integrity": "sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.29.1" + "@shikijs/types": "1.29.2" } }, "node_modules/@shikijs/themes": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-1.29.1.tgz", - "integrity": "sha512-lb11zf72Vc9uxkl+aec2oW1HVTHJ2LtgZgumb4Rr6By3y/96VmlU44bkxEb8WBWH3RUtbqAJEN0jljD9cF7H7g==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-1.29.2.tgz", + "integrity": "sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.29.1" + "@shikijs/types": "1.29.2" } }, "node_modules/@shikijs/types": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.1.tgz", - "integrity": "sha512-aBqAuhYRp5vSir3Pc9+QPu9WESBOjUo03ao0IHLC4TyTioSsp/SkbAZSrIH4ghYYC1T1KTEpRSBa83bas4RnPA==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", + "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", "dev": true, "license": "MIT", "dependencies": { @@ -3616,9 +3845,9 @@ } }, "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz", - "integrity": "sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", "dev": true, "license": "MIT" }, @@ -4201,9 +4430,9 @@ } }, "node_modules/@types/node": { - "version": "22.13.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.2.tgz", - "integrity": "sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "dev": true, "license": "MIT", "dependencies": { @@ -4244,9 +4473,9 @@ } }, "node_modules/@types/react-dom": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz", - "integrity": "sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz", + "integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4290,117 +4519,31 @@ "license": "MIT" }, "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz", - "integrity": "sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/type-utils": "8.24.1", - "@typescript-eslint/utils": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz", - "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz", - "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz", - "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz", - "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", + "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/type-utils": "8.27.0", + "@typescript-eslint/utils": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "engines": { @@ -4411,18 +4554,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz", - "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==", + "node_modules/@typescript-eslint/parser": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", + "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4430,17 +4578,21 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz", - "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", + "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1" + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4451,14 +4603,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz", - "integrity": "sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", + "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.24.1", - "@typescript-eslint/utils": "8.24.1", + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/utils": "8.27.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -4471,13 +4623,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz", - "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", + "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", "dev": true, "license": "MIT", "engines": { @@ -4489,14 +4641,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz", - "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", + "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4512,20 +4664,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz", - "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", + "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/typescript-estree": "8.24.1" + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4536,17 +4688,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz", - "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", + "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4892,34 +5044,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.2.tgz", - "integrity": "sha512-8evxG++iWyWnhng3g5RP+kwn6j+2vKLfew8pVoekn87FcfsDm92zJXKwSrU6pl+m5eAbGFhFF/gCYEQiRdbPlA==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.21.0.tgz", + "integrity": "sha512-hexLq2lSO1K5SW9j21Ubc+q9Ptx7dyRTY7se19U8lhIlVMLCNXWCyQ6C22p9ez8ccX0v7QVmwkl2l1CnuGoO2Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-abtesting": "5.20.2", - "@algolia/client-analytics": "5.20.2", - "@algolia/client-common": "5.20.2", - "@algolia/client-insights": "5.20.2", - "@algolia/client-personalization": "5.20.2", - "@algolia/client-query-suggestions": "5.20.2", - "@algolia/client-search": "5.20.2", - "@algolia/ingestion": "1.20.2", - "@algolia/monitoring": "1.20.2", - "@algolia/recommend": "5.20.2", - "@algolia/requester-browser-xhr": "5.20.2", - "@algolia/requester-fetch": "5.20.2", - "@algolia/requester-node-http": "5.20.2" + "@algolia/client-abtesting": "5.21.0", + "@algolia/client-analytics": "5.21.0", + "@algolia/client-common": "5.21.0", + "@algolia/client-insights": "5.21.0", + "@algolia/client-personalization": "5.21.0", + "@algolia/client-query-suggestions": "5.21.0", + "@algolia/client-search": "5.21.0", + "@algolia/ingestion": "1.21.0", + "@algolia/monitoring": "1.21.0", + "@algolia/recommend": "5.21.0", + "@algolia/requester-browser-xhr": "5.21.0", + "@algolia/requester-fetch": "5.21.0", + "@algolia/requester-node-http": "5.21.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.24.1.tgz", - "integrity": "sha512-knYRACqLH9UpeR+WRUrBzBFR2ulGuOjI2b525k4PNeqZxeFMHJE7YcL7s6Jh12Qza0rtHqZdgHMfeuaaAkf4wA==", + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.24.2.tgz", + "integrity": "sha512-vBw/INZDfyh/THbVeDy8On8lZqd2qiUAHde5N4N1ygL4SoeLqLGJ4GHneHrDAYsjikRwTTtodEP0fiXl5MxHFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5263,15 +5415,15 @@ } }, "node_modules/astro": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.2.1.tgz", - "integrity": "sha512-OYR2kUo9EqX6OYZ1OmM14xP8mjFwgrk1FzIr+3K3tS0gCCKJsXtfboCUhX3lODZFIsmY/on7NPZd+2PURA0R2Q==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.4.1.tgz", + "integrity": "sha512-z9BiBz8pV7pZVn1evZv/9bJil3A9UZNyEjDFH3IjD87ioz95HHGLgbjRbbqF1EwSy8JOLKlMNyuQPqjrX8xqWw==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/compiler": "^2.10.3", - "@astrojs/internal-helpers": "0.5.0", - "@astrojs/markdown-remark": "6.1.0", + "@astrojs/compiler": "^2.10.4", + "@astrojs/internal-helpers": "0.6.0", + "@astrojs/markdown-remark": "6.2.0", "@astrojs/telemetry": "3.2.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", @@ -5292,39 +5444,39 @@ "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", - "esbuild": "^0.24.2", + "esbuild": "^0.25.0", "estree-walker": "^3.0.3", - "fast-glob": "^3.3.3", "flattie": "^1.1.1", "github-slugger": "^2.0.0", - "html-escaper": "^3.0.3", + "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "micromatch": "^4.0.8", "mrmime": "^2.0.0", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", - "p-queue": "^8.0.1", - "preferred-pm": "^4.0.0", + "p-queue": "^8.1.0", + "picomatch": "^4.0.2", + "preferred-pm": "^4.1.1", "prompts": "^2.4.2", "rehype": "^13.0.2", - "semver": "^7.6.3", - "shiki": "^1.29.1", + "semver": "^7.7.1", + "shiki": "^1.29.2", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.12", "tsconfck": "^3.1.4", "ultrahtml": "^1.5.3", "unist-util-visit": "^5.0.0", "unstorage": "^1.14.4", "vfile": "^6.0.3", - "vite": "^6.0.11", + "vite": "^6.2.0", "vitefu": "^1.0.5", - "which-pm": "^3.0.0", + "which-pm": "^3.0.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", - "yocto-spinner": "^0.1.2", + "yocto-spinner": "^0.2.0", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1", "zod-to-ts": "^1.2.0" @@ -5443,12 +5595,13 @@ } }, "node_modules/astro/node_modules/@astrojs/markdown-remark": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.1.0.tgz", - "integrity": "sha512-emZNNSTPGgPc3V399Cazpp5+snogjaF04ocOSQn9vy3Kw/eIC4vTQjXOrWDEoSEy+AwPDZX9bQ4wd3bxhpmGgQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.2.0.tgz", + "integrity": "sha512-LUDjgd9p1yG0qTFSocaj3GOLmZs8Hsw/pNtvqzvNY58Acebxvb/46vDO/e/wxYgsKgIfWS+p+ZI5SfOjoVrbCg==", "dev": true, "license": "MIT", "dependencies": { + "@astrojs/internal-helpers": "0.6.0", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", @@ -5462,7 +5615,7 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", - "shiki": "^1.29.1", + "shiki": "^1.29.2", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", @@ -5471,27 +5624,10 @@ "vfile": "^6.0.3" } }, - "node_modules/astro/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/astro/node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], @@ -5506,9 +5642,9 @@ } }, "node_modules/astro/node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], @@ -5523,9 +5659,9 @@ } }, "node_modules/astro/node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], @@ -5540,9 +5676,9 @@ } }, "node_modules/astro/node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], @@ -5557,9 +5693,9 @@ } }, "node_modules/astro/node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], @@ -5574,9 +5710,9 @@ } }, "node_modules/astro/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], @@ -5591,9 +5727,9 @@ } }, "node_modules/astro/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], @@ -5608,9 +5744,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], @@ -5625,9 +5761,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -5642,9 +5778,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], @@ -5659,9 +5795,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], @@ -5676,9 +5812,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], @@ -5693,9 +5829,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], @@ -5710,9 +5846,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], @@ -5727,9 +5863,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], @@ -5744,9 +5880,9 @@ } }, "node_modules/astro/node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -5761,9 +5897,9 @@ } }, "node_modules/astro/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], @@ -5777,27 +5913,10 @@ "node": ">=18" } }, - "node_modules/astro/node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/astro/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], @@ -5812,9 +5931,9 @@ } }, "node_modules/astro/node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], @@ -5829,9 +5948,9 @@ } }, "node_modules/astro/node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], @@ -5846,9 +5965,9 @@ } }, "node_modules/astro/node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], @@ -5863,9 +5982,9 @@ } }, "node_modules/astro/node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], @@ -5912,9 +6031,9 @@ "license": "MIT" }, "node_modules/astro/node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5925,31 +6044,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/astro/node_modules/glob-parent": { @@ -6448,6 +6567,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -6711,6 +6837,19 @@ "node": ">=8" } }, + "node_modules/cidr-tools": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/cidr-tools/-/cidr-tools-11.0.3.tgz", + "integrity": "sha512-7p0rp7B2P+nZfBkJlrQzUMDyUHeYK2h/XCJY80VUl1v5oxwLxQjZMy39BXVOXugwAX67l0oJ/QQ6OhANgUtUbw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-bigint": "^8.2.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cjs-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", @@ -8490,59 +8629,113 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/esast-util-from-js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", - "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild/node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "acorn": "^8.0.0", - "esast-util-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/esbuild": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", - "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "node_modules/esbuild/node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.17.19", - "@esbuild/android-arm64": "0.17.19", - "@esbuild/android-x64": "0.17.19", - "@esbuild/darwin-arm64": "0.17.19", - "@esbuild/darwin-x64": "0.17.19", - "@esbuild/freebsd-arm64": "0.17.19", - "@esbuild/freebsd-x64": "0.17.19", - "@esbuild/linux-arm": "0.17.19", - "@esbuild/linux-arm64": "0.17.19", - "@esbuild/linux-ia32": "0.17.19", - "@esbuild/linux-loong64": "0.17.19", - "@esbuild/linux-mips64el": "0.17.19", - "@esbuild/linux-ppc64": "0.17.19", - "@esbuild/linux-riscv64": "0.17.19", - "@esbuild/linux-s390x": "0.17.19", - "@esbuild/linux-x64": "0.17.19", - "@esbuild/netbsd-x64": "0.17.19", - "@esbuild/openbsd-x64": "0.17.19", - "@esbuild/sunos-x64": "0.17.19", - "@esbuild/win32-arm64": "0.17.19", - "@esbuild/win32-ia32": "0.17.19", - "@esbuild/win32-x64": "0.17.19" + "node": ">=18" } }, "node_modules/escalade": { @@ -8569,22 +8762,23 @@ } }, "node_modules/eslint": { - "version": "9.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.0.tgz", - "integrity": "sha512-aL4F8167Hg4IvsW89ejnpTwx+B/UQRzJPGgbIOl+4XqffWsahVVsLEWoZvnrVuwpWmnRd7XeXmQI1zlKcFDteA==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.11.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.20.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.22.0", + "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -8592,7 +8786,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -8805,9 +8999,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8834,19 +9028,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", - "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9123,6 +9304,13 @@ "@expressive-code/plugin-text-markers": "^0.40.1" } }, + "node_modules/exsolve": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", + "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==", + "dev": true, + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -9220,23 +9408,19 @@ "license": "BSD-3-Clause" }, "node_modules/fast-xml-parser": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz", - "integrity": "sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.0.9.tgz", + "integrity": "sha512-2mBwCiuW3ycKQQ6SOesSB8WeF+fIGb6I/GG5vU5/XEptwFFhp9PE8b9O7fbs2dpq9fXn4ULR3UsfydNUCntf5A==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.0.5" }, "bin": { "fxparser": "src/cli/cli.js" @@ -9262,6 +9446,21 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -9306,9 +9505,9 @@ } }, "node_modules/find-up-simple": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", - "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", "dev": true, "license": "MIT", "engines": { @@ -10158,9 +10357,9 @@ } }, "node_modules/hast-util-select": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.3.tgz", - "integrity": "sha512-OVRQlQ1XuuLP8aFVLYmC2atrfWHS5UD3shonxpnyrjcCkwtvmt/+N6kYJdcY4mkMJhxp4kj2EFIxQ9kvkkt/eQ==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", "dev": true, "license": "MIT", "dependencies": { @@ -10175,7 +10374,7 @@ "hast-util-to-string": "^3.0.0", "hast-util-whitespace": "^3.0.0", "nth-check": "^2.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" @@ -10185,6 +10384,17 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select/node_modules/property-information": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz", + "integrity": "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/hast-util-to-estree": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.1.tgz", @@ -10266,6 +10476,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", + "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", @@ -10505,9 +10742,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10559,17 +10796,10 @@ "@babel/runtime": "^7.1.2" } }, - "node_modules/instantsearch.css": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/instantsearch.css/-/instantsearch.css-8.5.1.tgz", - "integrity": "sha512-lu4gWSa2crIA1OAuFwtrNJy4d8oRvKmkY5gv8Dbf3tuedQMm6cf7K+1kXJKRAHLm4pZos9RXIH10m57UfDKbyg==", - "dev": true, - "license": "MIT" - }, "node_modules/instantsearch.js": { - "version": "4.77.3", - "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.77.3.tgz", - "integrity": "sha512-nlNDHpRa15lXw6HEzCyEtickhRZOzmWXiLuhlfRazC/LjqbmmfE2ZMfGUp8YMeLIrP9i4HuK02/+esd2MsnrKA==", + "version": "4.78.0", + "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.78.0.tgz", + "integrity": "sha512-MLQl9F7/7Id1VlU4VTtKR88yADWGVk+CBoNkKi3wZjfxhblnLIXdZHfb6v/l6XHShTp+10JDny17Nl+jpTkxkw==", "dev": true, "license": "MIT", "dependencies": { @@ -10578,7 +10808,7 @@ "@types/google.maps": "^3.55.12", "@types/hogan.js": "^3.0.0", "@types/qs": "^6.5.3", - "algoliasearch-helper": "3.24.1", + "algoliasearch-helper": "3.24.2", "hogan.js": "^3.0.2", "htm": "^3.0.0", "instantsearch-ui-components": "0.11.1", @@ -10615,6 +10845,16 @@ "node": ">=12" } }, + "node_modules/ip-bigint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/ip-bigint/-/ip-bigint-8.2.1.tgz", + "integrity": "sha512-ji9uf6Sfp+v2TgsDEWKRRRDEJHbWOF+2Oaqqd0keUtNRHymJQ/HaL1svJScL+aqMWlEhH34OaJC1Ai2e+3YUzA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=18" + } + }, "node_modules/iron-webcrypto": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", @@ -11363,6 +11603,16 @@ "node": ">=6" } }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/kolorist": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", @@ -11764,13 +12014,6 @@ "node": ">=6" } }, - "node_modules/load-yaml-file/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/local-pkg": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", @@ -12326,45 +12569,32 @@ } }, "node_modules/mermaid": { - "version": "11.4.1", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.4.1.tgz", - "integrity": "sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A==", + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.5.0.tgz", + "integrity": "sha512-IYhyukID3zzDj1EihKiN1lp+PXNImoJ3Iyz73qeDAgnus4BNGsJV1n471P4PyeGxPVONerZxignwGxGTSwZnlg==", "dev": true, "license": "MIT", "dependencies": { - "@braintree/sanitize-url": "^7.0.1", - "@iconify/utils": "^2.1.32", + "@braintree/sanitize-url": "^7.0.4", + "@iconify/utils": "^2.1.33", "@mermaid-js/parser": "^0.3.0", "@types/d3": "^7.4.3", - "cytoscape": "^3.29.2", + "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.11", - "dayjs": "^1.11.10", - "dompurify": "^3.2.1", + "dayjs": "^1.11.13", + "dompurify": "^3.2.4", "katex": "^0.16.9", "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "marked": "^13.0.2", + "marked": "^15.0.7", "roughjs": "^4.6.6", - "stylis": "^4.3.1", + "stylis": "^4.3.6", "ts-dedent": "^2.2.0", - "uuid": "^9.0.1" - } - }, - "node_modules/mermaid/node_modules/marked": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", - "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" + "uuid": "^11.1.0" } }, "node_modules/micromark": { @@ -13205,9 +13435,9 @@ } }, "node_modules/miniflare": { - "version": "3.20250204.1", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250204.1.tgz", - "integrity": "sha512-B4PQi/Ai4d0ZTWahQwsFe5WAfr1j8ISMYxJZTc56g2/btgbX+Go099LmojAZY/fMRLhIYsglcStW8SeW3f/afA==", + "version": "4.20250317.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250317.0.tgz", + "integrity": "sha512-fCyFTa3G41Vyo24QUZD5xgdm+6RMKT6VC3vk9Usmr+Pwf/15HcH1AVLPVgzmJaJosWVb8r4S0HQ9a/+bmmZx0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -13217,8 +13447,8 @@ "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", - "undici": "^5.28.4", - "workerd": "1.20250204.0", + "undici": "^5.28.5", + "workerd": "1.20250317.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" @@ -13227,7 +13457,7 @@ "miniflare": "bootstrap.js" }, "engines": { - "node": ">=16.13" + "node": ">=18.0.0" } }, "node_modules/miniflare/node_modules/undici": { @@ -13672,6 +13902,13 @@ "regex-recursion": "^5.1.1" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -13770,9 +14007,9 @@ } }, "node_modules/p-queue": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", - "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", + "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", "dev": true, "license": "MIT", "dependencies": { @@ -13853,6 +14090,13 @@ "node": ">=6" } }, + "node_modules/parse-duration": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-2.1.3.tgz", + "integrity": "sha512-MtbharL7Bets65qDBXuDOHHWyY1BxTJZmJ/xGmS90iEbKE0gZ6yZpZtCda7O79GeOi/f0NwBaplIuReExIoVsw==", + "dev": true, + "license": "MIT" + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -14212,9 +14456,9 @@ } }, "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "dev": true, "funding": [ { @@ -14408,15 +14652,15 @@ } }, "node_modules/preferred-pm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-4.0.0.tgz", - "integrity": "sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-4.1.1.tgz", + "integrity": "sha512-rU+ZAv1Ur9jAUZtGPebQVQPzdGhNzaEiQ7VL9+cjsAWPHFYOccNXPNiev1CCDSOg/2j7UujM7ojNhpkuILEVNQ==", "dev": true, "license": "MIT", "dependencies": { "find-up-simple": "^1.0.0", "find-yarn-workspace-root2": "1.2.16", - "which-pm": "^3.0.0" + "which-pm": "^3.0.1" }, "engines": { "node": ">=18.12" @@ -14433,9 +14677,9 @@ } }, "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -14652,6 +14896,41 @@ "react": "*" } }, + "node_modules/react-instantsearch": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/react-instantsearch/-/react-instantsearch-7.15.4.tgz", + "integrity": "sha512-gr2oxOXPmMirFgTVYRo//Lr0wXMOYdcOiybJxRzA/jAN/5Hom+COt/wCgBmH8yH1RNIqjN+y6k86wXzH08HAww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "instantsearch-ui-components": "0.11.1", + "instantsearch.js": "4.78.0", + "react-instantsearch-core": "7.15.4" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6", + "react": ">= 16.8.0 < 20", + "react-dom": ">= 16.8.0 < 20" + } + }, + "node_modules/react-instantsearch-core": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/react-instantsearch-core/-/react-instantsearch-core-7.15.4.tgz", + "integrity": "sha512-s2PPiAhQbamWoxSttxyfg4TKVteiEVkpmyYE7ef/6yoAO3QXVLZH5XsrqxBBLpH8XcpheuGYD3HvI/dhyUKYxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "algoliasearch-helper": "3.24.2", + "instantsearch.js": "4.78.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6", + "react": ">= 16.8.0 < 20" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -14660,13 +14939,14 @@ "license": "MIT" }, "node_modules/react-markdown": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.3.tgz", - "integrity": "sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", @@ -14954,6 +15234,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", @@ -15002,6 +15297,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-remark": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-10.0.0.tgz", + "integrity": "sha512-+aDXY/icqMFOafJQomVjxe3BAP7aR3lIsQ3GV6VIwpbCD2nvNFOXjGvotMe5p0Ny+Gt6L13DhEf/FjOOpTuUbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "hast-util-to-mdast": "^10.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-stringify": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", @@ -15188,9 +15501,9 @@ } }, "node_modules/remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "dev": true, "license": "MIT", "dependencies": { @@ -15475,63 +15788,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", - "dev": true, - "license": "MIT", - "dependencies": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" - } - }, - "node_modules/rollup-plugin-inject/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/rollup-plugin-inject/node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", - "dev": true, - "license": "MIT", - "dependencies": { - "rollup-plugin-inject": "^3.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true, - "license": "MIT" - }, "node_modules/roughjs": { "version": "4.6.6", "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", @@ -15680,9 +15936,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -15805,18 +16061,18 @@ } }, "node_modules/shiki": { - "version": "1.29.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.29.1.tgz", - "integrity": "sha512-TghWKV9pJTd/N+IgAIVJtr0qZkB7FfFCUrrEJc0aRmZupo3D1OCVRknQWVRVA7AX/M0Ld7QfoAruPzr3CnUJuw==", + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.29.2.tgz", + "integrity": "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "1.29.1", - "@shikijs/engine-javascript": "1.29.1", - "@shikijs/engine-oniguruma": "1.29.1", - "@shikijs/langs": "1.29.1", - "@shikijs/themes": "1.29.1", - "@shikijs/types": "1.29.1", + "@shikijs/core": "1.29.2", + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/langs": "1.29.2", + "@shikijs/themes": "1.29.2", + "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } @@ -16021,14 +16277,6 @@ "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true, - "license": "MIT" - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -16040,6 +16288,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -16059,12 +16314,13 @@ } }, "node_modules/starlight-image-zoom": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/starlight-image-zoom/-/starlight-image-zoom-0.10.1.tgz", - "integrity": "sha512-1uEwijShhFFcYA++lDmFV32WmZkpp/VMvD4+PC5h+7InnyPGMiT+mSVJzbddNEit44OxM5kxbO6/OqcBtjKpOA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/starlight-image-zoom/-/starlight-image-zoom-0.11.1.tgz", + "integrity": "sha512-TmnAyS+MWWV6h1fjuezrMFA36REd+7QzcjDFFFyC4ws5FDMoHsjQn0MlHM0cUaHEKfQ9y1PpL9LijCvRFuGbuw==", "dev": true, "license": "MIT", "dependencies": { + "mdast-util-mdx-jsx": "^3.1.3", "rehype-raw": "^7.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" @@ -16073,13 +16329,13 @@ "node": ">=18" }, "peerDependencies": { - "@astrojs/starlight": ">=0.30.0" + "@astrojs/starlight": ">=0.32.0" } }, "node_modules/starlight-links-validator": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/starlight-links-validator/-/starlight-links-validator-0.14.2.tgz", - "integrity": "sha512-OsPngajtW4kB/oxiW3Kt1Fd+rY3opdIWbD/n5pGQMzil03QujT6rAeHEBR4tXRdjQW4HnFZYIy/ANhBu4kUNfQ==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/starlight-links-validator/-/starlight-links-validator-0.14.3.tgz", + "integrity": "sha512-2CvQs0ZdIVExrEQ1bn0r2aFx4n+VSOb6vDWK+gTNb5N1c+nXJ7VjUbEsQhj+9Lb7XgY6Nxqz9JXUM9364hJ3ZA==", "dev": true, "license": "MIT", "dependencies": { @@ -16089,6 +16345,7 @@ "hast-util-has-property": "^3.0.0", "is-absolute-url": "^4.0.1", "kleur": "^4.1.5", + "mdast-util-mdx-jsx": "^3.1.3", "mdast-util-to-string": "^4.0.0", "picomatch": "^4.0.2", "unist-util-visit": "^5.0.0" @@ -16415,10 +16672,16 @@ } }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz", + "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "license": "MIT" }, "node_modules/style-to-object": { @@ -16432,9 +16695,9 @@ } }, "node_modules/stylis": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.5.tgz", - "integrity": "sha512-K7npNOKGRYuhAFFzkzMGfxFDpN6gDwf8hcMiE+uveTVbBgm93HrNP3ZDUpKqzZ4pG7TP6fmb+EMAQPjq9FqqvA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", "dev": true, "license": "MIT" }, @@ -16550,6 +16813,13 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", @@ -16782,6 +17052,23 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -16846,6 +17133,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -16871,13 +17169,13 @@ } }, "node_modules/ts-blank-space": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ts-blank-space/-/ts-blank-space-0.6.0.tgz", - "integrity": "sha512-/idfg2ezyTe9YjfLPoFEjFnBCM0rnB1yp64q7+ujaz4UwBSasA28hiOW3FoRLXLpNMtwE3JlnuLZdOUoZNxhrQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/ts-blank-space/-/ts-blank-space-0.6.1.tgz", + "integrity": "sha512-LcM3W5HEyzTaXUeQITV8ploUOGe+zuuoFYsCfPscFLhx3bZn2sSfHMKxsULVG/zA7an9UhReiHv4Kk/6QzlpXQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "typescript": "5.1.6 - 5.7.x" + "typescript": "5.1.6 - 5.8.x" }, "engines": { "node": ">=18.0.0" @@ -16929,13 +17227,13 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", - "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.23.0", + "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -16948,27 +17246,10 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], @@ -16983,9 +17264,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], @@ -17000,9 +17281,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], @@ -17017,9 +17298,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], @@ -17034,9 +17315,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], @@ -17051,9 +17332,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], @@ -17068,9 +17349,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], @@ -17085,9 +17366,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], @@ -17102,9 +17383,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -17119,9 +17400,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], @@ -17136,9 +17417,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], @@ -17153,9 +17434,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], @@ -17170,9 +17451,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], @@ -17187,9 +17468,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], @@ -17204,9 +17485,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], @@ -17221,9 +17502,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -17238,9 +17519,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], @@ -17255,9 +17536,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], @@ -17272,9 +17553,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], @@ -17289,9 +17570,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], @@ -17306,9 +17587,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], @@ -17323,9 +17604,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], @@ -17340,9 +17621,9 @@ } }, "node_modules/tsx/node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -17353,30 +17634,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/tunnel": { @@ -17501,9 +17783,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -17525,40 +17807,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.24.1.tgz", - "integrity": "sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.24.1", - "@typescript-eslint/parser": "8.24.1", - "@typescript-eslint/utils": "8.24.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.1.tgz", - "integrity": "sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz", + "integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/typescript-estree": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", - "debug": "^4.3.4" + "@typescript-eslint/eslint-plugin": "8.27.0", + "@typescript-eslint/parser": "8.27.0", + "@typescript-eslint/utils": "8.27.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -17569,7 +17826,7 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/ufo": { @@ -17630,19 +17887,33 @@ "license": "MIT" }, "node_modules/unenv": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.1.tgz", - "integrity": "sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg==", + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.14.tgz", + "integrity": "sha512-od496pShMen7nOy5VmVJCnq8rptd45vh6Nx/r2iPbrba6pa6p+tS2ywuIHRZ/OBvSbQZB0kWvpO9XBNVFXHD3Q==", "dev": true, "license": "MIT", "dependencies": { "defu": "^6.1.4", - "mlly": "^1.7.4", - "ohash": "^1.1.4", - "pathe": "^1.1.2", + "exsolve": "^1.0.1", + "ohash": "^2.0.10", + "pathe": "^2.0.3", "ufo": "^1.5.4" } }, + "node_modules/unenv/node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unenv/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -17857,6 +18128,16 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17875,9 +18156,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -17885,7 +18166,7 @@ ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/validate.io-array": { @@ -17972,14 +18253,14 @@ } }, "node_modules/vite": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", - "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz", + "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.5.1", + "esbuild": "^0.25.0", + "postcss": "^8.5.3", "rollup": "^4.30.1" }, "bin": { @@ -18086,27 +18367,10 @@ } } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], @@ -18121,9 +18385,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], @@ -18138,9 +18402,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], @@ -18155,9 +18419,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], @@ -18172,9 +18436,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], @@ -18189,9 +18453,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], @@ -18206,9 +18470,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], @@ -18223,9 +18487,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], @@ -18240,9 +18504,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -18257,9 +18521,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], @@ -18274,9 +18538,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], @@ -18291,9 +18555,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], @@ -18308,9 +18572,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], @@ -18325,9 +18589,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], @@ -18342,9 +18606,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], @@ -18359,9 +18623,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -18376,9 +18640,9 @@ } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], @@ -18392,27 +18656,10 @@ "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], @@ -18427,9 +18674,9 @@ } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], @@ -18444,9 +18691,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], @@ -18461,9 +18708,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], @@ -18478,9 +18725,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], @@ -18495,9 +18742,9 @@ } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -18508,31 +18755,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/vitefu": { @@ -19043,9 +19290,9 @@ } }, "node_modules/which-pm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-3.0.0.tgz", - "integrity": "sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-3.0.1.tgz", + "integrity": "sha512-v2JrMq0waAI4ju1xU5x3blsxBBMgdgZve580iYMN5frDaLGjbA24fok7wKCsya8KLVO19Ju4XDc5+zTZCJkQfg==", "dev": true, "license": "MIT", "dependencies": { @@ -19137,9 +19384,9 @@ } }, "node_modules/workerd": { - "version": "1.20250204.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250204.0.tgz", - "integrity": "sha512-zcKufjVFsQMiD3/acg1Ix00HIMCkXCrDxQXYRDn/1AIz3QQGkmbVDwcUk1Ki2jBUoXmBCMsJdycRucgMVEypWg==", + "version": "1.20250317.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250317.0.tgz", + "integrity": "sha512-m+aqA4RS/jsIaml0KuTi96UBlkx1vC0mcLClGKPFNPiMStK75hVQxUhupXEMI4knHtb/vgNQyPFMKAJtxW5c6w==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -19150,43 +19397,42 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20250204.0", - "@cloudflare/workerd-darwin-arm64": "1.20250204.0", - "@cloudflare/workerd-linux-64": "1.20250204.0", - "@cloudflare/workerd-linux-arm64": "1.20250204.0", - "@cloudflare/workerd-windows-64": "1.20250204.0" + "@cloudflare/workerd-darwin-64": "1.20250317.0", + "@cloudflare/workerd-darwin-arm64": "1.20250317.0", + "@cloudflare/workerd-linux-64": "1.20250317.0", + "@cloudflare/workerd-linux-arm64": "1.20250317.0", + "@cloudflare/workerd-windows-64": "1.20250317.0" } }, "node_modules/wrangler": { - "version": "3.109.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.109.0.tgz", - "integrity": "sha512-hh/04/2+e8lUHdJhMJTiT7Ea1kt+0b+WVM2u3RKwRBCQ3SaN6jw6h0EX3DJtC1C+wrrzTJYDcsp1tWrcGDMaGA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.1.0.tgz", + "integrity": "sha512-HcQZ2YappySGipEDEdbjMq01g3v+mv+xZYZSzwPTmRsoTfnbL5yteObshcK1JX9jdx7Qw23Ywd/4BPa1JyKIUQ==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.3.4", - "@esbuild-plugins/node-globals-polyfill": "0.2.3", - "@esbuild-plugins/node-modules-polyfill": "0.2.2", + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.0.2", "blake3-wasm": "2.1.5", - "esbuild": "0.17.19", - "miniflare": "3.20250204.1", + "esbuild": "0.24.2", + "miniflare": "4.20250317.0", "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.1", - "workerd": "1.20250204.0" + "unenv": "2.0.0-rc.14", + "workerd": "1.20250317.0" }, "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=16.17.0" + "node": ">=18.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20250204.0" + "@cloudflare/workers-types": "^4.20250317.0" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -19591,9 +19837,9 @@ } }, "node_modules/yocto-spinner": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.1.2.tgz", - "integrity": "sha512-VfmLIh/ZSZOJnVRQZc/dvpPP90lWL4G0bmxQMP0+U/2vKBA8GSpcBuWv17y7F+CZItRuO97HN1wdbb4p10uhOg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.1.tgz", + "integrity": "sha512-lHHxjh0bXaLgdJy3cNnVb/F9myx3CkhrvSOEVTkaUgNMXnYFa2xYPVhtGnqhh3jErY2gParBOHallCbc7NrlZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -19642,9 +19888,9 @@ } }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index d94bd1218d5998..4090e780163635 100644 --- a/package.json +++ b/package.json @@ -27,88 +27,101 @@ "devDependencies": { "@actions/core": "1.11.1", "@actions/github": "6.0.0", + "@apidevtools/swagger-parser": "10.1.1", "@astrojs/check": "0.9.4", - "@astrojs/react": "4.2.0", + "@astrojs/react": "4.2.1", "@astrojs/rss": "4.0.11", - "@astrojs/sitemap": "3.2.1", - "@astrojs/starlight": "0.31.1", - "@astrojs/starlight-docsearch": "0.5.0", + "@astrojs/sitemap": "3.3.0", + "@astrojs/starlight": "0.32.3", + "@astrojs/starlight-docsearch": "0.6.0", "@astrojs/starlight-tailwind": "3.0.0", "@astrojs/tailwind": "5.1.5", - "@cloudflare/vitest-pool-workers": "0.6.14", - "@cloudflare/workers-types": "4.20250204.0", + "@cloudflare/vitest-pool-workers": "0.8.2", + "@cloudflare/workers-types": "4.20250319.0", "@codingheads/sticky-header": "1.0.2", "@expressive-code/plugin-collapsible-sections": "0.40.2", + "@floating-ui/react": "0.27.5", "@iarna/toml": "2.2.5", "@marsidev/react-turnstile": "1.1.0", + "@octokit/webhooks-types": "7.6.1", "@stoplight/json-schema-tree": "4.0.0", "@types/hast": "3.0.4", "@types/he": "1.2.3", - "@types/node": "22.13.2", + "@types/node": "22.13.10", "@types/react": "19.0.7", - "@types/react-dom": "19.0.3", - "@typescript-eslint/parser": "8.25.0", - "algoliasearch": "5.20.2", - "astro": "5.2.1", + "@types/react-dom": "19.0.4", + "@typescript-eslint/parser": "8.27.0", + "algoliasearch": "5.21.0", + "astro": "5.4.1", "astro-breadcrumbs": "3.3.1", "astro-icon": "1.1.5", "astro-live-code": "0.0.5", + "cidr-tools": "11.0.3", "codeowners-utils": "1.0.2", "date-fns": "4.1.0", "dedent": "1.5.3", "dompurify": "3.2.4", "dot-prop": "9.0.0", - "eslint": "9.20.0", + "eslint": "9.22.0", "eslint-plugin-astro": "1.3.1", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.4", "fast-glob": "3.3.3", + "fast-xml-parser": "5.0.9", "github-slugger": "2.0.0", "globals": "16.0.0", + "hast-util-select": "6.0.4", "hastscript": "9.0.1", "he": "1.2.0", - "instantsearch.css": "8.5.1", - "instantsearch.js": "4.77.3", "jsonc-parser": "3.3.1", "lz-string": "1.5.0", "marked": "15.0.7", + "mdast-util-from-markdown": "2.0.2", + "mdast-util-mdx": "3.0.0", "mdast-util-mdx-expression": "2.0.1", - "mermaid": "11.4.1", + "mermaid": "11.5.0", + "micromark-extension-mdxjs": "3.0.0", "node-html-parser": "7.0.1", - "prettier": "3.5.2", + "openapi-types": "12.1.3", + "parse-duration": "2.1.3", + "prettier": "3.5.3", "prettier-plugin-astro": "0.14.1", "prettier-plugin-tailwindcss": "0.6.9", "pretty-bytes": "6.1.1", "react": "19.0.0", "react-dom": "19.0.0", "react-icons": "5.5.0", - "react-markdown": "9.0.3", + "react-instantsearch": "7.15.4", + "react-markdown": "10.1.0", "redirects-in-workers": "0.0.5", "rehype": "13.0.2", "rehype-autolink-headings": "7.1.0", "rehype-external-links": "3.0.0", "rehype-parse": "9.0.1", + "rehype-remark": "10.0.0", "rehype-stringify": "10.0.1", "rehype-title-figure": "0.1.2", "remark": "15.0.1", + "remark-gfm": "4.0.1", + "remark-stringify": "11.0.0", "sharp": "0.33.5", "solarflare-theme": "0.0.4", - "starlight-image-zoom": "0.10.1", - "starlight-links-validator": "0.14.2", + "starlight-image-zoom": "0.11.1", + "starlight-links-validator": "0.14.3", "starlight-package-managers": "0.10.0", "strip-markdown": "6.0.0", "svgo": "3.3.2", "tailwindcss": "3.4.17", "tippy.js": "6.3.7", - "ts-blank-space": "0.6.0", - "tsx": "4.19.2", - "typescript": "5.7.3", - "typescript-eslint": "8.24.1", + "ts-blank-space": "0.6.1", + "tsx": "4.19.3", + "typescript": "5.8.2", + "typescript-eslint": "8.27.0", "unified": "11.0.5", "unist-util-visit": "5.0.0", "vite-tsconfig-paths": "5.1.4", "vitest": "2.1.6", - "wrangler": "3.109.0" + "wrangler": "4.1.0" }, "engines": { "node": ">=22" diff --git a/public/.assetsignore b/public/.assetsignore index 3f34b99be43241..bb2205126f9a8e 100644 --- a/public/.assetsignore +++ b/public/.assetsignore @@ -1 +1 @@ -_redirects +/__redirects diff --git a/public/_redirects b/public/__redirects similarity index 95% rename from public/_redirects rename to public/__redirects index 07b10d48849d63..930efe496eadb2 100644 --- a/public/_redirects +++ b/public/__redirects @@ -1,4 +1,5 @@ # homepage +/api /api/ 301 /docs/ /products/ 301 /zero-trust/ /products/?product-group=Cloudflare+One 301 /dashboard-landing/ / 301 @@ -98,6 +99,18 @@ # agents /agents/build/prompts/ /workers/get-started/prompting/ 301 +/agents/examples/browse-the-web/ /agents/api-reference/browse-the-web/ 301 +/agents/examples/manage-and-sync-state/ /agents/api-reference/store-and-sync-state/ 301 +/agents/examples/rag/ /agents/api-reference/rag/ 301 +/agents/examples/run-workflows/ /agents/api-reference/run-workflows/ 301 +/agents/examples/schedule-tasks/ /agents/api-reference/schedule-tasks/ 301 +/agents/examples/using-ai-models/ /agents/api-reference/using-ai-models/ 301 +/agents/examples/websockets/ /agents/api-reference/websockets/ 301 +/agents/examples/sdk/ /agents/api-reference/agents-api/ 301 +/agents/examples/build-mcp-server/ /agents/api-reference/build-mcp-server/ 301 +/agents/api-reference/build-mcp-server/ /agents/guides/build-mcp-server/ 301 +/agents/api-reference/sdk/ /agents/api-reference/ 301 +/agents/guides/build-mcp-server/ /agents/guides/remote-mcp-server/ 301 # ai /ai/ /use-cases/ai/ 301 @@ -179,6 +192,11 @@ /bots/reference/verified-bot-categories/ /bots/concepts/bot/verified-bots/categories/ 301 /bots/reference/verified-bot-policy/ /bots/concepts/bot/verified-bots/policy/ 301 +#browser-rendering +/browser-rendering/get-started/browser-rendering-with-do/ /browser-rendering/workers-binding-api/browser-rendering-with-do/ 301 +/browser-rendering/get-started/reuse-sessions/ /browser-rendering/workers-binding-api/reuse-sessions/ 301 +/browser-rendering/get-started/screenshots/ /browser-rendering/workers-binding-api/screenshots/ 301 + # byoip /byoip/about/dynamic-advertisement/ /byoip/concepts/dynamic-advertisement/ 301 /byoip/best-practices/dynamic-advertisement/ /byoip/concepts/dynamic-advertisement/best-practices/ 301 @@ -247,6 +265,7 @@ # china network /support/about-cloudflare/enterprise-documentation/understanding-and-configuring-an-icp-number/ /china-network/concepts/icp/ 301 +/china-network/concepts/china-express/ /china-network/concepts/global-acceleration/ 301 # cloudflare for platforms /cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/regional-services-for-saas/ /data-localization/regional-services/get-started/ 301 @@ -299,6 +318,7 @@ /d1/platform/environments/ /d1/configuration/environments/ 301 /d1/platform/metrics-analytics/ /d1/observability/metrics-analytics/ 301 /d1/platform/migrations/ /d1/reference/migrations/ 301 +/d1/platform/changelog/ /d1/platform/release-notes/ 301 /d1/reference/client-api/ /d1/worker-api/ 301 /d1/reference/environments/ /d1/configuration/environments/ 301 /d1/reference/metrics-analytics/ /d1/observability/metrics-analytics/ 301 @@ -387,6 +407,7 @@ /support/dns/troubleshooting/my-dns-doesnt-work/ /dns/troubleshooting/dns-issues/ 301 /support/dns/troubleshooting/why-was-my-domain-deleted-from-cloudflare/ /dns/zone-setups/troubleshooting/domain-deleted/ 301 +# Durable Objects /durable-objects/examples/durable-object-example/ /durable-objects/examples/durable-object-in-memory-state/ 301 /durable-objects/api/hibernatable-websockets-api/ /durable-objects/best-practices/websockets/ 301 /durable-objects/api/alarms-in-durable-objects/ /durable-objects/api/alarms/ 301 @@ -410,9 +431,19 @@ /durable-objects/reference/graphql-analytics/ /durable-objects/observability/graphql-analytics/ 301 /durable-objects/reference/websockets/ /durable-objects/best-practices/websockets/ 301 /durable-objects/api/transactional-storage-api/ /durable-objects/api/storage-api/ 301 -/durable-objects/platform/changelog/ /durable-objects/changelog/ 301 +/durable-objects/platform/changelog/ /durable-objects/release-notes/ 301 +/durable-objects/changelog/ /durable-objects/release-notes/ 301 /durable-objects/glossary/ /durable-objects/reference/glossary/ 301 /durable-objects/get-started/walkthrough/ /durable-objects/get-started/tutorial/ 301 +/durable-objects/get-started/video-series/intro/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/app-frontend/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/deploy-app/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/durable-objects/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/index/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/make-answer-webrtc-calls/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/real-time-messaging/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/serverless-websocket/ /durable-objects/video-tutorials/ 301 +/durable-objects/get-started/video-series/ /durable-objects/video-tutorials/ 301 # email-routing /email-routing/enable-email-routing/ /email-routing/get-started/enable-email-routing/ 301 @@ -426,6 +457,14 @@ /email-security/email-configuration/retract-settings/gmail-retraction/ /email-security/deployment/api/setup/gsuite-bcc-setup/add-retraction/ 301 /cloudflare-one/insights/email-monitoring/email-security-logs/ /cloudflare-one/insights/email-monitoring/enable-logs/ 301 /cloudflare-one/insights/email-monitoring/phishing-report/ /cloudflare-one/insights/email-monitoring/download-disposition-report/ 301 +/cloudflare-one/insights/email-monitoring/download-disposition-report/ /cloudflare-one/email-security/email-monitoring/download-disposition-report/ 301 +/cloudflare-one/insights/email-monitoring/ /cloudflare-one/email-security/email-monitoring/ 301 +/cloudflare-one/insights/email-monitoring/search-email/ /cloudflare-one/email-security/email-monitoring/search-email/ 301 +/cloudflare-one/insights/email-monitoring/phish-submissions/ /cloudflare-one/email-security/phish-submissions/ 301 +/cloudflare-one/insights/email-monitoring/enable-logs/ /cloudflare-one/insights/logs/enable-logs/ 301 +/cloudflare-one/email-security/directories/manage-ms-directories/ /cloudflare-one/email-security/directories/manage-integrated-directories/ 301 +/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory/ /cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory/ 301 +/cloudflare-one/email-security/directories/manage-ms-directories/manage-users-directory/ /cloudflare-one/email-security/directories/manage-integrated-directories/manage-users-directory/ 301 # firewall @@ -751,7 +790,7 @@ /learning-paths/secure-o365-email/ /learning-paths/secure-o365-email/concepts/ 301 /learning-paths/workers/ /learning-paths/workers/concepts/ 301 /learning-paths/zero-trust-web-access/ /learning-paths/zero-trust-web-access/concepts/ 301 - +/learning-paths/application-security/default-traffic-security/security-level/ /learning-paths/application-security/default-traffic-security/browser-integrity/ 301 # more redirects in the /dynamic/ section @@ -991,6 +1030,7 @@ # radar /fundamentals/radar/ /radar/ 301 /fundamentals/radar/glossary/ /radar/glossary/ 301 +/radar/changelog/ /radar/release-notes/ 301 # railgun /railgun/user-guide/increase-logging/ /railgun/user-guide/troubleshooting/increase-logging/ 301 @@ -1024,6 +1064,8 @@ /rules/url-forwarding/single-redirects/examples/ /rules/url-forwarding/examples/ 301 /rules/url-forwarding/dynamic-redirects/parameters/ /rules/url-forwarding/single-redirects/settings/ 301 /rules/transform/manage/ /rules/transform/ 301 +/rules/page-rules/how-to/rewrite-host-headers/ /rules/origin-rules/examples/change-uri-path-and-host-header/ 301 +/rules/page-rules/how-to/override-url-or-ip-address/ /rules/origin-rules/features/ 301 # ruleset engine /ruleset-engine/rules-language/fields/standard-fields/ /ruleset-engine/rules-language/fields/reference/ 301 @@ -1196,6 +1238,7 @@ /support/troubleshooting/general-troubleshooting/contacting-cloudflare-support/ /support/contacting-cloudflare-support/ 301 /support/troubleshooting/performance/http2-and-enhanced-http2-prioritization-options-may-affect-content-loading-on-iossafari-devices/ /speed/optimization/protocol/troubleshooting/enhanced-http2-prioritization-ios-safari/ 301 /support/troubleshooting/performance/ /speed/optimization/ 301 +/support/troubleshooting/planned-maintenance/disruptive-maintenance-windows/ /support/troubleshooting/disruptive-maintenance/ 301 /support/page-rules/ /rules/page-rules/ 301 /support/page-rules/configuring-url-forwarding-or-redirects-with-page-rules/ /rules/page-rules/how-to/url-forwarding/ 301 /support/page-rules/how-do-i-include-or-exclude-a-specific-url-from-cloudflares-page-rules/ /rules/page-rules/reference/wildcard-matching/ 301 @@ -1275,8 +1318,9 @@ /r2/examples/boto3/ /r2/examples/aws/boto3/ 301 /r2/buckets/data-location/ /r2/reference/data-location/ 301 /r2/reference/audit-logs/ /r2/platform/audit-logs/ 301 -/r2/reference/changelog/ /r2/platform/changelog/ 301 -/r2/reference/changelog/index.xml /r2/platform/changelog/index.xml 301 +/r2/reference/changelog/ /r2/platform/release-notes/ 301 +/r2/reference/changelog/index.xml /r2/platform/release-notes/index.xml 301 +/r2/platform/changelog/ /r2/platform/release-notes 301 /r2/reference/limits/ /r2/platform/limits/ 301 /r2/reference/metrics-analytics/ /r2/platform/metrics-analytics/ 301 /r2/examples/mastodon/ /r2/tutorials/mastodon/ 301 @@ -1353,6 +1397,7 @@ /waf/custom-rules/manage-dashboard/ /waf/custom-rules/create-dashboard/ 301 /waf/security-analytics/ /waf/analytics/security-analytics/ 301 /waf/custom-rules/use-cases/require-valid-hmac-token/ /waf/custom-rules/use-cases/configure-token-authentication/ 301 +/waf/custom-rules/use-cases/block-ip-reputation/ /waf/custom-rules/use-cases/block-attack-score/ 301 /waf/tools/scrape-shield/server-side-excludes/ /waf/tools/scrape-shield/ 301 /waf/rate-limiting-rules/create-account-dashboard/ /waf/account/rate-limiting-rulesets/create-dashboard/ 301 /waf/managed-rules/deploy-account-dashboard/ /waf/account/managed-rulesets/deploy-dashboard/ 301 @@ -1626,9 +1671,14 @@ /workers/observability/baselime-integration/ /workers/observability/integrations/baselime-integration/ 301 /workers-ai/tutorials/image-generator-flux/ /workers-ai/tutorials/image-generation-playground/ 301 +# workflows + +/workflows/reference/storage-options/ /workers/platform/storage-options/ 301 + # workers KV /kv/platform/environments/ /kv/reference/environments/ 301 /kv/platform/kv-commands/ /kv/reference/kv-commands/ 301 +/kv/platform/changelog/ /kv/platform/release-notes/ 301 /kv/learning/ /kv/reference/ 301 /kv/learning/how-kv-works/ /kv/concepts/how-kv-works/ 301 /kv/learning/kv-bindings/ /kv/concepts/kv-bindings/ 301 @@ -1662,7 +1712,8 @@ /hyperdrive/learning/query-caching/ /hyperdrive/configuration/query-caching/ 301 /hyperdrive/learning/troubleshooting/ /hyperdrive/reference/troubleshooting/ 301 /hyperdrive/platform/supported-databases/ /hyperdrive/reference/supported-databases/ 301 -/hyperdrive/changelog/ /hyperdrive/platform/changelog/ 301 +/hyperdrive/changelog/ /hyperdrive/platform/release-notes/ 301 +/hyperdrive/platform/changelog/ /hyperdrive/platform/release-notes/ 301 /hyperdrive/learning/ /hyperdrive/configuration/ 301 /hyperdrive/reference/metrics/ /hyperdrive/observability/metrics/ 301 /hyperdrive/reference/troubleshooting/ /hyperdrive/observability/troubleshooting/ 301 @@ -1696,11 +1747,12 @@ /cloudflare-one/api-terraform/gateway-api-examples/dns-policy/ /cloudflare-one/policies/gateway/dns-policies/common-policies/ 301 /cloudflare-one/api-terraform/gateway-api-examples/network-policy/ /cloudflare-one/policies/gateway/network-policies/common-policies/ 301 /cloudflare-one/api-terraform/gateway-api-examples/http-policy/ /cloudflare-one/policies/gateway/http-policies/common-policies/ 301 +/cloudflare-one/applications/casb/troubleshooting/ /cloudflare-one/applications/casb/troubleshooting/troubleshoot-integrations/ 301 /cloudflare-one/applications/configure-apps/self-hosted-apps/ /cloudflare-one/applications/configure-apps/self-hosted-public-app/ 301 /cloudflare-one/applications/non-http/arbitrary-tcp/ /cloudflare-one/applications/non-http/cloudflared-authentication/arbitrary-tcp/ 301 /cloudflare-one/connections/connect-apps/configuration/ /cloudflare-one/connections/connect-networks/configure-tunnels/ 301 /cloudflare-one/connections/connect-apps/install-and-setup/setup/ /cloudflare-one/connections/connect-networks/get-started/ 301 -/cloudflare-one/connections/connect-apps/run-tunnel/deploy-cloudflared-replicas/ /cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/ 301 +/cloudflare-one/connections/connect-apps/run-tunnel/deploy-cloudflared-replicas/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/ 301 /cloudflare-one/connections/connect-apps/create-tunnel/ /cloudflare-one/connections/connect-networks/get-started/ 301 /cloudflare-one/connections/connect-apps/configuration/remote-management/ /cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/ 301 /cloudflare-one/connections/connect-apps/run-tunnel/ /cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/ 301 @@ -1719,8 +1771,8 @@ /cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-commands/ /cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-useful-commands/ 301 /cloudflare-one/connections/connect-apps/configuration/private-networks/ /cloudflare-one/connections/connect-networks/private-net/ 301 /cloudflare-one/connections/connect-apps/routing-to-tunnel/kubernetes/ /cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/kubernetes/ 301 -/cloudflare-one/connections/connect-apps/configuration/ports-and-ips/ /cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/ 301 -/cloudflare-one/connections/connect-apps/do-more-with-tunnels/ports-and-ips/ /cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/ 301 +/cloudflare-one/connections/connect-apps/configuration/ports-and-ips/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/ 301 +/cloudflare-one/connections/connect-apps/do-more-with-tunnels/ports-and-ips/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/ 301 /cloudflare-one/connections/connect-apps/run-tunnel/trycloudflare/ /cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/ 301 /cloudflare-one/connections/connect-apps/trycloudflare/ /cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/ 301 /cloudflare-one/connections/connect-apps/tunnel-monitoring/ /cloudflare-one/connections/connect-networks/monitor-tunnels/ 301 @@ -1736,13 +1788,13 @@ /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-guide/local/local-management/arguments/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/ 301 /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-guide/local/run-tunnel/ /cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/ 301 /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-guide/local/tunnel-useful-commands/ /cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-useful-commands/ 301 -/cloudflare-one/connections/connect-networks/install-and-setup/deploy-cloudflared-replicas/ /cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/ 301 +/cloudflare-one/connections/connect-networks/install-and-setup/deploy-cloudflared-replicas/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/ 301 /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-permissions/ /cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions/ 301 /cloudflare-one/connections/connect-networks/install-and-setup/installation /cloudflare-one/connections/connect-networks/downloads/update-cloudflared/ 307 /cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-permissions/ /cloudflare-one/connections/connect-networks/configure-tunnels/ 301 -/cloudflare-one/connections/connect-networks/install-and-setup/ports-and-ips/ /cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/ 301 +/cloudflare-one/connections/connect-networks/install-and-setup/ports-and-ips/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/ 301 /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-useful-terms/ /cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/ 301 -/cloudflare-one/connections/connect-networks/do-more-with-tunnels/secure-server/ /cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/ 301 +/cloudflare-one/connections/connect-networks/do-more-with-tunnels/secure-server/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/ 301 /cloudflare-one/connections/connect-networks/do-more-with-tunnels/grafana/ /cloudflare-one/connections/connect-networks/monitor-tunnels/grafana/ 301 /cloudflare-one/connections/connect-networks/downloads/system-requirements/ /cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/ 301 /cloudflare-one/connections/connect-networks/private-net/connect-private-networks/ /cloudflare-one/connections/connect-networks/private-net/cloudflared/ 301 @@ -1761,6 +1813,14 @@ /cloudflare-one/connections/connect-devices/warp/user-side-certificates/install-cloudflare-cert/ /cloudflare-one/connections/connect-devices/warp/user-side-certificates/manual-deployment/ 301 /cloudflare-one/connections/connect-devices/warp/user-side-certificates/install-cert-with-warp/ /cloudflare-one/connections/connect-devices/warp/user-side-certificates/automated-deployment/ 301 /cloudflare-one/connections/connect-networks/locations/ /cloudflare-one/connections/connect-devices/agentless/dns/locations/ 301 +/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/ /cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/ 301 +/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/ /cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/ 301 +/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/ /cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/ 301 +/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/ /cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/ 301 +/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/ 301 +/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/ 301 +/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/ /cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/ 301 +/cloudflare-one/connections/connect-networks/deploy-tunnels/ /cloudflare-one/connections/connect-networks/get-started/ 301 /cloudflare-one/connections/connect-networks/monitor-tunnels/grafana/ /cloudflare-one/tutorials/grafana/ 301 /cloudflare-one/connections/connect-networks/use-cases/kubectl/ /cloudflare-one/tutorials/many-cfd-one-tunnel/ 301 /cloudflare-one/connections/connect-networks/use_cases/ssh/ /cloudflare-one/connections/connect-networks/use-cases/ssh/ 301 @@ -1853,7 +1913,9 @@ /cloudflare-one/tutorials/zsh-env-var/ /cloudflare-one/tutorials/cli/ 301 ### DYNAMIC REDIRECTS ### +/api-next/* /api/:splat 301 /changelog-next/* /changelog/:splat 301 +/browser-rendering/quick-actions-rest-api/* /browser-rendering/rest-api/:splat 301 /*/sitemap.xml /sitemap-index.xml 301 /access/configuring-identity-providers/* /cloudflare-one/identity/idp-integration/:splat 301 /api-security/* /api-shield/:splat 301 @@ -1885,8 +1947,9 @@ # Cloudflare One / Zero Trust /cloudflare-one/connections/connect-networks/install-and-setup/tunnel-guide/local/as-a-service/* /cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/:splat 301 -/cloudflare-one/connections/connect-apps/install-and-setup/deployment-guides/* /cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/:splat 301 -/cloudflare-one/connections/connect-networks/deployment-guides/* /cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/:splat 301 +/cloudflare-one/connections/connect-apps/install-and-setup/deployment-guides/* /cloudflare-one/connections/connect-networks/deployment-guides/:splat 301 +/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/* /cloudflare-one/connections/connect-networks/deployment-guides/:splat 301 +/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/* /cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/:splat 301 /cloudflare-one/analytics/logs/* /cloudflare-one/insights/logs/:splat 301 /cloudflare-one/applications/scan-apps/* /cloudflare-one/applications/casb/:splat 301 /cloudflare-one/connections/connect-apps/use_cases/* /cloudflare-one/connections/connect-networks/use-cases/:splat 301 @@ -1901,6 +1964,7 @@ /cloudflare-one/policies/filtering/http-policies/data-loss-prevention/* /cloudflare-one/policies/data-loss-prevention/ 301 /cloudflare-one/policies/data-loss-prevention/configuration-guides/* /cloudflare-one/policies/data-loss-prevention/dlp-policies/common-policies/ 301 /cloudflare-one/insights/dex/fleet-status/ /cloudflare-one/insights/dex/monitoring/ 301 +/cloudflare-one/identity/idp-integration/gsuite/ /cloudflare-one/identity/idp-integration/google-workspace/ 301 # Learning paths /learning-paths/modules/cybersafe/cybersafe-account-creation/* /learning-paths/cybersafe/account-creation/:splat 301 diff --git a/public/_headers b/public/_headers new file mode 100644 index 00000000000000..fbd8ac72f61fcf --- /dev/null +++ b/public/_headers @@ -0,0 +1,5 @@ +/* + Access-Control-Allow-Origin: * + +/_astro/* + Cache-Control: public, max-age=604800, immutable diff --git a/public/robots.txt b/public/robots.txt index 2614eb35265613..d791ced8021f86 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -5,5 +5,7 @@ Disallow: /plans/ Disallow: /constellation Disallow: /cdn-cgi/ Disallow: /google-tag-first-party-mode/ +Disallow: /security/ +Disallow: /email-security/ Sitemap: https://developers.cloudflare.com/sitemap-index.xml diff --git a/src/assets/images/agents/agent-workflow.svg b/src/assets/images/agents/agent-workflow.svg index 82ccd7f92120e1..9302ad7c4c2329 100644 --- a/src/assets/images/agents/agent-workflow.svg +++ b/src/assets/images/agents/agent-workflow.svg @@ -1,7363 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/assets/images/agents/co-pilot.svg b/src/assets/images/agents/co-pilot.svg index acc6077c12bbb0..dbebe9ae9b15fa 100644 --- a/src/assets/images/agents/co-pilot.svg +++ b/src/assets/images/agents/co-pilot.svg @@ -1,7356 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/assets/images/agents/human-in-the-loop.svg b/src/assets/images/agents/human-in-the-loop.svg index 96a8fe98234916..6d316d455986f5 100644 --- a/src/assets/images/agents/human-in-the-loop.svg +++ b/src/assets/images/agents/human-in-the-loop.svg @@ -1,7367 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/assets/images/agents/mcp-demo-oauth-flow.png b/src/assets/images/agents/mcp-demo-oauth-flow.png new file mode 100644 index 00000000000000..beb9181b8e8dac Binary files /dev/null and b/src/assets/images/agents/mcp-demo-oauth-flow.png differ diff --git a/src/assets/images/agents/mcp-inspector-authenticated.png b/src/assets/images/agents/mcp-inspector-authenticated.png new file mode 100644 index 00000000000000..7029fc27bc4280 Binary files /dev/null and b/src/assets/images/agents/mcp-inspector-authenticated.png differ diff --git a/src/assets/images/agents/mcp-inspector-enter-url.png b/src/assets/images/agents/mcp-inspector-enter-url.png new file mode 100644 index 00000000000000..ed3596f4045bab Binary files /dev/null and b/src/assets/images/agents/mcp-inspector-enter-url.png differ diff --git a/src/assets/images/agents/npm-i-agents.apng b/src/assets/images/agents/npm-i-agents.apng new file mode 100644 index 00000000000000..bd246619482fc5 Binary files /dev/null and b/src/assets/images/agents/npm-i-agents.apng differ diff --git a/src/assets/images/agents/workflow-automation.svg b/src/assets/images/agents/workflow-automation.svg index 0688a2485400c8..0ada7b15722c13 100644 --- a/src/assets/images/agents/workflow-automation.svg +++ b/src/assets/images/agents/workflow-automation.svg @@ -1,7348 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/assets/images/ai-gateway/Guardrails.png b/src/assets/images/ai-gateway/Guardrails.png new file mode 100644 index 00000000000000..002b4d1eeb6165 Binary files /dev/null and b/src/assets/images/ai-gateway/Guardrails.png differ diff --git a/src/assets/images/calls/deprecated-lifecycle-of-a-session.png b/src/assets/images/calls/deprecated-lifecycle-of-a-session.png deleted file mode 100644 index 3fe93c01202030..00000000000000 Binary files a/src/assets/images/calls/deprecated-lifecycle-of-a-session.png and /dev/null differ diff --git a/src/assets/images/calls/lifecycle-of-a-session.png b/src/assets/images/calls/lifecycle-of-a-session.png deleted file mode 100644 index 956154b595b939..00000000000000 Binary files a/src/assets/images/calls/lifecycle-of-a-session.png and /dev/null differ diff --git a/src/assets/images/calls/turn-charging.png b/src/assets/images/calls/turn-charging.png deleted file mode 100644 index 32b7e8f39337c2..00000000000000 Binary files a/src/assets/images/calls/turn-charging.png and /dev/null differ diff --git a/src/assets/images/changelog/access/oidc-claims.png b/src/assets/images/changelog/access/oidc-claims.png new file mode 100644 index 00000000000000..7d4c53fee2e02e Binary files /dev/null and b/src/assets/images/changelog/access/oidc-claims.png differ diff --git a/src/assets/images/changelog/access/saml-attribute-statements.png b/src/assets/images/changelog/access/saml-attribute-statements.png new file mode 100644 index 00000000000000..a7bb2b1f39d685 Binary files /dev/null and b/src/assets/images/changelog/access/saml-attribute-statements.png differ diff --git a/src/assets/images/changelog/access/transformation-box.png b/src/assets/images/changelog/access/transformation-box.png new file mode 100644 index 00000000000000..42c2a12721f086 Binary files /dev/null and b/src/assets/images/changelog/access/transformation-box.png differ diff --git a/src/assets/images/changelog/ai-gateway/guardrails-social-preview.png b/src/assets/images/changelog/ai-gateway/guardrails-social-preview.png new file mode 100644 index 00000000000000..3206baf0c772c9 Binary files /dev/null and b/src/assets/images/changelog/ai-gateway/guardrails-social-preview.png differ diff --git a/src/assets/images/changelog/dex/cloudflare-one-agent-health-monitoring.gif b/src/assets/images/changelog/dex/cloudflare-one-agent-health-monitoring.gif new file mode 100644 index 00000000000000..92657be0c62715 Binary files /dev/null and b/src/assets/images/changelog/dex/cloudflare-one-agent-health-monitoring.gif differ diff --git a/src/assets/images/changelog/hero.svg b/src/assets/images/changelog/hero.svg index d03758daeab2b2..6400db5132673b 100644 --- a/src/assets/images/changelog/hero.svg +++ b/src/assets/images/changelog/hero.svg @@ -1,111 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/images/changelog/logs/Oneclick.gif b/src/assets/images/changelog/logs/Oneclick.gif new file mode 100644 index 00000000000000..34f67e970759be Binary files /dev/null and b/src/assets/images/changelog/logs/Oneclick.gif differ diff --git a/src/assets/images/changelog/web-analytics/2025-02-26-rum-eu.png b/src/assets/images/changelog/web-analytics/2025-02-26-rum-eu.png new file mode 100644 index 00000000000000..3372afefa3247b Binary files /dev/null and b/src/assets/images/changelog/web-analytics/2025-02-26-rum-eu.png differ diff --git a/src/assets/images/changelog/workers/browse-rules-cve-2025-29927.png b/src/assets/images/changelog/workers/browse-rules-cve-2025-29927.png new file mode 100644 index 00000000000000..6d860a612331c9 Binary files /dev/null and b/src/assets/images/changelog/workers/browse-rules-cve-2025-29927.png differ diff --git a/src/assets/images/changelog/workers/builds-rerun.gif b/src/assets/images/changelog/workers/builds-rerun.gif new file mode 100644 index 00000000000000..4c2f2da01bfc44 Binary files /dev/null and b/src/assets/images/changelog/workers/builds-rerun.gif differ diff --git a/src/assets/images/changelog/workers/enable-rule-cve-2025-29927.png b/src/assets/images/changelog/workers/enable-rule-cve-2025-29927.png new file mode 100644 index 00000000000000..89bb23ddf63e58 Binary files /dev/null and b/src/assets/images/changelog/workers/enable-rule-cve-2025-29927.png differ diff --git a/src/assets/images/changelog/workers/high-res-CVE-2025-29927.gif b/src/assets/images/changelog/workers/high-res-CVE-2025-29927.gif new file mode 100644 index 00000000000000..9dff6fc1c0c0b3 Binary files /dev/null and b/src/assets/images/changelog/workers/high-res-CVE-2025-29927.gif differ diff --git a/src/assets/images/changelog/workers/managed-rules-edit-cve-2025-29927.png b/src/assets/images/changelog/workers/managed-rules-edit-cve-2025-29927.png new file mode 100644 index 00000000000000..0e06ecb3151d87 Binary files /dev/null and b/src/assets/images/changelog/workers/managed-rules-edit-cve-2025-29927.png differ diff --git a/src/assets/images/changelog/workers/waf-rule-cve-2025-29927.png b/src/assets/images/changelog/workers/waf-rule-cve-2025-29927.png new file mode 100644 index 00000000000000..aa0e39f49b3b45 Binary files /dev/null and b/src/assets/images/changelog/workers/waf-rule-cve-2025-29927.png differ diff --git a/src/assets/images/cloudflare-one/connections/get-unique-subdomain.png b/src/assets/images/cloudflare-one/connections/get-unique-subdomain.png deleted file mode 100644 index 7eed99349bfb81..00000000000000 Binary files a/src/assets/images/cloudflare-one/connections/get-unique-subdomain.png and /dev/null differ diff --git a/src/assets/images/cloudflare-one/identity/google/click-configure-consent.png b/src/assets/images/cloudflare-one/identity/google/click-configure-consent.png deleted file mode 100644 index e3f0ac1cbb006e..00000000000000 Binary files a/src/assets/images/cloudflare-one/identity/google/click-configure-consent.png and /dev/null differ diff --git a/src/assets/images/cloudflare-one/identity/google/configure-consent-screen.png b/src/assets/images/cloudflare-one/identity/google/configure-consent-screen.png new file mode 100644 index 00000000000000..583c95449e0b52 Binary files /dev/null and b/src/assets/images/cloudflare-one/identity/google/configure-consent-screen.png differ diff --git a/src/assets/images/cloudflare-one/identity/google/create-oauth-client.png b/src/assets/images/cloudflare-one/identity/google/create-oauth-client.png new file mode 100644 index 00000000000000..095687b7c0ed48 Binary files /dev/null and b/src/assets/images/cloudflare-one/identity/google/create-oauth-client.png differ diff --git a/src/assets/images/cloudflare-one/identity/google/create-oauth.png b/src/assets/images/cloudflare-one/identity/google/create-oauth.png deleted file mode 100644 index c6f481f1f32333..00000000000000 Binary files a/src/assets/images/cloudflare-one/identity/google/create-oauth.png and /dev/null differ diff --git a/src/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png b/src/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png index 6beb5456c4a81c..2d2fe2c1e0727c 100644 Binary files a/src/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png and b/src/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png differ diff --git a/src/assets/images/hyperdrive/configuration/hyperdrive-regional-pooling-query-latency-improvement.png b/src/assets/images/hyperdrive/configuration/hyperdrive-regional-pooling-query-latency-improvement.png new file mode 100644 index 00000000000000..45d6135a2e9806 Binary files /dev/null and b/src/assets/images/hyperdrive/configuration/hyperdrive-regional-pooling-query-latency-improvement.png differ diff --git a/src/assets/images/logs/logs-r2.png b/src/assets/images/logs/logs-r2.png new file mode 100644 index 00000000000000..4cbd8754c85e11 Binary files /dev/null and b/src/assets/images/logs/logs-r2.png differ diff --git a/src/assets/images/magic-transit/bgp-diagram.png b/src/assets/images/magic-transit/bgp-diagram.png deleted file mode 100644 index c0a507107ee69a..00000000000000 Binary files a/src/assets/images/magic-transit/bgp-diagram.png and /dev/null differ diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-1.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-1.svg new file mode 100644 index 00000000000000..2361294d281a82 --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-1.svg @@ -0,0 +1,7393 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-2.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-2.svg new file mode 100644 index 00000000000000..ba6fbbad355850 --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-2.svg @@ -0,0 +1,7421 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-3.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-3.svg new file mode 100644 index 00000000000000..78f9efc1b4597b --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-3.svg @@ -0,0 +1,7419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-4.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-4.svg new file mode 100644 index 00000000000000..8fd6093122227b --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-4.svg @@ -0,0 +1,7485 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-5.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-5.svg new file mode 100644 index 00000000000000..e51630e6b3342a --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-5.svg @@ -0,0 +1,7449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-6.svg b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-6.svg new file mode 100644 index 00000000000000..8420ee7dc8a270 --- /dev/null +++ b/src/assets/images/reference-architecture/programmable-platforms/programmable-platforms-6.svg @@ -0,0 +1,7409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/ssl/pqc-clientless-access.png b/src/assets/images/ssl/pqc-clientless-access.png new file mode 100644 index 00000000000000..4f311d2ed6973f Binary files /dev/null and b/src/assets/images/ssl/pqc-clientless-access.png differ diff --git a/src/assets/images/ssl/pqc-secure-web-gateway.png b/src/assets/images/ssl/pqc-secure-web-gateway.png new file mode 100644 index 00000000000000..dbcdcc8398e9b2 Binary files /dev/null and b/src/assets/images/ssl/pqc-secure-web-gateway.png differ diff --git a/src/assets/images/turnstile/challenge-outcomes.png b/src/assets/images/turnstile/challenge-outcomes.png new file mode 100644 index 00000000000000..0fa137a241ae0c Binary files /dev/null and b/src/assets/images/turnstile/challenge-outcomes.png differ diff --git a/src/assets/images/turnstile/solve-rates.png b/src/assets/images/turnstile/solve-rates.png new file mode 100644 index 00000000000000..531d1f3cdccd4b Binary files /dev/null and b/src/assets/images/turnstile/solve-rates.png differ diff --git a/src/assets/images/turnstile/token-validation.png b/src/assets/images/turnstile/token-validation.png new file mode 100644 index 00000000000000..ed9b51adf1d4d6 Binary files /dev/null and b/src/assets/images/turnstile/token-validation.png differ diff --git a/src/assets/images/turnstile/top-actions.png b/src/assets/images/turnstile/top-actions.png new file mode 100644 index 00000000000000..4d825ca1c47fb3 Binary files /dev/null and b/src/assets/images/turnstile/top-actions.png differ diff --git a/src/components/APIRequest.astro b/src/components/APIRequest.astro new file mode 100644 index 00000000000000..9747c428b49681 --- /dev/null +++ b/src/components/APIRequest.astro @@ -0,0 +1,155 @@ +--- +import { z } from "astro:schema"; +import { getProperty } from "dot-prop"; +import { getSchema } from "~/util/api.ts"; +import type { OpenAPIV3 } from "openapi-types"; +import CURL from "./CURL.astro"; +import Details from "./Details.astro"; + +type Props = z.input; + +const props = z + .object({ + path: z.string(), + method: z.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]), + parameters: z.record(z.string(), z.any()).optional(), + json: z.record(z.string(), z.any()).optional(), + form: z.record(z.string(), z.any()).optional(), + }) + .strict(); + +let { path, method, parameters, json, form } = props.parse(Astro.props); + +if (json && form) { + throw new Error(`[APIRequest] Cannot use both "json" and "form" properties.`); +} + +const schema = await getSchema(); + +const operation = getProperty( + schema, + `paths.${path}.${method.toLowerCase()}`, +) as unknown as + | OpenAPIV3.OperationObject<{ + "x-api-token-group"?: string[]; + }> + | undefined; + +if (!operation) { + throw new Error( + `[APIRequest] Operation ${method} ${path} not found in schema.`, + ); +} + +const url = new URL( + path.startsWith("/") ? path.slice(1) : path, + "https://api.cloudflare.com/client/v4/", +); +const headers: Record = {}; + +const providedParameters = Object.keys(parameters ?? {}); +const endpointParameters = (operation.parameters ?? + []) as OpenAPIV3.ParameterObject[]; + +const extraneousParameters = providedParameters.filter( + (parameter) => + !endpointParameters.some( + (endpointParam) => endpointParam.name === parameter, + ), +); + +if (extraneousParameters.length > 0) { + throw new Error( + `[APIRequest] Provided parameters ${extraneousParameters.join(", ")} not found in ${method} ${path} schema.`, + ); +} + +for (const parameter of endpointParameters) { + if (parameter.in === "path") { + const encoded = encodeURIComponent(`{${parameter.name}}`); + + if (parameters?.[parameter.name]) { + url.pathname = url.pathname.replace(encoded, parameters[parameter.name]); + } + } +} + +const segments = url.pathname.split("/").filter(Boolean); + +for (const segment of segments) { + const decoded = decodeURIComponent(segment); + + if (decoded.startsWith("{") && decoded.endsWith("}")) { + const placeholder = "$" + decoded.slice(1, -1).toUpperCase(); + url.pathname = url.pathname.replace(segment, placeholder); + } +} + +const security = operation.security as + | OpenAPIV3.SecurityRequirementObject[] + | undefined; + +if (security) { + const keys = security.flatMap((requirement) => Object.keys(requirement)); + + if (keys.includes("api_token")) { + headers["Authorization"] = `Bearer $CLOUDFLARE_API_TOKEN`; + } else if (keys.includes("api_key")) { + headers["X-Auth-Email"] = "$CLOUDFLARE_EMAIL"; + headers["X-Auth-Key"] = "$CLOUDFLARE_API_KEY"; + } +} + +const requestBody = operation?.requestBody as + | OpenAPIV3.RequestBodyObject + | undefined; + +const jsonSchema = requestBody?.content?.["application/json"]?.schema as + | OpenAPIV3.SchemaObject + | undefined; + +if (jsonSchema?.required) { + const providedProperties = Object.keys(json ?? {}); + const requiredProperties = jsonSchema.required; + + const missingProperties = requiredProperties.filter( + (property) => !providedProperties.includes(property), + ); + + if (missingProperties.length > 0) { + throw new Error( + `[APIRequest] Missing the following required properties for ${method} ${path}: ${missingProperties.join(", ")}`, + ); + } +} + +const tokenGroups = operation["x-api-token-group"]; +--- + +{ + tokenGroups && ( +
+ + At least one of the following{" "} + token permissions{" "} + is required: + +
    + {tokenGroups.map((group) => ( +
  • {group}
  • + ))} +
+
+ ) +} + + diff --git a/src/components/BaseSchemaProperties.astro b/src/components/BaseSchemaProperties.astro new file mode 100644 index 00000000000000..e24441c0ebda33 --- /dev/null +++ b/src/components/BaseSchemaProperties.astro @@ -0,0 +1,75 @@ +--- +import { z } from "astro:schema"; +import { baseSchema } from "~/schemas"; +import { marked } from "marked"; + +import Type from "./Type.astro"; +import MetaInfo from "./MetaInfo.astro"; +import AnchorHeading from "./AnchorHeading.astro"; +import Details from "./Details.astro"; + +const schema = baseSchema({ + // @ts-expect-error Normally passed in by Astro but we are using the schema standalone. + image: () => z.function(), +}).shape; + +const getInnerType = ({ _def }: z.ZodTypeAny | z.ZodEffects) => { + if (_def.innerType) return getInnerType(_def.innerType); + + return _def; +}; +--- + +{ + Object.entries(schema) + .sort() + .map(([key, outer]) => { + const outerType = outer._def.typeName; + const outerDescription = outer._def.description; + + const inner = getInnerType(outer); + const innerType = + key === "preview_image" + ? "string" + : inner.typeName.split("Zod")[1].toLowerCase(); + + return ( + <> + +

+ Type: + + {outerType === "ZodOptional" && ( + <> + {" "} + + + )} +

+ {outerDescription && ( +

+ Description: + +

+ )} + {inner.typeName === "ZodUnion" && ( +

+

+
    + {inner.options + .filter( + (option: any) => option._def.typeName === "ZodLiteral", + ) + .map((option: any) => ( +
  • + {option._def.value} +
  • + ))} +
+
+

+ )} + + ); + }) +} diff --git a/src/components/CURL.astro b/src/components/CURL.astro new file mode 100644 index 00000000000000..80226dfec565ba --- /dev/null +++ b/src/components/CURL.astro @@ -0,0 +1,50 @@ +--- +import { z } from "astro:schema"; +import type { ComponentProps } from "astro/types"; +import { Code } from "@astrojs/starlight/components"; + +type Props = z.input; + +const props = z.object({ + method: z + .enum(["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"]) + .default("GET"), + url: z.string().url(), + headers: z.record(z.string(), z.string()).default({}), + json: z.record(z.string(), z.any()).optional(), + form: z.record(z.string(), z.any()).optional(), + code: z + .custom, "code" | "lang">>() + .optional(), +}); + +const { method, url, headers, json, form, code } = props.parse(Astro.props); + +if (json && form) { + throw new Error("[CURL] Cannot use both 'json' and 'form' properties."); +} + +const lines = [`curl ${url}`, `\t--request ${method}`]; + +if (headers) { + for (const [key, value] of Object.entries(headers)) { + lines.push(`\t--header "${key}: ${value}"`); + } +} + +if (json) { + const jsonLines = JSON.stringify(json, null, "\t\t").split("\n"); + jsonLines[jsonLines.length - 1] = "\t" + jsonLines[jsonLines.length - 1]; + + lines.push(`\t--json '${jsonLines.join("\n")}'`); +} + +if (form) { + const formLines = Object.entries(form).map( + ([key, value]) => `\t--form "${key}=${value}"`, + ); + lines.push(...formLines); +} +--- + + diff --git a/src/components/ComponentsUsage.astro b/src/components/ComponentsUsage.astro new file mode 100644 index 00000000000000..3b79b5c3fba9a6 --- /dev/null +++ b/src/components/ComponentsUsage.astro @@ -0,0 +1,40 @@ +--- +import { getComponentsUsage } from "~/util/components"; +import AnchorHeading from "./AnchorHeading.astro"; +import Details from "./Details.astro"; + +const components = await getComponentsUsage(); + +const alphabetical = Object.entries(components).sort(([a], [b]) => + a.localeCompare(b), +); +--- + +{ + alphabetical.map(([component, usage]) => ( + <> + +

+ {component} is used {usage.count} times on{" "} + {usage.pages.size} pages. +

+
+
    + {[...usage.pages].map((path) => ( +
  • + + {path} + +
  • + ))} +
+
+ + )) +} diff --git a/src/components/Description.astro b/src/components/Description.astro index 0a5d1c985bba07..1421a69b49f13e 100644 --- a/src/components/Description.astro +++ b/src/components/Description.astro @@ -1,3 +1,3 @@ -
+
diff --git a/src/components/FieldCatalog.tsx b/src/components/FieldCatalog.tsx index bb2598175d415f..a84308e3b1bc6a 100644 --- a/src/components/FieldCatalog.tsx +++ b/src/components/FieldCatalog.tsx @@ -142,14 +142,11 @@ const FieldCatalog = ({ fields }: { fields: Fields }) => { {field.name}
- - {field.summary} - - +
+ + {field.summary} + +
{field.plan_info_label && (
diff --git a/src/components/Flex.astro b/src/components/Flex.astro index e3d03f3928a2f6..0a34ac38d178f5 100644 --- a/src/components/Flex.astro +++ b/src/components/Flex.astro @@ -1,3 +1,3 @@ -
+
diff --git a/src/components/HeaderDropdowns.tsx b/src/components/HeaderDropdowns.tsx new file mode 100644 index 00000000000000..7153cbf81571e2 --- /dev/null +++ b/src/components/HeaderDropdowns.tsx @@ -0,0 +1,100 @@ +import { + useFloating, + useInteractions, + useClick, + useDismiss, + shift, + offset, + autoUpdate, +} from "@floating-ui/react"; +import { useState } from "react"; +import { PiCaretDownBold } from "react-icons/pi"; + +const links = [ + { label: "Docs Directory", href: "/products/" }, + { + label: "APIs", + href: "https://developers.cloudflare.com/api/", + }, + { label: "SDKs", href: "/fundamentals/api/reference/sdks/" }, +]; + +const dropdowns = Object.entries({ + Help: [ + { label: "Help center", href: "https://support.cloudflare.com/" }, + { label: "Cloudflare status", href: "https://www.cloudflarestatus.com/" }, + { label: "Community", href: "https://community.cloudflare.com/" }, + ], +}); + +function Dropdown({ dropdown }: { dropdown: (typeof dropdowns)[number] }) { + const [label, pages] = dropdown; + const [isOpen, setIsOpen] = useState(false); + + const { refs, floatingStyles, context } = useFloating({ + open: isOpen, + onOpenChange: setIsOpen, + middleware: [shift(), offset(5)], + whileElementsMounted: autoUpdate, + }); + + const click = useClick(context); + const dismiss = useDismiss(context); + + const { getReferenceProps, getFloatingProps } = useInteractions([ + click, + dismiss, + ]); + + return ( + <> + + {isOpen && ( + + )} + + ); +} + +export default function HeaderDropdownsComponent() { + return ( +
+ {links.map(({ label, href }) => ( + + {label} + + ))} + {dropdowns.map((dropdown) => ( + + ))} +
+ ); +} diff --git a/src/components/HomepageHero.astro b/src/components/HomepageHero.astro index 3f7400ad2ca4b1..bea37bdedb241f 100644 --- a/src/components/HomepageHero.astro +++ b/src/components/HomepageHero.astro @@ -1,9 +1,8 @@ --- import { Image } from "astro:assets"; -import type { Props } from "@astrojs/starlight/props"; import type { ImageMetadata } from "astro"; -const { data } = Astro.props.entry; +const { data } = Astro.locals.starlightRoute.entry; const { title = data.title, tagline, image } = data.hero || {}; const imageAttrs = { @@ -45,15 +44,15 @@ if (image) { {rawHtml &&
}
-

{tagline &&
} diff --git a/src/components/LearningPathCatalog.tsx b/src/components/LearningPathCatalog.tsx index b71cc42be4ec0f..f2b50612b041e1 100644 --- a/src/components/LearningPathCatalog.tsx +++ b/src/components/LearningPathCatalog.tsx @@ -42,6 +42,7 @@ const LearningPathCatalog = ({ description: lp.description, products: lp.products, groups, + video: lp.video, }; }); @@ -152,24 +153,25 @@ const LearningPathCatalog = ({ href={path.link} className="rounded-md border border-solid border-gray-200 p-6 !text-inherit no-underline hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800" > - {path.icon && ( -
- -
- )} +
+ {path.icon && ( +
+ +
+ )} + {path.video && Video} +

{path.title}

- - {path.description} - +
+ + {path.description} + +
); })} diff --git a/src/components/ListTutorials.astro b/src/components/ListTutorials.astro index b1d4f75a442ebb..3b6e0db4813883 100644 --- a/src/components/ListTutorials.astro +++ b/src/components/ListTutorials.astro @@ -20,6 +20,8 @@ if (!currentProduct) { } const productTitle = currentProduct.data.product.title; +const videoText = "🎥 Video" +const tutorialText = "📝 Tutorial" const docs = await getCollection("docs", (entry) => { return ( @@ -82,7 +84,7 @@ const timeAgo = (date?: Date) => { {timeAgo(tutorial.data.updated)} - {tutorial.data.content_type} + {tutorial.collection === "docs" ? tutorialText : videoText} {tutorial.data.difficulty} ); diff --git a/src/components/MetaInfo.astro b/src/components/MetaInfo.astro index d302876d77b893..302a1858144fec 100644 --- a/src/components/MetaInfo.astro +++ b/src/components/MetaInfo.astro @@ -12,4 +12,4 @@ const props = z const { text } = props.parse(Astro.props); --- -{text} +{text} diff --git a/src/components/ProductFeatures.astro b/src/components/ProductFeatures.astro index c5345136429c77..e080742c499773 100644 --- a/src/components/ProductFeatures.astro +++ b/src/components/ProductFeatures.astro @@ -56,21 +56,23 @@ const entries = Object.entries(plan); )} {additional_descriptions && ( <> - {value.lite || - (value.free && ( + {value.lite ? ( +
  • + Lite: + +
  • + ) : ( + value.free && (
  • Lite: - {value.lite ? ( - - ) : ( - - )} +
  • - ))} + ) + )} )} {value.pro && ( @@ -83,23 +85,23 @@ const entries = Object.entries(plan); )} {additional_descriptions && ( <> - {value.pro_plus || - (value.pro && ( + {value.pro_plus ? ( +
  • + Pro Plus: + +
  • + ) : ( + value.pro && (
  • Pro Plus: - {value.pro_plus ? ( - - ) : ( - - )} +
  • - ))} + ) + )} )} {value.biz && ( diff --git a/src/components/RelatedProduct.astro b/src/components/RelatedProduct.astro index d307ea7196e05f..48479a68ee4d07 100644 --- a/src/components/RelatedProduct.astro +++ b/src/components/RelatedProduct.astro @@ -13,10 +13,10 @@ const props = z.object({ const { header, href, product } = props.parse(Astro.props); --- -
    +
    diff --git a/src/components/Stream.astro b/src/components/Stream.astro index a5e778ced4157b..070e32207e3de5 100644 --- a/src/components/Stream.astro +++ b/src/components/Stream.astro @@ -1,55 +1,96 @@ --- -interface Props { - videoId: string; - videoTitle: string; - thumbnailTimeOrURL: string; - moreVideosLink: string; -} +import { z } from "astro:schema"; +import { Badge } from "@astrojs/starlight/components"; +import parse from "parse-duration"; + +type Props = z.input; + +const props = z + .object({ + id: z.string(), + title: z.string(), + thumbnail: z.string().optional(), + chapters: z.record(z.string(), z.string()).optional(), + showMoreVideos: z.boolean().default(true), + }) + .strict(); + +const { id, title, thumbnail, chapters, showMoreVideos } = props.parse( + Astro.props, +); -const { - videoId, - videoTitle, - thumbnailTimeOrURL, - moreVideosLink = "true", -} = Astro.props; +const BASE_URL = `https://customer-1mwganm1ma0xgnmj.cloudflarestream.com/`; -const customerId = "1mwganm1ma0xgnmj"; -const baseUrl = `https://customer-${customerId}.cloudflarestream.com/`; +const url = new URL(`${id}/iframe`, BASE_URL); +const thumbnailUrl = new URL(`${id}/thumbnails/thumbnail.jpg`, BASE_URL); -const url = new URL(`${videoId}/iframe`, baseUrl); url.searchParams.set("preload", "true"); url.searchParams.set("letterboxColor", "transparent"); -// full url option -if (thumbnailTimeOrURL !== undefined) { - if (!thumbnailTimeOrURL.startsWith("http")) { - const thumbnailUrl = new URL( - `${videoId}/thumbnails/thumbnail.jpg`, - baseUrl, - ); +if (thumbnail) { + if (thumbnail.startsWith("http")) { + url.searchParams.set("poster", thumbnail); + } else { thumbnailUrl.searchParams.set("fit", "crop"); - thumbnailUrl.searchParams.set("time", thumbnailTimeOrURL); + thumbnailUrl.searchParams.set("time", thumbnail); url.searchParams.set("poster", encodeURI(thumbnailUrl.toString())); - } else { - url.searchParams.set("poster", thumbnailTimeOrURL); } } --- - +
    + title={title} + id={id}>
    { - moreVideosLink == "true" && ( + chapters && ( +

    + Chapters +

      + {Object.entries(chapters).map(([chapter, time]) => { + const totalSeconds = parse(time, "s"); + + const thumbnail = new URL(thumbnailUrl); + thumbnail.searchParams.set("fit", "crop"); + thumbnail.searchParams.set("time", `${totalSeconds}s`); + + return ( +
    • + +
    • + ); + })} +
    +

    + ) + } + + { + showMoreVideos && ( Watch more videos on our Developer Channel @@ -71,10 +112,55 @@ if (thumbnailTimeOrURL !== undefined) { const title = this.dataset.title as string; const player = this.querySelector(`#${id}`) as HTMLIFrameElement; + const stream = Stream(player); - Stream(player).addEventListener("play", () => { - track("play docs video", { title: title }); + stream.addEventListener("play", () => { + track("play docs video", { title }); }); + + stream.addEventListener("pause", () => { + track("paused docs video", { + title, + time: stream.currentTime.toFixed(1), + }); + }); + + stream.addEventListener("seeked", () => { + track("seeked docs video", { + title, + time: stream.currentTime.toFixed(1), + }); + }); + + stream.addEventListener("ended", () => { + track("ended docs video", { title }); + }); + + stream.addEventListener("ratechange", () => { + if (stream.playbackRate === 0 || stream.playbackRate === 1) return; + + track("changed playback rate docs video", { + title, + rate: stream.playbackRate, + }); + }); + + const buttons = + this.querySelectorAll("[data-chapter]"); + + for (const button of buttons) { + button.addEventListener("click", () => { + const chapter = button.dataset.chapter as string; + const time = Number(button.dataset.time); + + stream.currentTime = time; + + track("clicked chapter docs video", { + title, + chapter, + }); + }); + } } } diff --git a/src/components/SubtractIPCalculator.tsx b/src/components/SubtractIPCalculator.tsx new file mode 100644 index 00000000000000..75da6e02b9774f --- /dev/null +++ b/src/components/SubtractIPCalculator.tsx @@ -0,0 +1,87 @@ +import { useEffect, useState } from "react"; +import { excludeCidr, parseCidr } from "cidr-tools"; + +export default function SubtractIPCalculator({ + defaults, +}: { + defaults: { + base?: string; + exclude?: string[]; + }; +}) { + const [base, setBase] = useState(defaults?.base ?? ""); + const [exclude, setExclude] = useState(defaults?.exclude ?? []); + + const [result, setResult] = useState([]); + + function calculate() { + setResult(excludeCidr(base, exclude)); + } + + function disableButton() { + try { + parseCidr(base); + exclude.map((cidr) => parseCidr(cidr)); + + return false; + } catch { + return true; + } + } + + useEffect(() => { + if (defaults) { + calculate(); + } + }, []); + + return ( +
    +
    + + +
    +
    + +
    +
    + {result.length > 0 && ( + <> + Results: + {result.map((cidr, idx) => ( + <> + {cidr} + {idx < result.length - 1 && , } + + ))} + + )} +
    +
    + //
      + // {excludeCidr("10.0.0.0/8", ["10.0.0.0/24"]).map((cidr) => ( + //
    • {cidr}
    • + // ))} + //
    + ); +} diff --git a/src/components/TagsUsage.astro b/src/components/TagsUsage.astro new file mode 100644 index 00000000000000..da5e31b0ba2bc5 --- /dev/null +++ b/src/components/TagsUsage.astro @@ -0,0 +1,40 @@ +--- +import { getCollection } from "astro:content"; +import AnchorHeading from "./AnchorHeading.astro"; +import Details from "./Details.astro"; + +const entries = await getCollection("docs", (e) => Boolean(e.data.tags)); + +const byTag: Record = {}; + +for (const entry of entries) { + for (const tag of entry.data.tags!) { + byTag[tag] ??= []; + byTag[tag].push(entry.id); + } +} +--- + +{ + Object.entries(byTag) + .sort() + .map(([tag, pages]) => ( + <> + +

    + {tag} is used on {pages.length} pages. +

    +
    + +
    + + )) +} diff --git a/src/components/Type.astro b/src/components/Type.astro index 9f36a01f8c6650..a9f2a961cfdfeb 100644 --- a/src/components/Type.astro +++ b/src/components/Type.astro @@ -1,6 +1,7 @@ --- import { z } from "astro:schema"; import { Badge } from "@astrojs/starlight/components"; +import { componentToString } from "~/util/container"; type Props = z.infer; @@ -11,15 +12,17 @@ const props = z .strict(); const { text } = props.parse(Astro.props); ---- - + }, +}); +--- + + diff --git a/src/components/homepage/FeaturedContentSection.astro b/src/components/homepage/FeaturedContentSection.astro index 3b5cdae088a036..b017f51839c2cc 100644 --- a/src/components/homepage/FeaturedContentSection.astro +++ b/src/components/homepage/FeaturedContentSection.astro @@ -32,7 +32,7 @@ const { title, text, image, cards, imagePosition } = props.parse(Astro.props);
    { imagePosition === "before" && ( -
    +
    {`${title} - +
    ) : ( @@ -80,7 +83,7 @@ const { title, text, image, cards, imagePosition } = props.parse(Astro.props); { imagePosition === "after" && ( -
    +
    {`${title} +
    { blocks.map(({ title, text, links }) => (
    @@ -68,13 +66,13 @@ const blocks = [

    {text}

      {links.map((link) => ( -
    • +
    • - + {link.text}
    • @@ -84,19 +82,3 @@ const blocks = [ )) }
    - - diff --git a/src/components/homepage/TryItSection.astro b/src/components/homepage/TryItSection.astro index 733696a85b19a0..6b78f53a3e8e7e 100644 --- a/src/components/homepage/TryItSection.astro +++ b/src/components/homepage/TryItSection.astro @@ -14,7 +14,7 @@ import Render from "~/components/Render.astro";
    -
    +
    @@ -34,7 +34,7 @@ import Render from "~/components/Render.astro";
    -
    +
    diff --git a/src/components/index.ts b/src/components/index.ts index 76ae234db69b35..49d8392bd9d73a 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -6,9 +6,12 @@ export { PackageManagers } from "starlight-package-managers"; export { Icon as AstroIcon } from "astro-icon/components"; // Custom components export { default as AnchorHeading } from "./AnchorHeading.astro"; +export { default as APIRequest } from "./APIRequest.astro"; export { default as AvailableNotifications } from "./AvailableNotifications.astro"; export { default as CompatibilityFlag } from "./CompatibilityFlag.astro"; export { default as CompatibilityFlags } from "./CompatibilityFlags.astro"; +export { default as ComponentsUsage } from "./ComponentsUsage.astro"; +export { default as CURL } from "./CURL.astro"; export { default as Description } from "./Description.astro"; export { default as Details } from "./Details.astro"; export { default as DirectoryListing } from "./DirectoryListing.astro"; @@ -48,6 +51,7 @@ export { default as ResourcesBySelector } from "./ResourcesBySelector.astro"; export { default as RuleID } from "./RuleID.astro"; export { default as SpotlightAuthorDetails } from "./SpotlightAuthorDetails.astro"; export { default as Stream } from "./Stream.astro"; +export { default as TagsUsage } from "./TagsUsage.astro"; export { default as TroubleshootingList } from "./TroubleshootingList.astro"; export { default as TunnelCalculator } from "./TunnelCalculator.astro"; export { default as Type } from "./Type.astro"; diff --git a/src/components/live-code/Layout.astro b/src/components/live-code/Layout.astro deleted file mode 100644 index ed65e21802f926..00000000000000 --- a/src/components/live-code/Layout.astro +++ /dev/null @@ -1,27 +0,0 @@ -
    -
    -
    - -
    -
    - -
    - - diff --git a/src/components/models/SchemaViewer.astro b/src/components/models/SchemaViewer.astro index eec7994f22ee64..7f3b2e28fa7fef 100644 --- a/src/components/models/SchemaViewer.astro +++ b/src/components/models/SchemaViewer.astro @@ -53,7 +53,7 @@ const jsonSchemaTree = new SchemaTree(schema, { jsonSchemaTree.populate(); --- -
      +
        { (jsonSchemaTree.root.children[0] as RegularNode).children?.map( (node: SchemaNode) => , diff --git a/src/components/overrides/Footer.astro b/src/components/overrides/Footer.astro index ee4806108eb700..69c7049cbefcfb 100644 --- a/src/components/overrides/Footer.astro +++ b/src/components/overrides/Footer.astro @@ -1,31 +1,12 @@ --- -import type { Props } from "@astrojs/starlight/props"; import Default from "@astrojs/starlight/components/Footer.astro"; +import { Icon } from "@astrojs/starlight/components"; +import type { StarlightIcon } from "@astrojs/starlight/types"; + import OneTrust from "../OneTrust.astro"; import FeedbackPrompt from "../FeedbackPrompt.tsx"; -import { getEntry } from "astro:content"; - -let links = { - "Cloudflare Dashboard": "https://dash.cloudflare.com", - Discord: "https://discord.cloudflare.com", - Community: "https://community.cloudflare.com", - "Learning Center": "https://www.cloudflare.com/learning/", - "Support Portal": "/support/contacting-cloudflare-support/", -}; - -const currentSection = Astro.params.slug?.split("/")[0]; -if (currentSection) { - const product = await getEntry("products", currentSection); - - if (product) { - if (product.data.resources?.dashboard_link) { - links["Cloudflare Dashboard"] = product.data.resources.dashboard_link; - } - } -} - -const homepageLinks = Object.entries({ +const groups = Object.entries({ Resources: [ { text: "API", href: "/api/" }, { @@ -60,16 +41,35 @@ const homepageLinks = Object.entries({ { text: "RPKI Toolkit", href: "https://rpki.cloudflare.com/" }, { text: "Certificate Transparency", href: "https://ct.cloudflare.com/" }, ], + Community: [ + { text: "X", href: "https://x.com/cloudflare", icon: "x.com" }, + { + text: "Discord", + href: "http://discord.cloudflare.com/", + icon: "discord", + }, + { + text: "YouTube", + href: "https://www.youtube.com/cloudflare", + icon: "youtube", + }, + { + text: "GitHub", + href: "https://github.com/cloudflare/cloudflare-docs", + icon: "github", + }, + ], }); -const homepageLegalLinks = Object.entries({ +const links = Object.entries({ "Privacy Policy": "https://www.cloudflare.com/privacypolicy/", "Terms of Use": "https://www.cloudflare.com/website-terms/", "Report Security Issues": "https://www.cloudflare.com/disclosure/", Trademark: "https://www.cloudflare.com/trademark/", }); -const isHomepage = Astro.props.id === ""; +const homepage = Astro.locals.starlightRoute.entry.id === ""; +const splash = Astro.locals.starlightRoute.entry.data.template === "splash"; let isProduction = false; @@ -82,80 +82,71 @@ if ( --- { - isHomepage ? ( - <> -
        -
        - {homepageLinks.map(([header, links]) => ( -
        - {header} - -
        - ))} -
        -
        -
        -
          -
        • - 2024 Cloudflare, Inc. + !homepage && ( + + ) +} +{!splash && } +
          +
          + { + groups.map(([title, items]) => ( + -
          - - ) : ( -
          - - - -
          - ) -} +
        • + ) + } +
        +
        +
    diff --git a/src/components/overrides/Head.astro b/src/components/overrides/Head.astro index 0021e2de4a9e88..ce02b16a69df1b 100644 --- a/src/components/overrides/Head.astro +++ b/src/components/overrides/Head.astro @@ -1,123 +1,71 @@ --- -import type { Props } from "@astrojs/starlight/props"; import Default from "@astrojs/starlight/components/Head.astro"; import { differenceInCalendarDays } from "date-fns"; import "tippy.js/dist/tippy.css"; import { getEntry } from "astro:content"; +import { getOgImage } from "~/util/og"; +import type { CollectionEntry } from "astro:content"; + +const NOINDEX_PRODUCTS = ["email-security", "style-guide", "security"]; -// grab the current top-level folder. Remove . characters for 1.1.1.1 URL const currentSection = Astro.url.pathname.split("/")[1].replaceAll(".", ""); +const entry = Astro.locals.starlightRoute.entry; +const frontmatter = entry.data; +const head = frontmatter.head; + +const metaTags = [] as Record[]; + +const shouldNoIndex = + NOINDEX_PRODUCTS.includes(currentSection) || + frontmatter.noindex || + frontmatter.external_link; + if (currentSection) { const product = await getEntry("products", currentSection); if (product) { if (product.data.meta.title) { - const titleIdx = Astro.props.entry.data.head.findIndex( - (x) => x.tag === "title", - ); + const titleIdx = head.findIndex((x) => x.tag === "title"); let title: string; if (titleIdx !== -1) { - const existingTitle = Astro.props.entry.data.head[titleIdx].content; + const existingTitle = head[titleIdx].content; title = `${existingTitle} · ${product.data.meta.title}`; - Astro.props.entry.data.head[titleIdx] = { + head[titleIdx] = { tag: "title", attrs: {}, content: title, }; } else { - title = `${Astro.props.entry.data.title} · ${product.data.meta.title}`; - Astro.props.entry.data.head.push({ + title = `${frontmatter.title} · ${product.data.meta.title}`; + head.push({ tag: "title", attrs: {}, content: title, }); } - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { property: "og:title", content: title }, - content: "", + metaTags.push({ + property: "og:title", + content: title, }); } if (product.data.product.title) { - const productName = product.data.product.title; - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "pcx_product", - content: productName, - }, - content: "", - }); - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "algolia_product_filter", - content: productName, - }, - content: "", + ["pcx_product", "algolia_product_filter"].map((name) => { + metaTags.push({ + name, + content: product.data.product.title, + }); }); } if (product.data.product.group) { - const group = product.data.product.group.toLowerCase(); - - let ogImage = "https://developers.cloudflare.com/cf-twitter-card.png"; - - const images: Record = { - "cloudflare essentials": - "https://developers.cloudflare.com/core-services-preview.png", - "cloudflare one": "https://developers.cloudflare.com/zt-preview.png", - "developer platform": - "https://developers.cloudflare.com/dev-products-preview.png", - "network security": - "https://developers.cloudflare.com/core-services-preview.png", - "application performance": - "https://developers.cloudflare.com/core-services-preview.png", - "application security": - "https://developers.cloudflare.com/core-services-preview.png", - }; - - if (images[group]) { - ogImage = images[group]; - } - - const tags = [ - { - tag: "meta", - attrs: { - name: "image", - content: ogImage, - }, - content: "", - }, - { - tag: "meta", - attrs: { - name: "og:image", - content: ogImage, - }, - content: "", - }, - { - tag: "meta", - attrs: { - name: "twitter:image", - content: ogImage, - }, - content: "", - }, - ] as const; - - Astro.props.entry.data.head.push(...tags); - - Astro.props.entry.data.head.push({ + head.push({ tag: "meta", attrs: { name: "pcx_content_group", @@ -127,136 +75,58 @@ if (currentSection) { }); } } - - if (currentSection === "style-guide") { - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "robots", - content: "noindex", - }, - content: "", - }); - } - - if (currentSection === "changelog") { - let changelogImage = - "https://developers.cloudflare.com/changelog-preview.png"; - - const tags = [ - { - tag: "meta", - attrs: { - name: "image", - content: changelogImage, - }, - content: "", - }, - { - tag: "meta", - attrs: { - name: "og:image", - content: changelogImage, - }, - content: "", - }, - { - tag: "meta", - attrs: { - name: "twitter:image", - content: changelogImage, - }, - content: "", - }, - ] as const; - - Astro.props.entry.data.head.push(...tags); - } } -// Add noindex tag if present in frontmatter - -if (Astro.props.entry.data.noindex) { - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "robots", - content: "noindex", - }, - content: "", +if (shouldNoIndex) { + metaTags.push({ + name: "robots", + content: "noindex", }); } -// Adding metadata used for reporting and search indexing -// content type -if (Astro.props.entry.data.pcx_content_type) { - const contentType = Astro.props.entry.data.pcx_content_type; - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "pcx_content_type", - content: contentType, - }, - content: "", - }); - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "algolia_content_type", - content: contentType, - }, - content: "", +if (frontmatter.pcx_content_type) { + ["pcx_content_type", "algolia_content_type"].map((name) => { + metaTags.push({ + name, + content: frontmatter.pcx_content_type as string, + }); }); } -// other products -if (Astro.props.entry.data.products) { - const additionalProducts = Astro.props.entry.data.products; - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "pcx_additional_products", - content: additionalProducts.toString(), - }, - content: "", +if (frontmatter.products) { + metaTags.push({ + name: "pcx_additional_products", + content: frontmatter.products.toString(), }); } -// other products -if (Astro.props.entry.data.tags) { - const pageTags = Astro.props.entry.data.tags; - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "pcx_tags", - content: pageTags.toString(), - }, - content: "", +if (frontmatter.tags) { + metaTags.push({ + name: "pcx_tags", + content: frontmatter.tags.toString(), }); } -if (Astro.props.entry.data.updated) { - const daysBetween = differenceInCalendarDays( - new Date(), - Astro.props.entry.data.updated, - ); - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - name: "pcx_last_reviewed", - content: daysBetween.toString(), - }, - content: "", +if (frontmatter.updated) { + const daysBetween = differenceInCalendarDays(new Date(), frontmatter.updated); + + metaTags.push({ + name: "pcx_last_reviewed", + content: daysBetween.toString(), }); } -// end metadata +if (frontmatter.external_link) { + metaTags.push({ + content: `0; url=${frontmatter.external_link}`, + "http-equiv": "refresh", + }); +} -if (Astro.props.entry.data.pcx_content_type === "changelog") { - const href = new URL(Astro.site ?? ""); - href.pathname = Astro.props.entry.slug.concat("/index.xml"); +if (frontmatter.pcx_content_type === "changelog") { + const href = new URL(entry.id.concat("/index.xml"), Astro.url.origin); - Astro.props.entry.data.head.push({ + head.push({ tag: "link", attrs: { rel: "alternate", @@ -267,27 +137,29 @@ if (Astro.props.entry.data.pcx_content_type === "changelog") { }); } -if (Astro.props.entry.data.external_link) { - Astro.props.entry.data.head.push({ - tag: "meta", - attrs: { - content: "noindex", - name: "robots", - }, - content: "", +const ogImagePath = await getOgImage( + (Astro.locals.starlightRoute.originalEntry as CollectionEntry<"changelog">) ?? + Astro.locals.starlightRoute.entry, +); +const ogImageUrl = new URL(ogImagePath, Astro.url.origin).toString(); + +["image", "og:image", "twitter:image"].map((property) => { + metaTags.push({ + property, + content: ogImageUrl, }); - Astro.props.entry.data.head.push({ +}); + +metaTags.map((attrs) => { + head.push({ tag: "meta", - attrs: { - content: `0; url=${Astro.props.entry.data.external_link}`, - "http-equiv": "refresh", - }, + attrs, content: "", }); -} +}); --- - + diff --git a/src/components/overrides/Header.astro b/src/components/overrides/Header.astro new file mode 100644 index 00000000000000..f979a17046c521 --- /dev/null +++ b/src/components/overrides/Header.astro @@ -0,0 +1,73 @@ +--- +import LanguageSelect from "@astrojs/starlight/components/LanguageSelect.astro"; +import DocSearch from "@astrojs/starlight-docsearch/DocSearch.astro"; +import SiteTitle from "@astrojs/starlight/components/SiteTitle.astro"; +import ThemeSelect from "@astrojs/starlight/components/ThemeSelect.astro"; + +import HeaderDropdowns from "../HeaderDropdowns.tsx"; +--- + +
    + +
    +
    + +
    + +
    +
    + + + + diff --git a/src/components/overrides/Hero.astro b/src/components/overrides/Hero.astro index 33a3d554439c03..72cfac91f08b11 100644 --- a/src/components/overrides/Hero.astro +++ b/src/components/overrides/Hero.astro @@ -1,9 +1,8 @@ --- -import type { Props } from "@astrojs/starlight/props"; import Default from "@astrojs/starlight/components/Hero.astro"; import HomepageHero from "../HomepageHero.astro"; -const isHomepage = Astro.props.id === ""; +const isHomepage = Astro.locals.starlightRoute.id === ""; --- -{isHomepage ? : } +{isHomepage ? : } diff --git a/src/components/overrides/Page.astro b/src/components/overrides/Page.astro index 0db2d9a6f0e06f..e50309ab45e813 100644 --- a/src/components/overrides/Page.astro +++ b/src/components/overrides/Page.astro @@ -1,13 +1,10 @@ --- -import type { Props } from "@astrojs/starlight/props"; import Default from "@astrojs/starlight/components/Page.astro"; import { generateDescription, generateTableOfContents } from "~/util/props"; -import { getSidebar, flattenSidebar, type SidebarEntry } from "~/util/sidebar"; +import { getSidebar, flattenSidebar } from "~/util/sidebar"; -type Group = Extract; - -const props = Astro.props; +const props = Astro.locals.starlightRoute; const data = props.entry.data; const html = await Astro.slots.render("default"); @@ -17,12 +14,11 @@ if (props.toc) { } if (props.hasSidebar) { - (props.sidebar as unknown as Group) = await getSidebar(Astro); + const group = await getSidebar(Astro); + props.sidebar = group.entries; if (props.pagination) { - const flattened = flattenSidebar( - props.sidebar.entries as unknown as SidebarEntry[], - ); + const flattened = flattenSidebar(props.sidebar); const idx = flattened.findIndex((entry) => entry.isCurrent); @@ -61,7 +57,7 @@ if (data.updated) { } --- - + -{ hideTitle && hideBreadcrumbs && +{ hideTitle && hideBreadcrumbs && diff --git a/src/components/overrides/TableOfContents.astro b/src/components/overrides/TableOfContents.astro index 1924ca7dac90e9..1dd01c361f0c35 100644 --- a/src/components/overrides/TableOfContents.astro +++ b/src/components/overrides/TableOfContents.astro @@ -1,10 +1,35 @@ --- -import type { Props } from "@astrojs/starlight/props"; import Default from "@astrojs/starlight/components/TableOfContents.astro"; +import { Icon } from "@astrojs/starlight/components"; import FeedbackPrompt from "../FeedbackPrompt.tsx"; --- - +
    +{ + !Astro.url.pathname.startsWith("/support/") && ( + <> +
    +
    + {Astro.locals.starlightRoute.editUrl && ( + + + Edit + + )} + + + Issue + +
    + + ) +} diff --git a/src/components/search/InstantSearch.tsx b/src/components/search/InstantSearch.tsx new file mode 100644 index 00000000000000..4fe9de39f0e8cc --- /dev/null +++ b/src/components/search/InstantSearch.tsx @@ -0,0 +1,95 @@ +import { liteClient as algoliasearch } from "algoliasearch/lite"; +import { useEffect } from "react"; +import { + InstantSearch, + Highlight, + Configure, + useSearchBox, + type UseSearchBoxProps, + useInfiniteHits, + type UseInfiniteHitsProps, +} from "react-instantsearch"; + +function SearchBox(props: UseSearchBoxProps) { + const { query, refine } = useSearchBox(props); + + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const query = params.get("q") ?? params.get("query"); + + if (query) { + refine(query); + } + }, []); + + return ( +
    + refine(event.target.value)} + className="w-full border-none bg-transparent p-0 text-sm outline-none" + placeholder="Search..." + /> +
    + ); +} + +function InfiniteHits(props: UseInfiniteHitsProps) { + const { items, isLastPage, showMore } = useInfiniteHits(props); + + return ( +
    + {items.map((item) => { + const hierarchy = Object.entries(item.hierarchy) + .filter(([, value]) => value !== null) + .sort((a, b) => a[0].localeCompare(b[0])) + .map(([, value]) => value); + + const title = hierarchy ? hierarchy.join(" > ") : "Documentation"; + + return ( + + {title} +

    + +

    +
    + ); + })} + {items.length !== 0 && !isLastPage && ( +
    + +
    + )} +
    + ); +} + +export default function InstantSearchComponent() { + return ( + + + + + + ); +} diff --git a/src/content/changelog/access/2025-03-03-saml-oidc-fields-saml-transformations.mdx b/src/content/changelog/access/2025-03-03-saml-oidc-fields-saml-transformations.mdx new file mode 100644 index 00000000000000..57f1541cf3d911 --- /dev/null +++ b/src/content/changelog/access/2025-03-03-saml-oidc-fields-saml-transformations.mdx @@ -0,0 +1,28 @@ +--- +title: New SAML and OIDC Fields and SAML transforms for Access for SaaS +description: Access for SaaS new SAML and OIDC Fields and SAML transforms +date: 2025-03-03T6:00:00Z +--- + +[Access for SaaS applications](/cloudflare-one/applications/configure-apps/saas-apps/) now include more configuration options to support a wider array of SaaS applications. + +### SAML and OIDC Field Additions + +OIDC apps now include: + +- Group Filtering via RegEx +- OIDC Claim mapping from an IdP +- OIDC token lifetime control +- Advanced OIDC auth flows including hybrid and implicit flows + +![OIDC field additions](~/assets/images/changelog/access/oidc-claims.png) + +SAML apps now include improved SAML attribute mapping from an IdP. + +![SAML field additions](~/assets/images/changelog/access/saml-attribute-statements.png) + +### SAML transformations + +SAML identities sent to Access applications can be fully customized using JSONata expressions. This allows admins to configure the precise identity SAML statement sent to a SaaS application. + +![Configured SAML statement sent to application](~/assets/images/changelog/access/transformation-box.png) diff --git a/src/content/changelog/agents/2025-02-25-agents-sdk.mdx b/src/content/changelog/agents/2025-02-25-agents-sdk.mdx index b49a025a9280f5..26d5a5b4eca3c9 100644 --- a/src/content/changelog/agents/2025-02-25-agents-sdk.mdx +++ b/src/content/changelog/agents/2025-02-25-agents-sdk.mdx @@ -1,31 +1,31 @@ --- -title: Introducing the agents-sdk -description: Build and ship AI Agents on Cloudflare using the agents-sdk +title: Introducing the Agents SDK +description: Build and ship AI Agents on Cloudflare using the Agents SDK products: - agents - workers date: 2025-02-25T14:00:00Z --- -We've released the [agents-sdk](http://blog.cloudflare.com/build-ai-agents-on-cloudflare/), a package and set of tools that help you build and ship AI Agents. +We've released the [Agents SDK](http://blog.cloudflare.com/build-ai-agents-on-cloudflare/), a package and set of tools that help you build and ship AI Agents. -You can get up and running with a [chat-based AI Agent](https://github.com/cloudflare/agents-starter) (and deploy it to Workers) that uses the `agents-sdk`, tool calling, and state syncing with a React-based front-end by running the following command: +You can get up and running with a [chat-based AI Agent](https://github.com/cloudflare/agents-starter) (and deploy it to Workers) that uses the Agents SDK, tool calling, and state syncing with a React-based front-end by running the following command: ```sh npm create cloudflare@latest agents-starter -- --template="cloudflare/agents-starter" # open up README.md and follow the instructions ``` -You can also add an Agent to any existing Workers application by installing the `agents-sdk` package directly +You can also add an Agent to any existing Workers application by installing the `agents` package directly ```sh -npm i agents-sdk +npm i agents ``` ... and then define your first Agent: ```ts -import { Agent } from 'agents-sdk'; +import { Agent } from 'agents'; export class YourAgent extends Agent { // Build it out @@ -37,4 +37,4 @@ export class YourAgent extends Agent { } ``` -Head over to the [Agents documentation](/agents/) to learn more about the `agents-sdk`, the SDK APIs, as well as how to test and deploying agents to production. +Head over to the [Agents documentation](/agents/) to learn more about the Agents SDK, the SDK APIs, as well as how to test and deploying agents to production. diff --git a/src/content/changelog/agents/2025-03-18-npm-i-agents.mdx b/src/content/changelog/agents/2025-03-18-npm-i-agents.mdx new file mode 100644 index 00000000000000..9dfcfd7f56bbb2 --- /dev/null +++ b/src/content/changelog/agents/2025-03-18-npm-i-agents.mdx @@ -0,0 +1,135 @@ +--- +title: npm i agents +description: Install the latest version of the `agents` SDK to build multi-agent applications, use the new RPC API, and visit the latest documentation updates. +products: + - agents + - workers +date: 2025-03-18T14:00:00Z +--- + +import { Badge, MetaInfo, Render, TypeScriptExample } from "~/components" +import { Image } from 'astro:assets'; +import npmAgentsAnimated from "~/assets/images/agents/npm-i-agents.apng" + +npm i agents + +#### `agents-sdk` -> `agents` + +📝 **We've renamed the Agents package to `agents`**! + +If you've already been building with the Agents SDK, you can update your dependencies to use the new package name, and replace references to `agents-sdk` with `agents`: + +```sh +# Install the new package +npm i agents +``` + +```sh +# Remove the old (deprecated) package +npm uninstall agents-sdk + +# Find instances of the old package name in your codebase +grep -r 'agents-sdk' . +# Replace instances of the old package name with the new one +# (or use find-replace in your editor) +sed -i 's/agents-sdk/agents/g' $(grep -rl 'agents-sdk' .) +``` + +All future updates will be pushed to the new `agents` package, and the older package has been marked as deprecated. + +#### Agents SDK updates + +We've added a number of big new features to the Agents SDK over the past few weeks, including: + +- You can now set `cors: true` when using `routeAgentRequest` to return permissive default CORS headers to Agent responses. +- The regular client now syncs state on the agent (just like the React version). +- `useAgentChat` bug fixes for passing headers/credentials, includng properly clearing cache on unmount. +- Experimental `/schedule` module with a prompt/schema for adding scheduling to your app (with evals!). +- Changed the internal `zod` schema to be compatible with the limitations of Google's Gemini models by removing the discriminated union, allowing you to use Gemini models with the scheduling API. + +We've also fixed a number of bugs with state synchronization and the React hooks. + + + +```ts +// via https://github.com/cloudflare/agents/tree/main/examples/cross-domain +export default { + async fetch(request: Request, env: Env) { + return ( + // Set { cors: true } to enable CORS headers. + (await routeAgentRequest(request, env, { cors: true })) || + new Response("Not found", { status: 404 }) + ); + }, +} satisfies ExportedHandler; +``` + + + +#### Call Agent methods from your client code + +We've added a new [`@unstable_callable()`](/agents/api-reference/agents-api/) decorator for defining methods that can be called directly from clients. This allows you call methods from within your client code: you can call methods (with arguments) and get native JavaScript objects back. + + + +```ts +// server.ts +import { unstable_callable, Agent, type StreamingResponse } from "agents"; +import type { Env } from "../server"; + + export class Rpc extends Agent { + // Use the decorator to define a callable method + @unstable_callable({ + description: "rpc test", + }) + async getHistory() { + return this.sql`SELECT * FROM history ORDER BY created_at DESC LIMIT 10`; + } +} +``` +```tsx +// client.tsx +const { call } = useAgent({ agent: "rpc" }); + +const fetchUserHistory = async () => { + try { + setLoading(true); + // Call methods directly on the Agent! + const result = await call("getHistory"); + addToast(`RPC result: ${result}`, "success"); + } catch (error) { + addToast(`Error: ${error}`, "error"); + } finally { + setLoading(false); + } +}; +``` + + + +#### agents-starter + +We've fixed a number of small bugs in the [`agents-starter`](https://github.com/cloudflare/agents-starter) project — a real-time, chat-based example application with tool-calling & human-in-the-loop built using the Agents SDK. The starter has also been upgraded to use the latest [wrangler v4](/changelog/2025-03-13-wrangler-v4/) release. + +If you're new to Agents, you can install and run the `agents-starter` project in two commands: + +```sh +# Install it +$ npm create cloudflare@latest agents-starter -- --template="cloudflare/agents-starter" +# Run it +$ npm run start +``` + +You can use the starter as a template for your own Agents projects: open up `src/server.ts` and `src/client.tsx` to see how the Agents SDK is used. + +#### More documentation + +We've heard your feedback on the Agents SDK documentation, and we're shipping more API reference material and usage examples, including: + +- Expanded [API reference documentation](/agents/api-reference/), covering the methods and properties exposed by the Agents SDK, as well as more usage examples. +- More [Client API](/agents/api-reference/agents-api/#client-api) documentation that documents `useAgent`, `useAgentChat` and the new `@unstable_callable` RPC decorator exposed by the SDK. +- New documentation on how to [call agents](/agents/api-reference/calling-agents/) and (optionally) authenticate clients before they connect to your Agents. + +Note that the Agents SDK is continually growing: the type definitions included in the SDK will always include the latest APIs exposed by the `agents` package. + +If you're still wondering what Agents are, [read our blog on building AI Agents on Cloudflare](https://blog.cloudflare.com/build-ai-agents-on-cloudflare/) and/or visit the [Agents documentation](/agents/) to learn more. diff --git a/src/content/changelog/ai-gateway/2025-02-26-guardrails.mdx b/src/content/changelog/ai-gateway/2025-02-26-guardrails.mdx new file mode 100644 index 00000000000000..e82cf9ce2bf400 --- /dev/null +++ b/src/content/changelog/ai-gateway/2025-02-26-guardrails.mdx @@ -0,0 +1,18 @@ +--- +title: Introducing Guardrails in AI Gateway +description: Keep AI interactions secure and risk-free with Guardrails in AI Gateway +date: 2025-02-26T6:00:00Z +preview_image: ~/assets/images/changelog/ai-gateway/guardrails-social-preview.png +--- + +[AI Gateway](/ai-gateway/) now includes [Guardrails](/ai-gateway/guardrails/), to help you monitor your AI apps for harmful or inappropriate content and deploy safely. + +Within the AI Gateway settings, you can configure: + +- **Guardrails**: Enable or disable content moderation as needed. +- **Evaluation scope**: Select whether to moderate user prompts, model responses, or both. +- **Hazard categories**: Specify which categories to monitor and determine whether detected inappropriate content should be blocked or flagged. + +![Guardrails in AI Gateway](~/assets/images/ai-gateway/Guardrails.png) + +Learn more in the [blog](https://blog.cloudflare.com/guardrails-in-ai-gateway/) or our [documentation](/ai-gateway/guardrails/). diff --git a/src/content/changelog/ai-gateway/2025-03-20-websockets.mdx b/src/content/changelog/ai-gateway/2025-03-20-websockets.mdx new file mode 100644 index 00000000000000..5c9a63ac90fc26 --- /dev/null +++ b/src/content/changelog/ai-gateway/2025-03-20-websockets.mdx @@ -0,0 +1,37 @@ +--- +title: AI Gateway launches Realtime WebSockets API +description: AI Gateway now supports end-to-end, client-to-provider WebSockets +date: 2025-03-21T09:00:00Z +--- +We are excited to announce that [AI Gateway](/ai-gateway/) now supports real-time AI interactions with the new [Realtime WebSockets API](/ai-gateway/configuration/websockets-api/realtime-api/). + +This new capability allows developers to establish persistent, low-latency connections between their applications and AI models, enabling natural, real-time conversational AI experiences, including speech-to-speech interactions. + +The Realtime WebSockets API works with the [OpenAI Realtime API](https://platform.openai.com/docs/guides/realtime#connect-with-websockets), [Google Gemini Live API](https://ai.google.dev/gemini-api/docs/multimodal-live), and supports real-time text and speech interactions with models from [Cartesia](https://docs.cartesia.ai/api-reference/tts/tts), and [ElevenLabs](https://elevenlabs.io/docs/conversational-ai/api-reference/conversational-ai/websocket). + +Here's how you can connect AI Gateway to [OpenAI's Realtime API](https://platform.openai.com/docs/guides/realtime#connect-with-websockets) using WebSockets: +```javascript title="OpenAI Realtime API example" +import WebSocket from "ws"; + +const url = + "wss://gateway.ai.cloudflare.com/v1///openai?model=gpt-4o-realtime-preview-2024-12-17"; +const ws = new WebSocket(url, { + headers: { + "cf-aig-authorization": process.env.CLOUDFLARE_API_KEY, + Authorization: "Bearer " + process.env.OPENAI_API_KEY, + "OpenAI-Beta": "realtime=v1", + }, +}); + +ws.on("open", () => console.log("Connected to server.")); +ws.on("message", (message) => console.log(JSON.parse(message.toString()))); + +ws.send( + JSON.stringify({ + type: "response.create", + response: { modalities: ["text"], instructions: "Tell me a joke" }, + }), +); +``` + +Get started by checking out the [Realtime WebSockets API](/ai-gateway/configuration/websockets-api/realtime-api/) documentation. diff --git a/src/content/changelog/browser-isolation/2025-03-03-user-action-logging.mdx b/src/content/changelog/browser-isolation/2025-03-03-user-action-logging.mdx new file mode 100644 index 00000000000000..690222a0b68400 --- /dev/null +++ b/src/content/changelog/browser-isolation/2025-03-03-user-action-logging.mdx @@ -0,0 +1,28 @@ +--- +title: Gain visibility into user actions in Zero Trust Browser Isolation sessions +description: User action logs for Remote Browser Isolation +date: 2025-03-04T11:00:00Z +--- + +We're excited to announce that new logging capabilities for [Remote Browser Isolation (RBI)](/cloudflare-one/policies/browser-isolation/) through [Logpush](/logs/reference/log-fields/account/) are available in Beta starting today! + +With these enhanced logs, administrators can gain visibility into end user behavior in the remote browser and track blocked data extraction attempts, along with the websites that triggered them, in an isolated session. + +```json +{ + "AccountID": "$ACCOUNT_ID", + "Decision": "block", + "DomainName": "www.example.com", + "Timestamp": "2025-02-27T23:15:06Z", + "Type": "copy", + "UserID": "$USER_ID" +} +``` + +User Actions available: + +- **Copy & Paste** +- **Downloads & Uploads** +- **Printing** + +Learn more about how to get started with Logpush in our [documentation](/logs/get-started/). diff --git a/src/content/changelog/browser-rendering/2025-02-27-br-rest-api-beta.mdx b/src/content/changelog/browser-rendering/2025-02-27-br-rest-api-beta.mdx new file mode 100644 index 00000000000000..76f6070ec63564 --- /dev/null +++ b/src/content/changelog/browser-rendering/2025-02-27-br-rest-api-beta.mdx @@ -0,0 +1,35 @@ +--- +title: New REST API is in open beta! +description: We've released a new REST API in open beta. +products: + - browser-rendering +date: 2025-02-27T12:00:00Z +--- + +We've released a new REST API for [Browser Rendering](/browser-rendering/) in open beta, making interacting with browsers easier than ever. This new API provides endpoints for common browser actions, with more to be added in the future. + +With the **REST API** you can: + +- **Capture screenshots** – Use `/screenshot` to take a screenshot of a webpage from provided URL or HTML. +- **Generate PDFs** – Use `/pdf` to convert web pages into PDFs. +- **Extract HTML content** – Use `/content` to retrieve the full HTML from a page. + **Snapshot (HTML + Screenshot)** – Use `/snapshot` to capture both the page's HTML and a screenshot in one request +- **Scrape Web Elements** – Use `/scrape` to extract specific elements from a page. + +For example, to capture a screenshot: + +```bash title="Screenshot example" +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/screenshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "html": "Hello World!", + "screenshotOptions": { + "type": "webp", + "omitBackground": true + } + }' \ + --output "screenshot.webp" +``` + +Learn more in our [documentation](/browser-rendering/rest-api/). diff --git a/src/content/changelog/d1/2025-01-07-d1-faster-query.mdx b/src/content/changelog/d1/2025-01-07-d1-faster-query.mdx index b21c1d89eea61d..2988327d16602b 100644 --- a/src/content/changelog/d1/2025-01-07-d1-faster-query.mdx +++ b/src/content/changelog/d1/2025-01-07-d1-faster-query.mdx @@ -14,4 +14,4 @@ Users making [D1](/d1/) requests via the [Workers API](/d1/worker-api/) can see This performance improvement benefits all D1 Worker API traffic, especially cross-region requests where network latency is an outsized latency factor. For example, a user in Europe talking to a database in North America. D1 [location hints](/d1/configuration/data-location/#provide-a-location-hint) can be used to influence the geographic location of a database. -For more details on how D1 removed redundant round trips, see the D1 specific changelog [entry](/d1/platform/changelog/#2025-01-07). +For more details on how D1 removed redundant round trips, see the D1 specific release note [entry](/d1/platform/release-notes/#2025-01-07). diff --git a/src/content/changelog/dex/2025-03-07-cloudflare-one-device-health-monitoring.mdx b/src/content/changelog/dex/2025-03-07-cloudflare-one-device-health-monitoring.mdx new file mode 100644 index 00000000000000..e25e61e222a047 --- /dev/null +++ b/src/content/changelog/dex/2025-03-07-cloudflare-one-device-health-monitoring.mdx @@ -0,0 +1,19 @@ +--- +title: Cloudflare One Agent now supports Endpoint Monitoring +description: Monitor device health metrics directly from the Cloudflare One agent +date: 2025-03-07T6:00:00Z +--- + +[Digital Experience Monitoring (DEX)](/cloudflare-one/insights/dex/) provides visibility into device, network, and application performance across your Cloudflare SASE deployment. The latest release of the Cloudflare One agent (v2025.1.861) now includes device endpoint monitoring capabilities +to provide deeper visibility into end-user device performance which can be analyzed directly from the dashboard. + +Device health metrics are now automatically collected, allowing administrators to: +- View the last network a user was connected to +- Monitor CPU and RAM utilization on devices +- Identify resource-intensive processes running on endpoints + +![Device endpoint monitoring dashboard](~/assets/images/changelog/dex/cloudflare-one-agent-health-monitoring.gif) + +This feature complements existing DEX features like [synthetic application monitoring](/cloudflare-one/insights/dex/tests/) and [network path visualization](/cloudflare-one/insights/dex/tests/traceroute/), creating a comprehensive troubleshooting workflow that connects application performance with device state. + +For more details refer to our [DEX](/cloudflare-one/insights/dex/) documentation. diff --git a/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx b/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx new file mode 100644 index 00000000000000..d7fa895eff4ef8 --- /dev/null +++ b/src/content/changelog/email-routing/2025-03-12-reply-limits.mdx @@ -0,0 +1,51 @@ +--- +title: Threaded replies now possible in Email Workers +description: You can now use Email Workers to send multiple replies to the same email thread. +date: 2025-03-12T18:00:00Z +--- + +We’re removing some of the restrictions in Email Routing so that AI Agents and task automation can better handle email workflows, including how Workers can [reply](/email-routing/email-workers/reply-email-workers/) to incoming emails. + +It's now possible to keep a threaded email conversation with an [Email Worker](/email-routing/email-workers/) script as long as: + +* The incoming email has to have valid [DMARC](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/). +* The email can only be replied to once in the same `EmailMessage` event. +* The recipient in the reply must match the incoming sender. +* The outgoing sender domain must match the same domain that received the email. +* Every time an email passes through Email Routing or another MTA, an entry is added to the `References` list. We stop accepting replies to emails with more than 100 `References` entries to prevent abuse or accidental loops. + +Here's an example of a Worker responding to Emails using a Workers AI model: + +```ts title="AI model responding to emails" +import PostalMime from "postal-mime"; +import {createMimeMessage} from "mimetext" +import { EmailMessage } from "cloudflare:email"; + +export default { + async email(message, env, ctx) { + const email = await PostalMime.parse(message.raw) + const res = await env.AI.run('@cf/meta/llama-2-7b-chat-fp16', { + messages: [{ + role: "user", + content: email.text ?? '' + }] + }) + + // message-id is generated by mimetext + const response = createMimeMessage() + response.setHeader("In-Reply-To", message.headers.get("Message-ID")!); + response.setSender("agent@example.com"); + response.setRecipient(message.from); + response.setSubject("Llama response"); + response.addMessage({ + contentType: 'text/plain', + data: res instanceof ReadableStream ? await new Response(res).text() : res.response! + }) + + const replyMessage = new EmailMessage("", message.from, response.asRaw()); + await message.reply(replyMessage) + } +} satisfies ExportedHandler; +``` + +See [Reply to emails from Workers](/email-routing/email-workers/reply-email-workers/) for more information. \ No newline at end of file diff --git a/src/content/changelog/hyperdrive/2025-03-04-hyperdrive-pooling-near-database-and-ip-range-egress.mdx b/src/content/changelog/hyperdrive/2025-03-04-hyperdrive-pooling-near-database-and-ip-range-egress.mdx new file mode 100644 index 00000000000000..1399c9b6ba2fe4 --- /dev/null +++ b/src/content/changelog/hyperdrive/2025-03-04-hyperdrive-pooling-near-database-and-ip-range-egress.mdx @@ -0,0 +1,19 @@ +--- +title: Hyperdrive reduces query latency by up to 90% and now supports IP access control lists +description: Hyperdrive now pools database connections closer to your database to reduce query latency, and now also provides a documented IP address range for IP ACLs. +products: + - hyperdrive +date: 2025-03-07T18:00:00Z +--- + +Hyperdrive now pools database connections in one or more regions close to your database. This means that your uncached queries and new database connections have up to 90% less latency as measured from connection pools. + +![Hyperdrive query latency decreases by 90% during Hyperdrive's gradual rollout of regional pooling.](~/assets/images/hyperdrive/configuration/hyperdrive-regional-pooling-query-latency-improvement.png) + +By improving placement of Hyperdrive database connection pools, Workers' Smart Placement is now more effective when used with Hyperdrive, ensuring that your Worker can be placed as close to your database as possible. + +With this update, Hyperdrive also uses [Cloudflare's standard IP address ranges](https://www.cloudflare.com/ips/) to connect to your database. This enables you to configure the firewall policies (IP access control lists) of your database to only allow access from Cloudflare and Hyperdrive. + +Refer to [documentation on how Hyperdrive makes connecting to regional databases from Cloudflare Workers fast](/hyperdrive/configuration/how-hyperdrive-works/). + +This improvement is enabled on all Hyperdrive configurations. diff --git a/src/content/changelog/logs/2025-03-06-oneclick-logpush.mdx b/src/content/changelog/logs/2025-03-06-oneclick-logpush.mdx new file mode 100644 index 00000000000000..0364059f74a116 --- /dev/null +++ b/src/content/changelog/logs/2025-03-06-oneclick-logpush.mdx @@ -0,0 +1,15 @@ +--- +title: One-click Logpush Setup with R2 Object Storage +description: Seamlessly configure Logpush to R2 in just one click. +date: 2025-03-06T11:00:00Z +--- + +We’ve streamlined the [Logpush](/logs/get-started/) setup process by integrating R2 bucket creation directly into the Logpush workflow! + +Now, you no longer need to navigate multiple pages to manually create an R2 bucket or copy credentials. With this update, you can seamlessly **configure a Logpush job to R2 in just one click**, reducing friction and making setup faster and easier. + +This enhancement makes it easier for customers to adopt Logpush and R2. + +For more details refer to our [Logs](/logs/get-started/enable-destinations/r2/) documentation. + +![One CLick Logpush to R2](src/assets/images/changelog/logs/Oneclick.gif) diff --git a/src/content/changelog/r2/2025-03-06-r2-bucket-locks.mdx b/src/content/changelog/r2/2025-03-06-r2-bucket-locks.mdx new file mode 100644 index 00000000000000..6de77053611bd7 --- /dev/null +++ b/src/content/changelog/r2/2025-03-06-r2-bucket-locks.mdx @@ -0,0 +1,33 @@ +--- +title: Set retention polices for your R2 bucket with bucket locks +description: Set retention polices for your R2 bucket with bucket locks +products: + - r2 +date: 2025-03-06T10:00:00Z +--- + +You can now use [bucket locks](/r2/buckets/bucket-locks/) to set retention policies on your [R2 buckets](/r2/buckets/) (or specific prefixes within your buckets) for a specified period — or indefinitely. This can help ensure compliance by protecting important data from accidental or malicious deletion. + +Locks give you a few ways to ensure your objects are retained (not deleted or overwritten). You can: + +- Lock objects for a specific duration, for example 90 days. +- Lock objects until a certain date, for example January 1, 2030. +- Lock objects indefinitely, until the lock is explicitly removed. + +Buckets can have up to 1,000 [bucket lock rules](/r2/buckets/). Each rule specifies which objects it covers (via prefix) and how long those objects must remain retained. + +Here are a couple of examples showing how you can configure bucket lock rules using [Wrangler](/workers/wrangler/): + +#### Ensure all objects in a bucket are retained for at least 180 days + +```sh +npx wrangler r2 bucket lock add --name 180-days-all --retention-days 180 +``` + +#### Prevent deletion or overwriting of all logs indefinitely (via prefix) + +```sh +npx wrangler r2 bucket lock add --name indefinite-logs --prefix logs/ --retention-indefinite +``` + +For more information on bucket locks and how to set retention policies for objects in your R2 buckets, refer to our [documentation](/r2/buckets/bucket-locks/). diff --git a/src/content/changelog/radar/2025-02-27-radar-dns-insights.mdx b/src/content/changelog/radar/2025-02-27-radar-dns-insights.mdx new file mode 100644 index 00000000000000..28cc89fbb154f8 --- /dev/null +++ b/src/content/changelog/radar/2025-02-27-radar-dns-insights.mdx @@ -0,0 +1,32 @@ +--- +title: DNS Insights in Cloudflare Radar +description: Expanded DNS insights with new API endpoints for 1.1.1.1 resolver aggregated traffic data +products: + - radar +date: 2025-02-27T15:00:00Z +--- + +[**Radar**](/radar/) has expanded its DNS insights, providing visibility into aggregated traffic and usage trends observed by our [1.1.1.1](/1.1.1.1/) DNS resolver. +In addition to global, location, and ASN traffic trends, we are also providing perspectives on protocol usage, query/response characteristics, and DNSSEC usage. + +Previously limited to the [`top`](/api/resources/radar/subresources/dns/subresources/top/) locations and ASes endpoints, we have now introduced the following endpoints: + +- [`timeseries`](/api/resources/radar/subresources/dns/methods/timeseries/): Retrieves DNS query volume over time. +- [`summary`](/api/resources/radar/subresources/dns/subresources/summary/): Retrieves summaries of DNS query distribution across ten different dimensions. +- [`timeseries_group`](/api/resources/radar/subresources/dns/subresources/timeseries_groups/): Retrieves timeseries data for DNS query distribution across ten different dimensions. + +For the `summary` and `timeseries_groups` endpoints, the following dimensions are available, displaying the distribution of DNS queries based on: + +- `cache_hit`: Cache status (hit vs. miss). +- `dnsssec`: DNSSEC support status (secure, insecure, invalid or other). +- `dnsssec_aware`: DNSSEC client awareness (aware vs. not-aware). +- `dnsssec_e2e`: End-to-end security (secure vs. insecure). +- `ip_version`: IP version (IPv4 vs. IPv6). +- `matching_answer`: Matching answer status (match vs. no-match). +- `protocol`: Transport protocol (UDP, TLS, HTTPS or TCP). +- `query_type`: Query type (`A`, `AAAA`, `PTR`, etc.). +- `response_code`: Response code (`NOERROR`, `NXDOMAIN`, `REFUSED`, etc.). +- `response_ttl`: Response TTL. + + +Learn more about the new Radar DNS insights in our [blog post](https://blog.cloudflare.com/new-dns-section-on-cloudflare-radar/), and check out the [new Radar page](https://radar.cloudflare.com/dns). diff --git a/src/content/changelog/radar/2025-03-18-radar-leaked-credentials-insights.mdx b/src/content/changelog/radar/2025-03-18-radar-leaked-credentials-insights.mdx new file mode 100644 index 00000000000000..6a049555afbee8 --- /dev/null +++ b/src/content/changelog/radar/2025-03-18-radar-leaked-credentials-insights.mdx @@ -0,0 +1,23 @@ +--- +title: Leaked Credentials Insights in Cloudflare Radar +description: Expanded security insights with new API endpoints for aggregated authentication request data +products: + - radar +date: 2025-03-18T14:00:00Z +--- + +[**Radar**](/radar/) has expanded its security insights, providing visibility into aggregate trends in authentication requests, +including the detection of leaked credentials through [leaked credentials detection](/waf/detections/leaked-credentials/) scans. + +We have now introduced the following endpoints: + +- [`summary`](/api/resources/radar/subresources/leaked_credentials/subresources/summary/): Retrieves summaries of HTTP authentication requests distribution across two different dimensions. +- [`timeseries_group`](/api/resources/radar/subresources/leaked_credentials/subresources/timeseries_groups/): Retrieves timeseries data for HTTP authentication requests distribution across two different dimensions. + +The following dimensions are available, displaying the distribution of HTTP authentication requests based on: + +- `compromised`: Credential status (clean vs. compromised). +- `bot_class`: [Bot class](/radar/concepts/bot-classes) (human vs. bot). + + +Dive deeper into leaked credential detection in this [blog post](https://blog.cloudflare.com/password-reuse-rampant-half-user-logins-compromised/) and learn more about the expanded Radar security insights in our [blog post](https://blog.cloudflare.com/cloudflare-radar-ddos-leaked-credentials-bots). diff --git a/src/content/changelog/stream/2025-03-06-media-transformations.mdx b/src/content/changelog/stream/2025-03-06-media-transformations.mdx new file mode 100644 index 00000000000000..8eb85b5f4a38d5 --- /dev/null +++ b/src/content/changelog/stream/2025-03-06-media-transformations.mdx @@ -0,0 +1,49 @@ +--- +title: Introducing Media Transformations from Cloudflare Stream +description: > + Dynamically optimize, clip, and resize video from any origin, no storage + migration needed. +date: 2025-03-06T12:00:00Z +--- + +Today, we are thrilled to announce Media Transformations, a new service that +brings the magic of [Image Transformations](/images/transform-images/) to +_short-form video files,_ wherever they are stored! + +For customers with a huge volume of short video — generative AI output, +e-commerce product videos, social media clips, or short marketing content — +uploading those assets to Stream is not always practical. Sometimes, the +greatest friction to getting started was the thought of all that migrating. +Customers want a simpler solution that retains their current storage strategy to +deliver small, optimized MP4 files. Now you can do that with Media +Transformations. + +To transform a video or image, +[enable transformations](/stream/transform-videos/#getting-started) for your +zone, then make a simple request with a specially formatted URL. The result is +an MP4 that can be used in an HTML video element without a player library. +If your zone already has Image Transformations enabled, then it is ready to +optimize videos with Media Transformations, too. + +``` text title="URL format" +https://example.com/cdn-cgi/media// +``` + +For example, we have a short video of the mobile in Austin's office. The +original is nearly 30 megabytes and wider than necessary for this layout. +Consider a simple width adjustment: + + + +``` text title="Example URL" +https://example.com/cdn-cgi/media/width=640/ +https://developers.cloudflare.com/cdn-cgi/media/width=640/https://pub-d9fcbc1abcd244c1821f38b99017347f.r2.dev/aus-mobile.mp4 +``` + +The result is less than 3 megabytes, properly sized, and delivered dynamically +so that customers do not have to manage the creation and storage of these +transformed assets. + +For more information, learn about [Transforming Videos](/stream/transform-videos/). diff --git a/src/content/changelog/web-analytics/2025-02-25-rum-exclude-eu.mdx b/src/content/changelog/web-analytics/2025-02-25-rum-exclude-eu.mdx new file mode 100644 index 00000000000000..f4ceee60ddfb7c --- /dev/null +++ b/src/content/changelog/web-analytics/2025-02-25-rum-exclude-eu.mdx @@ -0,0 +1,15 @@ + +--- +title: Easily Exclude EU Visitors from RUM +description: Enable RUM monitoring for your website and respect privacy laws with ease. +date: 2024-02-26T11:00:00Z +--- +You can now easily enable Real User Monitoring (RUM) monitoring for your hostnames, while safely dropping requests from visitors in the European Union to comply with GDPR and CCPA. + +![RUM Enablement UI](~/assets/images/changelog/web-analytics/2025-02-26-rum-eu.png) + +Our Web Analytics product has always been centered on giving you insights into your users' experience that you need to provide the best quality experience, without sacrificing user privacy in the process. + +To help with that aim, you can now selectively enable RUM monitoring for your hostname and exclude EU visitor data in a single click. If you opt for this option, we will drop all metrics collected by our EU data centeres automatically. + +You can learn more about what metrics are reported by Web Analytics and how it is collected [in the Web Analytics documentation](/web-analytics/data-metrics/). You can enable Web Analytics on any hostname by going to the [Web Analytics](https://dash.cloudflare.com/?to=/:account/web-analytics/sites) section of the dashboard, selecting "Manage Site" for the hostname you want to monitor, and choosing the appropriate enablement option. \ No newline at end of file diff --git a/src/content/changelog/workers-ai/2025-02-25-json-mode.mdx b/src/content/changelog/workers-ai/2025-02-25-json-mode.mdx index a7bf9d52039d60..98d13202fe7903 100644 --- a/src/content/changelog/workers-ai/2025-02-25-json-mode.mdx +++ b/src/content/changelog/workers-ai/2025-02-25-json-mode.mdx @@ -1,7 +1,70 @@ --- -title: Workers AI JSON Mode +title: Workers AI now supports structured JSON outputs. description: Workers AI JSON Mode adds structured outputs support date: 2025-02-25T15:00:00Z --- -We've updated the Workers AI to support [JSON mode](/workers-ai/json-mode/), enabling applications to request a structured output response when interacting with AI models. \ No newline at end of file +import { TypeScriptExample } from "~/components"; + +Workers AI now supports structured JSON outputs with [JSON mode](/workers-ai/json-mode/), which allows you to request a structured output response when interacting with AI models. + +This makes it much easier to retrieve structured data from your AI models, and avoids the (error prone!) need to parse large unstructured text responses to extract your data. + +JSON mode in Workers AI is compatible with the OpenAI SDK's [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) `response_format` API, which can be used directly in a Worker: + + + +```ts +import { OpenAI } from "openai"; + +interface Env { + OPENAI_API_KEY: string; +} + +// Define your JSON schema for a calendar event +const CalendarEventSchema = { + type: 'object', + properties: { + name: { type: 'string' }, + date: { type: 'string' }, + participants: { type: 'array', items: { type: 'string' } }, + }, + required: ['name', 'date', 'participants'] +}; + +export default { + async fetch(request: Request, env: Env) { + const client = new OpenAI({ + apiKey: env.OPENAI_API_KEY, + // Optional: use AI Gateway to bring logs, evals & caching to your AI requests + // https://developers.cloudflare.com/ai-gateway/providers/openai/ + // baseUrl: "https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai" + }); + + const response = await client.chat.completions.create({ + model: 'gpt-4o-2024-08-06', + messages: [ + { role: 'system', content: 'Extract the event information.' }, + { role: 'user', content: 'Alice and Bob are going to a science fair on Friday.' }, + ], + // Use the `response_format` option to request a structured JSON output + response_format: { + // Set json_schema and provide ra schema, or json_object and parse it yourself + type: 'json_schema', + schema: CalendarEventSchema, // provide a schema + }, + }); + + // This will be of type CalendarEventSchema + const event = response.choices[0].message.parsed; + + return Response.json({ + "calendar_event": event, + }) + } +} +``` + + + +To learn more about JSON mode and structured outputs, visit the [Workers AI documentation](/workers-ai/json-mode/). \ No newline at end of file diff --git a/src/content/changelog/workers-ai/2025-03-17-new-workers-ai-models.mdx b/src/content/changelog/workers-ai/2025-03-17-new-workers-ai-models.mdx new file mode 100644 index 00000000000000..26524d1da7df31 --- /dev/null +++ b/src/content/changelog/workers-ai/2025-03-17-new-workers-ai-models.mdx @@ -0,0 +1,17 @@ +--- +title: New models in Workers AI +description: New text-to-speech, reranker, whisper, embeddings models now available! +date: 2025-03-17T17:00:00Z +--- + +Workers AI is excited to add 4 new models to the catalog, including 2 brand new classes of models with a text-to-speech and reranker model. Introducing: +- [@cf/baai/bge-m3](/workers-ai/models/bge-m3/) - a multi-lingual embeddings model that supports over 100 languages. It can also simultaneously perform dense retrieval, multi-vector retrieval, and sparse retrieval, with the ability to process inputs of different granularities. +- [@cf/baai/bge-reranker-base](/workers-ai/models/bge-reranker-base/) - our first reranker model! Rerankers are a type of text classification model that takes a query and context, and outputs a similarity score between the two. When used in RAG systems, you can use a reranker after the initial vector search to find the most relevant documents to return to a user by reranking the outputs. +- [@cf/openai/whisper-large-v3-turbo](/workers-ai/models/whisper-large-v3-turbo/) - a faster, more accurate speech-to-text model. This model was added earlier but is graduating out of beta with pricing included today. +- [@cf/myshell-ai/melotts](/workers-ai/models/melotts/) - our first text-to-speech model that allows users to generate an MP3 with voice audio from inputted text. + +Pricing is available for each of these models on the [Workers AI pricing page](/workers-ai/platform/pricing/). + +This docs update includes a few minor bug fixes to the model schema for llama-guard, llama-3.2-1b, which you can review on the [product changelog](/workers-ai/changelog/). + +Try it out and let us know what you think! Stay tuned for more models in the coming days. \ No newline at end of file diff --git a/src/content/changelog/workers-ai/2025-03-20-markdown-conversion.mdx b/src/content/changelog/workers-ai/2025-03-20-markdown-conversion.mdx new file mode 100644 index 00000000000000..fdb6200d1111e3 --- /dev/null +++ b/src/content/changelog/workers-ai/2025-03-20-markdown-conversion.mdx @@ -0,0 +1,62 @@ +--- +title: Markdown conversion in Workers AI +description: You can now convert documents in multiple formats to Markdown using the toMarkdown utility method in Workers AI. +date: 2025-03-20T18:00:00Z +--- + +Document conversion plays an important role when designing and developing AI applications and agents. Workers AI now provides the `toMarkdown` utility method that developers can use to for quick, easy, and convenient conversion and summary of documents in multiple formats to Markdown language. + +You can call this new tool using a binding by calling `env.AI.toMarkdown()` or the using the [REST API](/api/resources/ai/) endpoint. + +In this example, we fetch a PDF document and an image from R2 and feed them both to `env.AI.toMarkdown()`. The result is a list of converted documents. Workers AI models are used automatically to detect and summarize the image. + +```typescript +import { Env } from "./env"; + +export default { + async fetch(request: Request, env: Env, ctx: ExecutionContext) { + + // https://pub-979cb28270cc461d94bc8a169d8f389d.r2.dev/somatosensory.pdf + const pdf = await env.R2.get('somatosensory.pdf'); + + // https://pub-979cb28270cc461d94bc8a169d8f389d.r2.dev/cat.jpeg + const cat = await env.R2.get('cat.jpeg'); + + return Response.json( + await env.AI.toMarkdown([ + { + name: "somatosensory.pdf", + blob: new Blob([await pdf.arrayBuffer()], { type: "application/octet-stream" }), + }, + { + name: "cat.jpeg", + blob: new Blob([await cat.arrayBuffer()], { type: "application/octet-stream" }), + }, + ]), + ); + }, +}; +``` + +This is the result: + +```json +[ + { + "name": "somatosensory.pdf", + "mimeType": "application/pdf", + "format": "markdown", + "tokens": 0, + "data": "# somatosensory.pdf\n## Metadata\n- PDFFormatVersion=1.4\n- IsLinearized=false\n- IsAcroFormPresent=false\n- IsXFAPresent=false\n- IsCollectionPresent=false\n- IsSignaturesPresent=false\n- Producer=Prince 20150210 (www.princexml.com)\n- Title=Anatomy of the Somatosensory System\n\n## Contents\n### Page 1\nThis is a sample document to showcase..." + }, + { + "name": "cat.jpeg", + "mimeType": "image/jpeg", + "format": "markdown", + "tokens": 0, + "data": "The image is a close-up photograph of Grumpy Cat, a cat with a distinctive grumpy expression and piercing blue eyes. The cat has a brown face with a white stripe down its nose, and its ears are pointed upright. Its fur is light brown and darker around the face, with a pink nose and mouth. The cat's eyes are blue and slanted downward, giving it a perpetually grumpy appearance. The background is blurred, but it appears to be a dark brown color. Overall, the image is a humorous and iconic representation of the popular internet meme character, Grumpy Cat. The cat's facial expression and posture convey a sense of displeasure or annoyance, making it a relatable and entertaining image for many people." + } +] +``` + +See [Markdown Conversion](/workers-ai/markdown-conversion/) for more information on supported formats, REST API and pricing. \ No newline at end of file diff --git a/src/content/changelog/workers/2025-02-28-wrangler-v4-rc.mdx b/src/content/changelog/workers/2025-02-28-wrangler-v4-rc.mdx new file mode 100644 index 00000000000000..baf68eab12a1ff --- /dev/null +++ b/src/content/changelog/workers/2025-02-28-wrangler-v4-rc.mdx @@ -0,0 +1,64 @@ +--- +title: Use the latest JavaScript features with Wrangler CLI v4.0.0-rc.0 +description: You can now try out the v4 RC for Wrangler by installing `wrangler@4.0.0-rc.0` +products: + - workers +date: 2025-02-28T22:30:00Z +--- + +import { PackageManagers } from "~/components"; + +We've released a release candidate of the next major version of [Wrangler](/workers/wrangler/), the CLI for Cloudflare Workers — `wrangler@4.0.0-rc.0`. + +You can run the following command to install it and be one of the first to try it out: + + + +Unlike previous major versions of Wrangler, which were [foundational rewrites](https://blog.cloudflare.com/wrangler-v2-beta/) and [rearchitectures](https://blog.cloudflare.com/wrangler3/) — Version 4 of Wrangler includes a much smaller set of changes. If you use Wrangler today, your workflow is very unlikely to change. Before we release Wrangler v4 and advance past the release candidate stage, we'll share a detailed migration guide in the Workers developer docs. But for the vast majority of cases, you won't need to do anything to migrate — things will just work as they do today. We are sharing this release candidate in advance of the official release of v4, so that you can try it out early and share feedback. + +#### New JavaScript language features that you can now use with Wrangler v4 + +Version 4 of Wrangler updates the version of [esbuild](https://esbuild.github.io/) that Wrangler uses internally, allowing you to use modern JavaScript language features, including: + +##### The `using` keyword from Explicit Resource Management + +The [`using` keyword from the Explicit Resource Management standard](/workers/runtime-apis/rpc/lifecycle/#explicit-resource-management) makes it easier to work with the [JavaScript-native RPC system built into Workers](/workers/runtime-apis/rpc/). This means that when you obtain a stub, you can ensure that it is automatically disposed when you exit scope it was created in: + +```js +function sendEmail(id, message) { + using user = await env.USER_SERVICE.findUser(id); + await user.sendEmail(message); + + // user[Symbol.dispose]() is implicitly called at the end of the scope. +} +``` + +##### Import attributes + +[Import attributes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with) allow you to denote the type or other attributes of the module that your code imports. For example, you can import a JSON module, using the following syntax: + +```js +import data from "./data.json" with { type: "json" }; +``` + +#### Other changes + +##### `--local` is now the default for all CLI commands + +All commands that access resources (for example, `wrangler kv`, `wrangler r2`, `wrangler d1`) now access local datastores by default, ensuring consistent behavior. + +##### Clearer policy for the minimum required version of Node.js required to run Wrangler + +Moving forward, the [active, maintenance, and current versions of Node.js](https://nodejs.org/en/about/previous-releases) will be officially supported by Wrangler. This means the minimum officially supported version of Node.js you must have installed for Wrangler v4 will be Node.js v18 or later. This policy mirrors how many other packages and CLIs support older versions of Node.js, and ensures that as long as you are using a version of Node.js that the Node.js project itself supports, this will be supported by Wrangler as well. + +##### Features previously deprecated in Wrangler v3 are now removed in Wrangler v4 + +All previously deprecated features in [Wrangler v2](https://developers.cloudflare.com/workers/wrangler/deprecations/#wrangler-v2) and in [Wrangler v3](https://developers.cloudflare.com/workers/wrangler/deprecations/#wrangler-v3) have now been removed. Additionally, the following features that were deprecated during the Wrangler v3 release have been removed: + +- Legacy Assets (using `wrangler dev/deploy --legacy-assets` or the `legacy_assets` config file property). Instead, we recommend you [migrate to Workers assets](https://developers.cloudflare.com/workers/static-assets/). +- Legacy Node.js compatibility (using `wrangler dev/deploy --node-compat` or the `node_compat` config file property). Instead, use the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs). This includes the functionality from legacy `node_compat` polyfills and natively implemented Node.js APIs. +- `wrangler version`. Instead, use `wrangler --version` to check the current version of Wrangler. +- `getBindingsProxy()` (via `import { getBindingsProxy } from "wrangler"`). Instead, use the [`getPlatformProxy()` API](https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy), which takes exactly the same arguments. +- `usage_model`. This no longer has any effect, after the [rollout of Workers Standard Pricing](https://blog.cloudflare.com/workers-pricing-scale-to-zero/). + +We'd love your feedback! If you find a bug or hit a roadblock when upgrading to Wrangler v4, [open an issue on the `cloudflare/workers-sdk` repository on GitHub](https://github.com/cloudflare/workers-sdk/issues/new?template=bug-template.yaml). diff --git a/src/content/changelog/workers/2025-03-11-process-env-support.mdx b/src/content/changelog/workers/2025-03-11-process-env-support.mdx new file mode 100644 index 00000000000000..b0e1b4b65457e1 --- /dev/null +++ b/src/content/changelog/workers/2025-03-11-process-env-support.mdx @@ -0,0 +1,47 @@ +--- +title: Access your Worker's environment variables from process.env +description: With Node.js compatability on, process.env is automatically populated with environment variables and secrets +products: + - workers +date: 2025-03-11T15:00:00Z +--- + +import { WranglerConfig } from "~/components"; + +You can now access [environment variables](/workers/configuration/environment-variables/) and +[secrets](/workers/configuration/secrets/) on [`process.env`](/workers/runtime-apis/nodejs/process/#processenv) +when using the [`nodejs_compat` compatability flag](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag). + +```js +const apiClient = ApiClient.new({ apiKey: process.env.API_KEY }); +const LOG_LEVEL = process.env.LOG_LEVEL || "info"; +``` + +In Node.js, environment variables are exposed via the global `process.env` object. Some libraries +assume that this object will be populated, and many developers may be used to accessing variables +in this way. + +Previously, the `process.env` object was always empty unless written to in Worker code. This could +cause unexpected errors or friction when developing Workers using code previously written for Node.js. + +Now, [environment variables](/workers/configuration/environment-variables/), +[secrets](/workers/configuration/secrets/), and [version metadata](/workers/runtime-apis/bindings/version-metadata/) +can all be accessed on `process.env`. + +To opt-in to the new `process.env` behaviour now, add the [`nodejs_compat_populate_process_env`](/workers/configuration/compatibility-flags/#enable-auto-populating-processenv) compatibility flag to your +`wrangler.json` configuration: + + + +```jsonc +{ + // Rest of your configuration + // Add "nodejs_compat_populate_process_env" to your compatibility_flags array + "compatibility_flags": ["nodejs_compat", "nodejs_compat_populate_process_env"], + // Rest of your configuration +``` + + + +After April 1, 2025, populating `process.env` will become the default behavior when both `nodejs_compat` is enabled and +your Worker's `compatability_date` is after "2025-04-01". diff --git a/src/content/changelog/workers/2025-03-13-wrangler-v4.mdx b/src/content/changelog/workers/2025-03-13-wrangler-v4.mdx new file mode 100644 index 00000000000000..7cfebc29a45924 --- /dev/null +++ b/src/content/changelog/workers/2025-03-13-wrangler-v4.mdx @@ -0,0 +1,21 @@ +--- +title: Use the latest JavaScript features with Wrangler CLI v4 +description: Wrangler v4 is available! +products: + - workers +date: 2025-03-13T09:00:00Z +--- + +import { PackageManagers } from "~/components"; + +We've released the next major version of [Wrangler](/workers/wrangler/), the CLI for Cloudflare Workers — `wrangler@4.0.0`. Wrangler v4 is a major release focused on updates to underlying systems and dependencies, along with improvements to keep Wrangler commands consistent and clear. + +You can run the following command to install it in your projects: + + + +Unlike previous major versions of Wrangler, which were [foundational rewrites](https://blog.cloudflare.com/wrangler-v2-beta/) and [rearchitectures](https://blog.cloudflare.com/wrangler3/) — Version 4 of Wrangler includes a much smaller set of changes. If you use Wrangler today, your workflow is very unlikely to change. + +A [detailed migration guide](/workers/wrangler/migration/update-v3-to-v4) is available and if you find a bug or hit a roadblock when upgrading to Wrangler v4, [open an issue on the `cloudflare/workers-sdk` repository on GitHub](https://github.com/cloudflare/workers-sdk/issues/new?template=bug-template.yaml). + +Going forward, we'll continue supporting Wrangler v3 with bug fixes and security updates until Q1 2026, and with critical security updates until Q1 2027, at which point it will be out of support. diff --git a/src/content/changelog/workers/2025-03-14-breakpoint-debugging-with-vitest.mdx b/src/content/changelog/workers/2025-03-14-breakpoint-debugging-with-vitest.mdx new file mode 100644 index 00000000000000..6afc6360af74eb --- /dev/null +++ b/src/content/changelog/workers/2025-03-14-breakpoint-debugging-with-vitest.mdx @@ -0,0 +1,17 @@ +--- +title: Set breakpoints and debug your Workers tests with @cloudflare/vitest-pool-workers +description: You can now debug your workers tests with the Workers <> Vitest integration +products: + - workers +date: 2025-03-13T14:00:00Z +--- + +You can now debug your Workers tests with our [Vitest integration](/workers/testing/vitest-integration/) by running the following command: + +```sh +vitest --inspect --no-file-parallelism +``` + +Attach a debugger to the port 9229 and you can start stepping through your Workers tests. This is available with `@cloudflare/vitest-pool-workers` v0.7.5 or later. + +Learn more in our [documentation](/workers/testing/vitest-integration/debugging/). diff --git a/src/content/changelog/workers/2025-03-17-importable-env.mdx b/src/content/changelog/workers/2025-03-17-importable-env.mdx new file mode 100644 index 00000000000000..7282d14bdc3b70 --- /dev/null +++ b/src/content/changelog/workers/2025-03-17-importable-env.mdx @@ -0,0 +1,67 @@ +--- +title: Import `env` to access bindings in your Worker's global scope +description: More easily configure your Worker and call bindings from anywhere with an importable `env` +products: + - workers +date: 2025-03-17T15:00:00Z +--- + +import { Render, TypeScriptExample } from "~/components"; + +You can now access [bindings](/workers/runtime-apis/bindings/) +from anywhere in your Worker by importing the `env` object from `cloudflare:workers`. + +Previously, `env` could only be accessed during a request. This meant that +bindings could not be used in the top-level context of a Worker. + +Now, you can import `env` and access bindings such as [secrets](/workers/configuration/secrets/) +or [environment variables](/workers/configuration/environment-variables/) in the +initial setup for your Worker: + +```js +import { env } from "cloudflare:workers"; +import ApiClient from "example-api-client"; + +// API_KEY and LOG_LEVEL now usable in top-level scope +const apiClient = ApiClient.new({ apiKey: env.API_KEY }); +const LOG_LEVEL = env.LOG_LEVEL || "info"; + +export default { + fetch(req) { + // you can use apiClient or LOG_LEVEL, configured before any request is handled + }, +}; +``` + +:::note +Workers do not allow I/O from outside a request context. This means that even +though `env` is accessible from the top-level scope, you will not be able to access +every binding's methods. + +For instance, environment variables and secrets are accessible, and you are able to +call `env.NAMESPACE.get` to get a [Durable Object stub](/durable-objects/api/stub/) in the +top-level context. However, calling methods on the Durable Object stub, making [calls to a KV store](/kv/api/), +and [calling to other Workers](/workers/runtime-apis/bindings/service-bindings) will not work. +::: + +Additionally, `env` was normally accessed as a argument to a Worker's entrypoint handler, +such as [`fetch`](/workers/runtime-apis/fetch/). +This meant that if you needed to access a binding from a deeply nested function, +you had to pass `env` as an argument through many functions to get it to the +right spot. This could be cumbersome in complex codebases. + +Now, you can access the bindings from anywhere in your codebase +without passing `env` as an argument: + +```js +// helpers.js +import { env } from "cloudflare:workers"; + +// env is *not* an argument to this function +export async function getValue(key) { + let prefix = env.KV_PREFIX; + return await env.KV.get(`${prefix}-${key}`); +} +``` + +For more information, see [documentation on accessing `env`](/workers/runtime-apis/bindings#how-to-access-env). diff --git a/src/content/changelog/workers/2025-03-17-rerun-build.mdx b/src/content/changelog/workers/2025-03-17-rerun-build.mdx new file mode 100644 index 00000000000000..400aeba2eaac7d --- /dev/null +++ b/src/content/changelog/workers/2025-03-17-rerun-build.mdx @@ -0,0 +1,23 @@ +--- +title: Retry Pages & Workers Builds Directly from GitHub +description: Rerun builds for your Workers and Pages projects directly inside of GitHub. +products: + - workers + - pages +date: 2025-03-17T11:00:00Z +--- + +You can now retry your Cloudflare Pages and Workers builds directly from GitHub. No need to switch to the Cloudflare Dashboard for a simple retry! + +![Workers Builds GitHub Reruns](src/assets/images/changelog/workers/builds-rerun.gif) + +Let’s say you push a commit, but your build fails due to a spurious error like a network timeout. Instead of going to the Cloudflare Dashboard to manually retry, you can now rerun the build with just a few clicks inside GitHub, keeping you inside your workflow. + +For Pages and Workers projects connected to a GitHub repository: + +1. When a build fails, go to your GitHub repository or pull request +2. Select the failed Check Run for the build +3. Select "Details" on the Check Run +4. Select "Rerun" to trigger a retry build for that commit + +Learn more about [Pages Builds](/pages/configuration/git-integration/github-integration/) and [Workers Builds](/workers/ci-cd/builds/git-integration/github-integration/). diff --git a/src/content/changelog/workers/2025-03-22-next-js-vulnerability-waf.mdx b/src/content/changelog/workers/2025-03-22-next-js-vulnerability-waf.mdx new file mode 100644 index 00000000000000..a413a32723f860 --- /dev/null +++ b/src/content/changelog/workers/2025-03-22-next-js-vulnerability-waf.mdx @@ -0,0 +1,66 @@ +--- +title: New Managed WAF rule for Next.js CVE-2025-29927. +description: Automatic deployment of a Web Application Firewall rule to block requests that attempt to bypass authentication in Next.js applications as part of CVE-2025-29927. +products: + - workers + - pages + - waf + - rules +date: 2025-03-22T13:00:00Z +--- + +import { Image } from 'astro:assets'; +import managedRuleNextJsAuth from "~/assets/images/changelog/workers/high-res-CVE-2025-29927.gif" + +**Update**: We have changed this WAF rule to opt-in only, as sites that use auth middleware with third-party auth vendors were observing failing requests. + +**We strongly recommend updating your version of Next.js (if eligible)** to the patched versions, as your app will otherwise be vulnerable to an authentication bypass attack regardless of auth provider. + +### Enable the Managed Rule (strongly recommended) + +This rule is opt-in only for sites on the Pro plan or above in the [WAF managed ruleset](/waf/managed-rules/). + +To enable the rule: + +1. Head to Security > WAF > Managed rules in the Cloudflare dashboard for the zone (website) you want to protect. +2. Click the three dots next to **Cloudflare Managed Ruleset** and choose **Edit** +3. Scroll down and choose **Browse Rules** +4. Search for **CVE-2025-29927** (ruleId: `34583778093748cc83ff7b38f472013e`) +5. Change the **Status** to **Enabled** and the **Action** to **Block**. You can optionally set the rule to Log, to validate potential impact before enabling it. Log will not block requests. +6. Click **Next** +7. Scroll down and choose **Save** + +Enable the CVE-2025-29927 rule + +This will enable the WAF rule and block requests with the `x-middleware-subrequest` header regardless of Next.js version. + +### Create a WAF rule (manual) + +For users on the Free plan, or who want to define a more specific rule, you can create a [Custom WAF rule](/waf/custom-rules/create-dashboard/) to block requests with the `x-middleware-subrequest` header regardless of Next.js version. + +To create a custom rule: + +1. Head to Security > WAF > Custom rules in the Cloudflare dashboard for the zone (website) you want to protect. +2. Give the rule a name - e.g. `next-js-CVE-2025-29927` +3. Set the matching parameters for the rule match any request where the `x-middleware-subrequest` header `exists` per the rule expression below. + +```sh +(len(http.request.headers["x-middleware-subrequest"]) > 0) +``` + +4. Set the action to 'block'. If you want to observe the impact before blocking requests, set the action to 'log' (and edit the rule later). +5. **Deploy** the rule. + +![Next.js CVE-2025-29927 WAF rule](src/assets/images/changelog/workers/waf-rule-cve-2025-29927.png) + +### Next.js CVE-2025-29927 + +We've made a WAF (Web Application Firewall) rule available to all sites on Cloudflare to protect against the [Next.js authentication bypass vulnerability](https://github.com/advisories/GHSA-f82v-jwr5-mffw) (`CVE-2025-29927`) published on March 21st, 2025. + +**Note**: This rule is not enabled by default as it blocked requests across sites for specific authentication middleware. + +* This managed rule protects sites using Next.js on Workers and Pages, as well as sites using Cloudflare to protect Next.js applications hosted elsewhere. +* This rule has been made avaiable (but not enabled by default) to all sites as part of our [WAF Managed Ruleset](/waf/managed-rules/reference/cloudflare-managed-ruleset/) and blocks requests that attempt to bypass authentication in Next.js applications. +* The vulnerability affects almost all Next.js versions, and is patched in Next.js `14.2.25` and `15..2.3`. **Users on older versions of Next.js (`11.1.4` to `13.5.6`) do not have a patch available**. + +The managed WAF rule mitigates this by blocking _external_ user requests with the `x-middleware-subrequest` header regardless of Next.js version, but we recommend users using Next.js 14 and 15 upgrade to the patched versions of Next.js as an additional mitigation. diff --git a/src/content/changelog/workflows/2025-02-25-workflows-concurrency-increased.mdx b/src/content/changelog/workflows/2025-02-25-workflows-concurrency-increased.mdx new file mode 100644 index 00000000000000..3c5daf42f1036c --- /dev/null +++ b/src/content/changelog/workflows/2025-02-25-workflows-concurrency-increased.mdx @@ -0,0 +1,12 @@ +--- +title: Concurrent Workflow instances limits increased. +description: Increased concurrency limits for Workflows instances + - workflows +date: 2025-02-25T15:00:00Z +--- + +import { Render, PackageManagers, TypeScriptExample } from "~/components" + +[Workflows](/workflows/) now supports up to 4,500 concurrent (running) instances, up from the previous limit of 100. This limit will continue to increase during the Workflows open beta. This increase applies to all users on the Workers Paid plan, and takes effect immediately. + +Review the Workflows [limits documentation](/workflows/reference/limits) and/or dive into the [get started guide](/workflows/get-started/guide/) to start building on Workflows. diff --git a/src/content/compatibility-flags/nodejs-compat-populate-process-env.md b/src/content/compatibility-flags/nodejs-compat-populate-process-env.md new file mode 100644 index 00000000000000..e2be83bfacf179 --- /dev/null +++ b/src/content/compatibility-flags/nodejs-compat-populate-process-env.md @@ -0,0 +1,25 @@ +--- +name: "Enable auto-populating `process.env`" +sort_date: "2025-02-27" +enable_date: "2025-04-01" +enable_flag: "nodejs_compat_populate_process_env" +disable_flag: "nodejs_compat_do_not_populate_process_env" +--- + +When you enable the `nodejs_compat_populate_process_env` compatibility flag and the [`nodejs_compat`](/workers/runtime-apis/nodejs/) +flag is also enabled, `process.env` will be populated with values from any bindings with text or JSON values. +This means that if you have added [environment variables](/workers/configuration/environment-variables/), +[secrets](/workers/configuration/secrets/), or [version metadata](/workers/runtime-apis/bindings/version-metadata/) +bindings, these values can be accessed on `process.env`. + +```js +const apiClient = ApiClient.new({ apiKey: process.env.API_KEY }); +const LOG_LEVEL = process.env.LOG_LEVEL || "info"; +``` + +This makes accessing these values easier and conforms to common Node.js patterns, which can +reduce toil and help with compatability for existing Node.js libraries. + +If users do not wish for these values to be accessible via `process.env`, they can use the +`nodejs_compat_do_not_populate_process_env` flag. In this case, `process.env` will still be +available, but will not have values automatically added. diff --git a/src/content/compatibility-flags/queue-consumer-no-wait-waituntil.md b/src/content/compatibility-flags/queue-consumer-no-wait-waituntil.md new file mode 100644 index 00000000000000..82a917d18ac516 --- /dev/null +++ b/src/content/compatibility-flags/queue-consumer-no-wait-waituntil.md @@ -0,0 +1,38 @@ +--- +_build: + publishResources: false + render: never + list: never + +name: "Queue consumers don't wait for `ctx.waitUntil()` to resolve" +sort_date: "2025-03-19" +experimental: true +enable_flag: "queue_consumer_no_wait_for_wait_until" +--- + +By default, [Queues](/queues/) Consumer Workers acknowledge messages only after promises passed to [`ctx.waitUntil()`](/workers/runtime-apis/context) have resolved. This behavior can cause queue consumers which utilize `ctx.waitUntil()` to process messages slowly. The default behavior is documented in the [Queues Consumer Configuration Guide](/queues/configuration/javascript-apis#consumer). + +This Consumer Worker is an example of a Worker which utilizes `ctx.waitUntil()`. Under the default behavior, this consumer Worker will only acknowledge a batch of messages after the sleep function has resolved. +```js +export default { + async fetch(request, env, ctx) { + // omitted + }, + + async queue(batch, env, ctx) { + console.log(`received batch of ${batch.messages.length} messages to queue ${batch.queue}`); + for (let i = 0; i < batch.messages.length; ++i) { + console.log(`message #${i}: ${JSON.stringify(batch.messages[i])}`); + } + ctx.waitUntil(sleep(30 * 1000)); + } +}; + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} +``` + +If the `queue_consumer_no_wait_for_wait_until` flag is enabled, Queues consumers will no longer wait for promises passed to `ctx.waitUntil()` to resolve before acknowledging messages. This can improve the performance of queue consumers which utilize `ctx.waitUntil()`. With the flag enabled, in the above example, the consumer Worker will acknowledge the batch without waiting for the sleep function to resolve. + +Using this flag will not affect the behavior of `ctx.waitUntil()`. `ctx.waitUntil()` will continue to extend the lifetime of your consumer Worker to continue to work even after the batch of messages has been acknowledged. \ No newline at end of file diff --git a/src/content/docs/1.1.1.1/encryption/dns-over-https/dns-over-https-client.mdx b/src/content/docs/1.1.1.1/encryption/dns-over-https/dns-over-https-client.mdx index 188ef47cb336a1..8d17e6df525d8f 100644 --- a/src/content/docs/1.1.1.1/encryption/dns-over-https/dns-over-https-client.mdx +++ b/src/content/docs/1.1.1.1/encryption/dns-over-https/dns-over-https-client.mdx @@ -2,10 +2,10 @@ pcx_content_type: tutorial title: Connect to 1.1.1.1 using DoH clients slug: 1.1.1.1/encryption/dns-over-https/dns-over-https-client +description: Learn how to connect to Cloudflare's 1.1.1.1 using DNS over HTTPS (DoH) clients. --- There are several DoH clients you can use to connect to 1.1.1.1. - ## cloudflared 1. [Download and install the `cloudflared` daemon](/cloudflare-one/connections/connect-networks/downloads/). diff --git a/src/content/docs/1.1.1.1/encryption/oblivious-dns-over-https.mdx b/src/content/docs/1.1.1.1/encryption/oblivious-dns-over-https.mdx index 71c8e6f8c6efbb..517ed493fb7136 100644 --- a/src/content/docs/1.1.1.1/encryption/oblivious-dns-over-https.mdx +++ b/src/content/docs/1.1.1.1/encryption/oblivious-dns-over-https.mdx @@ -5,6 +5,7 @@ slug: 1.1.1.1/encryption/oblivious-dns-over-https sidebar: order: 6 label: Oblivious DoH +description: Learn how Cloudflare 1.1.1.1 supports Oblivious DNS over HTTPS (ODoH) to enhance privacy by separating HTTP request contents from requester IP addresses. --- As announced on [our blog](https://blog.cloudflare.com/oblivious-dns/), since late 2020, Cloudflare 1.1.1.1 supports Oblivious DNS over HTTPS (ODoH). diff --git a/src/content/docs/1.1.1.1/faq.mdx b/src/content/docs/1.1.1.1/faq.mdx index 57569899c5f734..a79c373a4b4ddd 100644 --- a/src/content/docs/1.1.1.1/faq.mdx +++ b/src/content/docs/1.1.1.1/faq.mdx @@ -5,6 +5,7 @@ structured_data: true sidebar: order: 12 slug: 1.1.1.1/faq +description: Find answers to common questions about Cloudflare's 1.1.1.1 DNS resolver, including setup, privacy features, IPv6 support, and troubleshooting tips. --- diff --git a/src/content/docs/1.1.1.1/setup/android.mdx b/src/content/docs/1.1.1.1/setup/android.mdx index 8c81129898ccc8..4655deee2ce1bf 100644 --- a/src/content/docs/1.1.1.1/setup/android.mdx +++ b/src/content/docs/1.1.1.1/setup/android.mdx @@ -6,6 +6,7 @@ sidebar: head: - tag: title content: Set up 1.1.1.1 on Android +description: Learn how to set up Cloudflare's 1.1.1.1 DNS resolver on Android devices. Encrypt DNS queries with DoT or DoH, and enable 1.1.1.1 for Families. slug: 1.1.1.1/setup/android --- @@ -17,7 +18,6 @@ import { Details, Render } from "~/components" The app also allows you to enable encryption for DNS queries or enable [WARP mode](/warp-client/), which keeps all your HTTP traffic private and secure, including your DNS queries to 1.1.1.1. You can select between the options available in the app settings. By default, 1.1.1.1: Faster Internet is configured to WARP mode. - ## Set up 1.1.1.1: Faster Internet 1. Download [1.1.1.1: Faster Internet from Google Play](https://play.google.com/store/apps/details?id=com.cloudflare.onedotonedotonedotone) for free. diff --git a/src/content/docs/agents/api-reference/agents-api.mdx b/src/content/docs/agents/api-reference/agents-api.mdx new file mode 100644 index 00000000000000..6654ea09e820d6 --- /dev/null +++ b/src/content/docs/agents/api-reference/agents-api.mdx @@ -0,0 +1,962 @@ +--- +title: Agents API +pcx_content_type: concept +sidebar: + order: 1 +--- + +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; + +This page provides an overview of the Agent SDK API, including the `Agent` class, methods and properties built-in to the Agents SDK. + +The Agents SDK exposes two main APIs: + +* The server-side `Agent` class. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, how to call AI models, and any error handling. +* The client-side `AgentClient` class, which allows you to connect to an Agent instance from a client-side application. The client APIs also include React hooks, including `useAgent` and `useAgentChat`, and allow you to automatically synchronize state between each unique Agent (running server-side) and your client applications. + +:::note + +Agents require [Cloudflare Durable Objects](/durable-objects/), see [Configuration](/agents/getting-started/testing-your-agent/#add-the-agent-configuration) to learn how to add the required bindings to your project. + +::: + + +You can also find more specific usage examples for each API in the [Agents API Reference](/agents/api-reference/). + + + +```ts +import { Agent } from "agents"; + +class MyAgent extends Agent { + // Define methods on the Agent +} + +export default MyAgent; +``` + + + +An Agent can have many (millions of) instances: each instance is a separate micro-server that runs independently of the others. This allows Agents to scale horizontally: an Agent can be associated with a single user, or many thousands of users, depending on the agent you're building. + +Instances of an Agent are addressed by a unique identifier: that identifier (ID) can be the user ID, an email address, GitHub username, a flight ticket number, an invoice ID, or any other identifier that helps to uniquely identify the instance and for whom it is acting on behalf of. + + + +### Agent class API + +Writing an Agent requires you to define a class that extends the `Agent` class from the Agents SDK package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. + +You can also define your own methods on an Agent: it's technically valid to publish an Agent only has your own methods exposed, and create/get Agents directly from a Worker. + +Your own methods can access the Agent's environment variables and bindings on `this.env`, state on `this.setState`, and call other methods on the Agent via `this.yourMethodName`. + +```ts +import { Agent } from "agents"; + +interface Env { + // Define environment variables & bindings here +} + +// Pass the Env as a TypeScript type argument +// Any services connected to your Agent or Worker as Bindings +// are then available on this.env. + +// The core class for creating Agents that can maintain state, orchestrate +// complex AI workflows, schedule tasks, and interact with users and other +// Agents. +class MyAgent extends Agent { + // Optional initial state definition + initialState = { + counter: 0, + messages: [], + lastUpdated: null + }; + + // Called when a new Agent instance starts or wakes from hibernation + async onStart() { + console.log('Agent started with state:', this.state); + } + + // Handle HTTP requests coming to this Agent instance + // Returns a Response object + async onRequest(request: Request): Promise { + return new Response("Hello from Agent!"); + } + + // Called when a WebSocket connection is established + // Access the original request via ctx.request for auth etc. + async onConnect(connection: Connection, ctx: ConnectionContext) { + // Connections are automatically accepted by the SDK. + // You can also explicitly close a connection here with connection.close() + // Access the Request on ctx.request to inspect headers, cookies and the URL + } + + // Called for each message received on a WebSocket connection + // Message can be string, ArrayBuffer, or ArrayBufferView + async onMessage(connection: Connection, message: WSMessage) { + // Handle incoming messages + connection.send("Received your message"); + } + + // Handle WebSocket connection errors + async onError(connection: Connection, error: unknown): Promise { + console.error(`Connection error:`, error); + } + + // Handle WebSocket connection close events + async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise { + console.log(`Connection closed: ${code} - ${reason}`); + } + + // Called when the Agent's state is updated from any source + // source can be "server" or a client Connection + onStateUpdate(state: State, source: "server" | Connection) { + console.log("State updated:", state, "Source:", source); + } + + // You can define your own custom methods to be called by requests, + // WebSocket messages, or scheduled tasks + async customProcessingMethod(data: any) { + // Process data, update state, schedule tasks, etc. + this.setState({ ...this.state, lastUpdated: new Date() }); + } +} +``` + + + +```ts +// Basic Agent implementation with custom methods +import { Agent } from "agents"; + +interface MyState { + counter: number; + lastUpdated: Date | null; +} + +class MyAgent extends Agent { + initialState = { + counter: 0, + lastUpdated: null + }; + + async onRequest(request: Request) { + if (request.method === "POST") { + await this.incrementCounter(); + return new Response(JSON.stringify(this.state), { + headers: { "Content-Type": "application/json" } + }); + } + return new Response(JSON.stringify(this.state), { + headers: { "Content-Type": "application/json" } + }); + } + + async incrementCounter() { + this.setState({ + counter: this.state.counter + 1, + lastUpdated: new Date() + }); + } +} +``` + + + +### WebSocket API + +The WebSocket API allows you to accept and manage WebSocket connections made to an Agent. + +#### Connection + +Represents a WebSocket connection to an Agent. + +```ts +// WebSocket connection interface +interface Connection { + // Unique ID for this connection + id: string; + + // Client-specific state attached to this connection + state: State; + + // Update the connection's state + setState(state: State): void; + + // Accept an incoming WebSocket connection + accept(): void; + + // Close the WebSocket connection with optional code and reason + close(code?: number, reason?: string): void; + + // Send a message to the client + // Can be string, ArrayBuffer, or ArrayBufferView + send(message: string | ArrayBuffer | ArrayBufferView): void; +} +``` + + + +```ts +// Example of handling WebSocket messages +export class YourAgent extends Agent { + async onMessage(connection: Connection, message: WSMessage) { + if (typeof message === 'string') { + try { + // Parse JSON message + const data = JSON.parse(message); + + if (data.type === 'update') { + // Update connection-specific state + connection.setState({ ...connection.state, lastActive: Date.now() }); + + // Update global Agent state + this.setState({ + ...this.state, + connections: this.state.connections + 1 + }); + + // Send response back to this client only + connection.send(JSON.stringify({ + type: 'updated', + status: 'success' + })); + } + } catch (e) { + connection.send(JSON.stringify({ error: 'Invalid message format' })); + } + } + } +} +``` + + + +#### WSMessage + +Types of messages that can be received from a WebSocket. + +```ts +// Types of messages that can be received from WebSockets +type WSMessage = string | ArrayBuffer | ArrayBufferView; +``` + +#### ConnectionContext + +Context information for a WebSocket connection. + +```ts +// Context available during WebSocket connection +interface ConnectionContext { + // The original HTTP request that initiated the WebSocket connection + request: Request; +} +``` + +### State synchronization API + +:::note + +To learn more about how to manage state within an Agent, refer to the documentation on [managing and syncing state](/agents/api-reference/store-and-sync-state/). + +::: + +#### State + +Methods and types for managing Agent state. + +```ts +// State management in the Agent class +class Agent { + // Initial state that will be set if no state exists yet + initialState: State = {} as unknown as State; + + // Current state of the Agent, persisted across restarts + get state(): State; + + // Update the Agent's state + // Persists to storage and notifies all connected clients + setState(state: State): void; + + // Called when state is updated from any source + // Override to react to state changes + onStateUpdate(state: State, source: "server" | Connection): void; +} +``` + + + +```ts +// Example of state management in an Agent +interface ChatState { + messages: Array<{ sender: string; text: string; timestamp: number }>; + participants: string[]; + settings: { + allowAnonymous: boolean; + maxHistoryLength: number; + }; +} + +interface Env { + // Your bindings and environment variables +} + +// Inside your Agent class +export class YourAgent extends Agent { + async addMessage(sender: string, text: string) { + // Update state with new message + this.setState({ + ...this.state, + messages: [ + ...this.state.messages, + { sender, text, timestamp: Date.now() } + ].slice(-this.state.settings.maxHistoryLength) // Maintain max history + }); + + // The onStateUpdate method will automatically be called + // and all connected clients will receive the update + } + + // Override onStateUpdate to add custom behavior when state changes + onStateUpdate(state: ChatState, source: "server" | Connection) { + console.log(`State updated by ${source === "server" ? "server" : "client"}`); + + // You could trigger additional actions based on state changes + if (state.messages.length > 0) { + const lastMessage = state.messages[state.messages.length - 1]; + if (lastMessage.text.includes('@everyone')) { + this.notifyAllParticipants(lastMessage); + } + } + } +} +``` + + + +### Scheduling API + +#### Scheduling tasks + +Schedule tasks to run at a specified time in the future. + +```ts +// Scheduling API for running tasks in the future +class Agent { + // Schedule a task to run in the future + // when: seconds from now, specific Date, or cron expression + // callback: method name on the Agent to call + // payload: data to pass to the callback + // Returns a Schedule object with the task ID + async schedule( + when: Date | string | number, + callback: keyof this, + payload?: T + ): Promise>; + + // Get a scheduled task by ID + // Returns undefined if the task doesn't exist + async getSchedule(id: string): Promise | undefined>; + + // Get all scheduled tasks matching the criteria + // Returns an array of Schedule objects + getSchedules(criteria?: { + description?: string; + id?: string; + type?: "scheduled" | "delayed" | "cron"; + timeRange?: { start?: Date; end?: Date }; + }): Schedule[]; + + // Cancel a scheduled task by ID + // Returns true if the task was cancelled, false otherwise + async cancelSchedule(id: string): Promise; +} +``` + + + +```ts +// Example of scheduling in an Agent +interface ReminderData { + userId: string; + message: string; + channel: string; +} + +export class YourAgent extends Agent { + // Schedule a one-time reminder in 2 hours + async scheduleReminder(userId: string, message: string) { + const twoHoursFromNow = new Date(Date.now() + 2 * 60 * 60 * 1000); + + const schedule = await this.schedule( + twoHoursFromNow, + 'sendReminder', + { userId, message, channel: 'email' } + ); + + console.log(`Scheduled reminder with ID: ${schedule.id}`); + return schedule.id; + } + + // Schedule a recurring daily task using cron + async scheduleDailyReport() { + // Run at 08:00 AM every day + const schedule = await this.schedule( + '0 8 * * *', // Cron expression: minute hour day month weekday + 'generateDailyReport', + { reportType: 'daily-summary' } + ); + + console.log(`Scheduled daily report with ID: ${schedule.id}`); + return schedule.id; + } + + // Method that will be called when the scheduled task runs + async sendReminder(data: ReminderData) { + console.log(`Sending reminder to ${data.userId}: ${data.message}`); + // Add code to send the actual notification + } +} +``` + + + +#### Schedule object + +Represents a scheduled task. + +```ts +// Represents a scheduled task +type Schedule = { + // Unique identifier for the schedule + id: string; + // Name of the method to be called + callback: string; + // Data to be passed to the callback + payload: T; +} & ( + | { + // One-time execution at a specific time + type: "scheduled"; + // Timestamp when the task should execute + time: number; + } + | { + // Delayed execution after a certain time + type: "delayed"; + // Timestamp when the task should execute + time: number; + // Number of seconds to delay execution + delayInSeconds: number; + } + | { + // Recurring execution based on cron expression + type: "cron"; + // Timestamp for the next execution + time: number; + // Cron expression defining the schedule + cron: string; + } +); +``` + + + +```ts +export class YourAgent extends Agent { + // Example of managing scheduled tasks + async viewAndManageSchedules() { + // Get all scheduled tasks + const allSchedules = this.getSchedules(); + console.log(`Total scheduled tasks: ${allSchedules.length}`); + + // Get tasks scheduled for a specific time range + const upcomingSchedules = this.getSchedules({ + timeRange: { + start: new Date(), + end: new Date(Date.now() + 24 * 60 * 60 * 1000) // Next 24 hours + } + }); + + // Get a specific task by ID + const taskId = "task-123"; + const specificTask = await this.getSchedule(taskId); + + if (specificTask) { + console.log(`Found task: ${specificTask.callback} at ${new Date(specificTask.time)}`); + + // Cancel a scheduled task + const cancelled = await this.cancelSchedule(taskId); + console.log(`Task cancelled: ${cancelled}`); + } + } +} +``` + + + +### SQL API + +Each Agent instance has an embedded SQLite database that can be accessed using the `this.sql` method within any method on your `Agent` class. + +#### SQL queries + +Execute SQL queries against the Agent's built-in SQLite database using the `this.sql` method within any method on your `Agent` class. + +```ts +// SQL query API for the Agent's embedded database +class Agent { + // Execute a SQL query with tagged template literals + // Returns an array of rows matching the query + sql>( + strings: TemplateStringsArray, + ...values: (string | number | boolean | null)[] + ): T[]; +} +``` + + + +```ts +// Example of using SQL in an Agent +interface User { + id: string; + name: string; + email: string; + created_at: number; +} + +export class YourAgent extends Agent { + async setupDatabase() { + // Create a table if it doesn't exist + this.sql` + CREATE TABLE IF NOT EXISTS users ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + email TEXT UNIQUE, + created_at INTEGER + ) + `; + } + + async createUser(id: string, name: string, email: string) { + // Insert a new user + this.sql` + INSERT INTO users (id, name, email, created_at) + VALUES (${id}, ${name}, ${email}, ${Date.now()}) + `; + } + + async getUserById(id: string): Promise { + // Query a user by ID + const users = this.sql` + SELECT * FROM users WHERE id = ${id} + `; + + return users.length ? users[0] : null; + } + + async searchUsers(term: string): Promise { + // Search users with a wildcard + return this.sql` + SELECT * FROM users + WHERE name LIKE ${'%' + term + '%'} OR email LIKE ${'%' + term + '%'} + ORDER BY created_at DESC + `; + } +} +``` + + + +:::note + +Visit the [state management API documentation](/agents/api-reference/store-and-sync-state/) within the Agents SDK, including the native `state` APIs and the built-in `this.sql` API for storing and querying data within your Agents. + +::: + + +### Client API + +The Agents SDK provides a set of client APIs for interacting with Agents from client-side JavaScript code, including: + +* React hooks, including `useAgent` and `useAgentChat`, for connecting to Agents from client applications. +* Client-side [state syncing](/agents/api-reference/store-and-sync-state/) that allows you to subscribe to state updates between the Agent and any connected client(s) when calling `this.setState` within your Agent's code. +* The ability to call remote methods (Remote Procedure Calls; RPC) on the Agent from client-side JavaScript code using the `@callable` method decorator. + +#### AgentClient + +Client for connecting to an Agent from the browser. + +```ts +import { AgentClient } from "agents/client"; + +// Options for creating an AgentClient +type AgentClientOptions = Omit & { + // Name of the agent to connect to (class name in kebab-case) + agent: string; + // Name of the specific Agent instance (optional, defaults to "default") + name?: string; + // Other WebSocket options like host, protocol, etc. +}; + +// WebSocket client for connecting to an Agent +class AgentClient extends PartySocket { + static fetch(opts: PartyFetchOptions): Promise; + constructor(opts: AgentClientOptions); +} +``` + + + +```ts +// Example of using AgentClient in the browser +import { AgentClient } from "agents/client"; + +// Connect to an Agent instance +const socket = new AgentClient({ + agent: "chat-agent", // Name of your Agent class in kebab-case + name: "support-room-123", // Specific instance name + + // Optional event handlers + onOpen: () => { + console.log("Connected to agent"); + // Send an initial message + socket.send(JSON.stringify({ type: "join", user: "user123" })); + }, + + onMessage: (event) => { + // Handle incoming messages + const data = JSON.parse(event.data); + console.log("Received:", data); + + if (data.type === "state_update") { + // Update local UI with new state + updateUI(data.state); + } + }, + + onClose: () => console.log("Disconnected from agent") +}); + +// Send messages to the Agent +function sendMessage(text) { + socket.send(JSON.stringify({ + type: "message", + text, + timestamp: Date.now() + })); +} +``` + + + +#### agentFetch + +Make an HTTP request to an Agent. + +```ts +import { agentFetch } from "agents/client"; + +// Options for the agentFetch function +type AgentClientFetchOptions = Omit & { + // Name of the agent to connect to + agent: string; + // Name of the specific Agent instance (optional) + name?: string; +}; + +// Make an HTTP request to an Agent +function agentFetch( + opts: AgentClientFetchOptions, + init?: RequestInit +): Promise; +``` + + + +```ts +// Example of using agentFetch in the browser +import { agentFetch } from "agents/client"; + +// Function to get data from an Agent +async function fetchAgentData() { + try { + const response = await agentFetch( + { + agent: "task-manager", + name: "user-123-tasks" + }, + { + method: "GET", + headers: { + "Authorization": `Bearer ${userToken}` + } + } + ); + + if (!response.ok) { + throw new Error(`Error: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Failed to fetch from agent:", error); + } +} +``` + + + +### React API + +The Agents SDK provides a React API for simplifying connection and routing to Agents from front-end frameworks, including React Router (Remix), Next.js, and Astro. + +#### useAgent + +React hook for connecting to an Agent. + +```ts +import { useAgent } from "agents/react"; + +// Options for the useAgent hook +type UseAgentOptions = Omit< + Parameters[0], + "party" | "room" +> & { + // Name of the agent to connect to + agent: string; + // Name of the specific Agent instance (optional) + name?: string; + // Called when the Agent's state is updated + onStateUpdate?: (state: State, source: "server" | "client") => void; +}; + +// React hook for connecting to an Agent +// Returns a WebSocket connection with setState method +function useAgent( + options: UseAgentOptions +): PartySocket & { + // Update the Agent's state + setState: (state: State) => void +}; +``` + +### Chat Agent + +The Agents SDK exposes an `AIChatAgent` class that extends the `Agent` class and exposes an `onChatMessage` method that simplifies building interactive chat agents. + +You can combine this with the `useAgentChat` React hook from the `agents/ai-react` package to manage chat state and messages between a user and your Agent(s). + +#### AIChatAgent + +Extension of the `Agent` class with built-in chat capabilities. + +```ts +import { AIChatAgent } from "agents/ai-chat-agent"; +import { Message, StreamTextOnFinishCallback, ToolSet } from "ai"; + +// Base class for chat-specific agents +class AIChatAgent extends Agent { + // Array of chat messages for the current conversation + messages: Message[]; + + // Handle incoming chat messages and generate a response + // onFinish is called when the response is complete + async onChatMessage( + onFinish: StreamTextOnFinishCallback + ): Promise; + + // Persist messages within the Agent's local storage. + async saveMessages(messages: Message[]): Promise; +} +``` + + + +```ts +// Example of extending AIChatAgent +import { AIChatAgent } from "agents/ai-chat-agent"; +import { Message } from "ai"; + +interface Env { + AI: any; // Your AI binding +} + +class CustomerSupportAgent extends AIChatAgent { + // Override the onChatMessage method to customize behavior + async onChatMessage(onFinish) { + // Access the AI models using environment bindings + const { openai } = this.env.AI; + + // Get the current conversation history + const chatHistory = this.messages; + + // Generate a system prompt based on knowledge base + const systemPrompt = await this.generateSystemPrompt(); + + // Generate a response stream + const stream = await openai.chat({ + model: "gpt-4o", + messages: [ + { role: "system", content: systemPrompt }, + ...chatHistory + ], + stream: true + }); + + // Return the streaming response + return new Response(stream, { + headers: { "Content-Type": "text/event-stream" } + }); + } + + // Helper method to generate a system prompt + async generateSystemPrompt() { + // Query knowledge base or use static prompt + return `You are a helpful customer support agent. + Respond to customer inquiries based on the following guidelines: + - Be friendly and professional + - If you don't know an answer, say so + - Current company policies: ...`; + } +} +``` + + + +### Chat Agent React API + +#### useAgentChat + +React hook for building AI chat interfaces using an Agent. + +```ts +import { useAgentChat } from "agents/ai-react"; +import { useAgent } from "agents/react"; +import type { Message } from "ai"; + +// Options for the useAgentChat hook +type UseAgentChatOptions = Omit< + Parameters[0] & { + // Agent connection from useAgent + agent: ReturnType; + }, + "fetch" +>; + +// React hook for building AI chat interfaces using an Agent +function useAgentChat(options: UseAgentChatOptions): { + // Current chat messages + messages: Message[]; + // Set messages and synchronize with the Agent + setMessages: (messages: Message[]) => void; + // Clear chat history on both client and Agent + clearHistory: () => void; + // Append a new message to the conversation + append: (message: Message, chatRequestOptions?: any) => Promise; + // Reload the last user message + reload: (chatRequestOptions?: any) => Promise; + // Stop the AI response generation + stop: () => void; + // Current input text + input: string; + // Set the input text + setInput: React.Dispatch>; + // Handle input changes + handleInputChange: (e: React.ChangeEvent) => void; + // Submit the current input + handleSubmit: (event?: { preventDefault?: () => void }, chatRequestOptions?: any) => void; + // Additional metadata + metadata?: Object; + // Whether a response is currently being generated + isLoading: boolean; + // Current status of the chat + status: "submitted" | "streaming" | "ready" | "error"; + // Tool data from the AI response + data?: any[]; + // Set tool data + setData: (data: any[] | undefined | ((data: any[] | undefined) => any[] | undefined)) => void; + // Unique ID for the chat + id: string; + // Add a tool result for a specific tool call + addToolResult: ({ toolCallId, result }: { toolCallId: string; result: any }) => void; + // Current error if any + error: Error | undefined; +}; +``` + + + +```tsx +// Example of using useAgentChat in a React component +import { useAgentChat } from "agents/ai-react"; +import { useAgent } from "agents/react"; +import { useState } from "react"; + +function ChatInterface() { + // Connect to the chat agent + const agentConnection = useAgent({ + agent: "customer-support", + name: "session-12345" + }); + + // Use the useAgentChat hook with the agent connection + const { + messages, + input, + handleInputChange, + handleSubmit, + isLoading, + error, + clearHistory + } = useAgentChat({ + agent: agentConnection, + initialMessages: [ + { role: "system", content: "You're chatting with our AI assistant." }, + { role: "assistant", content: "Hello! How can I help you today?" } + ] + }); + + return ( +
    +
    + {messages.map((message, i) => ( +
    + {message.role === 'user' ? '👤' : '🤖'} {message.content} +
    + ))} + + {isLoading &&
    AI is typing...
    } + {error &&
    Error: {error.message}
    } +
    + +
    + + + +
    +
    + ); +} +``` + +
    + + +### Next steps + +* [Build a chat Agent](/agents/getting-started/build-a-chat-agent/) using the Agents SDK and deploy it to Workers. +* Learn more [using WebSockets](/agents/api-reference/websockets/) to build interactive Agents and stream data back from your Agent. +* [Orchestrate asynchronous workflows](/agents/api-reference/run-workflows) from your Agent by combining the Agents SDK and [Workflows](/workflows). diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/api-reference/browse-the-web.mdx similarity index 99% rename from src/content/docs/agents/examples/browse-the-web.mdx rename to src/content/docs/agents/api-reference/browse-the-web.mdx index 703759ceb98909..689b856339b5e3 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/api-reference/browse-the-web.mdx @@ -2,7 +2,7 @@ title: Browse the web pcx_content_type: concept sidebar: - order: 99 + order: 7 --- import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; diff --git a/src/content/docs/agents/api-reference/calling-agents.mdx b/src/content/docs/agents/api-reference/calling-agents.mdx new file mode 100644 index 00000000000000..7bc38dccc1ee13 --- /dev/null +++ b/src/content/docs/agents/api-reference/calling-agents.mdx @@ -0,0 +1,266 @@ +--- +title: Calling Agents +pcx_content_type: concept +sidebar: + order: 2 + +--- + +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; + +Learn how to call your Agents from Workers, including how to create Agents on-the-fly, address them, and route requests to specific instances of an Agent. + +### Calling your Agent + +Agents are created on-the-fly and can serve multiple requests concurrently. Each Agent instance is isolated from other instances, can maintain its own state, and has a unique address. + + + +You can create and run an instance of an Agent directly from a Worker using either: + +* The `routeAgentRequest` helper: this will automatically map requests to an individual Agent based on the `/agents/:agent/:name` URL pattern. The value of `:agent` will be the name of your Agent class converted to `kebab-case`, and the value of `:name` will be the name of the Agent instance you want to create or retrieve. +* `getAgentByName`, which will create a new Agent instance if none exists by that name, or retrieve a handle to an existing instance. + +See the usage patterns in the following example: + + + +```ts +import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from 'agents'; + +interface Env { + // Define your Agent on the environment here + // Passing your Agent class as a TypeScript type parameter allows you to call + // methods defined on your Agent. + MyAgent: AgentNamespace; +} + +export default { + async fetch(request, env, ctx): Promise { + // Routed addressing + // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name + // Best for: connecting React apps directly to Agents using useAgent from agents/react + return (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); + + // Named addressing + // Best for: convenience method for creating or retrieving an agent by name/ID. + // Bringing your own routing, middleware and/or plugging into an existing + // application or framework. + let namedAgent = getAgentByName(env.MyAgent, 'my-unique-agent-id'); + // Pass the incoming request straight to your Agent + let namedResp = (await namedAgent).fetch(request); + return namedResp + }, +} satisfies ExportedHandler; + +export class MyAgent extends Agent { + // Your Agent implementation goes here +} +``` + + +#### Calling methods directly + +When using `getAgentByName`, you can pass both requests (including WebSocket) connections and call methods defined directly on the Agent itself using the native [JavaScript RPC](/workers/runtime-apis/rpc/) (JSRPC) API. + +For example, once you have a handle (or "stub") to an unique instance of your Agent, you can call methods on it: + + + +```ts +import { Agent, AgentNamespace, getAgentByName } from 'agents'; + +interface Env { + // Define your Agent on the environment here + // Passing your Agent class as a TypeScript type parameter allows you to call + // methods defined on your Agent. + MyAgent: AgentNamespace; +} + +interface UserHistory { + history: string[]; + lastUpdated: Date; +} + +export default { + async fetch(request, env, ctx): Promise { + let namedAgent = getAgentByName(env.MyAgent, 'my-unique-agent-id'); + // Call methods directly on the Agent, and pass native JavaScript objects + let chatResponse = namedAgent.chat('Hello!'); + // No need to serialize/deserialize it from a HTTP request or WebSocket + // message and back again + let agentState = getState() // agentState is of type UserHistory + return namedResp + }, +} satisfies ExportedHandler; + +export class MyAgent extends Agent { + // Your Agent implementation goes here + async chat(prompt: string) { + // call your favorite LLM + return "result" + } + + async getState() { + // Return the Agent's state directly + return this.state; + } + + // Other methods as you see fit! +} +``` + + +When using TypeScript, ensure you pass your Agent class as a TypeScript type parameter to the AgentNamespace type so that types are correctly inferred: + +```ts +interface Env { + // Passing your Agent class as a TypeScript type parameter allows you to call + // methods defined on your Agent. + MyAgent: AgentNamespace; +} + +export class CodeReviewAgent extends Agent { + // Agent methods here +} +``` + +### Naming your Agents + +When creating names for your Agents, think about what the Agent represents. A unique user? A team or company? A room or channel for collaboration? + +A consistent approach to naming allows you to: + +* direct incoming requests directly to the right Agent +* deterministically route new requests back to that Agent, no matter where the client is in the world. +* avoid having to rely on centralized session storage or external services for state management, since each Agent instance can maintain its own state. + +For a given Agent definition (or 'namespace' in the code below), there can be millions (or tens of millions) of instances of that Agent, each handling their own requests, making calls to LLMs, and maintaining their own state. + +For example, you might have an Agent for every user using your new AI-based code editor. In that case, you'd want to create Agents based on the user ID from your system, which would then allow that Agent to handle all requests for that user. + +It also ensures that [state within the Agent](/agents/api-reference/store-and-sync-state/), including chat history, language preferences, model configuration and other context can associated specifically with that user, making it easier to manage state. + +The example below shows how to create a unique agent Agent for each `userId` in a request: + + + +```ts +import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from 'agents'; + +interface Env { + MyAgent: AgentNamespace; +} + +export default { + async fetch(request, env, ctx): Promise { + let userId = new URL(request.url).searchParams.get('userId') || 'anonymous'; + // Use an identifier that allows you to route to requests, WebSockets or call methods on the Agent + // You can also put authentication logic here - e.g. to only create or retrieve Agents for known users. + let namedAgent = getAgentByName(env.MyAgent, 'my-unique-agent-id'); + return (await namedAgent).fetch(request); + }, +} satisfies ExportedHandler; + +export class MyAgent extends Agent { + // You can access the name of the agent via this.name in any method within + // the Agent + async onStartup() { console.log(`agent ${this.name} ready!`)} +} +``` + + +Replace `userId` with `teamName`, `channel`, `companyName` as fits your Agents goals - and/or configure authentication to ensure Agents are only created for known, authenticated users. + +### Authenticating Agents + +When building and deploying Agents using the Agents SDK, you will often want to authenticate clients before passing requests to an Agent in order to restrict who the Agent will call, authorize specific users for specific Agents, and/or to limit who can access administrative or debug APIs exposed by an Agent. + +As best practices: + +* Handle authentication in your Workers code, before you invoke your Agent. +* Use the built-in hooks when using the `routeAgentRequest` helper - `onBeforeConnect` and `onBeforeRequest` +* Use your preferred router (such as Hono) and authentication middleware or provider to apply custom authentication schemes before calling an Agent using other methods. + +The `routeAgentRequest` helper documented earlier in this guide exposes two useful hooks (`onBeforeConnect`, `onBeforeRequest`) that allow you to apply custom logic before creating or retrieving an Agent: + + + +```ts +import { Agent, AgentNamespace, routeAgentRequest } from 'agents'; + +interface Env { + MyAgent: AgentNamespace; +} + +export default { + async fetch(request, env, ctx): Promise { + // Use the onBeforeConnect and onBeforeRequest hooks to authenticate clients + // or run logic before handling a HTTP request or WebSocket. + return ( + (await routeAgentRequest(request, env, { + // Run logic before a WebSocket client connects + onBeforeConnect: (request) => { + // Your code/auth code here + // You can return a Response here - e.g. a HTTP 403 Not Authorized - + // which will stop further request processing and will NOT invoke the + // Agent. + // return Response.json({"error": "not authorized"}, { status: 403 }) + }, + // Run logic before a HTTP client clients + onBeforeRequest: (request) => { + // Your code/auth code here + // Returning nothing will result in the call to the Agent continuing + }, + // Prepend a prefix for how your Agents are named here + prefix: 'name-prefix-here', + })) || Response.json({ msg: 'no agent here' }, { status: 404 }) + ); + + }, +} satisfies ExportedHandler; +``` + + +If you are using `getAgentByName` or the underlying Durable Objects routing API, you should authenticate incoming requests or WebSocket connections before calling `getAgentByName`. + +For example, if you are using [Hono](https://hono.dev/), you can authenticate in the middleware before calling an Agent and passing a request (or a WebSocket connection) to it: + + + +```ts +import { Agent, AgentNamespace, getAgentByName } from 'agents'; +import { Hono } from 'hono'; + +const app = new Hono<{ Bindings: Env }>(); + +app.use('/code-review/*', async (c, next) => { + // Perform auth here + // e.g. validate a Bearer token, a JWT, use your preferred auth library + // return Response.json({ msg: 'unauthorized' }, { status: 401 }); + await next(); // continue on if valid +}); + +app.get('/code-review/:id', async (c) => { + const id = c.req.param('teamId'); + if (!id) return Response.json({ msg: 'missing id' }, { status: 400 }); + + // Call the Agent, creating it with the name/identifier from the ":id" segment + // of our URL + const agent = await getAgentByName(c.env.MyAgent, id); + + // Pass the request to our Agent instance + return await agent.fetch(c.req.raw); +}); +``` + + + +This ensures we only create Agents for authenticated users, and allows you to validate whether Agent names conform to your preferred naming scheme before instances are created. + +### Next steps + +* Review the [API documentation](/agents/api-reference/agents-api/) for the Agents class to learn how to define +* [Build a chat Agent](/agents/getting-started/build-a-chat-agent/) using the Agents SDK and deploy it to Workers. +* Learn more [using WebSockets](/agents/api-reference/websockets/) to build interactive Agents and stream data back from your Agent. +* [Orchestrate asynchronous workflows](/agents/api-reference/run-workflows) from your Agent by combining the Agents SDK and [Workflows](/workflows). diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index 24563dce3c49ce..79426eac85ff2c 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -2,14 +2,16 @@ title: Configuration pcx_content_type: concept sidebar: - order: 3 + order: 100 --- import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; An Agent is configured like any other Cloudflare Workers project, and uses [a wrangler configuration](/workers/wrangler/configuration/) file to define where your code is and what services (bindings) it will use. -The typical file structure for an Agent project created from `npm create cloudflare@latest -- --template cloudflare/agents` follows: +### Project structure + +The typical file structure for an Agent project created from `npm create cloudflare@latest agents-starter -- --template cloudflare/agents-starter` follows: ```sh . @@ -28,6 +30,8 @@ The typical file structure for an Agent project created from `npm create cloudfl `-- wrangler.jsonc // your Workers & Agent configuration ``` +### Example configuration + Below is a minimal `wrangler.jsonc` file that defines the configuration for an Agent, including the entry point, `durable_object` namespace, and code `migrations`: @@ -70,3 +74,5 @@ The configuration includes: - A `main` field that points to the entry point of your Agent, which is typically a TypeScript (or JavaScript) file. - A `durable_objects` field that defines the [Durable Object namespace](/durable-objects/reference/glossary/) that your Agents will run within. - A `migrations` field that defines the code migrations that your Agent will use. This field is mandatory and must contain at least one migration. The `new_sqlite_classes` field is mandatory for the Agent to store state. + +Agents must define these fields in their `wrangler.jsonc` (or `wrangler.toml`) config file. diff --git a/src/content/docs/agents/api-reference/http-sse.mdx b/src/content/docs/agents/api-reference/http-sse.mdx new file mode 100644 index 00000000000000..ef5916c26d340a --- /dev/null +++ b/src/content/docs/agents/api-reference/http-sse.mdx @@ -0,0 +1,114 @@ +--- +title: HTTP and Server-Sent Events +pcx_content_type: concept +sidebar: + order: 8 + +--- + +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; + +The Agents SDK allows you to handle HTTP requests and has native support for [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) (SSE). This allows you build applications that can push data to clients and avoid buffering. + +### Handling HTTP requests + +Agents can handle HTTP requests using the `onRequest` method, which is called whenever an HTTP request is received by the Agent instance. The method takes a `Request` object as a parameter and returns a `Response` object. + + + +```ts +class MyAgent extends Agent { + // Handle HTTP requests coming to this Agent instance + // Returns a Response object + async onRequest(request: Request) { + return new Response("Hello from Agent!"); + } + + async callAIModel(prompt: string) { + // Implement AI model call here + } +} +``` + + + +Review the [Agents API reference](/agents/api-reference/agents-api/) to learn more about the `Agent` class and its methods. + +### Implementing Server-Sent Events + +The Agents SDK support Server-Sent Events directly: you can use SSE to stream data back to the client over a long running connection. This avoids buffering large responses, which can both make your Agent feel slow, and forces you to buffer the entire response in memory. + +When an Agent is deployed to Cloudflare Workers, there is no effective limit on the total time it takes to stream the response back: large AI model responses that take several minutes to reason and then respond will not be prematurely terminated. + +Note that this does not mean the client can't potentially disconnect during the streaming process: you can account for this by either [writing to the Agent's stateful storage](/agents/api-reference/store-and-sync-state/) and/or [using WebSockets](/agents/api-reference/websockets/). Because you can always [route to the same Agent](/agents/api-reference/calling-agents/), you do not need to use a centralized session store to pick back up where you left off when a client disconnects. + +The following example uses the AI SDK to generate text and stream it back to the client. It will automatically stream the response back to the client as the model generates it: + + + +```ts +import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from 'agents'; +import { streamText } from 'ai'; +import { createOpenAI, openai } from '@ai-sdk/openai'; + +interface Env { + MyAgent: AgentNamespace; + OPENAI_API_KEY: string; +} + +export class MyAgent extends Agent { + async onRequest(request: Request) { + // Test it via: + // curl -d '{"prompt": "Write me a Cloudflare Worker"}' + let data = await request.json<{ prompt: string }>(); + let stream = await this.callAIModel(data.prompt); + // This uses Server-Sent Events (SSE) + return stream.toTextStreamResponse({ + headers: { + 'Content-Type': 'text/x-unknown', + 'content-encoding': 'identity', + 'transfer-encoding': 'chunked', + }, + }); + } + + async callAIModel(prompt: string) { + const openai = createOpenAI({ + apiKey: this.env.OPENAI_API_KEY, + }); + + return streamText({ + model: openai('gpt-4o'), + prompt: prompt, + }); + } +} + +export default { + async fetch(request: Request, env: Env) { + let agentId = new URL(request.url).searchParams.get('agent-id') || ''; + const agent = await getAgentByName(env.MyAgent, agentId); + return agent.fetch(request); + }, +}; +``` + + + +### WebSockets vs. Server-Sent Events + +Both WebSockets and Server-Sent Events (SSE) enable real-time communication between clients and Agents. Agents built on the Agents SDK can expose both WebSocket and SSE endpoints directly. + +* WebSockets provide full-duplex communication, allowing data to flow in both directions simultaneously. SSE only supports server-to-client communication, requiring additional HTTP requests if the client needs to send data back. +* WebSockets establish a single persistent connection that stays open for the duration of the session. SSE, being built on HTTP, may experience more overhead due to reconnection attempts and header transmission with each reconnection, especially when there is a lot of client-server communication. +* While SSE works well for simple streaming scenarios, WebSockets are better suited for applications requiring minutes or hours of connection time, as they maintain a more stable connection with built-in ping/pong mechanisms to keep connections alive. +* WebSockets use their own protocol (ws:// or wss://), separating them from HTTP after the initial handshake. This separation allows WebSockets to better handle binary data transmission and implement custom subprotocols for specialized use cases. + +If you're unsure of which is better for your use-case, we recommend WebSockets. The [WebSockets API documentation](/agents/api-reference/websockets/) provides detailed information on how to use WebSockets with the Agents SDK. + +### Next steps + +* Review the [API documentation](/agents/api-reference/agents-api/) for the Agents class to learn how to define them. +* [Build a chat Agent](/agents/getting-started/build-a-chat-agent/) using the Agents SDK and deploy it to Workers. +* Learn more [using WebSockets](/agents/api-reference/websockets/) to build interactive Agents and stream data back from your Agent. +* [Orchestrate asynchronous workflows](/agents/api-reference/run-workflows) from your Agent by combining the Agents SDK and [Workflows](/workflows). diff --git a/src/content/docs/agents/api-reference/index.mdx b/src/content/docs/agents/api-reference/index.mdx index 3db3271d4f644a..c06356d063d9f8 100644 --- a/src/content/docs/agents/api-reference/index.mdx +++ b/src/content/docs/agents/api-reference/index.mdx @@ -2,11 +2,11 @@ title: API Reference pcx_content_type: navigation sidebar: - order: 5 - group: - hideIndex: true + order: 3 --- import { DirectoryListing } from "~/components" +Learn more about what Agents can do, the `Agent` class, and the APIs that Agents expose: + diff --git a/src/content/docs/agents/examples/rag.mdx b/src/content/docs/agents/api-reference/rag.mdx similarity index 80% rename from src/content/docs/agents/examples/rag.mdx rename to src/content/docs/agents/api-reference/rag.mdx index c836faa1247899..b29014c20452f3 100644 --- a/src/content/docs/agents/examples/rag.mdx +++ b/src/content/docs/agents/api-reference/rag.mdx @@ -2,15 +2,15 @@ title: Retrieval Augmented Generation pcx_content_type: concept sidebar: - order: 7 + order: 9 --- import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -Agents can use Retrieval Augmented Generation (RAG) to retrieve relevant information and use it augment [calls to AI models](/agents/examples/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [web browsing](/agents/examples/browse-the-web/) tasks to enhance your Agent's capabilities. +Agents can use Retrieval Augmented Generation (RAG) to retrieve relevant information and use it augment [calls to AI models](/agents/api-reference/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [web browsing](/agents/api-reference/browse-the-web/) tasks to enhance your Agent's capabilities. -You can use the Agent's own [SQL database](/agents/examples/manage-and-sync-state) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. +You can use the Agent's own [SQL database](/agents/api-reference/store-and-sync-state) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. ### Vector search @@ -27,7 +27,7 @@ Here's an example of how to give an Agent retrieval capabilties: ```ts -import { Agent } from "agents-sdk"; +import { Agent } from "agents"; interface Env { AI: Ai; diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/api-reference/run-workflows.mdx similarity index 99% rename from src/content/docs/agents/examples/run-workflows.mdx rename to src/content/docs/agents/api-reference/run-workflows.mdx index d0c9049a95fd3a..442ba327df4ca2 100644 --- a/src/content/docs/agents/examples/run-workflows.mdx +++ b/src/content/docs/agents/api-reference/run-workflows.mdx @@ -2,7 +2,7 @@ title: Run Workflows pcx_content_type: concept sidebar: - order: 4 + order: 5 --- diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/api-reference/schedule-tasks.mdx similarity index 98% rename from src/content/docs/agents/examples/schedule-tasks.mdx rename to src/content/docs/agents/api-reference/schedule-tasks.mdx index f654eb984bd426..8d39c8ab52a9f2 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/api-reference/schedule-tasks.mdx @@ -2,7 +2,7 @@ title: Schedule tasks pcx_content_type: concept sidebar: - order: 5 + order: 4 --- import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; @@ -18,7 +18,7 @@ You can call `this.schedule` within any method on an Agent, and schedule tens-of ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" export class SchedulingAgent extends Agent { async onRequest(request) { diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx deleted file mode 100644 index 258a4d5c0753a2..00000000000000 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Agents SDK -pcx_content_type: concept -sidebar: - order: 2 - ---- - -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; - -At its most basic, an Agent is a JavaScript class that extends the `Agent` class from the `agents-sdk` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. - - - -```ts -import { Agent } from "agents-sdk"; - -class MyAgent extends Agent { - // Define methods on the Agent -} - -export default MyAgent; -``` - - - -An Agent can have many (millions of) instances: each instance is a separate micro-server that runs independently of the others. This allows Agents to scale horizontally: an Agent can be associated with a single user, or many thousands of users, depending on the agent you're building. - -Instances of an Agent are addressed by a unique identifier: that identifier (ID) can be the user ID, an email address, GitHub username, a flight ticket number, an invoice ID, or any other identifier that helps to uniquely identify the instance and for whom it is acting on behalf of. - -## The Agent class - -Writing an Agent requires you to define a class that extends the `Agent` class from the `agents-sdk` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. - -An Agent has the following class methods: - - - -```ts -import { Agent } from "agents-sdk"; - -interface Env { - // Define environment variables & bindings here -} - -// Pass the Env as a TypeScript type argument -// Any services connected to your Agent or Worker as Bindings -// are then available on this.env. -class MyAgent extends Agent { - // Called when an Agent is started (or woken up) - async onStart() { - // Can access this.env and this.state - console.log('Agent started'); - } - - // Called when a HTTP request is received - // Can be connected to routeAgentRequest to automatically route - // requests to an individual Agent. - async onRequest(request: Request) { - console.log("Received request!"); - } - - // Called when a WebSocket connection is established - async onConnect(connection: Connection, ctx: ConnectionContext) { - console.log("Connected!"); - // Check the request at ctx.request - // Authenticate the client - // Give them the OK. - connection.accept(); - } - - // Called for each message received on the WebSocket connection - async onMessage(connection: Connection, message: WSMessage) { - console.log(`message from client ID: ${connection.id}`) - // Send messages back to the client - connection.send("Hello!"); - } - - // WebSocket error and disconnection (close) handling. - async onError(connection: Connection, error: unknown): Promise { - console.error(`WS error: ${error}`); - } - - async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise { - console.log(`WS closed: ${code} - ${reason} - wasClean: ${wasClean}`); - connection.close(); - } - - // Called when the Agent's state is updated - // via this.setState or the useAgent hook from the agents-sdk/react package. - async onStateUpdate(state: any) { - // 'state' will be typed if you supply a type parameter to the Agent class. - } -} - -export default MyAgent; -``` - - - -:::note - -To learn more about how to manage state within an Agent, refer to the documentation on [managing and syncing state](/agents/examples/manage-and-sync-state/). - -::: - -You can also define your own methods on an Agent: it's technically valid to publish an Agent only has your own methods exposed, and create/get Agents directly from a Worker. - -Your own methods can access the Agent's environment variables and bindings on `this.env`, state on `this.setState`, and call other methods on the Agent via `this.yourMethodName`. - -## Calling Agents from Workers - -You can create and run an instance of an Agent directly from a Worker in one of three ways: - -1. Using the `routeAgentRequest` helper: this will automatically map requests to an individual Agent based on the `/agents/:agent/:name` URL pattern. The value of `:agent` will be the name of your Agent class converted to `kebab-case`, and the value of `:name` will be the name of the Agent instance you want to create or retrieve. -2. Calling `getAgentByName`, which will create a new Agent instance if none exists by that name, or retrieve a handle to an existing instance. -3. The [Durable Objects stub API](/durable-objects/api/id/), which provides a lower level API for creating and retrieving Agents. - -These three patterns are shown below: we recommend using either `routeAgentRequest` or `getAgentByName`, which help avoid some boilerplate. - - - -```ts -import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from 'agents-sdk'; - -interface Env { - // Define your Agent on the environment here - // Passing your Agent class as a TypeScript type parameter allows you to call - // methods defined on your Agent. - MyAgent: AgentNamespace; -} - -export default { - async fetch(request, env, ctx): Promise { - // Routed addressing - // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name - // Best for: connecting React apps directly to Agents using useAgent from agents-sdk/react - (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); - - // Named addressing - // Best for: convenience method for creating or retrieving an agent by name/ID. - let namedAgent = getAgentByName(env.MyAgent, 'my-unique-agent-id'); - // Pass the incoming request straight to your Agent - let namedResp = (await namedAgent).fetch(request); - - // Durable Objects-style addressing - // Best for: controlling ID generation, associating IDs with your existing systems, - // and customizing when/how an Agent is created or invoked - const id = env.MyAgent.newUniqueId(); - const agent = env.MyAgent.get(id); - // Pass the incoming request straight to your Agent - let resp = await agent.fetch(request); - - return Response.json({ hello: 'visit https://developers.cloudflare.com/agents for more' }); - }, -} satisfies ExportedHandler; - -export class MyAgent extends Agent { - // Your Agent implementation goes here -} -``` - diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/api-reference/store-and-sync-state.mdx similarity index 78% rename from src/content/docs/agents/examples/manage-and-sync-state.mdx rename to src/content/docs/agents/api-reference/store-and-sync-state.mdx index efa7b1abf18178..fea3f3949f54de 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/api-reference/store-and-sync-state.mdx @@ -1,5 +1,5 @@ --- -title: Manage and sync state +title: Store and sync state pcx_content_type: concept sidebar: order: 6 @@ -7,14 +7,17 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -Every Agent has built-in state management capabilities, including built-in storage and synchronization between the Agent and frontend applications. State within an Agent is: +Every Agent has built-in state management capabilities, including built-in storage and synchronization between the Agent and frontend applications. -* Persisted across Agent restarts: data is permanently persisted within the Agent. +State within an Agent is: + +* Persisted across Agent restarts: data is permanently stored within an Agent. * Automatically serialized/deserialized: you can store any JSON-serializable data. * Immediately consistent within the Agent: read your own writes. * Thread-safe for concurrent updates +* Fast: state is colocated wherever the Agent is running. Reads and writes do not need to traverse the network. -Agent state is stored in a SQL database that is embedded within each individual Agent instance: you can interact with it using the higher-level `this.setState` API (recommended) or by directly querying the database with `this.sql`. +Agent state is stored in a SQL database that is embedded within each individual Agent instance: you can interact with it using the higher-level `this.setState` API (recommended), which allows you to sync state and trigger events on state changes, or by directly querying the database with `this.sql`. #### State API @@ -23,7 +26,7 @@ Every Agent has built-in state management capabilities. You can set and update t ```ts -import { Agent } from "agents-sdk"; +import { Agent } from "agents"; export class MyAgent extends Agent { // Update state in response to events @@ -58,7 +61,7 @@ If you're using TypeScript, you can also provide a type for your Agent's state b ```ts -import { Agent } from "agents-sdk"; +import { Agent } from "agents"; interface Env {} @@ -66,7 +69,7 @@ interface Env {} interface FlightRecord { id: string; departureIata: string; - arrival: Date;; + arrival: Date; arrivalIata: string; price: number; } @@ -90,9 +93,39 @@ export class MyAgent extends Agent { +### Set the initial state for an Agent + +You can also set the initial state for an Agent via the `initialState` property on the `Agent` class: + + + +```ts +type State = { + counter: number; + text: string; + color: string; +}; + +class MyAgent extends Agent { + // Set a default, initial state + initialState = { + counter: 0, + text: "", + color: "#3B82F6", + }; + + doSomething() { + console.log(this.state); // {counter: 0, text: "", color: "#3B82F6"}, if you haven't set the state yet + } +} +``` + + +Any initial state is synced to clients connecting via [the `useAgent` hook](#synchronizing-state). + ### Synchronizing state -Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `agents-sdk/react`. +Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `agents/react`. A React application can call `useAgent` to connect to a named Agent over WebSockets at @@ -100,7 +133,7 @@ A React application can call `useAgent` to connect to a named Agent over WebSock ```ts import { useState } from "react"; -import { useAgent } from "agents-sdk/react"; +import { useAgent } from "agents/react"; function StateInterface() { const [state, setState] = useState({ counter: 0 }); @@ -198,7 +231,7 @@ The SQL API exposed to an Agent is similar to the one [within Durable Objects](/ ### Use Agent state as model context -You can combine the state and SQL APIs in your Agent with its ability to [call AI models](/agents/examples/using-ai-models/) to include historical context within your prompts to a model. Modern Large Language Models (LLMs) often have very large context windows (up to millions of tokens), which allows you to pull relevant context into your prompt directly. +You can combine the state and SQL APIs in your Agent with its ability to [call AI models](/agents/api-reference/using-ai-models/) to include historical context within your prompts to a model. Modern Large Language Models (LLMs) often have very large context windows (up to millions of tokens), which allows you to pull relevant context into your prompt directly. For example, you can use an Agent's built-in SQL database to pull history, query a model with it, and append to that history ahead of the next call to the model: @@ -249,3 +282,9 @@ export class ReasoningAgent extends Agent { This works because each instance of an Agent has its _own_ database, the state stored in that database is private to that Agent: whether it's acting on behalf of a single user, a room or channel, or a deep research tool. By default, you don't have to manage contention or reach out over the network to a centralized database to retrieve and store state. +### Next steps + +* Review the [API documentation](/agents/api-reference/agents-api/) for the Agents class to learn how to define them. +* [Build a chat Agent](/agents/getting-started/build-a-chat-agent/) using the Agents SDK and deploy it to Workers. +* Learn more [using WebSockets](/agents/api-reference/websockets/) to build interactive Agents and stream data back from your Agent. +* [Orchestrate asynchronous workflows](/agents/api-reference/run-workflows) from your Agent by combining the Agents SDK and [Workflows](/workflows). diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/api-reference/using-ai-models.mdx similarity index 83% rename from src/content/docs/agents/examples/using-ai-models.mdx rename to src/content/docs/agents/api-reference/using-ai-models.mdx index 5287b0fa581915..ee5950231f75af 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/api-reference/using-ai-models.mdx @@ -2,21 +2,29 @@ title: Using AI Models pcx_content_type: concept sidebar: - order: 7 + order: 3 --- import { AnchorHeading, MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic, and Google's Gemini, and use the model routing features in [AI Gateway](/ai-gateway/) to route across providers, eval responses, and manage AI provider rate limits. +Agents can communicate with AI models hosted on any provider, including: -Because Agents are built on top of [Durable Objects](/durable-objects/), each Agent or chat session is associated with a stateful compute instance. Tradtional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. +* [Workers AI](/workers-ai/) +* The [AI SDK](https://sdk.vercel.ai/docs/ai-sdk-core/overview) +* [OpenAI](https://platform.openai.com/docs/quickstart?language=javascript) +* [Anthropic](https://docs.anthropic.com/en/api/client-sdks#typescript) +* [Google's Gemini](https://ai.google.dev/gemini-api/docs/openai) + +You can also use the model routing features in [AI Gateway](/ai-gateway/) to route across providers, eval responses, and manage AI provider rate limits. + +Because Agents are built on top of [Durable Objects](/durable-objects/), each Agent or chat session is associated with a stateful compute instance. Traditional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. A user can disconnect during a long-running response from a modern reasoning model (such as `o3-mini` or DeepSeek R1), or lose conversational context when refreshing the browser. Instead of relying on request-response patterns and managing an external database to track & store conversation state, state can be stored directly within the Agent. If a client disconnects, the Agent can write to its own distributed storage, and catch the client up as soon as it reconnects: even if it's hours or days later. ## Calling AI Models -You can call models from any method within an Agent, including from HTTP requests using the [`onRequest`](/agents/api-reference/sdk/) handler, when a [scheduled task](/agents/examples/schedule-tasks/) runs, when handling a WebSocket message in the [`onMessage`](/agents/examples/websockets/) handler, or from any of your own methods. +You can call models from any method within an Agent, including from HTTP requests using the [`onRequest`](/agents/api-reference/agents-api/) handler, when a [scheduled task](/agents/api-reference/schedule-tasks/) runs, when handling a WebSocket message in the [`onMessage`](/agents/api-reference/websockets/) handler, or from any of your own methods. Importantly, Agents can call AI models on their own — autonomously — and can handle long-running responses that can take minutes (or longer) to respond in full. @@ -24,18 +32,17 @@ Importantly, Agents can call AI models on their own — autonomously — and can Modern [reasoning models](https://platform.openai.com/docs/guides/reasoning) or "thinking" model can take some time to both generate a response _and_ stream the response back to the client. -Instead of buffering the entire response, or risking the client disconecting, you can stream the response back to the client by using the [WebSocket API](/agents/examples/websockets/). +Instead of buffering the entire response, or risking the client disconecting, you can stream the response back to the client by using the [WebSocket API](/agents/api-reference/websockets/). ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" import { OpenAI } from "openai" export class MyAgent extends Agent { async onConnect(connection: Connection, ctx: ConnectionContext) { - // Omitted for simplicity: authenticating the user - connection.accept() + // } async onMessage(connection: Connection, message: WSMessage) { @@ -75,7 +82,7 @@ export class MyAgent extends Agent { -You can also persist AI model responses back to [Agent's internal state](/agents/examples/manage-and-sync-state/) by using the `this.setState` method. For example, if you run a [scheduled task](/agents/examples/schedule-tasks/), you can store the output of the task and read it later. Or, if a user disconnects, read the message history back and send it to the user when they reconnect. +You can also persist AI model responses back to [Agent's internal state](/agents/api-reference/store-and-sync-state/) by using the `this.setState` method. For example, if you run a [scheduled task](/agents/api-reference/schedule-tasks/), you can store the output of the task and read it later. Or, if a user disconnects, read the message history back and send it to the user when they reconnect. ### Workers AI @@ -88,7 +95,7 @@ Workers AI supports streaming responses out-of-the-box by setting `stream: true` ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" interface Env { AI: Ai; @@ -138,7 +145,7 @@ Model routing allows you to route requests to different AI models based on wheth ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" interface Env { AI: Ai; @@ -192,7 +199,7 @@ npm install ai @ai-sdk/openai ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" import { generateText } from 'ai'; import { openai } from '@ai-sdk/openai'; @@ -214,12 +221,12 @@ export class MyAgent extends Agent { Agents can call models across any service, including those that support the OpenAI API. For example, you can use the OpenAI SDK to use one of [Google's Gemini models](https://ai.google.dev/gemini-api/docs/openai#node.js) directly from your Agent. -Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/examples/websockets/) API in your Agent to responses back to a client, which is especially useful for larger models that can take over 30+ seconds to reply. +Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/api-reference/websockets/) API in your Agent to responses back to a client, which is especially useful for larger models that can take over 30+ seconds to reply. ```ts -import { Agent } from "agents-sdk" +import { Agent } from "agents" import { OpenAI } from "openai" export class MyAgent extends Agent { diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/api-reference/websockets.mdx similarity index 72% rename from src/content/docs/agents/examples/websockets.mdx rename to src/content/docs/agents/api-reference/websockets.mdx index 8eccb861b04b4e..6348a15808bb7b 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/api-reference/websockets.mdx @@ -2,7 +2,7 @@ title: Using WebSockets pcx_content_type: concept sidebar: - order: 2 + order: 10 --- @@ -20,28 +20,13 @@ Here's an example of an Agent that echoes back any message it receives: ```ts -import { Agent, Connection } from "agents-sdk"; +import { Agent, Connection } from "agents"; export class ChatAgent extends Agent { - async onConnect(connection: Connection, ctx: ConnectionContext) { - // Access the request to verify any authentication tokens - // provided in headers or cookies - let token = ctx.request.headers.get("Authorization"); - if (!token) { - await connection.close(4000, "Unauthorized"); - return; - } - - // Handle auth using your favorite library and/or auth scheme: - // try { - // await jwt.verify(token, env.JWT_SECRET); - // } catch (error) { - // connection.close(4000, 'Invalid Authorization header'); - // return; - // } - - // Accept valid connections - connection.accept() + async onConnect(connection: Connection, ctx: ConnectionContext) { + // Connections are automatically accepted by the SDK. + // You can also explicitly close a connection here with connection.close() + // Access the Request on ctx.request to inspect headers, cookies and the URL } async onMessage(connection: Connection, message: WSMessage) { @@ -53,14 +38,14 @@ export class ChatAgent extends Agent { -## Connecting clients +### Connecting clients -The Agent framework includes a useful helper package for connecting directly to your Agent (or other Agents) from a client application. Import `agents-sdk/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: +The Agent framework includes a useful helper package for connecting directly to your Agent (or other Agents) from a client application. Import `agents/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: ```ts -import { AgentClient } from "agents-sdk/client"; +import { AgentClient } from "agents/client"; const connection = new AgentClient({ agent: "dialogue-agent", @@ -81,14 +66,14 @@ connection.send( -## React clients +### React clients -React-based applications can import `agents-sdk/react` and use the `useAgent` hook to connect to an instance of an Agent directly: +React-based applications can import `agents/react` and use the `useAgent` hook to connect to an instance of an Agent directly: ```ts -import { useAgent } from "agents-sdk/react"; +import { useAgent } from "agents/react"; function AgentInterface() { const connection = useAgent({ @@ -120,16 +105,16 @@ function AgentInterface() { ``` -The `useAgent` hook automatically handles the lifecycle of the connection, ensuring that it is properly initialized and cleaned up when the component mounts and unmounts. You can also [combine `useAgent` with `useState`](/agents/examples/manage-and-sync-state/) to automatically synchronize state across all clients connected to your Agent. +The `useAgent` hook automatically handles the lifecycle of the connection, ensuring that it is properly initialized and cleaned up when the component mounts and unmounts. You can also [combine `useAgent` with `useState`](/agents/api-reference/store-and-sync-state/) to automatically synchronize state across all clients connected to your Agent. -## Handling WebSocket events +### Handling WebSocket events Define `onError` and `onClose` methods on your Agent to explicitly handle WebSocket client errors and close events. Log errors, clean up state, and/or emit metrics: ```ts -import { Agent, Connection } from "agents-sdk"; +import { Agent, Connection } from "agents"; export class ChatAgent extends Agent { // onConnect and onMessage methods diff --git a/src/content/docs/agents/concepts/tools.mdx b/src/content/docs/agents/concepts/tools.mdx index b5a235895dd50e..27336ec93ab0d6 100644 --- a/src/content/docs/agents/concepts/tools.mdx +++ b/src/content/docs/agents/concepts/tools.mdx @@ -29,7 +29,7 @@ The most common type of tools are those that wrap external APIs. These tools han #### Model Context Protocol (MCP) -The (Model Context Protocol)[https://modelcontextprotocol.io/introduction] provides a standardized way to define and interact with tools. Think of it as an abstraction on top of APIs designed for LLMs to interact with external resources. MCP defines a consistent interface for: +The [Model Context Protocol](https://modelcontextprotocol.io/introduction) provides a standardized way to define and interact with tools. Think of it as an abstraction on top of APIs designed for LLMs to interact with external resources. MCP defines a consistent interface for: - **Tool Discovery**: Systems can dynamically discover available tools - **Parameter Validation**: Tools specify their input requirements using JSON Schema diff --git a/src/content/docs/agents/examples/index.mdx b/src/content/docs/agents/examples/index.mdx deleted file mode 100644 index 34f41dbf12ee2e..00000000000000 --- a/src/content/docs/agents/examples/index.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -pcx_content_type: reference -title: Examples -sidebar: - order: 3 ---- - -import { DirectoryListing, PackageManagers } from "~/components"; - -Agents running on Cloudflare can: - - diff --git a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx index 2d5b78b88399e0..a22a297ccc70a0 100644 --- a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx +++ b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx @@ -5,5 +5,5 @@ external_link: https://github.com/cloudflare/agents-starter sidebar: order: 3 head: [] -description: A starter template for building AI-powered chat agents using Cloudflare's Agent platform, powered by agents-sdk. This project provides a foundation for creating interactive chat experiences with AI, complete with a modern UI and tool integration capabilities. +description: A starter template for building AI-powered chat agents using Cloudflare's Agent platform, powered by the Agents SDK. This project provides a foundation for creating interactive chat experiences with AI, complete with a modern UI and tool integration capabilities. --- \ No newline at end of file diff --git a/src/content/docs/agents/getting-started/prompting.mdx b/src/content/docs/agents/getting-started/prompting.mdx index 10736b5ab43eaa..463edb7e413db2 100644 --- a/src/content/docs/agents/getting-started/prompting.mdx +++ b/src/content/docs/agents/getting-started/prompting.mdx @@ -5,5 +5,5 @@ external_link: /workers/get-started/prompting/ sidebar: order: 10 head: [] -description: Use the Workers "mega prompt" to build a Agents using your preferred AI tools and/or IDEs. The prompt understands agents-sdk APIs, best practices and guidelines, and makes it easier to build valid Agents and Workers. +description: Use the Workers "mega prompt" to build a Agents using your preferred AI tools and/or IDEs. The prompt understands the Agents SDK APIs, best practices and guidelines, and makes it easier to build valid Agents and Workers. --- diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index d57f42948062a3..49a177ec2034b8 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -2,7 +2,7 @@ title: Testing your Agents pcx_content_type: get-started sidebar: - order: 10 + order: 9 --- @@ -16,14 +16,14 @@ Because Agents run on Cloudflare Workers and Durable Objects, they can be tested :::note -The `agents-sdk-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file. +The `agents-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file. ::: Before you write your first test, install the necessary packages: ```sh -npm install vitest@2.1.8 --save-dev --save-exact +npm install vitest@~3.0.0 --save-dev --save-exact npm install @cloudflare/vitest-pool-workers --save-dev ``` diff --git a/src/content/docs/agents/guides/human-in-the-loop.mdx b/src/content/docs/agents/guides/human-in-the-loop.mdx index 20b69c099ab7b8..af9554f744ac50 100644 --- a/src/content/docs/agents/guides/human-in-the-loop.mdx +++ b/src/content/docs/agents/guides/human-in-the-loop.mdx @@ -5,5 +5,5 @@ external_link: https://github.com/cloudflare/agents/tree/main/guides/anthropic-p sidebar: order: 3 head: [] -description: Implement common agent patterns using the `agents-sdk` framework. +description: Implement common agent patterns using the Agents SDK framework. --- diff --git a/src/content/docs/agents/guides/remote-mcp-server.mdx b/src/content/docs/agents/guides/remote-mcp-server.mdx new file mode 100644 index 00000000000000..ec5a0473c1bdb7 --- /dev/null +++ b/src/content/docs/agents/guides/remote-mcp-server.mdx @@ -0,0 +1,219 @@ +--- +pcx_content_type: concept +title: Build a remote MCP server +sidebar: + order: 4 +--- + +import { Details, Render, PackageManagers } from "~/components"; + +## Deploy your first MCP server + +This guide will walk you through how to deploy an [example MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-server) to your Cloudflare account. You will then customize this example to suit your needs. + +To get started, run the following command to create a new MCP server: + + + +Now, you have the MCP server setup, with dependencies installed. Move into that project folder: + +```sh +cd my-mcp-server +``` + +### Local development + +In the directory of your new project, run the following command to start the development server: + +```sh +npm start +``` + +Your MCP server is now running on `http://localhost:8787/sse`. + +In a new terminal, run the [MCP inspector](https://github.com/modelcontextprotocol/mcp-inspector). The MCP inspector is an interactive MCP client that allows you to connect to your MCP server and invoke tools from a web browser. + +```sh +npx @modelcontextprotocol/inspector@latest +``` + +Open the MCP inspector in your web browser: + +```sh +open http://localhost:5173 +``` + +In the inspector, enter the URL of your MCP server, `http://localhost:8787/sse`, and click **Connect**: + +![MCP inspector — where to enter the URL of your MCP server](~/assets/images/agents/mcp-inspector-enter-url.png) + +You will be redirected to an example OAuth login page. Enter any username and password and click "Log in and approve" to continue. (you can add your own authentication and/or authorization provider to replace this. Refer to the [authorization](/agents/model-context-protocol/authorization/) section for details on how to do this.) + +![MCP OAuth Login Page](~/assets/images/agents/mcp-demo-oauth-flow.png) + +Once you have logged in, you will be redirected back to the inspector. You should see the "List Tools" button, which will list the tools that your MCP server exposes. + +![MCP inspector — authenticated](~/assets/images/agents/mcp-inspector-authenticated.png) + +### Deploy your MCP server + +You can deploy your MCP server to Cloudflare using the following [Wrangler CLI command](/workers/wrangler) within the example project: + +```sh +npx wrangler@latest deploy +``` + +If you have already [connected a git repository](/workers/ci-cd/builds/) to the Worker with your MCP server, you can deploy your MCP server by pushing a change or merging a pull request to the main branch of the repository. + +After deploying, take the URL of your deployed MCP server, and enter it in the MCP inspector running on `http://localhost:5173`. You now have a remote MCP server, deployed to Cloudflare, that MCP clients can connect to. + +### Connect your remote MCP server to Claude and other MCP Clients via a local proxy + +Now that your MCP server is running with OAuth authentication, you can use the [`mcp-remote` local proxy](https://www.npmjs.com/package/mcp-remote) to connect Claude Desktop or other MCP clients to it — even though these tools aren't yet _remote_ MCP clients, and don't support remote transport or authorization on the client side. This lets you to test what an interaction with your OAuth-enabled MCP server will be like with a real MCP client. + +Update your Claude Desktop configuration to point to the URL of your MCP server. You can use either the `localhost:8787/sse` URL, or the URL of your deployed MCP server: + +```json +{ + "mcpServers": { + "math": { + "command": "npx", + "args": [ + "mcp-remote", + "https://your-worker-name.your-account.workers.dev/sse" + ] + } + } +} +``` + +Restart Claude Desktop and complete the authentication flow again. Once this is done, Claude will be able to make calls to your remote MCP server. you can test this by asking Claude to use one of your tools. For example: "Could you use the math tool to add 23 and 19?". Claude should invoke the tool and show the result generated by the MCP server. + +Learn more about other ways of using remote MCP servers with MCP clients here in [this section](/agents/guides/test-remote-mcp-server). + +## Add Authentication + +The example MCP server you just deployed above acts as an OAuth provider to MCP clients, handling authorization, but has a placeholder authentication flow. It lets you enter any username and password to log in, and doesn't actually authenticate you against any user database. + +In the next section, you will add a real authentication provider to your MCP server. Following these steps will show you more clearly how to integrate it with your MCP server. We'll use GitHub in this example, but you can use any OAuth provider that supports the OAuth 2.0 specification, including Google, Slack, Stytch, Auth0, and more. + +### Step 1 — Create and deploy a new MCP server + +Run the following command to create a new MCP server: + + + +Now, you have the MCP server setup, with dependencies installed. Move into that project folder: + +```sh +cd my-mcp-server-github-auth +``` + +Then, run the following command to deploy the MCP server: + +```sh +npx wrangler@latest deploy +``` + +You'll notice that in the example MCP server, if you open `src/index.ts`, the primary difference is that the `defaultHandler` is set to the `GitHubHandler`: + +```ts ins="OAuthProvider.GitHubHandler" +import GitHubHandler from "./github-handler"; + +export default new OAuthProvider({ + apiRoute: "/sse", + apiHandler: MyMCP.Router, + defaultHandler: GitHubHandler, + authorizeEndpoint: "/authorize", + tokenEndpoint: "/token", + clientRegistrationEndpoint: "/register", +}); +``` + +This will ensure that your users are redirected to GitHub to authenticate. To get this working though, you need to create OAuth client apps in the steps below. + +### Step 2 — Create an OAuth App + +You'll need to create two [GitHub OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) to use GitHub as an authentication provider for your MCP server — one for local development, and one for production. + +#### First create a new OAuth App for local development + +Navigate to [github.com/settings/developers](https://github.com/settings/developers) to create a new OAuth App with the following settings: + +- **Application name**: `My MCP Server (local)` +- **Homepage URL**: `http://localhost:8787` +- **Authorization callback URL**: `http://localhost:8787/callback` + +For the OAuth app you just created, add the client ID of the OAuth app as `GITHUB_CLIENT_ID` and generate a client secret, adding it as `GITHUB_CLIENT_SECRET` to a `.dev.vars` file in the root of your project, which [will be used to set secrets in local development](/workers/configuration/secrets/). + +```sh +touch .dev.vars +echo 'GITHUB_CLIENT_ID="your-client-id"' >> .dev.vars +echo 'GITHUB_CLIENT_SECRET="your-client-secret"' >> .dev.vars +cat .dev.vars +``` + +#### Next, run your MCP server locally + +Run the following command to start the development server: + +```sh +npm start +``` + +Your MCP server is now running on `http://localhost:8787/sse`. + +In a new terminal, run the [MCP inspector](https://github.com/modelcontextprotocol/mcp-inspector). The MCP inspector is an interactive MCP client that allows you to connect to your MCP server and invoke tools from a web browser. + +```sh +npx @modelcontextprotocol/inspector@latest +``` + +Open the MCP inspector in your web browser: + +```sh +open http://localhost:5173 +``` + +In the inspector, enter the URL of your MCP server, `http://localhost:8787/sse`, and click **Connect**: + +You should be redirected to a GitHub login or authorization page. After authorizing the MCP Client (the inspector) access to your GitHub account, you will be redirected back to the inspector. You should see the "List Tools" button, which will list the tools that your MCP server exposes. + +#### Second — create a new OAuth App for production + +You'll need to repeat these steps to create a new OAuth App for production. + +Navigate to [github.com/settings/developers](https://github.com/settings/developers) to create a new OAuth App with the following settings: + +- **Application name**: `My MCP Server (production)` +- **Homepage URL**: Enter the workers.dev URL of your deployed MCP server (ex: `worker-name.account-name.workers.dev`) +- **Authorization callback URL**: Enter the `/callback` path of the workers.dev URL of your deployed MCP server (ex: `worker-name.account-name.workers.dev/callback`) + +For the OAuth app you just created, add the client ID and client secret, using Wrangler CLI: + +```sh +wrangler secret put GITHUB_CLIENT_ID +``` + +```sh +wrangler secret put GITHUB_CLIENT_SECRET +``` + +#### Finally, connect to your MCP server + +Now that you've added the ID and secret of your production OAuth app, you should now be able to connect to your MCP server running at `worker-name.account-name.workers.dev/sse` using the MCP inspector or ([other MCP clients](/agents/guides/remote-mcp-server/#connect-your-mcp-server-to-claude-and-other-mcp-clients)), and authenticate with GitHub. + +## Next steps + +- Add [tools](/agents/model-context-protocol/tools/) to your MCP server. +- Customize your MCP Server's [authentication and authorization](/agents/model-context-protocol/authorization/). diff --git a/src/content/docs/agents/guides/test-remote-mcp-server.mdx b/src/content/docs/agents/guides/test-remote-mcp-server.mdx new file mode 100644 index 00000000000000..5a5c8e07e12eb4 --- /dev/null +++ b/src/content/docs/agents/guides/test-remote-mcp-server.mdx @@ -0,0 +1,73 @@ +--- +pcx_content_type: concept +title: Test a Remote MCP Server +sidebar: + order: 6 +--- + +import { Render } from "~/components"; + +Remote, authorized connections are an evolving part of the [Model Context Protocol (MCP) specification](https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/). Not all MCP clients support remote connections yet. + +This guide will show you options for how to start using your remote MCP server with MCP clients that support remote connections. If you haven't yet created and deployed a remote MCP server, you should follow the [Build a Remote MCP Server](/agents/guides/remote-mcp-server/) guide first. + +## The Model Context Protocol (MCP) inspector + +The [`@modelcontextprotocol/inspector` package](https://github.com/modelcontextprotocol/inspector) is a visual testing tool for MCP servers. + +You can run it locally by running the following command: + +```bash +npx @modelcontextprotocol/inspector +``` + +Then, enter the URL of your remote MCP server. You can use an MCP server running on your local machine on localhost, or you can use a remote MCP server running on Cloudflare. + +![MCP inspector](~/assets/images/agents/mcp-inspector-enter-url.png) + +Once you have authenticated, you will be redirected back to the inspector. You should see the "List Tools" button, which will list the tools that your MCP server exposes. + +![MCP inspector — authenticated](~/assets/images/agents/mcp-inspector-authenticated.png) + +## Connect your remote MCP server to Claude Desktop via a local proxy + +Even though [Claude Desktop](https://claude.ai/download) doesn't yet support remote MCP clients, you can use the [`mcp-remote` local proxy](https://www.npmjs.com/package/mcp-remote) to connect it to your remote MCP server. This lets you to test what an interaction with your remote MCP server will be like with a real-world MCP client. + +1. Open Claude Desktop and navigate to Settings -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access. +2. Replace the content with a configuration like this: + +```json +{ + "mcpServers": { + "math": { + "command": "npx", + "args": ["mcp-remote", "http://my-mcp-server.my-account.workers.dev/sse"] + } + } +} +``` + +This tells Claude to communicate with your MCP server running at `http://localhost:8787/sse`. + +3. Save the file and restart Claude Desktop (command/ctrl + R). When Claude restarts, a browser window will open showing your OAuth login page. Complete the authorization flow to grant Claude access to your MCP server. + +Once authenticated, you'll be able to see your tools by clicking the tools icon in the bottom right corner of Claude's interface. + +## Connect your remote MCP server to Cursor + +To connect [Cursor](https://www.cursor.com/) with your remote MCP server, choose `Type`: "Command" and in the `Command` field, combine the command and args fields into one (e.g.`npx mcp-remote https://your-worker-name.your-account.workers.dev/sse`). + +## Connect your remote MCP server to Windsurf + +You can connect your remote MCP server to [Windsurf](https://codeium.com/windsurf) by editing the [`mcp_config.json` file](https://docs.codeium.com/windsurf/mcp), and adding the following configuration: + +```json +{ + "mcpServers": { + "math": { + "command": "npx", + "args": ["mcp-remote", "http://my-mcp-server.my-account.workers.dev/sse"] + } + } +} +``` diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 701e8f694d16fd..752e856a1633af 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -21,13 +21,14 @@ import { Render, TabItem, Tabs, + TypeScriptExample, } from "~/components"; -Build and deploy AI-powered Agents on Cloudflare that can autonomously perform tasks, communicate with clients in real time, persist state, execute long-running and repeat tasks on a schedule, send emails, run asynchronous workflows, browse the web, query data from your Postgres database, call AI models, support human-in-the-loop use-cases, and more. +The Agents SDK enables you to build and deploy AI-powered agents that can autonomously perform tasks, communicate with clients in real time, call AI models, persist state, schedule tasks, run asynchronous workflows, browse the web, query data from your database, support human-in-the-loop interactions, and [a lot more](/agents/api-reference/). -#### Ship your first Agent +### Ship your first Agent -Use the agent started template to create your first Agent with the `agents-sdk`: +To use the Agent starter template and create your first Agent with the Agents SDK: ```sh # install it @@ -36,29 +37,49 @@ npm create cloudflare@latest agents-starter -- --template=cloudflare/agents-star npx wrangler@latest deploy ``` -Head to the guide on [building a chat agent](/agents/getting-started/build-a-chat-agent) to learn how to build and deploy an Agent to prod. +Head to the guide on [building a chat agent](/agents/getting-started/build-a-chat-agent) to learn how the starter project is built and how to use it as a foundation for your own agents. -If you're already building on [Workers](/workers/), you can install the `agents-sdk` package directly into an existing project: +If you're already building on [Workers](/workers/), you can install the `agents` package directly into an existing project: ```sh -npm i agents-sdk +npm i agents ``` -Dive into the [Agent SDK reference](/agents/api-reference/sdk/) to learn more about how to use the `agents-sdk` package and defining an `Agent`. +And then define your first Agent by creating a class that extends the `Agent` class: -#### Why build agents on Cloudflare? + -We built the `agents-sdk` with a few things in mind: +```ts +import { Agent, AgentNamespace } from 'agents'; -- **Batteries (state) included**: Agents come with [built-in state management](/agents/examples/manage-and-sync-state/), with the ability to automatically sync state between an Agent and clients, trigger events on state changes, and read+write to each Agent's SQL database. -- **Communicative**: You can connect to an Agent via [WebSockets](/agents/examples/websockets/) and stream updates back to client in real-time. Handle a long-running response from a reasoning model, the results of an [asynchronous workflow](/agents/examples/run-workflows/), or build a chat app that builds on the `useAgent` hook included in the `agents-sdk`. -- **Extensible**: Agents are code. Use the [AI models](/agents/examples/using-ai-models/) you want, bring-your-own headless browser service, pull data from your database hosted in another cloud, add your own methods to your Agent and call them. +export class MyAgent extends Agent { + // Define methods on the Agent: + // https://developers.cloudflare.com/agents/api-reference/agents-api/ + // + // Every Agent has built in state via this.setState and this.sql + // Built-in scheduling via this.schedule + // Agents support WebSockets, HTTP requests, state synchronization and + // can run for seconds, minutes or hours: as long as the tasks need. +} +``` + + + +Dive into the [Agent SDK reference](/agents/api-reference/agents-api/) to learn more about how to use the Agents SDK package and defining an `Agent`. + +### Why build agents on Cloudflare? -Agents built with `agents-sdk` can be deployed directly to Cloudflare and run on top of [Durable Objects](/durable-objects/) — which you can think of as stateful micro-servers that can scale to tens of millions — and are able to run wherever they need to. Run your Agents close to a user for low-latency interactivity, close to your data for throughput, and/or anywhere in between. +We built the Agents SDK with a few things in mind: -*** +- **Batteries (state) included**: Agents come with [built-in state management](/agents/api-reference/store-and-sync-state/), with the ability to automatically sync state between an Agent and clients, trigger events on state changes, and read+write to each Agent's SQL database. +- **Communicative**: You can connect to an Agent via [WebSockets](/agents/api-reference/websockets/) and stream updates back to client in real-time. Handle a long-running response from a reasoning model, the results of an [asynchronous workflow](/agents/api-reference/run-workflows/), or build a chat app that builds on the `useAgent` hook included in the Agents SDK. +- **Extensible**: Agents are code. Use the [AI models](/agents/api-reference/using-ai-models/) you want, bring-your-own headless browser service, pull data from your database hosted in another cloud, add your own methods to your Agent and call them. + +Agents built with Agents SDK can be deployed directly to Cloudflare and run on top of [Durable Objects](/durable-objects/) — which you can think of as stateful micro-servers that can scale to tens of millions — and are able to run wherever they need to. Run your Agents close to a user for low-latency interactivity, close to your data for throughput, and/or anywhere in between. + +--- -#### Build on the Cloudflare Platform +### Build on the Cloudflare Platform diff --git a/src/content/docs/agents/model-context-protocol/authorization.mdx b/src/content/docs/agents/model-context-protocol/authorization.mdx new file mode 100644 index 00000000000000..bb7d7da859343b --- /dev/null +++ b/src/content/docs/agents/model-context-protocol/authorization.mdx @@ -0,0 +1,132 @@ +--- +title: Authorization +sidebar: + order: 2 + group: + hideIndex: true +--- + +import { DirectoryListing } from "~/components"; + +When building a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server, you need both a way to allow users to login (authentication) and allow them to grant the MCP client access to resources on their account (authorization). + + + + + +The Model Context Protocol uses [a subset of OAuth 2.1 for authorization](https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/). OAuth allows your users to grant limited access to resources, without them having to share API keys or other credentials. + +Cloudflare provides an [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) that implements the provider side of the OAuth 2.1 protocol, allowing you to easily add authorization to your MCP server. + +You can use the OAuth Provider Library in three ways: + +1. **Your Worker handles authorization itself.** Your MCP server, running on Cloudflare, handles the complete OAuth flow. ([Example](/agents/guides/remote-mcp-server/)) +2. **Integrate directly with a third-party OAuth provider**, such as GitHub or Google. +3. **Integrate with your own OAuth provider**, including authorization-as-a-service providers you might already rely on, such as Stytch and Auth0. + +The following sections describe each of these options and link to runnable code examples for each. + +## Authorization options + +### (1) Your MCP Server handles authorization and authentication itself + +Your MCP Server, using the [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider), can handle the complete OAuth authorization flow, without any third-party involvement. + +The [Workers OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) is a Cloudflare Worker that implements a [`fetch()` handler](/workers/runtime-apis/handlers/fetch/), and handles incoming requests to your MCP server. + +You provide your own handlers for your MCP Server's API, and autentication and authorization logic, and URI paths for the OAuth endpoints, as shown below: + +```ts +export default new OAuthProvider({ + apiRoute: "/mcp", + // Your MCP server: + apiHandler: MyMCPServer.Router, + // Your handler for authentication and authorization: + defaultHandler: MyAuthHandler, + authorizeEndpoint: "/authorize", + tokenEndpoint: "/token", + clientRegistrationEndpoint: "/register", +}); +``` + +Refer to the [getting started example](/agents/guides/remote-mcp-server/) for a complete example of the `OAuthProvider` in use, with a mock authentication flow. + +The authorization flow in this case works like this: + +```mermaid +sequenceDiagram + participant B as User-Agent (Browser) + participant C as MCP Client + participant M as MCP Server (your Worker) + + C->>M: MCP Request + M->>C: HTTP 401 Unauthorized + Note over C: Generate code_verifier and code_challenge + C->>B: Open browser with authorization URL + code_challenge + B->>M: GET /authorize + Note over M: User logs in and authorizes + M->>B: Redirect to callback URL with auth code + B->>C: Callback with authorization code + C->>M: Token Request with code + code_verifier + M->>C: Access Token (+ Refresh Token) + C->>M: MCP Request with Access Token + Note over C,M: Begin standard MCP message exchange +``` + +Remember — [authentication is different from authorization](https://www.cloudflare.com/learning/access-management/authn-vs-authz/). Your MCP Server can handle authorization itself, while still relying on an external authentication service to first authenticate users. The [example](/agents/guides/remote-mcp-server) in getting started provides a mock authentdcation flow. You will need to implement your own authentication handler — either handling authentication yourself, or using an external authentication services. + +### (2) Third-party OAuth Provider + +The [OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) can be configured to use a third-party OAuth provider, such as GitHub or Google. You can see a complete example of this in the [GitHub example](/agents/guides/remote-mcp-server/#add-authentication). + +When you use a third-party OAuth provider, you must provide a handler to the `OAuthProvider` that implements the OAuth flow for the third-party provider. + +```ts ins="defaultHandler: MyAuthHandler," +import MyAuthHandler from "./auth-handler"; + +export default new OAuthProvider({ + apiRoute: "/mcp", + // Your MCP server: + apiHandler: MyMCPServer.Router, + // Replace this handler with your own handler for authentication and authorization with the third-party provider: + defaultHandler: MyAuthHandler, + authorizeEndpoint: "/authorize", + tokenEndpoint: "/token", + clientRegistrationEndpoint: "/register", +}); +``` + +Note that as [defined in the Model Context Protocol specification](https://spec.modelcontextprotocol.io/specification/draft/basic/authorization/#292-flow-description) when you use a third-party OAuth provider, the MCP Server (your Worker) generates and issues its own token to the MCP client: + +```mermaid +sequenceDiagram + participant B as User-Agent (Browser) + participant C as MCP Client + participant M as MCP Server (your Worker) + participant T as Third-Party Auth Server + + C->>M: Initial OAuth Request + M->>B: Redirect to Third-Party /authorize + B->>T: Authorization Request + Note over T: User authorizes + T->>B: Redirect to MCP Server callback + B->>M: Authorization code + M->>T: Exchange code for token + T->>M: Third-party access token + Note over M: Generate bound MCP token + M->>B: Redirect to MCP Client callback + B->>C: MCP authorization code + C->>M: Exchange code for token + M->>C: MCP access token +``` + +Read the docs for the [Workers oAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) for more details. + +### (3) Bring your own OAuth Provider + +If your application already implements an Oauth Provider itself, or you use Stytch, Auth0, or authorization-as-a-service provider, you can use this in the same way that you would use a third-party OAuth provider, described above in (2). + +## Next steps + +- [Learn how to use the Workers OAuth Provider Library](https://github.com/cloudflare/workers-oauth-provider) +- Learn how to use a third-party OAuth provider, using the [GitHub](/agents/guides/remote-mcp-server/#add-authentication) example MCP server. diff --git a/src/content/docs/agents/model-context-protocol/index.mdx b/src/content/docs/agents/model-context-protocol/index.mdx new file mode 100644 index 00000000000000..0ba9dce0cb5f92 --- /dev/null +++ b/src/content/docs/agents/model-context-protocol/index.mdx @@ -0,0 +1,31 @@ +--- +title: Model Context Protocol (MCP) +pcx_content_type: navigation +sidebar: + order: 4 + group: + hideIndex: false +--- + +You can build and deploy [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers on Cloudflare. + +## What is the Model Context Protocol (MCP)? + +[Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard that connects AI systems with external applications. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various accessories, MCP provides a standardized way to connect AI agents to different services. + +### MCP Terminology + +- **MCP Hosts**: AI assistants (like [Claude](http://claude.ai) or [Cursor](http://cursor.com)), AI agents, or applications that need to access external capabilities. +- **MCP Clients**: Clients embedded within the MCP hosts that connect to MCP servers and invoke tools. Each MCP client instance has a single connection to an MCP server. +- **MCP Servers**: Applications that expose [tools](/agents/model-context-protocol/tools/), [prompts](https://modelcontextprotocol.io/docs/concepts/prompts), and [resources](https://modelcontextprotocol.io/docs/concepts/resources) that MCP clients can use. + +### Remote vs. local MCP connections + +The MCP standard supports two modes of operation: + +- **Remote MCP connections**: MCP clients connect to MCP servers over the Internet, establishing a [long-lived connection using HTTP and Server-Sent Events (SSE)](/agents/model-context-protocol/transport/), and authorizing the MCP client access to resources on the user's account using [OAuth](/agents/model-context-protocol/authorization/). +- **Local MCP connections**: MCP clients connect to MCP servers on the same machine, using [stdio](https://spec.modelcontextprotocol.io/specification/draft/basic/transports/#stdio) as a local transport method. + +### Get Started + +Go to the [Getting Started](/agents/guides/remote-mcp-server/) guide to learn how to build and deploy your first remote MCP server to Cloudflare. diff --git a/src/content/docs/agents/model-context-protocol/tools.mdx b/src/content/docs/agents/model-context-protocol/tools.mdx new file mode 100644 index 00000000000000..d1e6aaa1483ee6 --- /dev/null +++ b/src/content/docs/agents/model-context-protocol/tools.mdx @@ -0,0 +1,34 @@ +--- +pcx_content_type: concept +title: Tools +sidebar: + order: 3 +--- + +import { Render, TypeScriptExample } from "~/components"; + +Model Context Protocol (MCP) tools are functions that a [MCP Server](/agents/model-context-protocol) provides and MCP clients can call. + +When you build MCP Servers with the `@cloudflare/model-context-protocol` package, you can define tools the [same way as shown in the `@modelcontextprotocol/typescript-sdk` package's examples](https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#tools). + +For example, the following code from [this example MCP server](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-server) defines a simple MCP server that adds two numbers together: + + +```ts title="src/index.ts" +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp"; +import { DurableMCP } from "@cloudflare/model-context-protocol"; + +export class MyMCP extends DurableMCP { + server = new McpServer({ name: "Demo", version: "1.0.0" }); + async init() { + this.server.tool( + "add", + { a: z.number(), b: z.number() }, + async ({ a, b }) => ({ + content: [{ type: "text", text: String(a + b) }], + }), + ); + } +} +``` + diff --git a/src/content/docs/agents/model-context-protocol/transport.mdx b/src/content/docs/agents/model-context-protocol/transport.mdx new file mode 100644 index 00000000000000..06f4291848dc2e --- /dev/null +++ b/src/content/docs/agents/model-context-protocol/transport.mdx @@ -0,0 +1,21 @@ +--- +pcx_content_type: concept +title: Transport +sidebar: + order: 5 +--- + +import { Render } from "~/components"; + +The Model Context Protocol (MCP) specification defines [two standard transport mechanisms](https://spec.modelcontextprotocol.io/specification/draft/basic/transports/): + +1. **stdio, communication over standard in and standard out** — designed for local MCP connections +2. **HTTP with Server-Sent Events (SSE)** — designed for remote MCP connections + +MCP Servers deployed to Cloudflare support remote MCP connections, using HTTP with Server-Sent Events (SSE) as transport. SSE requires a persistent HTTP connection, which is supported by Cloudflare [Durable Objects](/durable-objects/). Transport is configured and handled automatically. You don't need to configure anything — it just works. + +:::note +Even if the MCP client you are using only supports local MCP connections, you can still connect it to a remote MCP server. + +Follow [this guide](/agents/guides/test-remote-mcp-server/) for instructions on how to connect to your remote MCP server from Claude Desktop, Cursor, Windsurf, and other local MCP clients, using the [`mcp-remote` local proxy](https://www.npmjs.com/package/mcp-remote). +::: diff --git a/src/content/docs/agents/platform/index.mdx b/src/content/docs/agents/platform/index.mdx index 77d033f1bfa25a..59ce231e2cb7b7 100644 --- a/src/content/docs/agents/platform/index.mdx +++ b/src/content/docs/agents/platform/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: reference -title: Reference +title: Platform sidebar: order: 10 group: @@ -9,6 +9,4 @@ sidebar: import { DirectoryListing } from "~/components"; -Build AI Agents on Cloudflare - diff --git a/src/content/docs/agents/platform/limits.mdx b/src/content/docs/agents/platform/limits.mdx index be10fa8a1fb944..7279c9b4a66186 100644 --- a/src/content/docs/agents/platform/limits.mdx +++ b/src/content/docs/agents/platform/limits.mdx @@ -12,8 +12,6 @@ Limits that apply to authoring, deploying, and running Agents are detailed below Many limits are inherited from those applied to Workers scripts and/or Durable Objects, and are detailed in the [Workers limits](/workers/platform/limits/) documentation. -::: note - | Feature | Limit | | ----------------------------------------- | ----------------------- | | Max concurrent (running) Agents per account | Tens of millions+ [^1] @@ -26,6 +24,6 @@ Many limits are inherited from those applied to Workers scripts and/or Durable O [^1]: Yes, really. You can have tens of millions of Agents running concurrently, as each Agent is mapped to a [unique Durable Object](/durable-objects/what-are-durable-objects/) (actor). [^2]: You can deploy up to [500 scripts per account](/workers/platform/limits/), but each script (project) can define multiple Agents. Each deployed script can be up to 10 MB on the [Workers Paid Plan](/workers/platform/pricing/#workers) -[^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/examples/schedule-tasks/), or an incoming WebSocket message. +[^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/api-reference/schedule-tasks/), or an incoming WebSocket message. diff --git a/src/content/docs/agents/platform/llms.txt.mdx b/src/content/docs/agents/platform/prompt.txt.mdx similarity index 74% rename from src/content/docs/agents/platform/llms.txt.mdx rename to src/content/docs/agents/platform/prompt.txt.mdx index 9e4d540f2fd35d..a39d4719ad45f2 100644 --- a/src/content/docs/agents/platform/llms.txt.mdx +++ b/src/content/docs/agents/platform/prompt.txt.mdx @@ -1,7 +1,7 @@ --- pcx_content_type: navigation -title: llms.txt -external_link: /llms.txt +title: prompt.txt +external_link: /workers/prompt.txt sidebar: order: 99 head: [] diff --git a/src/content/docs/ai-gateway/configuration/custom-costs.mdx b/src/content/docs/ai-gateway/configuration/custom-costs.mdx index 57b86741ad78a9..a3b2cb28d53a3c 100644 --- a/src/content/docs/ai-gateway/configuration/custom-costs.mdx +++ b/src/content/docs/ai-gateway/configuration/custom-costs.mdx @@ -45,3 +45,8 @@ curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/ ] }' ``` + +:::note + +If a response is served from cache (cache hit), the cost is always `0`, even if you specified a custom cost. Custom costs only apply when the request reaches the model provider. +::: diff --git a/src/content/docs/ai-gateway/configuration/fallbacks.mdx b/src/content/docs/ai-gateway/configuration/fallbacks.mdx index 9f3e69c604f10c..162151ca9647e8 100644 --- a/src/content/docs/ai-gateway/configuration/fallbacks.mdx +++ b/src/content/docs/ai-gateway/configuration/fallbacks.mdx @@ -9,7 +9,7 @@ import { Render } from "~/components"; Specify model or provider fallbacks with your [Universal endpoint](/ai-gateway/providers/universal/) to handle request failures and ensure reliability. -Cloudflare can trigger your fallback provider in response to [request errors](#request-failures) or [predetermined request timeouts](#request-timeouts). The [response header `cf-aig-step`](#response-headercf-aig-step) indicates which step successfully processed the request. +Cloudflare can trigger your fallback provider in response to [request errors](#request-failures) or [predetermined request timeouts](/ai-gateway/configuration/request-handling#request-timeouts). The [response header `cf-aig-step`](#response-headercf-aig-step) indicates which step successfully processed the request. ## Request failures diff --git a/src/content/docs/ai-gateway/configuration/websockets-api/index.mdx b/src/content/docs/ai-gateway/configuration/websockets-api/index.mdx new file mode 100644 index 00000000000000..731efe17563d82 --- /dev/null +++ b/src/content/docs/ai-gateway/configuration/websockets-api/index.mdx @@ -0,0 +1,35 @@ +--- +title: WebSockets API +pcx_content_type: configuration +sidebar: + group: + badge: Beta +--- + +The AI Gateway WebSockets API provides a persistent connection for AI interactions, eliminating repeated handshakes and reducing latency. This API is divided into two categories: + +- **Realtime APIs** - Designed for AI providers that offer low-latency, multimodal interactions over WebSockets. +- **Non-Realtime APIs** - Supports standard WebSocket communication for AI providers, including those that do not natively support WebSockets. + +## When to use WebSockets? + +WebSockets are long-lived TCP connections that enable bi-directional, real-time and non realtime communication between client and server. Unlike HTTP connections, which require repeated handshakes for each request, WebSockets maintain the connection, supporting continuous data exchange with reduced overhead. WebSockets are ideal for applications needing low-latency, real-time data, such as voice assistants. + +## Key benefits + +- **Reduced overhead**: Avoid overhead of repeated handshakes and TLS negotiations by maintaining a single, persistent connection. +- **Provider compatibility**: Works with all AI providers in AI Gateway. Even if your chosen provider does not support WebSockets, Cloudflare handles it for you, managing the requests to your preferred AI provider. + +## **Key differences** + +| Feature | Realtime APIs | Non-Realtime APIs | +| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------- | +| **Purpose** | Enables real-time, multimodal AI interactions for providers that offer dedicated WebSocket endpoints. | Supports WebSocket-based AI interactions with providers that do not natively support WebSockets. | +| **Use Case** | Streaming responses for voice, video, and live interactions. | Text-based queries and responses, such as LLM requests. | +| **AI Provider Support** | [Limited to providers offering real-time WebSocket APIs.](/ai-gateway/configuration/websockets-api/realtime-api/#supported-providers) | [All AI providers in AI Gateway.](/ai-gateway/providers) | +| **Streaming Support** | Providers natively support real-time data streaming. | AI Gateway handles streaming via WebSockets. | + +For details on implementation, refer to the next sections: + +- [Realtime WebSockets API](/ai-gateway/configuration/websockets-api/realtime-api/) +- [Non-Realtime WebSockets API](/ai-gateway/configuration/websockets-api/non-realtime-api/) diff --git a/src/content/docs/ai-gateway/configuration/websockets-api.mdx b/src/content/docs/ai-gateway/configuration/websockets-api/non-realtime-api.mdx similarity index 70% rename from src/content/docs/ai-gateway/configuration/websockets-api.mdx rename to src/content/docs/ai-gateway/configuration/websockets-api/non-realtime-api.mdx index ad676b49c74e13..ea598d58a8a4d4 100644 --- a/src/content/docs/ai-gateway/configuration/websockets-api.mdx +++ b/src/content/docs/ai-gateway/configuration/websockets-api/non-realtime-api.mdx @@ -1,21 +1,11 @@ --- -title: WebSockets API pcx_content_type: configuration +title: Non-realtime WebSockets API sidebar: - badge: - text: Beta + order: 3 --- -The AI Gateway WebSockets API provides a single persistent connection, enabling continuous communication. By using WebSockets, you can establish a single connection for multiple AI requests, eliminating the need for repeated handshakes and TLS negotiations, which enhances performance and reduces latency. This API supports all AI providers connected to AI Gateway, including those that do not natively support WebSockets. - -## When to use WebSockets? - -WebSockets are long-lived TCP connections that enable bi-directional, real-time communication between client and server. Unlike HTTP connections, which require repeated handshakes for each request, WebSockets maintain the connection, supporting continuous data exchange with reduced overhead. WebSockets are ideal for applications needing low-latency, real-time data, such as voice assistants. - -## Key benefits - -- **Reduced Overhead**: Avoid overhead of repeated handshakes and TLS negotiations by maintaining a single, persistent connection. -- **Provider Compatibility**: Works with all AI providers in AI Gateway. Even if your chosen provider does not support WebSockets, we handle it for you, managing the requests to your preferred AI provider. +The Non-realtime WebSockets API allows you to establish persistent connections for AI requests without requiring repeated handshakes. This approach is ideal for applications that do not require real-time interactions but still benefit from reduced latency and continuous communication. ## Set up WebSockets API diff --git a/src/content/docs/ai-gateway/configuration/websockets-api/realtime-api.mdx b/src/content/docs/ai-gateway/configuration/websockets-api/realtime-api.mdx new file mode 100644 index 00000000000000..00dec7238fa608 --- /dev/null +++ b/src/content/docs/ai-gateway/configuration/websockets-api/realtime-api.mdx @@ -0,0 +1,133 @@ +--- +pcx_content_type: configuration +title: Realtime WebSockets API +sidebar: + order: 2 +--- + +Some AI providers support real-time, low-latency interactions over WebSockets. AI Gateway allows seamless integration with these APIs, supporting multimodal interactions such as text, audio, and video. + +## Supported Providers + +- [OpenAI](https://platform.openai.com/docs/guides/realtime-websocket) +- [Google AI Studio](https://ai.google.dev/gemini-api/docs/multimodal-live) +- [Cartesia](https://docs.cartesia.ai/api-reference/tts/tts) +- [ElevenLabs](https://elevenlabs.io/docs/conversational-ai/api-reference/conversational-ai/websocket) + +## Authentication + +For real-time WebSockets, authentication can be done using: + +- Headers (for non-browser environments) +- `sec-websocket-protocol` (for browsers) + +## Examples + +### OpenAI + +```javascript +import WebSocket from "ws"; + +const url = + "wss://gateway.ai.cloudflare.com/v1///openai?model=gpt-4o-realtime-preview-2024-12-17"; +const ws = new WebSocket(url, { + headers: { + "cf-aig-authorization": process.env.CLOUDFLARE_API_KEY, + Authorization: "Bearer " + process.env.OPENAI_API_KEY, + "OpenAI-Beta": "realtime=v1", + }, +}); + +ws.on("open", () => console.log("Connected to server.")); +ws.on("message", (message) => console.log(JSON.parse(message.toString()))); + +ws.send( + JSON.stringify({ + type: "response.create", + response: { modalities: ["text"], instructions: "Tell me a joke" }, + }), +); +``` + +### Google AI Studio + +```javascript +const ws = new WebSocket( + "wss://gateway.ai.cloudflare.com/v1///google?api_key=", + ["cf-aig-authorization."], +); + +ws.on("open", () => console.log("Connected to server.")); +ws.on("message", (message) => console.log(message.data)); + +ws.send( + JSON.stringify({ + setup: { + model: "models/gemini-2.0-flash-exp", + generationConfig: { responseModalities: ["TEXT"] }, + }, + }), +); +``` + +### Cartesia + +```javascript +const ws = new WebSocket( + "wss://gateway.ai.cloudflare.com/v1///cartesia?cartesia_version=2024-06-10&api_key=", + ["cf-aig-authorization."], +); + +ws.on("open", function open() { + console.log("Connected to server."); +}); + +ws.on("message", function incoming(message) { + console.log(message.data); +}); + +ws.send( + JSON.stringify({ + model_id: "sonic", + transcript: "Hello, world! I'm generating audio on ", + voice: { mode: "id", id: "a0e99841-438c-4a64-b679-ae501e7d6091" }, + language: "en", + context_id: "happy-monkeys-fly", + output_format: { + container: "raw", + encoding: "pcm_s16le", + sample_rate: 8000, + }, + add_timestamps: true, + continue: true, + }), +); +``` + +### ElevenLabs + +```javascript +const ws = new WebSocket( + "wss://gateway.ai.cloudflare.com/v1///elevenlabs?agent_id=", + [ + "xi-api-key.", + "cf-aig-authorization.", + ], +); + +ws.on("open", function open() { + console.log("Connected to server."); +}); + +ws.on("message", function incoming(message) { + console.log(message.data); +}); + +ws.send( + JSON.stringify({ + text: "This is a sample text ", + voice_settings: { stability: 0.8, similarity_boost: 0.8 }, + generation_config: { chunk_length_schedule: [120, 160, 250, 290] }, + }), +); +``` diff --git a/src/content/docs/ai-gateway/get-started.mdx b/src/content/docs/ai-gateway/get-started.mdx index 91859f2a328ee0..3aa222748a7ac0 100644 --- a/src/content/docs/ai-gateway/get-started.mdx +++ b/src/content/docs/ai-gateway/get-started.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: get-started -title: Get started +title: Getting started updated: 2024-06-19 sidebar: order: 2 diff --git a/src/content/docs/ai-gateway/guardrails/index.mdx b/src/content/docs/ai-gateway/guardrails/index.mdx new file mode 100644 index 00000000000000..e373c051466c30 --- /dev/null +++ b/src/content/docs/ai-gateway/guardrails/index.mdx @@ -0,0 +1,43 @@ +--- +title: Guardrails +pcx_content_type: navigation +order: 1 +sidebar: + order: 8 + group: + badge: Beta +--- + +import { CardGrid, LinkTitleCard, YouTube } from "~/components"; + +Guardrails help you deploy AI applications safely by intercepting and evaluating both user prompts and model responses for harmful content. Acting as a proxy between your application and [model providers](/ai-gateway/providers/) (such as OpenAI, Anthropic, DeepSeek, and others), AI Gateway's Guardrails ensure a consistent and secure experience across your entire AI ecosystem. + +Guardrails proactively monitor interactions between users and AI models, giving you: + +- **Consistent moderation**: Uniform moderation layer that works across models and providers. +- **Enhanced safety and user trust**: Proactively protect users from harmful or inappropriate interactions. +- **Flexibility and control over allowed content**: Specify which categories to monitor and choose between flagging or outright blocking. +- **Auditing and compliance capabilities**: Receive updates on evolving regulatory requirements with logs of user prompts, model responses, and enforced guardrails. + +## Video demo + + + +## How Guardrails work + +AI Gateway inspects all interactions in real time by evaluating content against predefined safety parameters. Guardrails work by: + +1. Intercepting interactions: + AI Gateway proxies requests and responses, sitting between the user and the AI model. + +2. Inspecting content: + + - User prompts: AI Gateway checks prompts against safety parameters (for example, violence, hate, or sexual content). Based on your settings, prompts can be flagged or blocked before reaching the model. + - Model responses: Once processed, the AI model response is inspected. If hazardous content is detected, it can be flagged or blocked before being delivered to the user. + +3. Applying actions: + Depending on your configuration, flagged content is logged for review, while blocked content is prevented from proceeding. + +## Related resource + +- [Cloudflare Blog: Keep AI interactions secure and risk-free with Guardrails in AI Gateway](https://blog.cloudflare.com/guardrails-in-ai-gateway/) diff --git a/src/content/docs/ai-gateway/guardrails/set-up-guardrail.mdx b/src/content/docs/ai-gateway/guardrails/set-up-guardrail.mdx new file mode 100644 index 00000000000000..f2e187ccba23b7 --- /dev/null +++ b/src/content/docs/ai-gateway/guardrails/set-up-guardrail.mdx @@ -0,0 +1,28 @@ +--- +pcx_content_type: how-to +title: Set up Guardrails +sidebar: + order: 3 +--- + +Add Guardrails to any gateway to start evaluating and potentially modifying responses. + +1. Log into the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. Go to **AI** > **AI Gateway**. +3. Select a gateway. +4. Go to **Guardrails**. +5. Switch the toggle to **On**. +6. To customize categories, select **Change** > **Configure specific categories**. +7. Update your choices for how Guardrails works on specific prompts or responses (**Flag**, **Ignore**, **Block**). + - For **Prompts**: Guardrails will evaluate and transform incoming prompts based on your security policies. + - For **Responses**: Guardrails will inspect the model's responses to ensure they meet your content and formatting guidelines. +8. Select **Save**. + +:::note[Usage considerations] +For additional details about how to implement Guardrails, refer to [Usage considerations](/ai-gateway/guardrails/usage-considerations/). +::: + +## Viewing Guardrail Results in Logs + +After enabling Guardrails, you can monitor results through **AI Gateway Logs** in the Cloudflare dashboard. Guardrail logs are marked with a **green shield icon**, and each logged request includes an `eventID`, which links to its corresponding Guardrail evaluation log(s) for easy tracking. Logs are generated for all requests, including those that **pass** Guardrail checks. + diff --git a/src/content/docs/ai-gateway/guardrails/supported-model-types.mdx b/src/content/docs/ai-gateway/guardrails/supported-model-types.mdx new file mode 100644 index 00000000000000..17a6e2bc6a61d6 --- /dev/null +++ b/src/content/docs/ai-gateway/guardrails/supported-model-types.mdx @@ -0,0 +1,18 @@ +--- +pcx_content_type: reference +title: Supported model types +sidebar: + order: 3 +--- + +AI Gateway's Guardrails detects the type of AI model being used and applies safety checks accordingly: + +- **Text generation models**: Both prompts and responses are evaluated. +- **Embedding models**: Only the prompt is evaluated, as the response consists of numerical embeddings, which are not meaningful for moderation. +- **Unknown models**: If the model type cannot be determined, only the prompt is evaluated, while the response bypass Guardrails. + +:::note[Note] + +Guardrails does not yet support streaming responses. Support for streaming is planned for a future update. + +::: diff --git a/src/content/docs/ai-gateway/guardrails/usage-considerations.mdx b/src/content/docs/ai-gateway/guardrails/usage-considerations.mdx new file mode 100644 index 00000000000000..f1510e8172491f --- /dev/null +++ b/src/content/docs/ai-gateway/guardrails/usage-considerations.mdx @@ -0,0 +1,24 @@ +--- +pcx_content_type: reference +title: Usage considerations +sidebar: + order: 4 +--- + +Guardrails currently uses [Llama Guard 3 8B](https://ai.meta.com/research/publications/llama-guard-llm-based-input-output-safeguard-for-human-ai-conversations/) on [Workers AI](/workers-ai/) to perform content evaluations. The underlying model may be updated in the future, and we will reflect those changes within Guardrails. + +Since Guardrails runs on Workers AI, enabling it incurs usage on Workers AI. You can monitor usage through the Workers AI Dashboard. + +## Additional considerations + +- **Model availability**: If at least one hazard category is set to `block`, but AI Gateway is unable to receive a response from Workers AI, the request will be blocked. Conversely, if a hazard category is set to `flag` and AI Gateway cannot obtain a response from Workers AI, the request will proceed without evaluation. This approach prioritizes availability, allowing requests to continue even when content evaluation is not possible. +- **Latency impact**: Enabling Guardrails adds some latency. Enabling Guardrails introduces additional latency to requests. Typically, evaluations using Llama Guard 3 8B on Workers AI add approximately 500 milliseconds per request. However, larger requests may experience increased latency, though this increase is not linear. Consider this when balancing safety and performance. +- **Handling long content**: When evaluating long prompts or responses, Guardrails automatically segments the content into smaller chunks, processing each through separate Guardrail requests. This approach ensures comprehensive moderation but may result in increased latency for longer inputs. +- **Supported languages**: Llama Guard 3.3 8B supports content safety classification in the following languages: English, French, German, Hindi, Italian, Portuguese, Spanish, and Thai. + + +:::note + +Llama Guard is provided as-is without any representations, warranties, or guarantees. Any rules or examples contained in blogs, developer docs, or other reference materials are provided for informational purposes only. You acknowledge and understand that you are responsible for the results and outcomes of your use of AI Gateway. + +::: diff --git a/src/content/docs/ai-gateway/index.mdx b/src/content/docs/ai-gateway/index.mdx index 15438b81f06246..f75d406618f0cd 100644 --- a/src/content/docs/ai-gateway/index.mdx +++ b/src/content/docs/ai-gateway/index.mdx @@ -1,11 +1,11 @@ --- -title: Overview +title: Cloudflare AI Gateway pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: AI Gateway + content: Overview --- import { diff --git a/src/content/docs/ai-gateway/integrations/aig-workers-ai-binding.mdx b/src/content/docs/ai-gateway/integrations/aig-workers-ai-binding.mdx index 04ad7fdccf89bb..b47581f9f1c8da 100644 --- a/src/content/docs/ai-gateway/integrations/aig-workers-ai-binding.mdx +++ b/src/content/docs/ai-gateway/integrations/aig-workers-ai-binding.mdx @@ -27,7 +27,7 @@ Running `npm create cloudflare@latest` will prompt you to install the create-clo product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/ai-gateway/observability/logging/index.mdx b/src/content/docs/ai-gateway/observability/logging/index.mdx index 1246ba1f4dc915..cd96b55466bcbb 100644 --- a/src/content/docs/ai-gateway/observability/logging/index.mdx +++ b/src/content/docs/ai-gateway/observability/logging/index.mdx @@ -12,8 +12,7 @@ Logging is a fundamental building block for application development. Logs provid Your AI Gateway dashboard shows logs of individual requests, including the user prompt, model response, provider, timestamp, request status, token usage, cost, and duration. These logs persist, giving you the flexibility to store them for your preferred duration and do more with valuable request data. -You can store up to 10 million logs per gateway. If your limit is reached, new logs will stop being saved. To continue saving logs, you must delete older logs to free up space for new logs. - +By default, each gateway can store up to 10 million logs. You can customize this limit per gateway in your gateway settings to align with your specific requirements. If your storage limit is reached, new logs will stop being saved. To continue saving logs, you must delete older logs to free up space for new logs. To learn more about your plan limits, refer to [Limits](/ai-gateway/reference/limits/). We recommend using an authenticated gateway when storing logs to prevent unauthorized access and protects against invalid requests that can inflate log storage usage and make it harder to find the data you need. Learn more about setting up an [authenticated gateway](/ai-gateway/configuration/authentication/). @@ -51,17 +50,23 @@ curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/ ' ``` +## Managing log storage + +To manage your log storage effectively, you can: +- Set Storage Limits: Configure a limit on the number of logs stored per gateway in your gateway settings to ensure you only pay for what you need. +- Enable Automatic Log Deletion: Activate the Automatic Log Deletion feature in your gateway settings to automatically delete the oldest logs once the log limit you’ve set or the default storage limit of 10 million logs is reached. This ensures new logs are always saved without manual intervention. + ## How to delete logs -### Auto Log Cleanup +To manage your log storage effectively and ensure continuous logging, you can delete logs using the following methods: -Enable Auto Log Cleanup to automatically delete the oldest logs once the default storage limit of 10 million logs is reached, ensuring that new logs are always saved without needing manual deletion. Logs are deleted in chunks of 0.1% of the storage limit, which equates to 10,000 logs at a time. +### Automatic Log Deletion -This setting is useful for maintaining continuous logging while staying within the default storage constraints. +​To maintain continuous logging within your gateway's storage constraints, enable Automatic Log Deletion in your Gateway settings. This feature automatically deletes the oldest logs once the log limit you've set or the default storage limit of 10 million logs is reached, ensuring new logs are saved without manual intervention. ### Manual deletion -To manually delete logs, navigate to the Logs tab in the dashboard. Use the available filters such as status, cache, provider, cost, or any other options in the dropdown to refine the logs you wish to delete. Once filtered, select Delete logs to complete the action. +To manually delete logs through the dashboard, navigate to the Logs tab in the dashboard. Use the available filters such as status, cache, provider, cost, or any other options in the dropdown to refine the logs you wish to delete. Once filtered, select Delete logs to complete the action. See full list of available filters and their descriptions below: @@ -80,3 +85,7 @@ See full list of available filters and their descriptions below: | Metadata Value | equals, does not equal | specific metadata values. | | Log ID | equals, does not equal | a specific Log ID. | | Event ID | equals, does not equal | a specific Event ID. | + +### API deletion + +You can programmatically delete logs using the AI Gateway API. For more comprehensive information on the `DELETE` logs endpoint, check out the [Cloudflare API documentation](https://developers.cloudflare.com/api/resources/ai_gateway/subresources/logs/methods/delete/). diff --git a/src/content/docs/ai-gateway/reference/pricing.mdx b/src/content/docs/ai-gateway/reference/pricing.mdx index f233db5031f8fe..4b1b79e5b56871 100644 --- a/src/content/docs/ai-gateway/reference/pricing.mdx +++ b/src/content/docs/ai-gateway/reference/pricing.mdx @@ -17,7 +17,7 @@ You can monitor your usage in the AI Gateway dashboard. :::note[Note] -Billing for persistent logs has not yet started. Users on paid plans can store logs beyond the included volume of 200,000 logs stored a month without being charged during this period. (Users on the free plan remain limited to the 100,000 logs cap for their plan.) We will provide plenty of advanced notice before charging begins for persistent log storage. +Billing for persistent log storage will begin on April 15, 2025. Users on paid plans can store logs beyond the included volume of 200,000 logs stored a month without being charged until this date. Users on the free plan remain limited to the 100,000 logs cap for their plan. Please ensure your stored logs are within your plan's included volume before April 14, 2025, if you do not want to be charged. ::: @@ -30,7 +30,9 @@ Persistent logs are available on all plans, with a free allocation for both free | Workers Free | 100,000 logs total | N/A – Upgrade to Workers Paid | | Workers Paid | 200,000 logs total | $8 per 100,000 logs stored per month | -Allocations are based on the total logs stored across all gateways. If your limit is reached, new logs will stop being saved. To continue saving logs, you must [delete logs](/ai-gateway/observability/logging/#how-to-delete-logs/) to free up space. +Allocations are based on the total logs stored across all gateways. For guidance on managing or deleting logs, please see our [documentation](/ai-gateway/observability/logging). + +For example, if you are a Workers Paid plan user storing 300,000 logs, you will be charged for the excess 100,000 logs (300,000 total logs - 200,000 free logs), resulting in an $8/month charge. ## Logpush diff --git a/src/content/docs/ai-gateway/tutorials/create-first-aig-workers.mdx b/src/content/docs/ai-gateway/tutorials/create-first-aig-workers.mdx index 0c92de852e4203..ca54bb553afc6e 100644 --- a/src/content/docs/ai-gateway/tutorials/create-first-aig-workers.mdx +++ b/src/content/docs/ai-gateway/tutorials/create-first-aig-workers.mdx @@ -1,6 +1,5 @@ --- pcx_content_type: tutorial -content_type: 📝 Tutorial difficulty: Beginner updated: 2024-08-01 title: Create your first AI Gateway using Workers AI diff --git a/src/content/docs/ai-gateway/tutorials/deploy-aig-worker.mdx b/src/content/docs/ai-gateway/tutorials/deploy-aig-worker.mdx index dd17a8a90c9bec..b635bd187ab07f 100644 --- a/src/content/docs/ai-gateway/tutorials/deploy-aig-worker.mdx +++ b/src/content/docs/ai-gateway/tutorials/deploy-aig-worker.mdx @@ -1,7 +1,6 @@ --- updated: 2023-09-27 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial tags: - AI @@ -41,7 +40,7 @@ Create a Worker project in the command line: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/analytics/account-and-zone-analytics/threat-types.mdx b/src/content/docs/analytics/account-and-zone-analytics/threat-types.mdx index ff138e8d3c6c4a..4c35819cd91f13 100644 --- a/src/content/docs/analytics/account-and-zone-analytics/threat-types.mdx +++ b/src/content/docs/analytics/account-and-zone-analytics/threat-types.mdx @@ -2,7 +2,6 @@ pcx_content_type: reference source: https://support.cloudflare.com/hc/en-us/articles/204191238-What-are-the-types-of-Threats- title: Threat types - --- Cloudflare classifies the threats that it blocks or challenges. To help you understand more about your site’s traffic, the “Type of Threats Mitigated” metric on the analytics page measures threats blocked or challenged by the following categories: @@ -21,19 +20,19 @@ Cloudflare's [Browser Integrity Check](/waf/tools/browser-integrity-check/) look Visitors were presented with an interactive challenge page and failed to pass. -*Note: An interactive challenge page is a difficult to read word or set of numbers that only a human can translate. If entered incorrectly or not answered in a timely fashion, the request is blocked.* +_Note: An interactive challenge page is a difficult to read word or set of numbers that only a human can translate. If entered incorrectly or not answered in a timely fashion, the request is blocked._ ## Browser challenge A bot gave an invalid answer to the JavaScript challenge (in most cases this will not happen, bots typically do not respond to the challenge at all, so "failed" JavaScript challenges would not get logged). -*Note: During a JavaScript challenge you will be shown an interstitial page for about five seconds while Cloudflare performs a series of mathematical challenges to make sure it is a legitimate human visitor.* +_Note: During a JavaScript challenge you will be shown an interstitial page for about five seconds while Cloudflare performs a series of mathematical challenges to make sure it is a legitimate human visitor._ ## Bad IP -A request that came from an IP address that is not trusted by Cloudflare based on the Threat Score. +A request that came from an IP address that is not trusted by Cloudflare based on the threat score. -Cloudflare uses Threat Scores gathered from sources such as Project Honeypot, as well as our own communities' traffic to determine whether a visitor is legitimate or malicious. When a legitimate visitor passes a challenge, that helps offset the Threat Score against the previous negative behavior seen from that IP address. Our system learns who is a threat from this activity. Site owners may override the Threat Score at any time using Cloudflare's security settings. +Cloudflare uses threat scores gathered from sources such as Project Honeypot, as well as our own communities' traffic to determine whether a visitor is legitimate or malicious. When a legitimate visitor passes a challenge, that helps offset the threat score against the previous negative behavior seen from that IP address. Our system learns who is a threat from this activity. ## Country block @@ -59,7 +58,7 @@ A /24 IP range that was blocked based on the [user configuration](/waf/tools/ip- Requests made by a bot that failed to pass the challenge. -*Note: An interactive challenge page is a difficult to read word or set of numbers that only a human can translate. If entered incorrectly or not answered in a timely fashion, the request is blocked.* +_Note: An interactive challenge page is a difficult to read word or set of numbers that only a human can translate. If entered incorrectly or not answered in a timely fashion, the request is blocked._ ## Bot Request @@ -67,6 +66,6 @@ Request that came from a bot. ## Unclassified -Unclassified threats comprises a number of automatic blocks that are not related to the Browser Integrity Challenge (Bad Browser). These threats usually relate to Hotlink Protection, and other actions that happen on Cloudflare's global network based on the composition of the request (and not its content). +Unclassified threats comprises a number of automatic blocks that are not related to the Browser Integrity Challenge (Bad Browser). These threats usually relate to Hotlink Protection, and other actions that happen on Cloudflare's global network based on the composition of the request (and not its content). Unclassified means a number of conditions under which we group common threats related to Hotlink Protection as well as certain cases of IP reputation and specific requests that are blocked at Cloudflare's global network before reaching your servers. diff --git a/src/content/docs/analytics/account-and-zone-analytics/total-threats-stopped.mdx b/src/content/docs/analytics/account-and-zone-analytics/total-threats-stopped.mdx index f1221325ea6190..aa12f1da2328d2 100644 --- a/src/content/docs/analytics/account-and-zone-analytics/total-threats-stopped.mdx +++ b/src/content/docs/analytics/account-and-zone-analytics/total-threats-stopped.mdx @@ -2,15 +2,14 @@ pcx_content_type: reference source: https://support.cloudflare.com/hc/en-us/articles/204964927-How-does-Cloudflare-calculate-Total-threats-stopped- title: Total threats stopped - --- Total Threats Stopped measures the number of “suspicious” and “bad” requests that were aimed at your site. Requests receive these labels by our IP Reputation Database as they enter Cloudflare’s network: -* **Legitimate:** request pass directly to your site -* **Suspicious:** request has been challenged with a [Cloudflare challenge](/waf/reference/cloudflare-challenges/) -* **Bad:** request has been blocked because our Browser Integrity Check, or because of user configured settings like WAF rules or IP range block. +- **Legitimate:** Request passed directly to your site. +- **Suspicious:** Request has been challenged with a [Cloudflare challenge](/waf/reference/cloudflare-challenges/). +- **Bad:** Request has been blocked because our Browser Integrity Check, or because of user configured settings like WAF rules or IP range block. -Cloudflare uses Threat Scores gathered from sources such as Project Honeypot, as well as our own communities' traffic to determine whether a visitor is legitimate or malicious. When a legitimate visitor passes a challenge, that helps offset the Threat Score against the previous negative behavior seen from that IP address. Our system learns who is a threat from this activity. +Cloudflare uses threat scores gathered from sources such as Project Honeypot, as well as our own communities' traffic to determine whether a visitor is legitimate or malicious. When a legitimate visitor passes a challenge, that helps offset the threat score against the previous negative behavior seen from that IP address. Our system learns who is a threat from this activity. In addition to threat analytics you can also monitor search engine crawlers going to your websites. For most websites, threats and crawlers make up 20% to 50% of traffic. diff --git a/src/content/docs/analytics/dashboards.mdx b/src/content/docs/analytics/dashboards.mdx new file mode 100644 index 00000000000000..b815be86a99057 --- /dev/null +++ b/src/content/docs/analytics/dashboards.mdx @@ -0,0 +1,96 @@ +--- +pcx_content_type: reference +title: Custom dashboards +sidebar: + order: 8 + +--- + +Custom dashboards allow you to create tailored dashboards to monitor application security, performance, and usage. You can create monitors for ongoing monitoring of a previous incident, use them to identify indicators of suspicious activity, and access templates to help you get started. + +Dashboards provide a visual interface that displays key metrics and analytics, helping you monitor and analyze data efficiently. Different dashboards serve different purposes. For example, a security dashboard tracks attack attempts and threats, a performance dashboard monitors API latency and uptime, and a usage dashboard analyzes traffic patterns and user behavior. + +Different metrics serve distinct roles in providing insights into your application’s performance. For example, total HTTP requests offers an overview of traffic volume, while average response time helps assess application speed. Additionally, usage metrics such as traffic patterns and user behavior provide insight into how users interact with your application. These metrics together enable you to spot trends, identify problems, and make informed, data-driven decisions. + +:::note +Custom Dashboards is currently available to customers participating in the Log Explorer beta. To begin using custom dashboards, you will first need to request access to [Log Explorer](/logs/log-explorer/). +::: + +## Create a new dashboard + +To create a new dashboard, log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account. Then, navigate to **Analytics & Logs** and open the **Dashboards** section. + +When creating a dashboard, you have two options: building one from scratch or using a pre-designed template. + +- A **from-scratch dashboard** gives you full control over its structure, allowing you to choose the exact datasets, metrics, and visualizations that fit your needs. This approach is ideal if you have specific monitoring goals or need a highly customized view of your data. +- On the other hand, **templates** provide a faster way to set up a dashboard with commonly used metrics and charts. They are useful for standard use cases, such as monitoring security threats, API performance, or bot traffic. Templates help you get started quickly while still allowing modifications to fit your requirements. + +Choosing between these options depends on whether you need a quick setup with predefined insights or a fully customized dashboard tailored to your unique analysis needs. + +### Create a dashboard from scratch + +When creating a dashboard from scratch, select the option **Create a new**. You can follow the instructions in the following sections to start adding charts to your dashboard. + +#### Create a new chart + +To create a new chart, select **Add chart**. There are two ways to create a chart: + +- **Use a prompt**: Enter a query like `Compare status code ranges over time`. The AI model decides the most appropriate visualization and constructs your chart configuration. +- **Customize your chart**: Select the chart elements manually, including the chart type, title, dataset to query, metrics, and filters. This option gives you full control over your chart’s structure. + +Refer to the following sections for more information about the charts, datasets, fields, metrics, and filters available. + +##### Chart types + +The available chart types include: + +- **Timeseries**: Displays trends over time, enabling comparisons across multiple series. +- **Categorical**: Compares proportions across different series. +- **Stat**: Highlights a single value, showing its delta and sparkline for quick insights. +- **Percentage**: Represents one value as a percentage of another. +- **Top N**: Identifies the highest-ranking values for a given attribute. + +##### Datasets and metrics + +The available metrics and filters vary based on the dataset you want to use. For example, when using the HTTP Requests dataset, you can select **origin response duration** as a metric. You can then choose your preferred aggregation method for that metric, such as total, median, or quantiles. The following table outlines the datasets, fields, and available metrics: + + +| Dataset | Field | Definition | Metrics | +|-----------------|-----------------|------------|---------| +| HTTP Requests | Requests | The number of requests sent by a client to a server over the HTTP protocol. | Total | +| | DNS Response Time | The time taken for a DNS query to be resolved, measured from when a request is made to when a response is received. | Total, Average, Median, 95th percentile, 99th percentile | +| | Time to First Byte | The duration from when a request is made to when the first byte of the response is received from the server. | Total, Average, Median, 95th percentile, 99th percentile | +| | Bytes returned to the Client | The amount of data (in bytes) sent from the server to the client in response to requests. | Total, Average, Median, 95th percentile, 99th percentile | +| | Number of visits | Unique visits or sessions to a website or application. | Total | +| | Origin response duration | The time taken by the origin server to process and respond to a request. | Total, Average, Median, 95th percentile, 99th percentile | +| Security Events | Security events | Actions taken by Application Security products such as WAF and Bot Management. | Total | + +##### Filters + +You can also adjust the scope of your analytics by entering filter conditions. This allows you to focus on the most relevant data. + +1. Select **Add filter**. +2. Select a **field**, an **operator**, and a **value**. For example, to filter events by source IP address, select the _Source IP_ field, select the _equals_ operator, and enter the _IP address_. +3. Select **Apply**. + +### Create a dashboard from a template + +Alternatively, you can choose to create your dashboard using a pre-designed dashboard template. The templates available are: + +- **Bot monitoring**: Allows you to identify automated traffic accessing your website. +- **API Security**: Allows you to monitor data transfers and exceptions for API endpoints in your application. +- **API Performance**: Allows you to view timing data for API endpoints in your application, along with error rates. +- **Account takeover**: Allows you to monitor login attempts, usage of leaked credentials, and account takeover attacks. + +## Edit a dashboard or chart + +After creating your dashboard, to view your saved dashboards, select **Back to all dashboards** to access the full list. Regardless of the way you choose to create your dashboard, you can always edit existing charts and add new ones as needed. + +## Further analysis + +For each chart, you can: + +- Review related traffic in [Security Analytics](/waf/analytics/security-analytics/). +- Explore detailed logs in [Log Explorer](/logs/log-explorer/). + +This ensures deeper insights into your application's security, performance, and usage patterns. diff --git a/src/content/docs/analytics/graphql-api/index.mdx b/src/content/docs/analytics/graphql-api/index.mdx index d36a16653263db..8026fc789447f1 100644 --- a/src/content/docs/analytics/graphql-api/index.mdx +++ b/src/content/docs/analytics/graphql-api/index.mdx @@ -25,3 +25,7 @@ You can use `curl` to make requests to the GraphQL Analytics API. Alternatively, ## Clients We are using [GraphiQL](https://github.com/skevy/graphiql-app) for our example GraphQL queries. There are many other popular open-source clients that you can find online, such as [Altair](https://altair.sirmuel.design) and [Insomnia](https://insomnia.rest). + +## Limitations + +The purpose of the GraphQL API is to provide aggregated analytics about various Cloudflare products. These datasets should not be used as a measure for usage that Cloudflare uses for billing purposes. Billable traffic [excludes things like DDoS traffic](https://blog.cloudflare.com/unmetered-mitigation), while GraphQL is a measure of overall consumption/usage, so it will include all measurable traffic. \ No newline at end of file diff --git a/src/content/docs/api-shield/api-gateway.mdx b/src/content/docs/api-shield/api-gateway.mdx index 603ea3f8d1e005..3498e62641b371 100644 --- a/src/content/docs/api-shield/api-gateway.mdx +++ b/src/content/docs/api-shield/api-gateway.mdx @@ -9,7 +9,7 @@ sidebar: API Gateway is a package of features that will do everything for your APIs, including: -- **Security**: Protect your API from malicious traffic with [API Discovery](/api-shield/security/api-discovery/), [Schema Validation](/api-shield/security/schema-validation/), [mTLS validation](/api-shield/security/mtls/), and more. +- **Security**: Protect your API from malicious traffic with [API Discovery](/api-shield/security/api-discovery/), [Schema validation](/api-shield/security/schema-validation/), [mTLS validation](/api-shield/security/mtls/), and more. - **Management and monitoring**: Streamline API management with [Endpoint Management](/api-shield/management-and-monitoring/) and [tools](https://blog.cloudflare.com/api-gateway/) like analytics, routing, and authentication. - **Logging, quota management, and more**: All of Cloudflare's [established features](https://blog.cloudflare.com/api-gateway/), like caching, load balancing, and log integrations work natively with API Gateway. diff --git a/src/content/docs/api-shield/frequently-asked-questions.mdx b/src/content/docs/api-shield/frequently-asked-questions.mdx index a51c69cb34a5ba..3ecf2201e4866d 100644 --- a/src/content/docs/api-shield/frequently-asked-questions.mdx +++ b/src/content/docs/api-shield/frequently-asked-questions.mdx @@ -59,7 +59,7 @@ Not currently. ## What version of OpenAPI specification do you support? -The importing ([Schema Validation](/api-shield/security/schema-validation/)) and exporting ([Schema Learning](/api-shield/management-and-monitoring/#endpoint-schema-learning)) of OpenAPI schemas from our product to customers is done using **OpenAPI v3.0**. Any specifications using patched versions (3.0.x) are compatible as well. +The importing ([Schema validation](/api-shield/security/schema-validation/)) and exporting ([Schema Learning](/api-shield/management-and-monitoring/#endpoint-schema-learning)) of OpenAPI schemas from our product to customers is done using **OpenAPI v3.0**. Any specifications using patched versions (3.0.x) are compatible as well. --- diff --git a/src/content/docs/api-shield/get-started.mdx b/src/content/docs/api-shield/get-started.mdx index 0a4c4c7395c1c7..f43f691d45ea8f 100644 --- a/src/content/docs/api-shield/get-started.mdx +++ b/src/content/docs/api-shield/get-started.mdx @@ -26,15 +26,15 @@ Enabling API Shield features will have no impact on your traffic until you choos -## Upload a schema using Schema Validation (optional) +## Upload a schema using Schema validation (optional) -Schema Validation protects your APIs by ensuring only requests matching your API schema are allowed to communicate with your origin. +Schema validation protects your APIs by ensuring only requests matching your API schema are allowed to communicate with your origin. -While not strictly required, uploading a pre-existing schema will offer the chance to automatically add endpoints to Endpoint Management. If you already have a schema, you can upload it to [Schema Validation](/api-shield/security/schema-validation/). +While not strictly required, uploading a pre-existing schema will offer the chance to automatically add endpoints to Endpoint Management. If you already have a schema, you can upload it to [Schema validation](/api-shield/security/schema-validation/). :::note -It is recommended to start with Schema Validation rules set to `log` to review logged requests in **Security** > **Events**. When you are confident that only the correct requests are logged, you should switch the rule to `block`. +It is recommended to start with Schema validation rules set to `log` to review logged requests in **Security** > **Events**. When you are confident that only the correct requests are logged, you should switch the rule to `block`. ::: If you do not have a schema to upload, continue reading this guide to learn how to generate a schema with API Shield. @@ -56,14 +56,14 @@ Cloudflare’s machine learning models have already inspected your existing traf :::note -Schema Validation, Schema Learning, JWT Validation, Sequence Analytics, Sequence Mitigation, and rate limit recommendations only run on endpoints saved to Endpoint Management. +Schema validation, Schema Learning, JWT validation, Sequence Analytics, Sequence Mitigation, and rate limit recommendations only run on endpoints saved to Endpoint Management. ::: -You can save your endpoints directly from [API Discovery](/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery), [Schema Validation](/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation), or [manually](/api-shield/management-and-monitoring/#add-endpoints-manually) by method, path, and host. +You can save your endpoints directly from [API Discovery](/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery), [Schema validation](/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation), or [manually](/api-shield/management-and-monitoring/#add-endpoints-manually) by method, path, and host. This will add the specified endpoints to your list of managed endpoints. You can view your list of saved endpoints in the **Endpoint Management** page. -Cloudflare will aggregate [performance data](/api-shield/management-and-monitoring/#endpoint-performance-analysis) and security data on your endpoint once it is saved. +Cloudflare will aggregate [performance data](/api-shield/management-and-monitoring/#endpoint-analysis) and security data on your endpoint once it is saved. ### Allow the system to learn your traffic patterns @@ -81,7 +81,7 @@ We recommend proceeding with [additional configurations](/api-shield/get-started You can observe Cloudflare suggested rate limits in Endpoint Management for endpoints using session identifiers. Unlike many security tools, these recommended rate limits are per-endpoint and per-session, not site-wide and not based on IP address. When creating a rule, it will be based on only traffic to that specific endpoint from unique visitors during their session. This feature allows you to be very specific and targeted with your rate limit enforcement, both lowering abusive traffic and false positives due to broadly scoped rules. -## Import a learned schema to Schema Validation +## Import a learned schema to Schema validation Cloudflare learns schema parameters via traffic inspection for all endpoints stored in Endpoint Management. You can export OpenAPI schemas in OpenAPI v3.0.0 format by hostname. @@ -103,15 +103,15 @@ You can observe the top sequences in your API traffic that contain endpoints sto [Sequence Mitigation](/api-shield/security/sequence-mitigation/) allows you to enforce request patterns for authenticated clients communicating with your API. Use Sequence Analytics to better understand the request sequences used by your API clients. -You should apply all possible API Shield protections (rate limiting suggestions, Schema Validation, JWT Validation, and mTLS) to API endpoints found in high correlation score sequences that make up the critical request flows in your application. You should also check their specific endpoint order with your development team. +You should apply all possible API Shield protections (rate limiting suggestions, Schema validation, JWT validation, and mTLS) to API endpoints found in high correlation score sequences that make up the critical request flows in your application. You should also check their specific endpoint order with your development team. For more information, refer to [Detecting API abuse automatically using sequence analysis](https://blog.cloudflare.com/api-sequence-analytics) blog post. ## Additional configuration -### Set up JSON Web Tokens (JWT) Validation +### Set up JSON Web Tokens (JWT) validation -Use the Cloudflare API to configure [JSON Web Tokens Validation](/api-shield/security/jwt-validation/), which validates the integrity and validity of JWTs sent by clients to your API or web application. +Use the Cloudflare API to configure [JSON Web Tokens validation](/api-shield/security/jwt-validation/), which validates the integrity and validity of JWTs sent by clients to your API or web application. ### Set up GraphQL Malicious Query Protection diff --git a/src/content/docs/api-shield/index.mdx b/src/content/docs/api-shield/index.mdx index 4f660e9e72fc98..579d37e4c5667e 100644 --- a/src/content/docs/api-shield/index.mdx +++ b/src/content/docs/api-shield/index.mdx @@ -1,13 +1,12 @@ --- -title: Overview +title: Cloudflare API Shield pcx_content_type: overview type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare API Shield - + content: Overview --- import { Description, Feature, Plan, RelatedProduct, Render } from "~/components" @@ -41,7 +40,7 @@ A package of features that will do everything for your APIs. Cloudflare API Security products are available to Enterprise customers only, though anyone can set up [Mutual TLS](/api-shield/security/mtls/) with a Cloudflare-managed certificate authority. -The full API Shield security suite is available as an Enterprise-only paid add-on, but all customers can access [Endpoint Management](/api-shield/management-and-monitoring/) and [Schema Validation](/api-shield/security/schema-validation/) functionalities. +The full API Shield security suite is available as an Enterprise-only paid add-on, but all customers can access [Endpoint Management](/api-shield/management-and-monitoring/) and [Schema validation](/api-shield/security/schema-validation/) functionalities. ## Related products diff --git a/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx b/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx index b058a258786be3..a8904526ed0dd0 100644 --- a/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/developer-portal.mdx @@ -22,7 +22,7 @@ Once endpoints are saved If you do not have a schema to upload or to select from a pre-existing schema, export your Endpoint Management schema. For best results, include the learned parameters. - Only API schemas uploaded to Schema Validation 2.0 are available when selecting existing schemas + Only API schemas uploaded to Schema validation 2.0 are available when selecting existing schemas ::: 5. Select **Download project files** to save a local copy of the files that will be uploaded to Cloudflare Pages. Downloading the project files can be helpful if you wish to modify the project in any way and then upload the new version manually to Pages. diff --git a/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx b/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx index 27903cc6305f81..5ba71624e3460d 100644 --- a/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/endpoint-labels.mdx @@ -5,10 +5,9 @@ title: Endpoint labeling service sidebar: order: 1 label: Labeling service - --- -import { Render } from "~/components" +import { Render } from "~/components"; API Shield's labeling service will help you organize your endpoints and address vulnerabilities in your API. The labeling service comes with managed and user-defined labels. @@ -18,7 +17,11 @@ User-defined labels can also be added to endpoints in API Shield by creating a l You can filter your endpoints based on the labels. -## Managed labels +## Categories + +### Managed labels + +Use managed labels to identify endpoints by use case. Cloudflare may automatically apply these labels in a future release. `cf-log-in`: Add this label to endpoints that accept user credentials. You may have multiple endpoints if you accept username, password, and multi-factor authentication (MFA) across multiple endpoints or requests. @@ -42,6 +45,12 @@ You can filter your endpoints based on the labels. `cf-rss-feed`: Add this label to endpoints that expect traffic from RSS clients. +`cf-llm`: Services that are (partially) powered by Large Language Model (LLM). + +### Risk labels + +Cloudflare automatically runs risk scans every 24 hours on your saved endpoints. API Shield applies these labels when a scan finds security risks on your endpoints. A corresponding Security Center Insight is also raised when risks are found. + `cf-risk-missing-auth`: Automatically added when all successful requests lack a session identifier. Refer to the table below for more information. `cf-risk-mixed-auth`: Automatically added when some successful requests contain a session identifier and some successful requests lack a session identifier. Refer to the table below for more information. @@ -50,11 +59,11 @@ You can filter your endpoints based on the labels. `cf-risk-missing-schema`: Automatically added when a learned schema is available for an endpoint that has no active schema. -`cf-risk-error-anomaly`: Automatically added when an endpoint experiences a recent increase in response errors over the last 24 hours. +`cf-risk-error-anomaly`: Automatically added when an endpoint experiences a recent increase in response errors over the last 24 hours. -`cf-risk-latency-anomaly`: Automatically added when an endpoint experiences a recent increase in response latency over the last 24 hours. +`cf-risk-latency-anomaly`: Automatically added when an endpoint experiences a recent increase in response latency over the last 24 hours. -`cf-risk-size-anomaly`: Automatically added when an endpoint experiences a spike in response body size over the last 24 hours. +`cf-risk-size-anomaly`: Automatically added when an endpoint experiences a spike in response body size over the last 24 hours. :::note Cloudflare will only add authentication labels to endpoints with successful response codes. Refer to the below table for more details. @@ -100,4 +109,4 @@ Alternatively, you can create a user-defined label via Endpoint Management in AP ## Availability -Endpoint Management's labeling service is currently available to Enterprise API Shield subscribers. \ No newline at end of file +Endpoint Management's labeling service is available to all customers. diff --git a/src/content/docs/api-shield/management-and-monitoring/index.mdx b/src/content/docs/api-shield/management-and-monitoring/index.mdx index d36e73cfce0ad2..d726add9562e4e 100644 --- a/src/content/docs/api-shield/management-and-monitoring/index.mdx +++ b/src/content/docs/api-shield/management-and-monitoring/index.mdx @@ -18,7 +18,7 @@ Monitor the health of your API endpoints **API Shield**. -3. Add your endpoints [manually](#add-endpoints-manually), from [Schema Validation](#add-endpoints-from-schema-validation), or from [API Discovery](#add-endpoints-from-api-discovery). +3. Add your endpoints [manually](#add-endpoints-manually), from [Schema validation](#add-endpoints-from-schema-validation), or from [API Discovery](#add-endpoints-from-api-discovery). ## Add endpoints from API Discovery @@ -47,9 +47,9 @@ There are two ways to add API endpoints from Discovery. 2. Select the discovered endpoints you would like to add. 3. Select **Save selected endpoints**. -## Add endpoints from Schema Validation +## Add endpoints from Schema validation -1. Add a schema by [configuring Schema Validation](/api-shield/security/schema-validation/). +1. Add a schema by [configuring Schema validation](/api-shield/security/schema-validation/). 2. On **Review schema endpoints**, save new endpoints to endpoint management by checking the box. 3. Select **Save as draft** or **Save and Deploy**. Endpoints will be saved regardless of whether the Schema is saved as a draft or published. @@ -106,7 +106,7 @@ You can delete endpoints one at a time or in bulk. Cloudflare learns schema parameters via traffic inspection. For all endpoints saved to Endpoint Management, you can export OpenAPI schemas in `v3.0.0` format by hostname. You can also include learned schema parameters. -To protect your API with a learned schema, refer to [Schema Validation](/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-an-entire-hostname). +To protect your API with a learned schema, refer to [Schema validation](/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-an-entire-hostname). ### Export a schema diff --git a/src/content/docs/api-shield/plans.mdx b/src/content/docs/api-shield/plans.mdx index 3efede5e0bf2e4..997744000fbbba 100644 --- a/src/content/docs/api-shield/plans.mdx +++ b/src/content/docs/api-shield/plans.mdx @@ -7,11 +7,11 @@ sidebar: --- -Free, Pro, Business, and Enterprise customers without an API Gateway subcription can access [Endpoint Management](/api-shield/management-and-monitoring/) and [Schema Validation](/api-shield/security/schema-validation/), but no other [API Gateway](/api-shield/api-gateway/) features. +Free, Pro, Business, and Enterprise customers without an API Gateway subscription can access [Endpoint Management](/api-shield/management-and-monitoring/) and [Schema validation](/api-shield/security/schema-validation/), but no other [API Gateway](/api-shield/api-gateway/) features. To subscribe to API Gateway, upgrade to an Enterprise plan and contact your account team. -Limits to endpoints apply to Endpoint Management and Schema Validation. Refer to the table below for limits based on your zone plan. +Limits to endpoints apply to Endpoint Management and Schema validation. Refer to the table below for limits based on your zone plan. | Plan type | Saved endpoints | Uploaded schemas | Total uploaded schema size | Rule action | | --- | --- | --- | --- | --- | diff --git a/src/content/docs/api-shield/reference/classic-schema-validation.mdx b/src/content/docs/api-shield/reference/classic-schema-validation.mdx index 1c84f10c98783b..3c249bb043148f 100644 --- a/src/content/docs/api-shield/reference/classic-schema-validation.mdx +++ b/src/content/docs/api-shield/reference/classic-schema-validation.mdx @@ -1,56 +1,56 @@ --- -title: Classic Schema Validation (deprecated) +title: Classic Schema validation (deprecated) pcx_content_type: how-to type: overview head: - tag: title - content: Configure Classic Schema Validation (deprecated) + content: Configure Classic Schema validation (deprecated) sidebar: badge: text: Deprecated order: 1 - label: Classic Schema Validation + label: Classic Schema validation --- import { GlossaryTooltip } from "~/components" :::caution[Deprecation notice] -Classic Schema Validation has been deprecated. +Classic Schema validation has been deprecated. -Upload all new schemas to [Schema Validation 2.0](/api-shield/security/schema-validation/). +Upload all new schemas to [Schema validation 2.0](/api-shield/security/schema-validation/). ::: -Use the **API Shield** interface to configure [API Schema Validation](/api-shield/security/schema-validation/), which validates requests according to the API schema you provide. +Use the **API Shield** interface to configure [API Schema validation](/api-shield/security/schema-validation/), which validates requests according to the API schema you provide. -Before you can configure Schema Validation for an API, you must obtain an API Schema file matching our [specifications](/api-shield/security/schema-validation/#specifications). +Before you can configure Schema validation for an API, you must obtain an API Schema file matching our [specifications](/api-shield/security/schema-validation/#specifications). -If you are in the Schema Validation 2.0, you can make changes to your settings but you cannot add any new Classic Schema Validation schemas. +If you are in the Schema validation 2.0, you can make changes to your settings but you cannot add any new Classic Schema validation schemas. :::note This feature is only available for customers on an Enterprise plan. Contact your Cloudflare Customer Success Manager to get access. ::: -## Create an API Shield with Schema Validation +## Create an API Shield with Schema validation -To configure Schema Validation in the Cloudflare dashboard: +To configure Schema validation in the Cloudflare dashboard: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to **Schema Validation** and select **Add schema**. -4. Enter a descriptive name for your policy and optionally edit the expression to trigger Schema Validation. For example, if your API is available at `http://api.example.com/v1`, include a check for the *Hostname* field — equal to `api.example.com` — and a check for the *URI Path* field using a regular expression — matching the regex `^/v1`. +3. Go to **Schema validation** and select **Add schema**. +4. Enter a descriptive name for your policy and optionally edit the expression to trigger Schema validation. For example, if your API is available at `http://api.example.com/v1`, include a check for the *Hostname* field — equal to `api.example.com` — and a check for the *URI Path* field using a regular expression — matching the regex `^/v1`. :::caution[Important] To validate the hostname, you must include the *Hostname* field explicitly in the rule, even if the hostname value is in the schema file. Any hostname value present in the schema file will be ignored. ::: 5. Select **Next**. 6. Upload your schema file. -7. Select **Save** to validate the content of the schema file and deploy the Schema Validation rule. If you get a validation error, ensure that you are using one of the [supported file formats](/api-shield/security/schema-validation/#specifications) and that each endpoint and method pair has a unique operation ID. +7. Select **Save** to validate the content of the schema file and deploy the Schema validation rule. If you get a validation error, ensure that you are using one of the [supported file formats](/api-shield/security/schema-validation/#specifications) and that each endpoint and method pair has a unique operation ID. After deploying your API Shield rule, Cloudflare displays a summary of all API endpoints organized by their protection level and actions that will occur for non-compliant and unprotected requests. -1. In the **Endpoint action** dropdown, select an action for every request that targets a protected endpoint and fails Schema Validation. +1. In the **Endpoint action** dropdown, select an action for every request that targets a protected endpoint and fails Schema validation. 2. In the **Fallthrough action** dropdown, select an action for every request that targets an unprotected endpoint. 3. Optionally, you can save the endpoints to Endpoint Management at the same time the Schema is saved by selecting **Save new endpoints to [endpoint management](/api-shield/management-and-monitoring/)**. Endpoints will be saved regardless of whether the Schema is saved as a draft or published live. 4. Select **Done**. diff --git a/src/content/docs/api-shield/reference/terraform.mdx b/src/content/docs/api-shield/reference/terraform.mdx index 6d923644bf85ea..87684363f2a51f 100644 --- a/src/content/docs/api-shield/reference/terraform.mdx +++ b/src/content/docs/api-shield/reference/terraform.mdx @@ -18,11 +18,11 @@ The following resources are available to configure through Terraform: - [`api_shield_operation`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_operation) for configuring endpoints in Endpoint Management. -**Schema Validation 2.0** +**Schema validation 2.0** -- [`api_shield_schema`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_schema) for configuring a schema in [Schema Validation 2.0](/api-shield/security/schema-validation/). -- [`api_shield_schema_validation_settings`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_schema_validation_settings) for configuring zone-level Schema Validation 2.0 settings. -- [`api_shield_operation_schema_validation_settings`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_operation_schema_validation_settings) for configuring operation-level Schema Validation 2.0 settings. +- [`api_shield_schema`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_schema) for configuring a schema in [Schema validation 2.0](/api-shield/security/schema-validation/). +- [`api_shield_schema_validation_settings`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_schema_validation_settings) for configuring zone-level Schema validation 2.0 settings. +- [`api_shield_operation_schema_validation_settings`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_operation_schema_validation_settings) for configuring operation-level Schema validation 2.0 settings. ## Manage API Shield session identifiers @@ -58,14 +58,14 @@ resource "cloudflare_api_shield_operation" "post_image" { } ``` -## Manage Schema Validation 2.0 +## Manage Schema validation 2.0 :::note -It is required to configure Endpoint Management if you want to set up Schema Validation 2.0 using Terraform. +It is required to configure Endpoint Management if you want to set up Schema validation 2.0 using Terraform. ::: -Refer to the example configuration below to manage [Schema Validation 2.0](/api-shield/security/schema-validation/configure/) on your zone. +Refer to the example configuration below to manage [Schema validation 2.0](/api-shield/security/schema-validation/configure/) on your zone. ```tf title="Example configuration" # Schema that should be used for schema validation 2.0 diff --git a/src/content/docs/api-shield/security/api-discovery.mdx b/src/content/docs/api-shield/security/api-discovery.mdx index e4cc45a2e5f162..d05eddaa7c4379 100644 --- a/src/content/docs/api-shield/security/api-discovery.mdx +++ b/src/content/docs/api-shield/security/api-discovery.mdx @@ -51,7 +51,7 @@ API Shield first catalogs your discovered API endpoints in an email inbox-style You should save all discovered API endpoints to Endpoint Management while ignoring any potential false positives in the API Discovery results by selecting **Save** or **Ignore** on each line. Alternatively, you can bulk-select endpoints to save or ignore. You can get started with saving endpoints by saving all endpoints with a variable. Search for `var1` in the search box and add all the resulting endpoints. You can examine endpoints without path variables for accuracy later on. -By adding endpoints to Endpoint Management, you will unlock further [security](/api-shield/security/), [visibility](/api-shield/management-and-monitoring/#endpoint-performance-analysis), and [management](/api-shield/management-and-monitoring/) features of the platform. Endpoint Management monitors the health of your API endpoints by saving, updating, and monitoring performance metrics. +By adding endpoints to Endpoint Management, you will unlock further [security](/api-shield/security/), [visibility](/api-shield/management-and-monitoring/#endpoint-analysis), and [management](/api-shield/management-and-monitoring/) features of the platform. Endpoint Management monitors the health of your API endpoints by saving, updating, and monitoring performance metrics. To restore any errantly ignored endpoints, you can filter by **Ignored** and select **Restore**. diff --git a/src/content/docs/api-shield/security/index.mdx b/src/content/docs/api-shield/security/index.mdx index 7b4b8b47aa9a1e..2cdfe17258e513 100644 --- a/src/content/docs/api-shield/security/index.mdx +++ b/src/content/docs/api-shield/security/index.mdx @@ -21,27 +21,27 @@ The following table provides examples of how you might match Cloudflare products | OWASP issue | Example Cloudflare solution | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Broken Object Level Authorization | [Sequence Mitigation], [Schema Validation], [JWT Validation], [Rate Limiting] | -| Broken Authentication | [mTLS](/api-shield/security/mtls/), [JWT Validation], [Exposed Credential Checks](/waf/managed-rules/check-for-exposed-credentials/), [Bot Management] | -| Broken Object Property Level Authorization | [Schema Validation], [JWT Validation] | +| Broken Object Level Authorization | [Sequence Mitigation], [Schema validation], [JWT validation], [Rate Limiting] | +| Broken Authentication | [mTLS](/api-shield/security/mtls/), [JWT validation], [Exposed Credential Checks](/waf/managed-rules/check-for-exposed-credentials/), [Bot Management](/bots/), [Authentication Posture](/api-shield/security/authentication-posture/) | +| Broken Object Property Level Authorization | [Schema validation], [JWT validation] | | Unrestricted Resource Consumption | [Rate Limiting], [Sequence Mitigation], [Bot Management], [GraphQL Query Protection] | -| Broken Function Level Authorization | [Schema Validation], [JWT Validation] | +| Broken Function Level Authorization | [Schema validation], [JWT validation] | | Unrestricted Access to Sensitive Business Flows | [Sequence Mitigation], [Bot Management], [GraphQL Query Protection] | -| Server Side Request Forgery | [Schema Validation], [WAF Managed Rules], [WAF Custom Rules](/waf/custom-rules/) | -| Security Misconfiguration | [Sequence Mitigation], [Schema Validation], [WAF Managed Rules], [GraphQL Query Protection] | +| Server Side Request Forgery | [Schema validation], [WAF managed rules], [WAF custom rules](/waf/custom-rules/) | +| Security Misconfiguration | [Sequence Mitigation], [Schema validation], [WAF managed rules], [GraphQL Query Protection] | | Improper Inventory Management | [Discovery](/api-shield/security/api-discovery/), [Schema Learning](/api-shield/management-and-monitoring/#endpoint-schema-learning) | -| Unsafe Consumption of APIs | [JWT Validation], [WAF Managed Rules] | +| Unsafe Consumption of APIs | [JWT validation], [WAF managed rules] | -[Schema Validation]: /api-shield/security/schema-validation/ +[Schema validation]: /api-shield/security/schema-validation/ [Sequence Mitigation]: /api-shield/security/sequence-mitigation/ -[JWT Validation]: /api-shield/security/jwt-validation/ +[JWT validation]: /api-shield/security/jwt-validation/ [GraphQL Query Protection]: /api-shield/security/graphql-protection/ -[Bot Management]: /bots/ +[Bot management]: /bots/ -[Rate Limiting]: /waf/rate-limiting-rules/ +[Rate limiting]: /waf/rate-limiting-rules/ -[WAF Managed Rules]: /waf/managed-rules/ +[WAF managed rules]: /waf/managed-rules/ diff --git a/src/content/docs/api-shield/security/jwt-validation/configure.mdx b/src/content/docs/api-shield/security/jwt-validation/configure.mdx index b388a63e142da8..32a1f84558aaeb 100644 --- a/src/content/docs/api-shield/security/jwt-validation/configure.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/configure.mdx @@ -1,29 +1,29 @@ --- -title: Configure JWT Validation +title: Configure JWT validation pcx_content_type: how-to type: overview sidebar: order: 1 head: - tag: title - content: Configure JWT Validation + content: Configure JWT validation --- import { GlossaryTooltip } from "~/components" -Use the Cloudflare API to configure [JWT Validation](/api-shield/security/jwt-validation/), which requires Token Configurations and Token Validation Rules. +Use the Cloudflare API to configure [JWT validation](/api-shield/security/jwt-validation/), which requires token configurations and token validation rules. -## Token Configurations +## Token configurations -A Token Configuration defines a JSON Web Key Set (JWKs), which is used to validate JSON Web Tokens (JWTs) sent by clients and information on where these JWTs are sent in the request. +A token configuration defines a JSON Web Key Set (JWKs), which is used to validate JSON Web Tokens (JWTs) sent by clients and information on where these JWTs are sent in the request. :::note -A zone may have up to four Token Configurations. +A zone may have up to four token configurations. ::: -Token Configurations require the following information: +Token configurations require the following information: |
    Field name
    | Description | Example | Notes | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | @@ -53,9 +53,9 @@ Cloudflare will remove any fields that are unnecessary from each key and will dr It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended. -## Token Configuration JSON object +## Token configuration JSON object -The example below shows a JSON object with all of the information necessary to create a Token Configuration using the Cloudflare API. If you would like to create JWKs for testing, refer to [mkjwk JSON Web Key Generator](https://mkjwk.org/). +The example below shows a JSON object with all of the information necessary to create a token configuration using the Cloudflare API. If you would like to create JWKs for testing, refer to [mkjwk JSON Web Key Generator](https://mkjwk.org/). ```json title="Example" { @@ -82,9 +82,9 @@ The example below shows a JSON object with all of the information necessary to c } ``` -## Create a Token Configuration using the Cloudflare API +## Create a token configuration using the Cloudflare API -Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT Validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](/fundamentals/api/get-started/create-token/) header. +Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](/fundamentals/api/get-started/create-token/) header. ```bash title="Example using cURL" curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_validation" \ @@ -113,7 +113,7 @@ curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/token_val }' ``` -The response will be in a Cloudflare `v4` response envelope and the result contains the created configuration. Note the returned ID, as it will be used to reference the Token Configuration when creating Token Validation rules using the API. +The response will be in a Cloudflare `v4` response envelope and the result contains the created configuration. Note the returned ID, as it will be used to reference the token configuration when creating token validation rules using the API. ```json title="Example response" { @@ -147,15 +147,15 @@ The response will be in a Cloudflare `v4` response envelope and the result conta } ``` -## Token Validation Rules +## Token validation rules -Token Validation Rules allow you to enforce a security policy using existing Token Configurations. +Token validation rules allow you to enforce a security policy using existing token configurations. -Token Validation Rules can be configured using the Cloudflare API or [dashboard](/api-shield/security/jwt-validation/#add-a-jwt-validation-rule). +Token validation rules can be configured using the Cloudflare API or [dashboard](/api-shield/security/jwt-validation/#add-a-jwt-validation-rule). |
    Field name
    | Description | Example | Notes | | ----------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `title` | A human-readable name allowing you to quickly identify it. | JWT Validation on `v1` and `v2.example.com` | Limited to 50 characters. | +| `title` | A human-readable name allowing you to quickly identify it. | JWT validation on `v1` and `v2.example.com` | Limited to 50 characters. | | `description` | A human-readable description that gives more details than `title` and helps to document it. | Log requests without a valid `authorization` header. | Limited to 500 characters. | | `action` | The Firewall Action taken on requests that do not meet `expression`. | `log` | Possible: `log` or `block` | | `enabled` | Enable or disable the rule. | `true` | Possible: `true` or `false` | @@ -166,7 +166,7 @@ Token Validation Rules can be configured using the Cloudflare API or [dashboard] Selectors control the scope of your token validation rule. -If you only need JWT Validation on specific hostnames or subdomains of your apex domain, use the hostname in a selector to include it in the JWT Validation rule. +If you only need JWT validation on specific hostnames or subdomains of your apex domain, use the hostname in a selector to include it in the JWT validation rule. If you need to exclude endpoints from JWT validation that never have valid JWTs used with them (by design), such as a path and method used to establish a valid JWT in the first place, you must use the endpoint’s operation ID to exclude the endpoint in a selector. @@ -181,14 +181,14 @@ A request must also match an operation covered by this rule to trigger an action Refer to [Apply a rule to operations](/api-shield/security/jwt-validation/configure/#apply-a-rule-to-operations) for more information. ::: -A Token Validation rule's expression defines a security policy that a request must meet. +A token validation rule's expression defines a security policy that a request must meet. For example, the expression `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")` will trigger if an incoming request does not have at least one valid authentication token. These expressions are similar to [expressions used in Ruleset Engine](/ruleset-engine/rules-language/), with a few key differences: -- The Token Validation rule actions trigger if the expression evaluates `false`, as opposed to Ruleset expressions. -- The Token Validation rules can use dedicated functions that reference Token Configurations. +- The token validation rule actions trigger if the expression evaluates `false`, as opposed to Ruleset expressions. +- The token validation rules can use dedicated functions that reference token configurations. Operators such as `or`, `and`, `eq`, and more are usable in expressions in the same way as in expressions used in Ruleset Engine. @@ -196,8 +196,8 @@ The following functions can be used to interact with JWT Tokens on a request: |
    Function
    | Description | Notes | | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `is_jwt_valid(token_configuration_id String) bool` | `True` if the request has a valid token according to the Token Configuration with the ID `token_configuration_id`. | `token_configuration_id` must be the ID of an existing Token Configuration. This will return `false` if the token is missing from the request. | -| `is_jwt_present(token_configuration_id String) bool` | `True` if the request has a token as configured in the Token Configuration with the ID `token_configuration_id`. | `token_configuration_id` must be the ID of an existing Token Configuration. | +| `is_jwt_valid(token_configuration_id String) bool` | `True` if the request has a valid token according to the token configuration with the ID `token_configuration_id`. | `token_configuration_id` must be the ID of an existing token configuration. This will return `false` if the token is missing from the request. | +| `is_jwt_present(token_configuration_id String) bool` | `True` if the request has a token as configured in the token configuration with the ID `token_configuration_id`. | `token_configuration_id` must be the ID of an existing token configuration. | ### Common use cases @@ -207,13 +207,13 @@ Refer to the following example use cases to understand which security policy to The `is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request is missing a JWT. -It can be combined with a `log` action in the Token Validation rule to log requests that are missing an authentication header. +It can be combined with a `log` action in the token validation rule to log requests that are missing an authentication header. #### Require a valid token The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request does not have a valid JWT. -It can be combined with a `block` action in the Token Validation rule to block requests with no or invalid credentials. +It can be combined with a `block` action in the token validation rule to block requests with no or invalid credentials. #### Require at least one of two possible tokens @@ -227,13 +227,13 @@ The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or not is_jwt_valid("5 ## Apply a rule to operations -Only one Token Validation rule can apply to an operation. If an operation is covered by multiple rules, then the rule with highest precedence will take effect. +Only one token validation rule can apply to an operation. If an operation is covered by multiple rules, then the rule with highest precedence will take effect. -You can configure which operations JWT Validation is enforced on using the `selector` field. +You can configure which operations JWT validation is enforced on using the `selector` field. :::note -Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that Token Validation rule. +Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that token validation rule. ::: For example, the following selector will apply a rule to all operations in `v1.example.com` and `v2.example.com`, except for two operations on these hosts: @@ -379,7 +379,7 @@ The `state` field can be `ignored`, `excluded`, or `included`. Included operatio } ``` -Operations with a `included` state will be covered by the Token Validation Rule. The response also shows the hostnames of included operations in `result.selected_hosts` and shows all hostnames used by all zone operations in `result.available_hosts`. +Operations with a `included` state will be covered by the token validation rule. The response also shows the hostnames of included operations in `result.selected_hosts` and shows all hostnames used by all zone operations in `result.available_hosts`. You can also send an empty object in the request body: @@ -392,11 +392,11 @@ curl --request PUT \ The response will show all zone operations and all possible hosts, which you can use to build your own selector. -## Token Validation Rule JSON object +## Token validation rule JSON object -The example below shows a JSON object with all the necessary information to create a Token Validation Rule using the Cloudflare API. +The example below shows a JSON object with all the necessary information to create a token validation rule using the Cloudflare API. -Replace any Token Configurations IDs and operation IDs with the IDs that exist in your zone. +Replace any token configurations IDs and operation IDs with the IDs that exist in your zone. ```json title="Token Validation Rule JSON example" [ @@ -428,11 +428,11 @@ Replace any Token Configurations IDs and operation IDs with the IDs that exist i ] ``` -## Create a Token Validation Rule using the Cloudflare API +## Create a token Validation rule using the Cloudflare API -Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT Validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](/fundamentals/api/get-started/create-token/) header. +Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](/fundamentals/api/get-started/create-token/) header. -Replace any Token Configurations IDs and operation IDs with the IDs that exist in your zone. +Replace any token configurations IDs and operation IDs with the IDs that exist in your zone. A single request can create multiple rules. To do so, pass multiple rule objects in the JSON array of the request body. @@ -511,7 +511,7 @@ The response will be in a Cloudflare `v4` response envelope and the result conta ## Maintenance -### Update Token Configuration +### Update token configuration It is best practice to rotate keys after some time. To support updating the keys, Cloudflare allows up to four keys per configuration. This allows you to add a second, new key to an already existing key. You can start issuing JWTs with the new key only and remove the old key after some time. Additionally, this feature allows the deployment of testing or development keys next to production keys. @@ -554,9 +554,9 @@ curl --request PUT \ Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](/fundamentals/api/get-started/create-token/) header. -### Update Token Validation Rules +### Update token validation rules -Token Validation rules can be updated with a `PATCH` request. A single `PATCH` request can update multiple rules. +Token validation rules can be updated with a `PATCH` request. A single `PATCH` request can update multiple rules. A `PATCH` request is specified as a JSON array in the request body. Each item in that array contains updates to a single rule, defined by `id`. @@ -613,9 +613,9 @@ curl --request PATCH \ ]' ``` -## Perform JWT Validation +## Perform JWT validation -Here is an overview of how JWT Validation processes incoming requests: +Here is an overview of how JWT validation processes incoming requests: 1. We extract the JWT in accordance with the configuration from the incoming request. 2. We decode the JWT and look for the JWTs header KID claim. diff --git a/src/content/docs/api-shield/security/jwt-validation/index.mdx b/src/content/docs/api-shield/security/jwt-validation/index.mdx index 8270b6083c3ff0..fa6d9b12839539 100644 --- a/src/content/docs/api-shield/security/jwt-validation/index.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -title: JSON Web Tokens Validation +title: JSON Web Tokens validation sidebar: order: 6 @@ -10,15 +10,15 @@ import { GlossaryTooltip } from "~/components" JSON web tokens (JWT) are often used as part of an authentication component on many web applications today. Since JWTs are crucial to identifying users and their access, ensuring the token’s integrity is important. -API Shield’s JWT Validation stops JWT replay attacks and JWT tampering by cryptographically verifying incoming JWTs before they are passed to your API origin. JWT Validation will also stop requests with expired tokens or tokens that are not yet valid. +API Shield’s JWT validation stops JWT replay attacks and JWT tampering by cryptographically verifying incoming JWTs before they are passed to your API origin. JWT validation will also stop requests with expired tokens or tokens that are not yet valid. ## Process -Endpoints must be added to [Endpoint Management](/api-shield/management-and-monitoring/) for JWT Validation to protect them. +Endpoints must be added to [Endpoint Management](/api-shield/management-and-monitoring/) for JWT validation to protect them. -A JWT Validation configuration consists of creating a Token Validation Configuration by adding your JWT signer's public JSON Web Key Set (JWKS) and a JWT Validation Rule by specifying which hostnames and endpoints should be included for validation. +A JWT validation configuration consists of creating a token validation configuration by adding your JWT signer's public JSON Web Key Set (JWKS) and a JWT validation rule by specifying which hostnames and endpoints should be included for validation. -### Add a Token Validation Configuration +### Add a token validation configuration 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account and domain. 2. Go to **Security** > **API Shield** > **Settings**. @@ -31,16 +31,17 @@ Each JWT issuer typically publishes public keys (JWKS) for verification at a kno To automatically keep your JWKS up to date when your identity provider refreshes them, you can use a Worker. Refer to [Configure Workers to automatically update keys](/api-shield/security/jwt-validation/jwt-worker/) to learn more about setting up the Worker. -### Add a JWT Validation Rule +### Add a JWT validation rule 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account and domain. 2. Go to **Security** > **API Shield** > **API Rules**. -3. Add a name for your rule. +3. + Add a name for your rule. 4. Select a hostname to protect requests with saved endpoints using the rule. -5. Deselect any endpoints that you want JWT Validation to ignore (for example, an endpoint used to generate a JWT). -6. Select the Token Validation Configuration that corresponds to the incoming requests. +5. Deselect any endpoints that you want JWT validation to ignore (for example, an endpoint used to generate a JWT). +6. Select the token validation configuration that corresponds to the incoming requests. 7. Choose whether to strictly enforce token presence on these endpoints. - - You may not expect 100% of clients to send in JWTs with their requests. If this is the case, choose *Ignore*. JWT Validation will still validate JWTs that are present. + - You may not expect 100% of clients to send in JWTs with their requests. If this is the case, choose *Ignore*. JWT validation will still validate JWTs that are present. - You may otherwise expect all requests to the selected hostname and endpoints to contain JWTs. If this is the case, choose *Mark as non-compliant*. 8. Choose an action to take for non-compliant requests. For example, JWTs that do not pass validation (expired, tampered with, or bad signature tokens) or requests with missing JWTs when *Mark as non-compliant* is selected in the previous step. 9. Select **Save**. @@ -66,11 +67,11 @@ API Shield will verify JSON Web Tokens regardless of whether or not they have th ## Availability -JWT Validation is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team. +JWT validation is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team. ## Limitations Currently, the following known limitations exist: -1. JWT Validation only operates on JWTs sent in client request headers or cookies. If your clients send in JWTs in a `POST` body, direct that feedback to your account team. -2. JWT Validation only operates for endpoints (host, method, and path) added to Endpoint Management. You can add all of your endpoints to endpoint management through [API Discovery](/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery), [Schema Validation](/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation), [manually via the Cloudflare dashboard](/api-shield/management-and-monitoring/#add-endpoints-manually), or via the [API](/api/resources/api_gateway/subresources/operations/methods/create/). +1. JWT validation only operates on JWTs sent in client request headers or cookies. If your clients send in JWTs in a `POST` body, direct that feedback to your account team. +2. JWT validation only operates for endpoints (host, method, and path) added to Endpoint Management. You can add all of your endpoints to endpoint management through [API Discovery](/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery), [Schema validation](/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation), [manually via the Cloudflare dashboard](/api-shield/management-and-monitoring/#add-endpoints-manually), or via the [API](/api/resources/api_gateway/subresources/operations/methods/create/). diff --git a/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx b/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx index 75523bc5f55b86..b75867541650ba 100644 --- a/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/jwt-worker.mdx @@ -6,7 +6,7 @@ sidebar: order: 2 head: - tag: title - content: Configure the Worker for JWT Validation + content: Configure the Worker for JWT validation --- Use a Worker to automatically keep your identity provider’s latest public key in the JWT Validation configuration. @@ -15,7 +15,7 @@ Use a Worker to automatically keep your identity provider’s latest public key - Find your zone ID. You can locate this ID in your zone overview in the [Cloudflare dashboard](https://dash.cloudflare.com/). - Find your identity provider’s JSON Web Key Set (JWKs) URL. Identity providers commonly list it in Open Authorization (OAuth) settings. -- Create a [Token Validation Configuration](/api-shield/security/jwt-validation/#add-a-token-validation-configuration). +- Create a [token validation configuration](/api-shield/security/jwt-validation/#add-a-token-validation-configuration). - [Create a new API token](https://dash.cloudflare.com/profile/api-tokens) with the API Gateway `Write` permission. ## Process @@ -64,7 +64,7 @@ curl https://.cloudflareaccess.com/cdn-cgi/access/certs -s | jq 1. [Create a new Worker](/workers/get-started/guide/). 2. Copy and paste the example code below into your new Worker, completely replacing any code that already exists. 3. Replace the current zone ID with your zone ID. -4. Replace the current Token Validation Configuration ID with your Token Validation Configuration. +4. Replace the current token validation configuration ID with your token validation configuration. 5. Replace the current identity provider’s URL with your identity provider’s key URL. :::note diff --git a/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx b/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx index e2b705f71acdff..2aced16c159320 100644 --- a/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx +++ b/src/content/docs/api-shield/security/jwt-validation/transform-rules.mdx @@ -13,13 +13,13 @@ You can forward information from a [JSON Web Token (JWT)](/api-shield/security/j Claims are available through the `http.request.jwt.claims` firewall fields. -For example, the following expression will extract the user claim from a token processed by the Token Configuration with `TOKEN_CONFIGURATION_ID`: +For example, the following expression will extract the user claim from a token processed by the token configuration with `TOKEN_CONFIGURATION_ID`: ```txt lookup_json_string(http.request.jwt.claims[""][0], "claim_name") ``` -Refer to [Configure JWT Validation](/api-shield/security/jwt-validation/configure/) for more information about creating a Token Configuration. +Refer to [Configure JWT validation](/api-shield/security/jwt-validation/configure/) for more information about creating a token configuration. ## Create a Transform Rule @@ -31,4 +31,4 @@ As an example, to send the `x-send-jwt-claim-user` request header to the origin, 4. Enter a rule name and a filter expression, if applicable. 5. Choose **Set dynamic**. 6. Set the header name to `x-send-jwt-claim-user`. -7. Set the value to `lookup_json_string(http.request.jwt.claims[""][0], "claim_name")`, where `` is your token configuration ID found in JWT Validation and `claim_name` is the JWT claim you want to add to the header. +7. Set the value to `lookup_json_string(http.request.jwt.claims[""][0], "claim_name")`, where `` is your token configuration ID found in JWT validation and `claim_name` is the JWT claim you want to add to the header. diff --git a/src/content/docs/api-shield/security/schema-validation/configure.mdx b/src/content/docs/api-shield/security/schema-validation/configure.mdx index 555d4cc7744c29..9c8b9ea580cdae 100644 --- a/src/content/docs/api-shield/security/schema-validation/configure.mdx +++ b/src/content/docs/api-shield/security/schema-validation/configure.mdx @@ -4,39 +4,39 @@ pcx_content_type: how-to type: overview head: - tag: title - content: Configure Schema Validation + content: Configure Schema validation --- import { GlossaryTooltip } from "~/components" -Schema Validation 2.0 allows all corresponding configuration calls to be made via API. This validation centers more around individual endpoints and lets you set mitigation actions for each endpoint individually. Additionally, you can use Cloudflare-provided learned schemas that we [learn automatically](/api-shield/management-and-monitoring/#endpoint-schema-learning) from your traffic for individual endpoints. +Schema validation 2.0 allows all corresponding configuration calls to be made via API. This validation centers more around individual endpoints and lets you set mitigation actions for each endpoint individually. Additionally, you can use Cloudflare-provided learned schemas that we [learn automatically](/api-shield/management-and-monitoring/#endpoint-schema-learning) from your traffic for individual endpoints. :::note -[Classic Schema Validation documentation](/api-shield/reference/classic-schema-validation/) is available for reference only. +[Classic Schema validation documentation](/api-shield/reference/classic-schema-validation/) is available for reference only. ::: -## Upload schemas via the API to Schema Validation +## Upload schemas via the API to Schema validation 1. Upload a schema. 2. Ensure that your endpoints are added in Endpoint Management. 3. Set the schema to `active` if it is not already done. -4. Set the Schema Validation zone-wide action from `none` to `log`. +4. Set the Schema validation zone-wide action from `none` to `log`. 5. Send test traffic that violates the schema. 6. View test traffic in Security Events by filtering for **Service** > **API Shield - Schema Validation**. 7. Optional: - Set a single endpoint to `block`. - - Set the Schema Validation zone-wide to `block`. + - Set the Schema validation zone-wide to `block`. - Temporarily override all schemas zone-wide to `none`. - Remove the temporary override. -Cloudflare recommends you to rerun test traffic and monitor the HTTP response codes after changing any settings to ensure Schema Validation is operating as expected. +Cloudflare recommends you to rerun test traffic and monitor the HTTP response codes after changing any settings to ensure Schema validation is operating as expected. Settings changes may take a few minutes to implement. :::note -Endpoints must be listed in Endpoint Management for Schema Validation to match requests. +Endpoints must be listed in Endpoint Management for Schema validation to match requests. ::: ## Configuration @@ -72,7 +72,7 @@ curl --request POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_ga } ``` -By default, Schema Validation is disabled for an uploaded schema so that you can inspect it first. You can upload a schema and enable it immediately by setting the form parameter `validation_enabled=true`. +By default, Schema validation is disabled for an uploaded schema so that you can inspect it first. You can upload a schema and enable it immediately by setting the form parameter `validation_enabled=true`. Use a `PATCH` request to activate a schema after inspection. @@ -107,7 +107,7 @@ When a schema is active, it executes the mitigation action specified for each op ### Add new operations to Endpoint Management -Schemas contain a set of servers, paths, and methods, which together define an operation. Schema Validation only acts on the requests to operations which have been added to the API Shield Endpoint Management. If a schema contains operations which have not been added to Endpoint Management, they can be retrieved together with the configuration information about added operations. +Schemas contain a set of servers, paths, and methods, which together define an operation. Schema validation only acts on the requests to operations which have been added to the API Shield Endpoint Management. If a schema contains operations which have not been added to Endpoint Management, they can be retrieved together with the configuration information about added operations. ```bash title="cURL command" curl --request GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/user_schemas/{schema_id}/operations?feature=schema_info&operation_status=new&page=1&per_page=5000" \ @@ -184,7 +184,7 @@ curl --silent "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/ :::note -If you run this command again immediately, it will result in an error as all `new_operations` are now `existing_operations`. +If you run this command again immediately, it will result in an error as all `new_operations` are now `existing_operations`. ::: ### Change the default and operation-specific mitigation action @@ -318,7 +318,7 @@ curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/user_sche :::note -We recommend using the query parameter `omit_source=true` to only display active schemas and not retrieve the source for every schema to get less output. +We recommend using the query parameter `omit_source=true` to only display active schemas and not retrieve the source for every schema to get less output. ::: ### Delete a schema @@ -414,12 +414,12 @@ curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gat :::note -Parameter schemas are updated between every 24 hours up to one week. To ensure that a parameter schema has not been updated during the inspection, Cloudflare recommends that you pass the `last_updated` timestamp of the parameter-schema feature (not the `last_updated` of the whole operation) as an identifier in the timestamp query parameter. +Parameter schemas are updated between every 24 hours up to one week. To ensure that a parameter schema has not been updated during the inspection, Cloudflare recommends that you pass the `last_updated` timestamp of the parameter-schema feature (not the `last_updated` of the whole operation) as an identifier in the timestamp query parameter. ::: -### Disable Schema Validation +### Disable Schema validation -To quickly disable schema validation for a whole zone, use `PATCH`. This operation will override all operation-mitigation actions. +To quickly disable Schema validation for a whole zone, use `PATCH`. This operation will override all operation-mitigation actions. ```bash title="cURL command" curl --request PATCH "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/settings/schema_validation" \ diff --git a/src/content/docs/api-shield/security/schema-validation/index.mdx b/src/content/docs/api-shield/security/schema-validation/index.mdx index d78be4be32e15a..2f4ee5ffcf5a5a 100644 --- a/src/content/docs/api-shield/security/schema-validation/index.mdx +++ b/src/content/docs/api-shield/security/schema-validation/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -title: Schema Validation +title: Schema validation sidebar: order: 8 @@ -12,15 +12,15 @@ import { GlossaryDefinition, GlossaryTooltip, Plan } from "~/components" -Schema Validation allows you to check if incoming traffic complies with a previously supplied API schema. When you provide an API schema or select from a list of learned schema, API Shield creates rules for incoming traffic from the schema definitions. These rules define which traffic is allowed and which traffic gets logged or blocked. +Schema validation allows you to check if incoming traffic complies with a previously supplied API schema. When you provide an API schema or select from a list of learned schema, API Shield creates rules for incoming traffic from the schema definitions. These rules define which traffic is allowed and which traffic gets logged or blocked. -Cloudflare has recently launched Schema Validation 2.0. For help configuring the previous version of Schema Validation for one or more hosts using the dashboard, refer to [Configure Classic Schema Validation](/api-shield/reference/classic-schema-validation/). You can make changes to your Classic Schema Validation settings but you cannot add any new schemas. +Cloudflare has recently launched Schema validation 2.0. For help configuring the previous version of Schema validation for one or more hosts using the dashboard, refer to [Configure Classic Schema validation](/api-shield/reference/classic-schema-validation/). You can make changes to your Classic Schema validation settings but you cannot add any new schemas. -You can migrate to Schema Validation 2.0 manually by uploading your schemas to the new system, or you can wait for a future release where we will add an easy migrate option per-schema. +You can migrate to Schema validation 2.0 manually by uploading your schemas to the new system, or you can wait for a future release where we will add an easy migrate option per-schema. ## Process -Endpoints must be added to [Endpoint Management](/api-shield/management-and-monitoring/) for Schema Validation to protect them. Uploading a schema via the Cloudflare dashboard will automatically add endpoints, or you can manually add them from [API Discovery](/api-shield/security/api-discovery/). +Endpoints must be added to [Endpoint Management](/api-shield/management-and-monitoring/) for Schema validation to protect them. Uploading a schema via the Cloudflare dashboard will automatically add endpoints, or you can manually add them from [API Discovery](/api-shield/security/api-discovery/). If you are uploading a schema via the API or Terraform, you must parse the schema and add your endpoints manually. @@ -35,7 +35,7 @@ To view the contents in your learned schema, refer to [Export a schema](/api-shi 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to **Schema Validation** and select **Add validation**. +3. Go to **Schema validation** and select **Add validation**. 4. Select your schema file for upload. 5. Observe the listed endpoints, their host, method, and path. Any new endpoints will automatically be added to Endpoint Management. 6. Choose an action for the non-compliant requests to your endpoints. @@ -50,7 +50,7 @@ Changes may take a few minutes to process depending on the number of added endpo 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to **Schema Validation** and filter by the learned schema available. +3. Go to **Schema validation** and filter by the learned schema available. 4. Select **Apply learned schema**. 5. Choose an action and select **Apply schema**. @@ -60,7 +60,7 @@ At this time, learned schemas will not overwrite customer-uploaded schemas. If a 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to **Schema Validation** and select **Add Validation**. +3. Go to **Schema validation** and select **Add validation**. 4. Select **Apply learned schema**. 5. Choose a hostname and review the endpoints that will be protected by the learned schema. 6. (Optional) Change the action if a request does not match the schema. @@ -99,16 +99,16 @@ You can use the `cf.api_gateway.fallthrough_triggered` syntax in your own custom 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to **Schema Validation** and select the schema in the Schema list. +3. Go to **Schema validation** and select the schema in the Schema list. 4. Check the multi-select box to select the endpoints shown on the current page. 5. Choose **Select all endpoints**. 6. Select **Change Action**. 7. Choose an action from the dropdown menu. 8. Select **Set action**. -### Change the global default action of Schema Validation +### Change the global default action of Schema validation -Schema Validation’s default action is visible on the main Schema Validation page. This action applies to any endpoint with its action set to `Default`. +Schema validation’s default action is visible on the main Schema validation page. This action applies to any endpoint with its action set to `Default`. - `Log` action: logs events to [Firewall Events](/firewall/). - `Block` action: blocks requests that fail the schema for an endpoint and logs events to [Firewall Events](/firewall/). @@ -118,7 +118,7 @@ To change the default action: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Go to **Security** > **API Shield**. -3. Select **Schema Validation**. +3. Select **Schema validation**. 4. Under the default `Log` action, select **Change**. 5. Choose a new action from the dropdown menu. 6. Observe the current action and accept the change by selecting **Change default action** in the popup window. @@ -127,7 +127,7 @@ Alternatively, you can modify the global action via **Security** > **API Shield* ### Change the action of a single endpoint -You can change individual endpoint actions separately from the default action in Schema Validation. +You can change individual endpoint actions separately from the default action in Schema validation. This allows you to be stricter on blocking non-compliant requests on certain endpoints when the default action is `Log`. It can also be used to relax constraints on non-compliant requests on certain endpoints when the default action is set to `Block`. You may want to silence known false positives on an endpoint by setting the action to `None`. @@ -135,18 +135,18 @@ To change the action on an individual endpoint: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Go to **Security** > **API Shield**. -3. Select **Schema Validation** and filter the selected endpoint. +3. Select **Schema validation** and filter the selected endpoint. 4. Select the ellipses on the endpoint's row. 5. Select **Change Action**. 6. Choose a new action from the dropdown menu and select **Set action**. -### Disable Schema Validation without changing actions +### Disable Schema validation without changing actions -You can disable Schema Validation entirely for temporary troubleshooting. You can override all actions at once, preventing Schema Validation from taking any action while you complete your troubleshooting. +You can disable Schema validation entirely for temporary troubleshooting. You can override all actions at once, preventing Schema validation from taking any action while you complete your troubleshooting. 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to the **Schema Validation** settings. +3. Go to the **Schema validation** settings. 4. Select **Disable**. Your per-endpoint configurations will be saved when modifying the setting, so that you do not lose your configuration. To re-enable your configurations after troubleshooting, navigate back to the settings and select **Enable**. @@ -157,7 +157,7 @@ To view currently uploaded or learned schemas: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to your **Schema Validation** settings. +3. Go to your **Schema validation** settings. 4. View your schemas under **Uploaded Schemas** and **Learned schemas**. 5. Select **Filter** on the endpoints in either schema. @@ -169,7 +169,7 @@ To delete currently uploaded or learned schemas: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Select **Security** > **API Shield**. -3. Go to your **Schema Validation** settings. +3. Go to your **Schema validation** settings. 4. View your schemas under **Uploaded Schemas** and **Learned schemas**. 5. Select the ellipses to access the menu and download or delete the listed schema. @@ -177,11 +177,11 @@ To delete currently uploaded or learned schemas: Cloudflare currently only accepts [OpenAPI v3 schemas](https://spec.openapis.org/oas/v3.0.3.html). The accepted file formats are YAML (`.yml` or `.yaml` file extension) and JSON (`.json` file extension). -OpenAPI schemas generated by different tooling may not be specific enough to import to Schema Validation. We recommend using a third-party tool such as [Swagger Editor](https://swagger.io/tools/swagger-editor/) to ensure that schemas are compliant to the OpenAPI specification. +OpenAPI schemas generated by different tooling may not be specific enough to import to Schema validation. We recommend using a third-party tool such as [Swagger Editor](https://swagger.io/tools/swagger-editor/) to ensure that schemas are compliant to the OpenAPI specification. ## Limitations -Schema Validation supports [OpenAPI Version 3.0.x schemas](https://spec.openapis.org/oas/v3.0.3). OpenAPI 3.1 is not supported yet, and we do not plan to expand support for OpenAPI 2.0. +Schema validation supports [OpenAPI Version 3.0.x schemas](https://spec.openapis.org/oas/v3.0.3). OpenAPI 3.1 is not supported yet, and we do not plan to expand support for OpenAPI 2.0. Currently, API Shield does not support some features of API schemas, including the following: all responses, external references, non-basic path templating, or unique items. @@ -191,26 +191,26 @@ For limits on Free, Pro, Business, or Enterprise customers not subscribed to API ### Required fields -Although not strictly required by the OpenAPI specification, Schema Validation strictly requires these fields. +Although not strictly required by the OpenAPI specification, Schema validation strictly requires these fields. #### `schema` - [`type`](https://spec.openapis.org/oas/v3.0.3#schema-object) - - All schemas require a type to be set. If the specific type is not supported by Schema Validation, it is usually best to simply set the type to `string` instead. + - All schemas require a type to be set. If the specific type is not supported by Schema validation, it is usually best to simply set the type to `string` instead. #### `parameter` - [`schema`](https://spec.openapis.org/oas/v3.0.3#schema-object) - - Schema Validation does not support the content field in parameters. For more details, refer to the [notes on validated and supported fields](#notes-on-validated-and-supported-fields) below. Instead, a schema is strictly required on all parameters objects. + - Schema validation does not support the content field in parameters. For more details, refer to the [notes on validated and supported fields](#notes-on-validated-and-supported-fields) below. Instead, a schema is strictly required on all parameters objects. ### Notes on validated and supported fields -Refer to the information below for more details on Schema Validation's current support for various OpenAPI specification (OAS) objects and fields. +Refer to the information below for more details on Schema validation's current support for various OpenAPI specification (OAS) objects and fields. #### `servers` - [`url`](https://spec.openapis.org/oas/v3.0.3#server-object) - - Schema Validation does not support relative URLs. + - Schema validation does not support relative URLs. - [`variables`](https://spec.openapis.org/oas/v3.0.3#server-variable-object) - Server variables are not validated. @@ -235,7 +235,7 @@ Refer to the information below for more details on Schema Validation's current s - `content` - [Request Body Object](https://spec.openapis.org/oas/v3.0.3#request-body-object) - [Media Type Object](https://spec.openapis.org/oas/v3.0.3#media-type-object) - - Schema Validation is able to validate `application/json` documents. If a given schema allows other content types, Schema Validation will accept those requests without validation. + - Schema validation is able to validate `application/json` documents. If a given schema allows other content types, Schema validation will accept those requests without validation. #### `parameter/schema` @@ -270,13 +270,13 @@ Refer to the information below for more details on Schema Validation's current s - `uint64` - [`uniqueItems`](https://spec.openapis.org/oas/v3.0.3#schema-object) - - This field is currently not validated by Schema Validation. + - This field is currently not validated by Schema validation. ## Body inspection API Shield has the ability to identify body specifications contained in uploaded schemas and validate that the data of incoming API requests adheres to them. -Schema Validation currently supports validating requests with content-type `application/json`. +Schema validation currently supports validating requests with content-type `application/json`. Within the OpenAPI specification, request body schemas are associated to media-ranges (such as `application/*`, `application/xml` or `application/json`). @@ -300,4 +300,4 @@ Media-ranges can also be configured to enforce a `charset` parameter. For this, ## Availability -Schema Validation is available for all customers. Refer to [Plans](/api-shield/plans/) for more information based on your plan type. \ No newline at end of file +Schema validation is available for all customers. Refer to [Plans](/api-shield/plans/) for more information based on your plan type. \ No newline at end of file diff --git a/src/content/docs/api-shield/security/sequence-analytics.mdx b/src/content/docs/api-shield/security/sequence-analytics.mdx index 3c555d9f1dd185..35a645a2454ae7 100644 --- a/src/content/docs/api-shield/security/sequence-analytics.mdx +++ b/src/content/docs/api-shield/security/sequence-analytics.mdx @@ -40,7 +40,7 @@ To proactively secure your API, you should inspect your highest-scoring sequence Using the above example, if `POST /api/v1/transferFunds` must legitimately always be preceded by `GET /api/v1/users/{user_id}/accounts` and `GET /api/v1/accounts/{account_id}/balance?`, you should create an **Allow** rule in Sequence Mitigation on the final operation of the sequence. -You should also consider applying other API Shield protections to these endpoints ([rate limiting suggestions](/api-shield/security/volumetric-abuse-detection/), [Schema Validation](/api-shield/security/schema-validation/), [JWT Validation](/api-shield/security/jwt-validation/), and [mTLS](/api-shield/security/mtls/)). +You should also consider applying other API Shield protections to these endpoints ([rate limiting suggestions](/api-shield/security/volumetric-abuse-detection/), [Schema validation](/api-shield/security/schema-validation/), [JWT validation](/api-shield/security/jwt-validation/), and [mTLS](/api-shield/security/mtls/)). For more information, refer to our [blog post](https://blog.cloudflare.com/api-sequence-analytics). diff --git a/src/content/docs/api-shield/security/sequence-mitigation/index.mdx b/src/content/docs/api-shield/security/sequence-mitigation/index.mdx index 1ec3ca47a75f78..031858678e36dd 100644 --- a/src/content/docs/api-shield/security/sequence-mitigation/index.mdx +++ b/src/content/docs/api-shield/security/sequence-mitigation/index.mdx @@ -45,7 +45,8 @@ For example, if there was an authorization bug that allowed users to iterate thr 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. 2. Go to **Security** > **API Shield** > **API Rules**. 3. Select **Create sequence rule**. -4. Name your rule. +4. + Name your rule. 5. Select a starting endpoint. This is the endpoint that you expect users to hit first in their request flow when using your API. 1. Choose a hostname to display the list of endpoints for that hostname. 2. Choose an endpoint. @@ -77,7 +78,7 @@ You can also explicitly set a priority order by selecting the three dots on your ### Endpoint Management -To track requests to API endpoints, they must be added to [Endpoint Management](/api-shield/management-and-monitoring/). Add your endpoints to endpoint management via [API Discovery](/api-shield/security/api-discovery/), [Schema Validation](/api-shield/security/schema-validation/), or [manually](/api-shield/management-and-monitoring/#add-endpoints-manually) through the Cloudflare dashboard. +To track requests to API endpoints, they must be added to [Endpoint Management](/api-shield/management-and-monitoring/). Add your endpoints to endpoint management via [API Discovery](/api-shield/security/api-discovery/), [Schema validation](/api-shield/security/schema-validation/), or [manually](/api-shield/management-and-monitoring/#add-endpoints-manually) through the Cloudflare dashboard. ### Session Identifiers diff --git a/src/content/docs/automatic-platform-optimization/index.mdx b/src/content/docs/automatic-platform-optimization/index.mdx index 576648bd534544..f13f9128823ad8 100644 --- a/src/content/docs/automatic-platform-optimization/index.mdx +++ b/src/content/docs/automatic-platform-optimization/index.mdx @@ -1,9 +1,11 @@ --- -title: Welcome +title: Automatic Platform Optimization pcx_content_type: overview sidebar: order: 1 - +head: + - tag: title + content: Overview --- Take your WordPress site’s performance to the next level with Automatic Platform Optimizations (APO). APO allows Cloudflare to serve your entire WordPress site from its edge network ensuring consistent, fast performance for visitors no matter where they are. diff --git a/src/content/docs/bots/concepts/bot-score/index.mdx b/src/content/docs/bots/concepts/bot-score/index.mdx index e2225c48ab98e9..0d10ae22ee6f85 100644 --- a/src/content/docs/bots/concepts/bot-score/index.mdx +++ b/src/content/docs/bots/concepts/bot-score/index.mdx @@ -3,10 +3,9 @@ pcx_content_type: concept title: Bot scores sidebar: order: 2 - --- -import { GlossaryTooltip, Render } from "~/components" +import { GlossaryTooltip, Render } from "~/components"; @@ -14,7 +13,7 @@ Bot scores are available to be used in rule expressions and with Workers to cust :::note -Granular bot scores are only available to Enterprise customers who have purchased Bot Management. All other customers can only access this information through [bot groupings](#bot-groupings) in Bot Analytics. +Granular bot scores are only available to Enterprise customers who have purchased Bot Management. All other customers can only access this information through [bot groupings](#bot-groupings) in Bot Analytics. ::: ## Bot groupings @@ -32,7 +31,7 @@ Bot scores are not computed for requests to paths that are handled by Cloudflare :::note -The following detection engines only apply to Enterprise Bot Management. For specific details about the engines included in your plan, refer to [Plans](/bots/plans/). +The following detection engines only apply to Enterprise Bot Management. For specific details about the engines included in your plan, refer to [Plans](/bots/plans/). ::: @@ -48,7 +47,3 @@ The following detection engines only apply to Enterprise Bot Management. For spe ### Notes on detection - -## Comparison to Threat Score - -Bot Score is different from Threat Score. Bot Score identifies bots and Threat Score measures IP reputation across our services. Most customers achieve the best results by relying on bot scores and avoiding IP reputation entirely. diff --git a/src/content/docs/bots/concepts/detection-ids.mdx b/src/content/docs/bots/concepts/detection-ids.mdx index c4946d5de4c810..f855a38a21d2cc 100644 --- a/src/content/docs/bots/concepts/detection-ids.mdx +++ b/src/content/docs/bots/concepts/detection-ids.mdx @@ -35,7 +35,7 @@ Detection tags are available in Security Analytics, but not in the Security Even ## Bot Detection IDs via Logpush -You can create or edit their existing Logpush jobs to include the new Bot Detection IDs field which will provide an array of IDs for each request that has heuristics match on it. The `BotDetectionIDs` field is available as part of the HTTP Requests dataset and you can add it to new or existing jobs via the Logpush API or on the Cloudflare dashboard. This is the primary method to discover Detection IDs. +You can create or edit existing Logpush jobs to include the new Bot Detection IDs field which will provide an array of IDs for each request that has heuristics match on it. The `BotDetectionIDs` field is available as part of the HTTP Requests dataset and you can add it to new or existing jobs via the Logpush API or on the Cloudflare dashboard. This is the primary method to discover Detection IDs. ### Via the Cloudflare dashboard diff --git a/src/content/docs/bots/concepts/ja3-ja4-fingerprint.mdx b/src/content/docs/bots/concepts/ja3-ja4-fingerprint.mdx index e343778ddefb81..65da4e485388f2 100644 --- a/src/content/docs/bots/concepts/ja3-ja4-fingerprint.mdx +++ b/src/content/docs/bots/concepts/ja3-ja4-fingerprint.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -title: JA3/JA4 Fingerprint +title: JA3/JA4 fingerprint --- @@ -72,6 +72,8 @@ When JA4 Signals are missing, the output appears as follows: This sample was generated using [Workers' Cloudflare Object script](/workers/examples/accessing-the-cloudflare-object/). ::: + + ## Analytics To get more information about potential bot requests, use these JA3 and JA4 fingerprints in: diff --git a/src/content/docs/bots/get-started/biz-and-ent.mdx b/src/content/docs/bots/get-started/biz-and-ent.mdx index 7a013f24e8f40d..06ffcf398438dc 100644 --- a/src/content/docs/bots/get-started/biz-and-ent.mdx +++ b/src/content/docs/bots/get-started/biz-and-ent.mdx @@ -46,6 +46,10 @@ If you have an Enterprise subscription without Bot Management, your application You can view blocked AI bot traffic via [Security Analytics](/waf/analytics/security-analytics/). ::: +### Enable AI Labyrinth + + + ## Analytics For more on analytics, see [Bot Analytics](/bots/bot-analytics/biz-and-ent/). diff --git a/src/content/docs/bots/get-started/bm-subscription.mdx b/src/content/docs/bots/get-started/bm-subscription.mdx index b53eeb188b9e9d..72742730e288bc 100644 --- a/src/content/docs/bots/get-started/bm-subscription.mdx +++ b/src/content/docs/bots/get-started/bm-subscription.mdx @@ -40,6 +40,10 @@ If you are not seeing Bot Management enabled on your zone or if you still see ** You can view blocked AI bot traffic via [Security Analytics](/waf/analytics/security-analytics/). ::: +### Enable AI Labyrinth + + + ## Setup For more guidance on setup, refer to your Customer Success Manager. diff --git a/src/content/docs/bots/get-started/free.mdx b/src/content/docs/bots/get-started/free.mdx index d2264214bef27c..81d59d18a23bf5 100644 --- a/src/content/docs/bots/get-started/free.mdx +++ b/src/content/docs/bots/get-started/free.mdx @@ -38,6 +38,10 @@ To disable Bot Fight Mode: You can view blocked AI bot traffic via [Security Analytics](/waf/analytics/security-analytics/). ::: +### Enable AI Labyrinth + + + ## Visibility You can see bot-related actions by going to **Security** > **Events**. Any requests challenged by this product will be labeled **Bot Fight Mode** in the **Service** field. This allows you to observe, analyze, and follow trends in your bot traffic over time. diff --git a/src/content/docs/bots/get-started/pro.mdx b/src/content/docs/bots/get-started/pro.mdx index 886d6501650090..0b34067b489821 100644 --- a/src/content/docs/bots/get-started/pro.mdx +++ b/src/content/docs/bots/get-started/pro.mdx @@ -41,6 +41,10 @@ Super Bot Fight Mode is included in your Pro subscription. When enabled, the pro You can view blocked AI bot traffic via [Security Analytics](/waf/analytics/security-analytics/). ::: +### Enable AI Labyrinth + + + ## Analytics ### Bot Report diff --git a/src/content/docs/bots/index.mdx b/src/content/docs/bots/index.mdx index d7901def4ba602..8e881a15d81dd2 100644 --- a/src/content/docs/bots/index.mdx +++ b/src/content/docs/bots/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare bot solutions pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare bot solutions - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, Render } from "~/components" diff --git a/src/content/docs/bots/troubleshooting.mdx b/src/content/docs/bots/troubleshooting.mdx index 1e4f1e59f59e50..f67698f6b61ed2 100644 --- a/src/content/docs/bots/troubleshooting.mdx +++ b/src/content/docs/bots/troubleshooting.mdx @@ -71,17 +71,6 @@ Yes. WAF rules are executed before Super Bot Fight Mode. If a WAF custom rule pe --- -## What is the difference between the threat score and bot management score? - -The difference is significant: - -- Threat score (_cf.threat_score_) is what Cloudflare uses to determine IP Reputation. It goes from 0 (good) to 100 (bad). -- Bot management score (_cf.bot_management.score_) is what Cloudflare uses in Bot Management to measure if the request is from a human or a script. The scores range from 1 (bot) to 99 (human). Lower scores indicate the request came from a script, API service, or an automated agent. Higher scores indicate that the request came from a human using a standard desktop or mobile web browser. - -These fields are available via [WAF custom rules](/waf/custom-rules/) and other products based on the Ruleset Engine. - ---- - ## What is cf.bot_management.verified_bot? A request's _cf.bot_management.verified_bot_ value is a boolean indicating whether such request comes from a Cloudflare allowed bot. @@ -94,13 +83,9 @@ To allow traffic from good bots, use the [Verified Bot](/ruleset-engine/rules-la --- -## Why might the ja3hash be empty in HTTP logs? - -The JA3 Fingerprint can be null or empty in some cases. The most common case is for HTTP requests, because JA3 is calculated in TLS, but can also be empty due to the following: - -- Orange to Orange zones (Cloudflare Zone proxied to another Cloudflare Zone). +## Why might the ja3hash or JA4 be empty in HTTP logs? -- Worker sending requests within the same zone or to a zone that is not proxied (or a 3rd party). + --- diff --git a/src/content/docs/browser-rendering/get-started.mdx b/src/content/docs/browser-rendering/get-started.mdx new file mode 100644 index 00000000000000..d75c19a3ac10af --- /dev/null +++ b/src/content/docs/browser-rendering/get-started.mdx @@ -0,0 +1,11 @@ +--- +pcx_content_type: navigation +title: Get started +sidebar: + order: 2 +--- + +Browser rendering can be used in two ways: + +- [Workers Binding API](/browser-rendering/workers-binding-api) for complex scripts. +- [REST API](/browser-rendering/rest-api/) for simple actions. diff --git a/src/content/docs/browser-rendering/how-to/pdf-generation.mdx b/src/content/docs/browser-rendering/how-to/pdf-generation.mdx index 22a40c370f7163..fd78e0b7f04bb5 100644 --- a/src/content/docs/browser-rendering/how-to/pdf-generation.mdx +++ b/src/content/docs/browser-rendering/how-to/pdf-generation.mdx @@ -7,7 +7,7 @@ sidebar: import { Aside, WranglerConfig } from "~/components"; -As seen in the [Getting Started guide](/browser-rendering/get-started/screenshots/), Browser Rendering can be used to generate screenshots for any given URL. Alongside screenshots, you can also generate full PDF documents for a given webpage, and can also provide the webpage markup and style ourselves. +As seen in the [Getting Started guide](/browser-rendering/workers-binding-api/screenshots/), Browser Rendering can be used to generate screenshots for any given URL. Alongside screenshots, you can also generate full PDF documents for a given webpage, and can also provide the webpage markup and style ourselves. ## Prerequisites @@ -26,7 +26,8 @@ npm install @cloudflare/puppeteer --save-dev 3. Add your Browser Rendering binding to your new Wrangler configuration: -```toml + +```toml title="wrangler.toml" browser = { binding = "BROWSER" } ``` diff --git a/src/content/docs/browser-rendering/how-to/queues.mdx b/src/content/docs/browser-rendering/how-to/queues.mdx new file mode 100644 index 00000000000000..610b1271d7df58 --- /dev/null +++ b/src/content/docs/browser-rendering/how-to/queues.mdx @@ -0,0 +1,7 @@ +--- +pcx_content_type: navigation +title: Build a web crawler with Queues and Browser Rendering +external_link: /queues/tutorials/web-crawler-with-browser-rendering/ +sidebar: + order: 2 +--- diff --git a/src/content/docs/browser-rendering/index.mdx b/src/content/docs/browser-rendering/index.mdx index 64d412a37bdd74..0b5eae484890f7 100644 --- a/src/content/docs/browser-rendering/index.mdx +++ b/src/content/docs/browser-rendering/index.mdx @@ -34,6 +34,7 @@ Use Browser Rendering to: - Test web applications. - Gather page load performance metrics. - Crawl web pages for information retrieval. + ## Related products diff --git a/src/content/docs/browser-rendering/platform/index.mdx b/src/content/docs/browser-rendering/platform/index.mdx index 6897db18a7316c..1b54a03e0c44f1 100644 --- a/src/content/docs/browser-rendering/platform/index.mdx +++ b/src/content/docs/browser-rendering/platform/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Platform sidebar: - order: 3 + order: 4 group: hideIndex: true --- diff --git a/src/content/docs/browser-rendering/platform/limits.mdx b/src/content/docs/browser-rendering/platform/limits.mdx index 823a9d21b4c71b..1cb7e9b7d18a8d 100644 --- a/src/content/docs/browser-rendering/platform/limits.mdx +++ b/src/content/docs/browser-rendering/platform/limits.mdx @@ -1,18 +1,34 @@ --- pcx_content_type: configuration title: Limits +description: Learn about the limits associated with Browser Rendering. sidebar: order: 30 --- -import { Render } from "~/components" +import { Render, Plan } from "~/components"; -| Feature | Limit | -| --------------------------------------------- | ------------------------------------------------------------- | -| Concurrent browsers per account | 10 per account [^1] | -| New browser instances per minute | 10 per minute [^1] | -| Browser timeout | 60 seconds [^1][^2] | + + +## Workers Binding API + +| Feature | Limit | +| -------------------------------- | ------------------- | +| Concurrent browsers per account | 10 per account [^1] | +| New browser instances per minute | 10 per minute [^1] | +| Browser timeout | 60 seconds [^1][^2] | + +## REST API + +| Feature | Limit | +| -------------------------------- | ------------------- | +| Concurrent browsers per account | 10 per account [^1] | +| New browser instances per minute | 10 per minute [^1] | +| Browser timeout | 60 seconds [^1][^2] | +| Total requests per minute | 60 per minute [^1] | [^1]: Contact our team to request increases to this limit. + [^2]: By default, a browser instance gets killed if it does not get any [devtools](https://chromedevtools.github.io/devtools-protocol/) command for 60 seconds, freeing one instance. Users can optionally increase this by using the `keep_alive` [option](/browser-rendering/platform/puppeteer/#keep-alive). `browser.close()` releases the browser instance. -close()` releases the browser instance. + + diff --git a/src/content/docs/browser-rendering/platform/puppeteer.mdx b/src/content/docs/browser-rendering/platform/puppeteer.mdx index 6e8b6717cb0031..cb58795616f59c 100644 --- a/src/content/docs/browser-rendering/platform/puppeteer.mdx +++ b/src/content/docs/browser-rendering/platform/puppeteer.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: concept title: Puppeteer +description: Learn how to use Puppeteer with Cloudflare Workers for browser automation. Access Puppeteer API, manage sessions, and optimize browser rendering. sidebar: order: 10 --- @@ -11,7 +12,7 @@ import { TabItem, Tabs } from "~/components"; Puppeteer typically connects to a local Chrome or Chromium browser using the DevTools port. Refer to the [Puppeteer API documentation on the `Puppeteer.connect()` method](https://pptr.dev/api/puppeteer.puppeteer.connect) for more information. -The Workers team forked a version of Puppeteer and patched it to connect to the Workers Browser Rendering API instead. The [changes between Workers Puppeteer fork and the Puppeteer core](https://github.com/cloudflare/puppeteer/blob/main/src/puppeteer-core.ts) are minimal. After connecting, the developers can then use the full [Puppeteer API](https://github.com/cloudflare/puppeteer/blob/main/docs/api/index.md) as they would on a standard setup. +The Workers team forked a version of Puppeteer and patched it to connect to the Workers Browser Rendering API instead. After connecting, the developers can then use the full [Puppeteer API](https://github.com/cloudflare/puppeteer/blob/main/docs/api/index.md) as they would on a standard setup. Our version is open sourced and can be found in [Cloudflare's fork of Puppeteer](https://github.com/cloudflare/puppeteer). The npm can be installed from [npmjs](https://www.npmjs.com/) as [@cloudflare/puppeteer](https://www.npmjs.com/package/@cloudflare/puppeteer): @@ -67,7 +68,7 @@ This script [launches](https://pptr.dev/api/puppeteer.puppeteernode.launch) the ### Keep Alive -If users omit the `browser.close()` statement, it will stay open, ready to be connected to again and [re-used](/browser-rendering/get-started/reuse-sessions/) but it will, by default, close automatically after 1 minute of inactivity. Users can optionally extend this idle time up to 10 minutes, by using the `keep_alive` option, set in milliseconds: +If users omit the `browser.close()` statement, it will stay open, ready to be connected to again and [re-used](/browser-rendering/workers-binding-api/reuse-sessions/) but it will, by default, close automatically after 1 minute of inactivity. Users can optionally extend this idle time up to 10 minutes, by using the `keep_alive` option, set in milliseconds: ```js const browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 }); diff --git a/src/content/docs/browser-rendering/platform/wrangler.mdx b/src/content/docs/browser-rendering/platform/wrangler.mdx index 91cd57c36cdca8..cb37c71e398976 100644 --- a/src/content/docs/browser-rendering/platform/wrangler.mdx +++ b/src/content/docs/browser-rendering/platform/wrangler.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: configuration title: Wrangler +description: Use Wrangler, a command-line tool, to deploy projects using Cloudflare's Workers Browser Rendering API. sidebar: order: 20 --- diff --git a/src/content/docs/browser-rendering/rest-api/api-reference.mdx b/src/content/docs/browser-rendering/rest-api/api-reference.mdx new file mode 100644 index 00000000000000..70d5c259e381f5 --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/api-reference.mdx @@ -0,0 +1,7 @@ +--- +pcx_content_type: navigation +title: Reference +external_link: /api/resources/browser_rendering/ +sidebar: + order: 8 +--- diff --git a/src/content/docs/browser-rendering/rest-api/content-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/content-endpoint.mdx new file mode 100644 index 00000000000000..7cd2942f0eb55d --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/content-endpoint.mdx @@ -0,0 +1,37 @@ +--- +pcx_content_type: how-to +title: Fetch HTML +sidebar: + order: 2 +--- + +The `/content` endpoint instructs the browser to navigate to a website and capture the fully rendered HTML of a page, including the `head` section, after JavaScript execution. This is ideal for capturing content from JavaScript-heavy or interactive websites. + +## Basic usage + +Go to `https://example.com` and return the rendered HTML. + +```bash +curl -X 'POST' 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/content' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer ' \ + -d '{"url": "https://example.com"}' +``` + +## Advanced usage + +Navigate to `https://cloudflare.com/` but block images and stylesheets from loading. Undesired requests can be blocked by resource type (`rejectResourceTypes`) or by using a regex pattern (`rejectRequestPattern`). The opposite can also be done, only allow requests that match `allowRequestPattern` or `allowResourceTypes`. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/content' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://cloudflare.com/", + "rejectResourceTypes": ["image"], + "rejectRequestPattern": ["/^.*\\.(css)"] + }' + +``` + +Many more options exist, like setting HTTP headers using `setExtraHTTPHeaders`, setting `cookies`, and using `gotoOptions` to control page load behaviour - check the endpoint [reference](/api/resources/browser_rendering/subresources/content/methods/create/) for all available parameters. diff --git a/src/content/docs/browser-rendering/rest-api/index.mdx b/src/content/docs/browser-rendering/rest-api/index.mdx new file mode 100644 index 00000000000000..bda3adf4671d03 --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/index.mdx @@ -0,0 +1,23 @@ +--- +pcx_content_type: navigation +title: REST API +sidebar: + order: 3 + group: + badge: Beta +--- + +The REST API is a RESTful interface that provides endpoints for common browser actions such as capturing screenshots, extracting HTML content, generating PDFs, and more. +The following are the available options: + +import { DirectoryListing } from "~/components"; + + + +Use the REST API when you need a fast, simple way to perform common browser tasks such as capturing screenshots, extracting HTML, or generating PDFs without writing complex scripts. If you require more advanced automation, custom workflows, or persistent browser sessions, the [Workers Binding API](/browser-rendering/workers-binding-api/) is the better choice. + +## Before you begin + +Before you begin, make sure you [create a custom API Token](/fundamentals/api/get-started/create-token/) with the following permissions: + +- `Browser Rendering - Edit` diff --git a/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx new file mode 100644 index 00000000000000..a08c009ab1895f --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/pdf-endpoint.mdx @@ -0,0 +1,89 @@ +--- +pcx_content_type: how-to +title: Render PDF +sidebar: + order: 5 +--- + +The `/pdf` endpoint instructs the browser to render the webpage as a PDF document. + +## Basic usage + +Navigate to `https://example.com/` and inject custom CSS and an external stylesheet. Then return the rendered page as a PDF. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/pdf' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://example.com/", + "addStyleTag": [ + { "content": "body { font-family: Arial; }" }, + { "url": "https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" } + ] + }' \ + --output "output.pdf" +``` + +## Advanced usage + +Navigate to `https://example.com`, first setting an additional HTTP request header and configuring the page size (`viewport`). Then, wait until there are no more than 2 network connections for at least 500 ms, or until the maximum timeout of 4500 ms is reached, before considering the page loaded and returning the rendered PDF document. + +The `goToOptions` parameter exposes most of [Puppeteer'd API](https://pptr.dev/api/puppeteer.gotooptions). + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/pdf' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://example.com/", + "setExtraHTTPHeaders": { + "X-Custom-Header": "value" + }, + "viewport": { + "width": 1200, + "height": 800 + }, + "gotoOptions": { + "waitUntil": "networkidle2", + "timeout": 45000 + } + }' \ + --output "advanced-output.pdf" +``` + +## Blocking images and styles when generating a PDF + +The options `rejectResourceTypes` and `rejectRequestPattern` can be used to block requests. The opposite can also be done, _only_ allow certain requests using `allowResourceTypes` and `allowRequestPattern`. + +```bash +curl -X POST https://api.cloudflare.com/client/v4/accounts//browser-rendering/pdf \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://cloudflare.com/", + "rejectResourceTypes": ["image"], + "rejectRequestPattern": ["/^.*\\.(css)"] +}' \ + --output "cloudflare.pdf" +``` + +## Generate PDF from custom HTML + +If you have HTML you'd like to generate a PDF from, the `html` option can be used. The option `addStyleTag` can be used to add custom styles. + +```bash +curl -X POST https://api.cloudflare.com/client/v4/accounts//browser-rendering/pdf \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "html": "Advanced Snapshot", + "addStyleTag": [ + { "content": "body { font-family: Arial; }" }, + { "url": "https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" } + ] +}' \ + --output "invoice.pdf" +``` + +Many more options exist, like setting HTTP credentials using `authenticate`, setting `cookies`, and using `gotoOptions` to control page load behaviour - check the endpoint [reference](/api/resources/browser_rendering/subresources/pdf/methods/create/) for all available parameters. diff --git a/src/content/docs/browser-rendering/rest-api/scrape-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/scrape-endpoint.mdx new file mode 100644 index 00000000000000..27c56c89d96b40 --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/scrape-endpoint.mdx @@ -0,0 +1,79 @@ +--- +pcx_content_type: how-to +title: Scrape HTML elements +sidebar: + order: 7 +--- + +The `/scrape` endpoint extracts structured data from specific elements on a webpage, returning details such as element dimensions and inner HTML. + +## Basic usage + +Go to `https://example.com` and extract metadata from all `h1` and `a` elements in the DOM. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/scrape' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://example.com/", + "elements": [{ + "selector": "h1" + }, + { + "selector": "a" + }] +}' +``` + +### JSON response + +```json title="json response" +{ + "success": true, + "result": [ + { + "results": [ + { + "attributes": [], + "height": 39, + "html": "Example Domain", + "left": 100, + "text": "Example Domain", + "top": 133.4375, + "width": 600 + } + ], + "selector": "h1" + }, + { + "results": [ + { + "attributes": [ + { "name": "href", "value": "https://www.iana.org/domains/example" } + ], + "height": 20, + "html": "More information...", + "left": 100, + "text": "More information...", + "top": 249.875, + "width": 142 + } + ], + "selector": "a" + } + ] +} +``` + +Many more options exist, like setting HTTP credentials using `authenticate`, setting `cookies`, and using `gotoOptions` to control page load behaviour - check the endpoint [reference](/api/resources/browser_rendering/subresources/scrape/methods/create/) for all available parameters. + +### Response fields + +- `results` _(array of objects)_ - Contains extracted data for each selector. + - `selector` _(string)_ - The CSS selector used. + - `results` _(array of objects)_ - List of extracted elements matching the selector. + - `text` _(string)_ - Inner text of the element. + - `html` _(string)_ - Inner HTML of the element. + - `attributes` _(array of objects)_ - List of extracted attributes such as `href` for links. + - `height`, `width`, `top`, `left` _(number)_ - Position and dimensions of the element. diff --git a/src/content/docs/browser-rendering/rest-api/screenshot-endpoint.mdx b/src/content/docs/browser-rendering/rest-api/screenshot-endpoint.mdx new file mode 100644 index 00000000000000..8002c210fef34f --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/screenshot-endpoint.mdx @@ -0,0 +1,79 @@ +--- +pcx_content_type: how-to +title: Capture screenshot +sidebar: + order: 3 +--- + +The `/screenshot` endpoint renders the webpage by processing its HTML and JavaScript, then captures a screenshot of the fully rendered page. + +## Basic usage + +Sets the HTML content of the page to `Hello World!` and then takes a screenshot. The option `omitBackground` hides the default white background and allows capturing screenshots with transparency. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/screenshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "html": "Hello World!", + "screenshotOptions": { + "omitBackground": true + } + }' \ + --output "screenshot.png" +``` + +For more options to control the final screenshot, like `clip`, `captureBeyondViewport`, `fullPage` and others, check the endpoint [reference](/api/resources/browser_rendering/subresources/screenshot/methods/create/). + +## Advanced usage + +Navigate to `https://cloudflare.com/`, changing the page size (`viewport`) and waiting until there are no active network connections (`waitUntil`) or up to a maximum of `4500ms` (`timeout`). Then take a `fullPage` screenshot. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/screenshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://cnn.com/", + "screenshotOptions": { + "fullPage": true + }, + "viewport": { + "width": 1280, + "height": 720 + }, + "gotoOptions": { + "waitUntil": "networkidle0", + "timeout": 45000 + } + }' \ + --output "advanced-screenshot.png" +``` + +## Customize CSS and embed custom JavaScript + +Instruct the browser to go to `https://example.com`, embed custom JavaScript (`addScriptTag`) and add extra styles (`addStyleTag`), both inline (`addStyleTag.content`) and by loading an external stylesheet (`addStyleTag.url`). + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/screenshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://example.com/", + "addScriptTag": [ + { "content": "document.querySelector(`h1`).innerText = `Hello World!!!`" } + ], + "addStyleTag": [ + { + "content": "div { background: linear-gradient(45deg, #2980b9 , #82e0aa ); }" + }, + { + "url": "https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" + } + ] + }' \ + --output "screenshot.png" +``` + +Many more options exist, like setting HTTP credentials using `authenticate`, setting `cookies`, and using `gotoOptions` to control page load behaviour - check the endpoint [reference](/api/resources/browser_rendering/subresources/screenshot/methods/create/) for all available parameters. diff --git a/src/content/docs/browser-rendering/rest-api/snapshot.mdx b/src/content/docs/browser-rendering/rest-api/snapshot.mdx new file mode 100644 index 00000000000000..165a1312c14387 --- /dev/null +++ b/src/content/docs/browser-rendering/rest-api/snapshot.mdx @@ -0,0 +1,84 @@ +--- +pcx_content_type: how-to +title: Take a webpage snapshot +sidebar: + order: 6 +--- + +The `/snapshot` endpoint captures both the HTML content and a screenshot of the webpage in one request. It returns the HTML as a text string and the screenshot as a Base64-encoded image. + +## Basic usage + +1. Go to `https://example.com/`. +2. Inject custom JavaScript. +3. Capture the rendered HTML. +4. Take a screenshot. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/snapshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "url": "https://example.com/", + "addScriptTag": [ + { "content": "document.body.innerHTML = \"Snapshot Page\";" } + ] + }' +``` + +### JSON response + +```json title="json response" +{ + "success": true, + "result": { + "screenshot": "Base64EncodedScreenshotString", + "content": "..." + } +} +``` + +## Advanced usage + +The `html` property in the JSON payload, it sets the html to `Advanced Snapshot` then does the following steps: + +1. Disable JavaScript. +2. Sets the screenshot to `fullPage`. +3. Changes the page size `(viewport)`. +4. Waits up to `30000ms` or until the `DOMContentLoaded` event fires. +5. Returns the rendered HTML content and a base-64 encoded screenshot of the page. + +```bash +curl -X POST 'https://api.cloudflare.com/client/v4/accounts//browser-rendering/snapshot' \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{ + "html": "Advanced Snapshot", + "setJavaScriptEnabled": false, + "screenshotOptions": { + "fullPage": true + }, + "viewport": { + "width": 1200, + "height": 800 + }, + "gotoOptions": { + "waitUntil": "domcontentloaded", + "timeout": 30000 + } + }' +``` + +### JSON response + +```json title="json response" +{ + "success": true, + "result": { + "screenshot": "AdvancedBase64Screenshot", + "content": "Advanced Snapshot" + } +} +``` + +Many more options exist, like setting HTTP credentials using `authenticate`, setting `cookies`, and using `gotoOptions` to control page load behaviour - check the endpoint [reference](/api/resources/browser_rendering/subresources/snapshot/) for all available parameters. diff --git a/src/content/docs/browser-rendering/get-started/browser-rendering-with-DO.mdx b/src/content/docs/browser-rendering/workers-binding-api/browser-rendering-with-DO.mdx similarity index 98% rename from src/content/docs/browser-rendering/get-started/browser-rendering-with-DO.mdx rename to src/content/docs/browser-rendering/workers-binding-api/browser-rendering-with-DO.mdx index 2468663d2116a4..779b94d5ffe9b3 100644 --- a/src/content/docs/browser-rendering/get-started/browser-rendering-with-DO.mdx +++ b/src/content/docs/browser-rendering/workers-binding-api/browser-rendering-with-DO.mdx @@ -6,7 +6,6 @@ products: - Durable Objects - R2 difficulty: Beginner -content_type: 📝 Tutorial updated: 2023-09-28 languages: - JavaScript @@ -173,7 +172,7 @@ export class Browser { await page.setViewport({ width: width[i], height: height[i] }); await page.goto("https://workers.cloudflare.com/"); const fileName = "screenshot_" + width[i] + "x" + height[i]; - const sc = await page.screenshot({ path: fileName + ".jpg" }); + const sc = await page.screenshot(); await this.env.BUCKET.put(folder + "/" + fileName + ".jpg", sc); } diff --git a/src/content/docs/browser-rendering/workers-binding-api/index.mdx b/src/content/docs/browser-rendering/workers-binding-api/index.mdx new file mode 100644 index 00000000000000..e90b1edc3feb37 --- /dev/null +++ b/src/content/docs/browser-rendering/workers-binding-api/index.mdx @@ -0,0 +1,14 @@ +--- +pcx_content_type: navigation +title: Workers Binding API +sidebar: + order: 2 +--- + +import { DirectoryListing } from "~/components"; + +The Workers Binding API allows you to execute advanced browser rendering scripts within Cloudflare Workers. It provides developers the flexibility to automate and control complex workflows and browser interactions. The following options are available for browser rendering tasks: + + + +Use the Workers Binding API when you need advanced browser automation, custom workflows, or complex interactions beyond basic rendering. For quick, one-off tasks like capturing screenshots or extracting HTML, the [REST API](/browser-rendering/rest-api/) is the simpler choice. diff --git a/src/content/docs/browser-rendering/get-started/reuse-sessions.mdx b/src/content/docs/browser-rendering/workers-binding-api/reuse-sessions.mdx similarity index 92% rename from src/content/docs/browser-rendering/get-started/reuse-sessions.mdx rename to src/content/docs/browser-rendering/workers-binding-api/reuse-sessions.mdx index 9c1f54f8d5ec77..e4e1d119ef86c9 100644 --- a/src/content/docs/browser-rendering/get-started/reuse-sessions.mdx +++ b/src/content/docs/browser-rendering/workers-binding-api/reuse-sessions.mdx @@ -7,7 +7,7 @@ sidebar: import { Render, PackageManagers, WranglerConfig } from "~/components"; -The best way to improve the performance of your browser rendering worker is to reuse sessions. One way to do that is via [Durable Objects](/browser-rendering/get-started/browser-rendering-with-do/), which allows you to keep a long running connection from a worker to a browser. Another way is to keep the browser open after you've finished with it, and connect to that session each time you have a new request. +The best way to improve the performance of your browser rendering Worker is to reuse sessions. One way to do that is via [Durable Objects](/browser-rendering/workers-binding-api/browser-rendering-with-do/), which allows you to keep a long running connection from a Worker to a browser. Another way is to keep the browser open after you've finished with it, and connect to that session each time you have a new request. In short, this entails using `browser.disconnect()` instead of `browser.close()`, and, if there are available sessions, using `puppeteer.connect(env.MY_BROWSER, sessionID)` instead of launching a new browser session. @@ -28,7 +28,7 @@ Create a new Worker project named `browser-worker` by running: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -51,6 +51,7 @@ compatibility_date = "2023-03-14" compatibility_flags = [ "nodejs_compat" ] browser = { binding = "MYBROWSER" } + ```
    diff --git a/src/content/docs/browser-rendering/get-started/screenshots.mdx b/src/content/docs/browser-rendering/workers-binding-api/screenshots.mdx similarity index 99% rename from src/content/docs/browser-rendering/get-started/screenshots.mdx rename to src/content/docs/browser-rendering/workers-binding-api/screenshots.mdx index 03ac0bcc3f3d2a..da009c3273c409 100644 --- a/src/content/docs/browser-rendering/get-started/screenshots.mdx +++ b/src/content/docs/browser-rendering/workers-binding-api/screenshots.mdx @@ -28,7 +28,7 @@ Create a new Worker project named `browser-worker` by running: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript / TypeScript", }} /> diff --git a/src/content/docs/byoip/address-maps/setup.mdx b/src/content/docs/byoip/address-maps/setup.mdx index c4ea246f0cd92e..d0325eb7a0a4c7 100644 --- a/src/content/docs/byoip/address-maps/setup.mdx +++ b/src/content/docs/byoip/address-maps/setup.mdx @@ -57,4 +57,25 @@ Setting up a default SNI is currently only supported via API. 1. If you have not already, create an address map. Refer to the [section above](#create-address-maps) or to the [Create Address Map](/api/resources/addressing/subresources/address_maps/methods/create/) API endpoint. 2. Take note of the address map `id`. If needed, you can use the [List Address Maps](/api/resources/addressing/subresources/address_maps/methods/list/) endpoint to get it. 3. Make sure you add the desired IPs to the address map. Cloudflare will respond with the default SNI on those IPs. Use the dashboard or refer to [Add An IP To An Address Map](/api/resources/addressing/subresources/address_maps/subresources/ips/methods/update/). -4. Configure the `default_sni` value on the address map created in step 1. Refer to the [Update Address Map](/api/resources/addressing/subresources/address_maps/methods/edit/) API endpoint for details. The default SNI can be any valid domain or subdomain owned by your account. \ No newline at end of file +4. Configure the `default_sni` value on the address map created in step 1. Refer to the [Update Address Map](/api/resources/addressing/subresources/address_maps/methods/edit/) API endpoint for details. The default SNI can be any valid domain or subdomain owned by your account. + +### Spectrum HTTPS applications + +Default SNI for Spectrum can only be created via API using the [Create Address Map](/api/resources/addressing/subresources/address_maps/methods/create/) endpoint. + +Do not include any membership in your command. Your API command should resemble the following: + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/addressing/address_maps \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + --header "Content-Type: application/json" \ + --data '{ + "description": "default_sni", + "default_sni": "sni.example.com", + "enabled": false, + "ips": [ + "192.0.0.1" + ], + "memberships": [] +}' +``` diff --git a/src/content/docs/cache/advanced-configuration/cache-reserve.mdx b/src/content/docs/cache/advanced-configuration/cache-reserve.mdx index 462912cbea0aa3..48196217fb0d97 100644 --- a/src/content/docs/cache/advanced-configuration/cache-reserve.mdx +++ b/src/content/docs/cache/advanced-configuration/cache-reserve.mdx @@ -124,7 +124,7 @@ Asset purges are free operations. Cache Reserve will be instantly purged along with edge cache when you send a purge by URL request. -Other purge methods, such as purge by tag, host, prefix, or purge everything will force an attempt to revalidate on the subsequent request for the Cache Reserve asset. Note that assets purged this way will still incur storage costs until their retention TTL expires. +Other purge methods, such as purge by tag, host, prefix, or purge everything will force an attempt to [revalidate](/cache/concepts/cache-responses/#revalidated) on the subsequent request for the Cache Reserve asset. Note that assets purged this way will still incur storage costs until their retention TTL expires. :::note Note this differs from the standard CDN's purge by tag, host, or prefix features which force a cache miss, requiring the origin to deliver the asset in full. diff --git a/src/content/docs/cache/how-to/cache-keys.mdx b/src/content/docs/cache/how-to/cache-keys.mdx index b9114660b5e201..69e77368c4e09c 100644 --- a/src/content/docs/cache/how-to/cache-keys.mdx +++ b/src/content/docs/cache/how-to/cache-keys.mdx @@ -120,7 +120,7 @@ Additionally, you cannot include the following headers: Host determines which host header to include in the Cache Key. * If `Use original host` (`resolved: false` in the API), Cloudflare includes the `Host` header in the HTTP request sent to the origin. -* If `Resolved host` (`resolved: true` in the API), Cloudflare includes the `Host` header that was resolved to get the `origin IP` for the request. The `Host` header may be different from the header actually sent if the [Cloudflare Resolve Override](/rules/page-rules/how-to/override-url-or-ip-address/) feature is used. +* If `Resolved host` (`resolved: true` in the API), Cloudflare includes the `Host` header that was resolved to get the `origin IP` for the request. The `Host` header may be different from the header actually sent if it has been changed with an [Origin Rule](/rules/origin-rules/features/#dns-record). ### Cookie diff --git a/src/content/docs/cache/how-to/purge-cache/purge-by-single-file.mdx b/src/content/docs/cache/how-to/purge-cache/purge-by-single-file.mdx index a916deb3a98335..70ee022618b0fd 100644 --- a/src/content/docs/cache/how-to/purge-cache/purge-by-single-file.mdx +++ b/src/content/docs/cache/how-to/purge-cache/purge-by-single-file.mdx @@ -37,7 +37,7 @@ Always use UTF-8 encoded URLs for single-file cache purges. Wildcards are not su 8. Select **Purge**. :::note -For information on how to use single-file purge to purge assets cached by a Workers fetch, refer to [Using Workers to purge](/workers/reference/how-the-cache-works/#single-file-purge-assets-cached-by-a-worker). +For information on how to use single-file purge to purge assets cached by a Workers fetch, refer to [Single file purge assets cached by a Worker](/workers/reference/how-the-cache-works/#single-file-purge-assets-cached-by-a-worker). ::: :::caution diff --git a/src/content/docs/cache/interaction-cloudflare-products/workers.mdx b/src/content/docs/cache/interaction-cloudflare-products/workers.mdx index f6926b8cd2d421..b3bb40676e16ce 100644 --- a/src/content/docs/cache/interaction-cloudflare-products/workers.mdx +++ b/src/content/docs/cache/interaction-cloudflare-products/workers.mdx @@ -17,6 +17,7 @@ The diagram below illustrates a common interaction flow between Workers and Cach 1. A User (a) Requests a URI, and this request is directed to a Worker. The Worker can then interact with the request, either requesting the content further upstream using (b) fetch() or sending a (f) Response back to the User. 2. If the content is cached, the Cache will send a (e) Response back to the Worker which can now interact with the response before sending a (f) Response back to the user. +3. When using cache rules with Workers, the cache rule should not be set based on the user URL/host (a). Instead, the rule must match the properties of the URL in the fetch() (b) request — such as headers, hostname, or URL path — otherwise, the rule will not be applied. Here are a few examples of how Workers can be used to customize cache behavior: diff --git a/src/content/docs/cache/performance-review/cache-analytics.mdx b/src/content/docs/cache/performance-review/cache-analytics.mdx index da446ee89d4dd2..a4dcee06f1dd9a 100644 --- a/src/content/docs/cache/performance-review/cache-analytics.mdx +++ b/src/content/docs/cache/performance-review/cache-analytics.mdx @@ -8,15 +8,25 @@ import { FeatureTable } from "~/components" Use Cache Analytics to improve site performance or reduce origin web server traffic. Cache Analytics helps determine if resources are missing from cache, expired, or ineligible for caching. Cache Analytics includes filter by hostname, list of top URLs that miss cache, and a query of up to three days of data. -First, determine whether to focus on Requests or Data Transfer. The default view is Requests, which helps with understanding performance because every cache miss degrades the speed of content delivery. Data Transfer helps with understanding cost because most hosting providers charge for every byte that leaves their network. +## Availability -You can toggle between Requests and Data Transfer while keeping other analytics filters enabled. + -For best practices related to Cache Analytics, refer to [Cache performance](/cache/performance-review/cache-performance/). +## Access Cache Analytics -## Availability +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account and domain. +2. Go to **Caching** > **Overview**. - +## Requests vs Data Transfer + +You can decide wheter to focus on **Requests** or **Data Transfer**: + +- **Requests** (default view) help assess performance, as each cache miss slows down content delivery. +- **Data Transfer** is useful for cost analysis, since most hosting providers charge for every byte that leaves their network. + +You can switch between these views while keeping other analytics filters applied. + +For best practices related to Cache Analytics, refer to [Cache performance](/cache/performance-review/cache-performance/). ## Add filters diff --git a/src/content/docs/cache/reference/etag-headers.mdx b/src/content/docs/cache/reference/etag-headers.mdx index 794b5ccf89761b..228c84d129267f 100644 --- a/src/content/docs/cache/reference/etag-headers.mdx +++ b/src/content/docs/cache/reference/etag-headers.mdx @@ -5,7 +5,7 @@ title: Using ETag Headers with Cloudflare --- -ETag headers identify whether the version of a resource cached in the browser is the same as the resource at the web server. A visitor's browser stores ETags. When a visitor revisits a site, the browser compares each ETag to the one it stored. Matching values cause a `304 Not-Modified HTTP` response that indicates the cached resource version is current. Cloudflare supports both strong and weak ETags configured at your origin web server. +ETag headers identify whether the version of a resource cached in the browser is the same as the resource at the origin web server. A visitor's browser stores ETags. When a visitor revisits a site, the browser compares each ETag to the one it stored. Matching values cause a `304 Not-Modified HTTP` response that indicates the cached resource version is current. Cloudflare supports both strong and weak ETags configured at your origin web server. ## Weak ETags diff --git a/src/content/docs/calls/datachannels.mdx b/src/content/docs/calls/datachannels.mdx index d65f9cb49cb9d2..113d4e0b266c41 100644 --- a/src/content/docs/calls/datachannels.mdx +++ b/src/content/docs/calls/datachannels.mdx @@ -3,10 +3,32 @@ pcx_content_type: get-started title: DataChannels sidebar: order: 8 - --- -Since Cloudflare Calls is basically a pub/sub server for WebRTC that can scale up to many subscribers per publisher, it's fit for arbitrary data besides media too. +DataChannels are a way to send arbitrary data, not just audio or video data, between client in low latency. DataChannels are useful for scenarios like chat, game state, or any other data that doesn't need to be encoded as audio or video but still needs to be sent between clients in real time. + +While it is possible to send audio and video over DataChannels, it's not optimal because audio and video transfer includes media specific optimizations that DataChannels do not have, such as simulcast, forward error correction, better caching across the Cloudflare network for retransmissions. + +```mermaid +graph LR + A[Publisher] -->|Arbitrary data| B[Cloudflare Calls SFU] + B -->|Arbitrary data| C@{ shape: procs, label: "Subscribers"} +``` + +DataChannels on Cloudflare Calls can scale up to many subscribers per publisher, there is no limit to the number of subscribers per publisher. + +### How to use DataChannels + +1. Create a two Calls sessions, one for the publisher and one for the subscribers. +2. Create a DataChannel by calling /datachannels/new with the location set to "local" and the dataChannelName set to the name of the DataChannel. +3. Create a DataChannel by calling /datachannels/new with the location set to "remote" and the sessionId set to the sessionId of the publisher. +4. Use the DataChannel to send data from the publisher to the subscribers. + +### Unidirectional DataChannels + +Cloudflare Calls SFU DataChannels are one way only. This means that you can only send data from the publisher to the subscribers. Subscribers cannot send data back to the publisher. While regular MediaStream WebRTC DataChannels are bidirectional, this introduces a problem for Cloudflare Calls because the SFU does not know which session to send the data back to. This is especially problematic for scenarios where you have multiple subscribers and you want to send data from the publisher to all subscribers at scale, such as distributing game score updates to all players in a multiplayer game. + +To send data in a bidirectional way, you can use two DataChannels, one for sending data from the publisher to the subscribers and one for sending data the opposite direction. ## Example diff --git a/src/content/docs/calls/https-api.mdx b/src/content/docs/calls/https-api.mdx index c3f7a0c5e74ca4..46af7056dce061 100644 --- a/src/content/docs/calls/https-api.mdx +++ b/src/content/docs/calls/https-api.mdx @@ -3,23 +3,22 @@ pcx_content_type: get-started title: Connection API sidebar: order: 5 - --- Cloudflare Calls simplifies the management of peer connections and media tracks through HTTPS API endpoints. These endpoints allow developers to efficiently manage sessions, add or remove tracks, and gather session information. ## API Endpoints -* **Create a New Session**: Initiates a new session on Cloudflare Calls, which can be modified with other endpoints below. - * `POST /apps/{appId}/sessions/new` -* **Add a New Track**: Adds a media track (audio or video) to an existing session. - * `POST /apps/{appId}/sessions/{sessionId}/tracks/new` -* **Renegotiate a Session**: Updates the session's negotiation state to accommodate new tracks or changes in the existing ones. - * `PUT /apps/{appId}/sessions/{sessionId}/renegotiate` -* **Close a Track**: Removes a specified track from the session. - * `PUT /apps/{appId}/sessions/{sessionId}/tracks/close` -* **Retrieve Session Information**: Fetches detailed information about a specific session. - * `GET /apps/{appId}/sessions/{sessionId}` +- **Create a New Session**: Initiates a new session on Cloudflare Calls, which can be modified with other endpoints below. + - `POST /apps/{appId}/sessions/new` +- **Add a New Track**: Adds a media track (audio or video) to an existing session. + - `POST /apps/{appId}/sessions/{sessionId}/tracks/new` +- **Renegotiate a Session**: Updates the session's negotiation state to accommodate new tracks or changes in the existing ones. + - `PUT /apps/{appId}/sessions/{sessionId}/renegotiate` +- **Close a Track**: Removes a specified track from the session. + - `PUT /apps/{appId}/sessions/{sessionId}/tracks/close` +- **Retrieve Session Information**: Fetches detailed information about a specific session. + - `GET /apps/{appId}/sessions/{sessionId}` [View full API and schema (OpenAPI format)](/calls/static/calls-api-2024-05-21.yaml) @@ -31,7 +30,7 @@ It is vital to manage App ID and its secret securely. While track and session ID Cloudflare Calls is designed to operate efficiently without the need for TURN servers in most scenarios, as Cloudflare exposes a publicly routable IP address for Calls. However, integrating a STUN server can be necessary for facilitating peer discovery and connectivity. -* **Cloudflare STUN Server**: `stun.cloudflare.com:3478` +- **Cloudflare STUN Server**: `stun.cloudflare.com:3478` Utilizing Cloudflare's STUN server can help the connection process for Calls applications. @@ -39,16 +38,54 @@ Utilizing Cloudflare's STUN server can help the connection process for Calls app This section provides an overview of the typical lifecycle of a simple session, focusing on audio-only applications. It illustrates how clients are notified by the backend server as new remote clients join or leave, incorporating video would introduce additional tracks and considerations into the session. -
    +```mermaid +sequenceDiagram + participant WA as WebRTC Agent + participant BS as Backend Server + participant CA as Calls API + + Note over BS: Client Joins + + WA->>BS: Request + BS->>CA: POST /sessions/new + CA->>BS: newSessionResponse + BS->>WA: Response + + WA->>BS: Request + BS->>CA: POST /sessions//tracks/new (Offer) + CA->>BS: newTracksResponse (Answer) + BS->>WA: Response + + WA-->>CA: ICE Connectivity Check + Note over WA: iceconnectionstatechange (connected) + WA-->>CA: DTLS Handshake + Note over WA: connectionstatechange (connected) + + WA<<->>CA: *Media Flow* + + Note over BS: Remote Client Joins -![Example Lifecycle](~/assets/images/calls/lifecycle-of-a-session.png) + WA->>BS: Request + BS->>CA: POST /sessions//tracks/new + CA->>BS: newTracksResponse (Offer) + BS->>WA: Response -
    + WA->>BS: Request + BS->>CA: PUT /sessions//renegotiate (Answer) + CA->>BS: OK + BS->>WA: Response -There is also a previously used, but now deprecated way to use the API illustrated below. If you are using this style please consider upgrading to the newer version illustrated above. + Note over BS: Remote Client Leaves -
    + WA->>BS: Request + BS->>CA: PUT /sessions//tracks/close + CA->>BS: closeTracksResponse + BS->>WA: Response -![Deprecated Lifecycle](~/assets/images/calls/deprecated-lifecycle-of-a-session.png) + Note over BS: Client Leaves -
    + WA->>BS: Request + BS->>CA: PUT /sessions//tracks/close + CA->>BS: closeTracksResponse + BS->>WA: Response +``` diff --git a/src/content/docs/calls/index.mdx b/src/content/docs/calls/index.mdx index 51d3275f92657f..403dfea95794ab 100644 --- a/src/content/docs/calls/index.mdx +++ b/src/content/docs/calls/index.mdx @@ -1,17 +1,14 @@ --- -title: Overview +title: Cloudflare Calls pcx_content_type: overview sidebar: order: 1 - badge: - text: Beta head: - tag: title - content: Cloudflare Calls - + content: Overview --- -import { Description, LinkButton } from "~/components" +import { Description, LinkButton } from "~/components"; @@ -23,5 +20,15 @@ Cloudflare Calls is infrastructure for real-time audio/video/data applications. Cloudflare Calls runs on [Cloudflare's global cloud network](https://www.cloudflare.com/network/) in hundreds of cities worldwide. - Get started Calls dashboard Orange Meets demo app - + + Get started + + + Calls dashboard + + + Orange Meets demo app + diff --git a/src/content/docs/calls/turn/faq.mdx b/src/content/docs/calls/turn/faq.mdx index 35485106995a42..3b0cad59cbc3f5 100644 --- a/src/content/docs/calls/turn/faq.mdx +++ b/src/content/docs/calls/turn/faq.mdx @@ -13,13 +13,27 @@ Cloudflare TURN pricing is based on the data sent from the Cloudflare edge to th Pricing for Cloudflare Calls TURN service is $0.05 per GB of data used. +Cloudflare's STUN service at `stun.cloudflare.com` is free and unlimited. + There is a free tier of 1,000 GB before any charges start. Cloudflare Calls billing appears as a single line item on your Cloudflare bill, covering both SFU and TURN. Traffic between Cloudflare Calls TURN and Cloudflare Calls SFU or Cloudflare Stream (WHIP/WHEP) does not incur any charges.
    -![TURN charging illustration](~/assets/images/calls/turn-charging.png) +```mermaid +--- +title: Cloudflare Calls TURN pricing +--- +flowchart LR + Client[TURN Client] + Server[TURN Server] + + Client -->|"Ingress (free)"| Server + Server -->|"Egress (charged)"| Client + + Server <-->|Not part of billing| PeerA[Peer A] +```
    @@ -120,12 +134,6 @@ Cloudflare Calls denies CreatePermission or ChannelBind requests if private IP r If you are a Cloudflare BYOIP customer and wish to connect to your BYOIP ranges with Calls TURN, please reach out to your account manager for further details. -### When I send packets to relayed address without using TURN, the packets don't arrive - -Cloudflare Calls denies CreatePermission or ChannelBind requests if private IP ranges (e.g loopback addresses, linklocal unicast or multicast blocks) or IP addresses that are part of [BYOIP](/byoip/) are used. - -If you are a Cloudflare BYOIP customer and wish to connect to your BYOIP ranges with Calls TURN, please reach out to your account manager for further details. - ### What will happen if TURN credentials expire while the TURN allocation is in use? Cloudflare Calls will immediately stop billing and recording usage for analytics. After a short delay, the connection will be disconnected. diff --git a/src/content/docs/calls/turn/generate-credentials.mdx b/src/content/docs/calls/turn/generate-credentials.mdx index b2ff149d21b9e8..c92140ffabda21 100644 --- a/src/content/docs/calls/turn/generate-credentials.mdx +++ b/src/content/docs/calls/turn/generate-credentials.mdx @@ -24,7 +24,7 @@ With a TURN key you can: You should generate short-lived credentials for each TURN user. In order to create credentials, you should have a back-end service that uses your TURN Token ID and API token to generate credentials. It will make an API call like this: ```bash -curl https://rtc.live.cloudflare.com/v1/turn/keys/$TURN_KEY_ID/credentials/generate \ +curl https://rtc.live.cloudflare.com/v1/turn/keys/$TURN_KEY_ID/credentials/generate-ice-servers \ --header "Authorization: Bearer $TURN_KEY_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{"ttl": 86400}' @@ -34,33 +34,43 @@ The JSON response below can then be passed on to your front-end application: ```json { - "iceServers": { - "urls": [ - "stun:stun.cloudflare.com:3478", - "turn:turn.cloudflare.com:3478?transport=udp", - "turn:turn.cloudflare.com:3478?transport=tcp", - "turns:turn.cloudflare.com:5349?transport=tcp" - ], - "username": "bc91b63e2b5d759f8eb9f3b58062439e0a0e15893d76317d833265ad08d6631099ce7c7087caabb31ad3e1c386424e3e", - "credential": "ebd71f1d3edbc2b0edae3cd5a6d82284aeb5c3b8fdaa9b8e3bf9cec683e0d45fe9f5b44e5145db3300f06c250a15b4a0" - } + "iceServers": [ + { + "urls": [ + "stun:stun.cloudflare.com:3478", + "stun:stun.cloudflare.com:53", + "turn:turn.cloudflare.com:3478?transport=udp", + "turn:turn.cloudflare.com:53?transport=udp", + "turn:turn.cloudflare.com:3478?transport=tcp", + "turn:turn.cloudflare.com:80?transport=tcp", + "turns:turn.cloudflare.com:5349?transport=tcp", + "turns:turn.cloudflare.com:443?transport=tcp" + ], + "username": "bc91b63e2b5d759f8eb9f3b58062439e0a0e15893d76317d833265ad08d6631099ce7c7087caabb31ad3e1c386424e3e", + "credential": "ebd71f1d3edbc2b0edae3cd5a6d82284aeb5c3b8fdaa9b8e3bf9cec683e0d45fe9f5b44e5145db3300f06c250a15b4a0" + } + ] } ``` -Use `username` and `credential` as follows when instantiating the `RTCPeerConnection` (note, `iceServers` is now an array): +Use `iceServers` as follows when instantiating the `RTCPeerConnection`: ```js const myPeerConnection = new RTCPeerConnection({ iceServers: [ { urls: [ - "stun:stun.cloudflare.com:3478", - "turn:turn.cloudflare.com:3478?transport=udp", - "turn:turn.cloudflare.com:3478?transport=tcp", - "turns:turn.cloudflare.com:5349?transport=tcp" + "stun:stun.cloudflare.com:3478", + "stun:stun.cloudflare.com:53", + "turn:turn.cloudflare.com:3478?transport=udp", + "turn:turn.cloudflare.com:53?transport=udp", + "turn:turn.cloudflare.com:3478?transport=tcp", + "turn:turn.cloudflare.com:80?transport=tcp", + "turns:turn.cloudflare.com:5349?transport=tcp", + "turns:turn.cloudflare.com:443?transport=tcp" ], - username: "REPLACE_WITH_USERNAME", - credential: "REPLACE_WITH_CREDENTIAL", + "username": "bc91b63e2b5d759f8eb9f3b58062439e0a0e15893d76317d833265ad08d6631099ce7c7087caabb31ad3e1c386424e3e", + "credential": "ebd71f1d3edbc2b0edae3cd5a6d82284aeb5c3b8fdaa9b8e3bf9cec683e0d45fe9f5b44e5145db3300f06c250a15b4a0" }, ], }); @@ -77,6 +87,6 @@ Short lived credentials can also be revoked before their TTL expires with a API ```bash curl --request POST \ -https://rtc.live.cloudflare.com/v1/turn/keys/$TURN_KEY_ID/credentials/username/$USERNAME/revoke \ +https://rtc.live.cloudflare.com/v1/turn/keys/$TURN_KEY_ID/credentials/$USERNAME/revoke \ --header "Authorization: Bearer $TURN_KEY_API_TOKEN" -``` +``` \ No newline at end of file diff --git a/src/content/docs/china-network/concepts/china-express.mdx b/src/content/docs/china-network/concepts/china-express.mdx deleted file mode 100644 index 98d94942c3f504..00000000000000 --- a/src/content/docs/china-network/concepts/china-express.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: China Express -pcx_content_type: concept -weight: 4 ---- - -# China Express - -:::note -China Express is an add-on to China Network and Zero Trust. -::: - -China Express is a suite of connectivity, performance offerings and professional services designed to simplify your global assets' deployment in China. China Express is provided by our partners including CMI, CBC, and JD Cloud. You may find the China Express offer with different scenarios: - -| Offer | Scenario | -| --------------------------------------------- | -------------------------------------------------------------------- | -| [Connectivity](#connectivity) | Higher performance of China Network CDN with dynamic content. | -| [Traffic Steering](#traffic-steering) | China Network CDN with specific requirements of Cloudflare features. | -| [WARP Connection](#warp-connection) | WARP client used in China. | -| [Magic WAN Connection](#magic-wan-connection) | Magic WAN used in China. | -| [ICP](#icp-services) | ICP services. | -| [MLPS](#mlps-services) | MLPS certification services. | -| [Travel SIM](#mlps-services) | Zero Trust clients in business traveling to China. | - -## Connectivity - -China Express Connectivity provides stable and reliable connections for dynamic content entering and exiting China, specifically beneficial for users' experience within the country. - -## Traffic Steering - -China Express Traffic Steering facilitates seamless dynamic traffic management, ensuring stable connectivity across multiple global origins. It can support more advanced scenarios of Cloudflare features with great performance, such as accessing Cloudflare R2 and Cloudflare Fonts in China. - -## WARP Connection - -WARP Connection is a verified solution for enabling WARP client access within China, allowing remote employees to maintain secure and consistent connections. - -## Magic WAN Connection - -Magic WAN Connection is a verified solution for enabling Magic WAN access within China, allowing in-office employees to maintain secure and reliable connectivity. - -## ICP services - -Internet Content Provider (ICP) service simplifies the complexities of acquiring an ICP for domains to operate compliantly within China. - -## MLPS services - -The Multi-Level Protection Scheme (MLPS) service add-on streamlines the certification process to secure the MLPS L3 certification for your applications. - -### Travel SIM - -Travel SIM offers temporary, seamless WARP access for individual employees traveling to China, ensuring uninterrupted connectivity during their visit. - ---- - -## General process - -### 1. Validate prerequisites - -Ensure that you have a Cloudflare [Enterprise plan](https://www.cloudflare.com/plans/enterprise/) and [China Network](/china-network/) if you want Connectivity, Traffic Steering, or other offer. Licenses of WARP and Magic WAN are required for WARP Connection or Magic WAN Connection. - -### 2. Sign contract - -Contact your Cloudflare account team. They will assist you to sign a contract with the China Express partner. - -### 3. Deploy China Express - -Our China Express partner will assist you to deploy China Express. diff --git a/src/content/docs/china-network/concepts/global-acceleration.mdx b/src/content/docs/china-network/concepts/global-acceleration.mdx new file mode 100644 index 00000000000000..074ca76b3bd90e --- /dev/null +++ b/src/content/docs/china-network/concepts/global-acceleration.mdx @@ -0,0 +1,60 @@ +--- +title: Global Acceleration +pcx_content_type: concept +weight: 4 +--- + +:::note +Global Acceleration a service offering that can be an add-on to China Network and also extend Zero Trust services into China. +::: + +Global Acceleration is a suite of connectivity, performance offerings and professional services designed to simplify your global assets' deployment in China. Global Acceleration is provided by our partners including CMI, CBC, and JD Cloud. Depending on what fits your needs best, Global Acceleration can support the following scenarios: + +| Offer | Scenario | +| ----------------------------------------------------- | ------------------------------------------------------------- | +| [CDN Global Acceleration](#cdn-global-acceleration) | Higher performance of China Network CDN with dynamic content. | +| [WARP Global Acceleration](#warp-global-acceleration) | WARP client used in China. | +| [Magic WAN Connection](#mwan-global-acceleration) | Magic WAN used in China. | +| [ICP](#icp-services) | ICP services. | +| [MLPS](#mlps-services) | MLPS certification services. | +| [Travel SIM](#travel-sim) | Zero Trust clients in business traveling to China. | + +## CDN Global Acceleration + +CDN Global Acceleration provides stable and reliable connections for dynamic content entering and exiting China, specifically beneficial for users' experience within the country. Additionally, this service can help facilitate seamless dynamic traffic management, ensuring stable connectivity across multiple global origins. It can support more advanced scenarios of Cloudflare features with great performance, such as accessing Cloudflare R2 and Cloudflare Fonts in China. + +## WARP Global Acceleration + +WARP Global Acceleration is a verified solution for enabling WARP client access within China, allowing remote employees to maintain secure and consistent connections. + +## Magic WAN Global Acceleration + +Magic WAN Global Acceleration is a verified solution for enabling Magic WAN access within China, allowing in-office employees to maintain secure and reliable connectivity. + +## ICP services + +Internet Content Provider (ICP) service simplifies the complexities of acquiring an ICP for domains to operate compliantly within China. + +## MLPS services + +The Multi-Level Protection Scheme (MLPS) service add-on streamlines the certification process to secure the MLPS L3 certification for your applications. + +### Travel SIM + +Travel SIM offers temporary, seamless WARP access for individual employees traveling to China, ensuring uninterrupted connectivity during their visit. + +--- + +## General process + +### 1. Validate prerequisites + +Ensure that you have a Cloudflare [Enterprise plan](https://www.cloudflare.com/plans/enterprise/) and [China Network](/china-network/) if you want CDN Global Acceleration or other offers. Licenses of WARP and Magic WAN are required for WARP Connection or Magic WAN Global Acceleration. + +### 2. Sign contract + +Contact your Cloudflare account team. They will assist you with contracting with our local China partners. + +### 3. Deploy Global Acceleration + +Our local China partners will assist you to deploy Global Acceleration. diff --git a/src/content/docs/china-network/index.mdx b/src/content/docs/china-network/index.mdx index 068bfb790e6df3..7686f5694d1357 100644 --- a/src/content/docs/china-network/index.mdx +++ b/src/content/docs/china-network/index.mdx @@ -8,7 +8,7 @@ head: content: Overview --- -import { Stream } from "~/components" +import { CardGrid, LinkCard } from "~/components" The [Cloudflare China Network](https://www.cloudflare.com/china-network/) is a package of selected Cloudflare's performance and security products running on data centers located in mainland China and operated by Cloudflare's partner JD Cloud. @@ -22,12 +22,7 @@ The Cloudflare China Network provides: - An unified experience for managing network traffic and security posture. You can manage all configurations on the same dashboard. - The same customer support capabilities as Cloudflare's global network. You may also have access to premium service and local language support. - [In-China Authoritative DNS and in-China nameservers](/china-network/concepts/china-dns/) to improve the Time to First Byte (TTFB) performance. -- [China Express](/china-network/concepts/china-express) is a suite of connectivity, performance offerings and professional services designed to simplify your global assets' deployment in China. - -### Video Introduction - - - +- [Global Acceleration](/china-network/concepts/global-acceleration/) is a suite of connectivity, performance offerings and professional services designed to simplify your global assets' deployment in China. ## Availability diff --git a/src/content/docs/china-network/videos.mdx b/src/content/docs/china-network/videos.mdx new file mode 100644 index 00000000000000..a80d8d12201307 --- /dev/null +++ b/src/content/docs/china-network/videos.mdx @@ -0,0 +1,16 @@ +--- +pcx_content_type: navigation +title: Videos +sidebar: + order: 4 +--- + +import { CardGrid, LinkCard } from "~/components"; + + + + diff --git a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/wpengine.mdx b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/wpengine.mdx index ba9a2822cfafb0..e0d2db30ee82d5 100644 --- a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/wpengine.mdx +++ b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/wpengine.mdx @@ -44,6 +44,14 @@ If you cannot activate your domain using [proxied DNS records](/dns/proxy-status +## Zone hold + +If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](/fundamentals/setup/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to WP Engine. WP Engine would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.` + +To successfully activate the custom hostname on WP Engine, the owner of the zone needs to [temporarily release the hold](/fundamentals/setup/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to WP Engine, only the subfeature titled `Also prevent Subdomains` needs to be temporarily disabled. + +Once the zone hold is temporarily disabled, follow WP Engine's instructions to refresh the custom hostname and it should activate. + ## Additional support diff --git a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls.mdx b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls.mdx index 8affd8a79afbcf..c6dbaca108e59b 100644 --- a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls.mdx +++ b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls.mdx @@ -53,20 +53,19 @@ While TLS 1.3 is the most recent and secure version, it is not supported by some ## Cipher suites -For security and regulatory reasons, you may want to only allow connections from certain cipher suites. Cloudflare provides recommended values and full cipher suite reference in our [Cipher suites documentation](/ssl/edge-certificates/additional-options/cipher-suites/). +For security and regulatory reasons, you may want to only allow connections from certain cipher suites. Cloudflare provides recommended values and full cipher suite reference in our [Cipher suites documentation](/ssl/edge-certificates/additional-options/cipher-suites/#resources). -
    - -Refer to [Edit zone setting](/api/resources/zones/subresources/settings/methods/edit/) and use `ciphers` as the setting name in the URI path. +
    +Refer to [Customize cipher suites - SSL/TLS](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/).
    -Refer to [SSL properties of a custom hostname](/api/resources/custom_hostnames/methods/edit/). +In the API documentation, refer to [SSL properties of a custom hostname](/api/resources/custom_hostnames/methods/edit/). diff --git a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin.mdx b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin.mdx index 2fc99d5f22e669..ca6c74277874f6 100644 --- a/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin.mdx +++ b/src/content/docs/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin.mdx @@ -54,6 +54,8 @@ Choose how your custom hostname populates the SNI value with SNI rewrites: * Currently, SNI Rewrite is not supported for wildcard custom hostnames. Subdomains covered by a wildcard custom hostname send the custom origin server name as the SNI value. +* In the [O2O context](/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) (when requests are originating from a proxied hostname on a zone also on Cloudflare), changing the SNI value to use host header is currently not supported. + * SNI overrides defined in an [Origin Rule](/rules/origin-rules/) will take precedence over SNI rewrites. * SNI Rewrite usage is subject to the [Service-Specific Terms](https://www.cloudflare.com/service-specific-terms-application-services/#ssl-for-saas-terms). diff --git a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets.mdx b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets.mdx index 4412286ed8ff5e..8314f3b05fe515 100644 --- a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets.mdx +++ b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets.mdx @@ -3,25 +3,33 @@ pcx_content_type: concept title: Static assets description: Host static assets on Cloudflare's global network and deliver faster load times worldwide with Workers for Platforms. --- + +import { Aside } from "@astrojs/starlight/components"; + Workers for Platforms lets you deploy front-end applications at scale. By hosting static assets on Cloudflare's global network, you can deliver faster load times worldwide and eliminate the need for external infrastructure. You can also combine these static assets with dynamic logic in Cloudflare Workers, providing a full-stack experience for your customers. ### What you can build #### Static sites + Host and serve HTML, CSS, JavaScript, and media files directly from Cloudflare's network, ensuring fast loading times worldwide. This is ideal for blogs, landing pages, and documentation sites. #### Full-stack applications + Combine asset hosting with Cloudflare Workers to power dynamic, interactive applications. Store and retrieve data using Cloudflare KV, D1, and R2 Storage, allowing you to serve both front-end assets and backend logic from a single Worker. ### Benefits #### Global caching for faster performance + Cloudflare automatically caches static assets at data centers worldwide, reducing latency and improving load times by up to 2x for users everywhere. #### Scalability without infrastructure management + Your applications scale automatically to handle high traffic without requiring you to provision or manage infrastructure. Cloudflare dynamically adjusts to demand in real time. #### Unified deployment for static and dynamic content + Deploy front-end assets alongside server-side logic, all within Cloudflare Workers. This eliminates the need for a separate hosting provider and ensures a streamlined deployment process. --- @@ -45,22 +53,29 @@ After these steps are completed, the User Worker's static assets will be live on Before sending any file data, you need to tell Cloudflare which files you intend to upload. That list of files is called a manifest. Each item in the manifest includes: -* A file path (for example, `"/index.html"` or `"/assets/logo.png"`) -* A hash (32-hex characters) representing the file contents -* The file size in bytes +- A file path (for example, `"/index.html"` or `"/assets/logo.png"`) +- A hash (32-hex characters) representing the file contents +- The file size in bytes + + #### Example manifest (JSON) ```json { - "/index.html": { - "hash": "08f1dfda4574284ab3c21666d1ee8c7d4", - "size": 1234 - }, - "/styles.css": { - "hash": "36b8be012ee77df5f269b11b975611d3", - "size": 5678 - } + "/index.html": { + "hash": "08f1dfda4574284ab3c21666d1ee8c7d4", + "size": 1234 + }, + "/styles.css": { + "hash": "36b8be012ee77df5f269b11b975611d3", + "size": 5678 + } } ``` @@ -71,8 +86,9 @@ POST /accounts/{account_id}/workers/dispatch/namespaces/{namespace}/scripts/{scr ``` Path Parameters: -* `namespace`: Name of the Workers for Platforms dispatch namespace -* `script_name`: Name of the User Worker + +- `namespace`: Name of the Workers for Platforms dispatch namespace +- `script_name`: Name of the User Worker In the request body, include a JSON object listing each file path along with its hash and size. This helps Cloudflare identify which files you intend to upload and allows Cloudflare to check if any of them are already stored. @@ -105,8 +121,8 @@ You can compute a SHA-256 digest of the file contents, then truncate or otherwis If all the files are already stored on Cloudflare, the response will only return the JWT token. If new or updated files are needed, the response will return: -* `jwt`: An upload token (valid for 1 hour) which will be used in the API request to upload the file contents (Step 2). -* `buckets`: An array of file-hash groups indicating which files to upload together. Files that have been recently uploaded won't appear in buckets, since Cloudflare already has them. +- `jwt`: An upload token (valid for 1 hour) which will be used in the API request to upload the file contents (Step 2). +- `buckets`: An array of file-hash groups indicating which files to upload together. Files that have been recently uploaded won't appear in buckets, since Cloudflare already has them. :::note This step alone does not store files on Cloudflare. You must upload the actual file data in the next step. @@ -118,6 +134,10 @@ If the response to the Upload Session API returns `buckets`, that means you have Use the [Workers Assets Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/assets/subresources/upload/) to transmit the raw file bytes in base64-encoded format for any missing or changed files. Once uploaded, Cloudflare will store these files so they can then be attached to a User Worker. + + #### API Request Authentication Unlike most Cloudflare API calls that use an account-wide API token in the Authorization header, uploading file contents requires using the short-lived JWT token returned in the `jwt` field of the `assets-upload-session` response. @@ -131,10 +151,11 @@ Authorization: Bearer This token is valid for one hour and must be supplied for each upload request to the Workers Assets Upload API. #### File fields (multipart/form-data) + You must send the files as multipart/form-data with base64-encoded content: -* Field name: The file hash (for example, `36b8be012ee77df5f269b11b975611d3`) -* Field value: A Base64-encoded string of the file's raw bytes +- Field name: The file hash (for example, `36b8be012ee77df5f269b11b975611d3`) +- Field value: A Base64-encoded string of the file's raw bytes #### Example: Uploading multiple files within a single bucket @@ -159,9 +180,9 @@ curl -X POST \ -F "36b8be012ee77df5f269b11b975611d3=" ``` -* `` is the token from step 1's assets-upload-session response -* `` is the Base64-encoded content of index.html -* `` is the Base64-encoded content of styles.css +- `` is the token from step 1's assets-upload-session response +- `` is the Base64-encoded content of index.html +- `` is the Base64-encoded content of styles.css If you have multiple buckets (for example, `[["hashA"], ["hashB"], ["hashC"]]`), you might need to repeat this process for each bucket, making one request per bucket group. @@ -169,12 +190,12 @@ Once every file in the manifest has been uploaded, a status code of `201` will b ```json { - "success": true, - "errors": [], - "messages": [], - "result": { - "jwt": "" - } + "success": true, + "errors": [], + "messages": [], + "result": { + "jwt": "" + } } ``` @@ -206,9 +227,9 @@ curl -X PUT \ -F 'index.js=@/path/to/index.js;type=application/javascript' ``` -* The `"jwt": ""` links the newly uploaded files to the Worker -* Including "html_handling" (or other fields under "config") is optional and can customize how static files are served -* If the user's Worker code has not changed, you can omit the code file or re-upload the same index.js +- The `"jwt": ""` links the newly uploaded files to the Worker +- Including "html_handling" (or other fields under "config") is optional and can customize how static files are served +- If the user's Worker code has not changed, you can omit the code file or re-upload the same index.js Once this PUT request succeeds, the files are served on the User Worker. Requests routed to that Worker will serve the new or updated static assets. @@ -236,8 +257,8 @@ binding = "ASSETS" -* `directory`: The local folder containing your static files (for example, `./public`). -* `binding`: The binding name used to reference these assets within your Worker code. +- `directory`: The local folder containing your static files (for example, `./public`). +- `binding`: The binding name used to reference these assets within your Worker code. ### 1. Organize your files @@ -247,11 +268,12 @@ If you need to reference these files in your Worker script to serve them dynamic ```js export default { - async fetch(request, env, ctx) { - return env.ASSETS.fetch(request); - }, + async fetch(request, env, ctx) { + return env.ASSETS.fetch(request); + }, }; ``` + ### 2. Deploy the User Worker with the static assets Run Wrangler to publish both your Worker code and the static assets: @@ -260,4 +282,4 @@ Run Wrangler to publish both your Worker code and the static assets: npx wrangler deploy --name --dispatch-namespace ``` -Wrangler will automatically detect your static files, bundle them, and upload them to Cloudflare along with your Worker code. \ No newline at end of file +Wrangler will automatically detect your static files, bundle them, and upload them to Cloudflare along with your Worker code. diff --git a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/demos.mdx b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/demos.mdx index fff3e0f1dc6167..71542466758430 100644 --- a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/demos.mdx +++ b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/demos.mdx @@ -1,12 +1,12 @@ --- pcx_content_type: navigation -title: Demos +title: Demos and architectures sidebar: order: 8 --- -import { ExternalResources, GlossaryTooltip } from "~/components" +import { ExternalResources, GlossaryTooltip, ResourcesBySelector } from "~/components" Learn how you can use Workers for Platforms within your existing architecture. @@ -15,3 +15,9 @@ Learn how you can use Workers for Platforms within your existing architecture. Explore the following demo applications for Workers for Platforms. + +## Reference architectures + +Explore the following reference architectures that use Workers: + + diff --git a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/configuration.mdx b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/configuration.mdx index 7750a40cacd968..a0b44b65907f53 100644 --- a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/configuration.mdx +++ b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/configuration.mdx @@ -102,7 +102,7 @@ Create your dynamic dispatch Worker. In this example, the dispatch Worker is cal product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -135,6 +135,7 @@ export default { }, }; ``` + This example shows a simple dynamic dispatch Worker that routes all requests to a single user Worker. For more advanced routing patterns, you could route based on hostname, path, custom metadata, or other request properties. Deploy your dynamic dispatch Worker: diff --git a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/developing-with-wrangler.mdx b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/developing-with-wrangler.mdx index 5b886dfa8728cc..2160adc63c0a79 100644 --- a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/developing-with-wrangler.mdx +++ b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/get-started/developing-with-wrangler.mdx @@ -27,7 +27,7 @@ Support for Workers for Platforms with `wrangler dev` in local mode is experimen product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -77,7 +77,7 @@ dispatch_namespace = "my-namespace" product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -111,8 +111,6 @@ export default { Update the Wrangler file for dispatch-worker and add the dispatch namespace binding: - - ```toml @@ -139,7 +137,7 @@ outbound = { service = "outbound-worker", parameters = ["paramCustomerName"] } product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/index.mdx b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/index.mdx index b0c035b66c23bd..b64d3c3cd0d4d5 100644 --- a/src/content/docs/cloudflare-for-platforms/workers-for-platforms/index.mdx +++ b/src/content/docs/cloudflare-for-platforms/workers-for-platforms/index.mdx @@ -24,18 +24,18 @@ Workers for Platforms is built on top of [Cloudflare Workers](/workers/). Worker

    - + *** ## Features -Learn how to set up Workers for Platforms. +Learn how to set up Workers for Platforms. -Learn about Workers for Platforms architecture. +Learn about Workers for Platforms architecture. *** diff --git a/src/content/docs/cloudflare-one/account-limits.mdx b/src/content/docs/cloudflare-one/account-limits.mdx index 9871c3c880f082..102f186b6569d9 100644 --- a/src/content/docs/cloudflare-one/account-limits.mdx +++ b/src/content/docs/cloudflare-one/account-limits.mdx @@ -35,6 +35,7 @@ This page lists the default account limits for rules, applications, fields, and | Egress policies per account | 500 | | Resolver policies per account | 500 | | DNS locations | 250 | +| Source IP CIDRs per DNS location | 1,500 | | Concurrent streams for HTTP/2 connections | 256 | | Proxy endpoints | 500 | | Source IP CIDRs per proxy endpoint | 2,000 | @@ -64,12 +65,10 @@ This page lists the default account limits for rules, applications, fields, and ## Digital Experience Monitoring (DEX) -| Feature | Limit | -| --------------------------------------------- | ----------------------------------------------------------------- | -| Tests per account | Free Plan: 10,
    Pro & Business Plans: 30,
    Enterprise: 50 | -| Remote captures per day (Free users) | 100 | -| Remote captures per day (Pay-as-you-go users) | 200 | -| Remote captures per day (Enterprise users) | 800 | +| Feature | Limit | +| ----------------------- | ------------------------------------------------------------------------------------------ | +| DEX Tests per account | Zero Trust Free: 10
    Zero Trust Standard: 30
    Zero Trust Enterprise: 50
    | +| Remote captures per day | Zero Trust Free: 100
    Zero Trust Standard: 200
    Zero Trust Enterprise: 800
    | ## Certificates diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/access-group.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/access-group.mdx index 12ec3662c3b016..3c39aa06531028 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/access-group.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/access-group.mdx @@ -1,20 +1,17 @@ --- type: example summary: Use a pre-existing rule group. -tags: - - Rule group title: Rule group pcx_content_type: example sidebar: order: 4 description: Use a pre-existing rule group. - --- ```json { - "group": { - "id": "aa0a4aab-672b-4bdb-bc33-a59f1130a11f" - } + "group": { + "id": "aa0a4aab-672b-4bdb-bc33-a59f1130a11f" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/any-service-token.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/any-service-token.mdx index 35f51d16168c0e..d96d19cfe9c423 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/any-service-token.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/any-service-token.mdx @@ -2,21 +2,18 @@ type: example summary: The request will need to present the headers for any service token created for this account. -tags: - - Any valid service token title: Any valid service token pcx_content_type: example sidebar: order: 4 description: The request will need to present the headers for any service token created for this account. - --- The request will need to present the headers for any service token created for this account ```json { - "any_valid_service_token": {} + "any_valid_service_token": {} } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/authentication-method.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/authentication-method.mdx index 3e3f465c4eface..90e41b2c4b725f 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/authentication-method.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/authentication-method.mdx @@ -1,20 +1,17 @@ --- type: example summary: Allow access based on the "amr" identifier. -tags: - - Authentication Method title: Authentication method pcx_content_type: example sidebar: order: 4 description: Allow access based on the "amr" identifier. - --- ```json { - "auth_method": { - "auth_method": "hwk" - } + "auth_method": { + "auth_method": "hwk" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/common-name.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/common-name.mdx index bc0ba9723d14aa..77d8db31ea214b 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/common-name.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/common-name.mdx @@ -2,21 +2,18 @@ type: example summary: The request will need to present a valid certificate with an expected common name. -tags: - - Common name title: Common name pcx_content_type: example sidebar: order: 4 description: The request will need to present a valid certificate with an expected common name. - --- ```json { - "common_name": { - "common_name": "james@example.com" - } + "common_name": { + "common_name": "james@example.com" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/country-code.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/country-code.mdx index 8d53041ab7b7e4..1d69829dca0838 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/country-code.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/country-code.mdx @@ -1,20 +1,17 @@ --- type: example summary: Allow a specific country. -tags: - - Country Code title: Country Code pcx_content_type: example sidebar: order: 4 description: Allow a specific country. - --- ```json { - "geo": { - "country_code": "US" - } + "geo": { + "country_code": "US" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email-domain.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email-domain.mdx index dc80389e2b5722..63ee5d6dfc24e5 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email-domain.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email-domain.mdx @@ -1,20 +1,17 @@ --- type: example summary: Allow an entire email domain. -tags: - - Email domain title: Email domain pcx_content_type: example sidebar: order: 4 description: Allow an entire email domain. - --- ```json { - "email_domain": { - "domain": "cloudflare.com" - } + "email_domain": { + "domain": "cloudflare.com" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email.mdx index dd06a7db4f7b0f..e6f5d3b7c7c9a6 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/email.mdx @@ -1,20 +1,17 @@ --- type: example summary: Allow a specific email address. -tags: - - Email title: Email pcx_content_type: example sidebar: order: 4 description: Allow a specific email address. - --- ```json { - "email": { - "email": "james@example.com" - } + "email": { + "email": "james@example.com" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/entra-group.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/entra-group.mdx index 0bfd23afa61a5f..15fc60dab496b7 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/entra-group.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/entra-group.mdx @@ -1,8 +1,6 @@ --- type: example summary: Allow members of a Microsoft Entra group. The ID is the group UUID (`id`) in Microsoft Entra ID. -tags: - - Microsoft Entra Group title: Microsoft Entra Group pcx_content_type: example sidebar: diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/everyone.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/everyone.mdx index 74dd0cff432468..b35cdab96372df 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/everyone.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/everyone.mdx @@ -1,18 +1,15 @@ --- type: example summary: Allow anyone to log in. -tags: - - Everyone title: Everyone pcx_content_type: example sidebar: order: 4 description: Allow anyone to log in. - --- ```json { - "everyone": {} + "everyone": {} } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/github-org.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/github-org.mdx index ee43dba8acc0e2..b6fac385d91067 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/github-org.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/github-org.mdx @@ -1,8 +1,6 @@ --- type: example summary: Allow members of a specific GitHub organization. -tags: - - GitHub Organization title: GitHub™ Organization pcx_content_type: example sidebar: diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/gsuite-group.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/gsuite-group.mdx index 6879330cf99b38..6407ec064f42a3 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/gsuite-group.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/gsuite-group.mdx @@ -1,8 +1,6 @@ --- type: example summary: Allow members of a specific G Suite group. -tags: - - G Suite Group title: G Suite Group pcx_content_type: example sidebar: diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/ip-range.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/ip-range.mdx index 5f5f0f00ed90ee..b5fd679eeda17b 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/ip-range.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/ip-range.mdx @@ -1,20 +1,17 @@ --- type: example summary: Allow an IP range. -tags: - - IP range title: IP range pcx_content_type: example sidebar: order: 4 description: Allow an IP range. - --- ```json { - "ip": { - "ip": "127.0.0.1/32" - } + "ip": { + "ip": "127.0.0.1/32" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/mtls-certificate.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/mtls-certificate.mdx index 2535e33ae76419..58565971d8c779 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/mtls-certificate.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/mtls-certificate.mdx @@ -1,18 +1,15 @@ --- type: example summary: The request will need to present a valid certificate. -tags: - - mTLS certificate title: mTLS certificate pcx_content_type: example sidebar: order: 4 description: The request will need to present a valid certificate. - --- ```json { - "certificate": {} + "certificate": {} } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/okta-group.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/okta-group.mdx index d51cd6ca3cea3a..943ab43e2223a7 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/okta-group.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/okta-group.mdx @@ -1,8 +1,6 @@ --- type: example summary: Allow members of an Okta Group. -tags: - - Okta Group title: Okta Group pcx_content_type: example sidebar: diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/saml-attribute.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/saml-attribute.mdx index 102cd109de8278..5a4b15abbf4453 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/saml-attribute.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/saml-attribute.mdx @@ -1,22 +1,19 @@ --- type: example summary: Allow users with specific SAML attributes. -tags: - - SAML Attribute title: SAML Attribute pcx_content_type: example sidebar: order: 4 description: Allow users with specific SAML attributes. - --- ```json { - "saml": { - "attribute_name": "group", - "attribute_value": "admins", - "identity_provider_id": "ca298b82-93b5-41bf-bc2d-10493f09b761" - } + "saml": { + "attribute_name": "group", + "attribute_value": "admins", + "identity_provider_id": "ca298b82-93b5-41bf-bc2d-10493f09b761" + } } ``` diff --git a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/service-token.mdx b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/service-token.mdx index 5437ba78b56790..2b449f6b54a7f9 100644 --- a/src/content/docs/cloudflare-one/api-terraform/access-api-examples/service-token.mdx +++ b/src/content/docs/cloudflare-one/api-terraform/access-api-examples/service-token.mdx @@ -1,20 +1,17 @@ --- type: example summary: The request will need to present the correct service token headers. -tags: - - Service token title: Service token pcx_content_type: example sidebar: order: 4 description: The request will need to present the correct service token headers. - --- ```json { - "service_token": { - "token_id": "e9808c3a-705c-4afc-a507-6e4b083ff399" - } + "service_token": { + "token_id": "e9808c3a-705c-4afc-a507-6e4b083ff399" + } } ``` diff --git a/src/content/docs/cloudflare-one/applications/casb/casb-integrations/aws-s3.mdx b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/aws-s3.mdx index 10b2f8d713f209..28ae82e64f17ef 100644 --- a/src/content/docs/cloudflare-one/applications/casb/casb-integrations/aws-s3.mdx +++ b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/aws-s3.mdx @@ -8,7 +8,10 @@ import { Render } from "~/components"; ## Integration prerequisites diff --git a/src/content/docs/cloudflare-one/applications/casb/casb-integrations/gcp-cloud-storage.mdx b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/gcp-cloud-storage.mdx new file mode 100644 index 00000000000000..6783305cd2e95b --- /dev/null +++ b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/gcp-cloud-storage.mdx @@ -0,0 +1,98 @@ +--- +pcx_content_type: reference +title: Google Cloud Platform (GCP) Cloud Storage +rss: file +--- + +import { Render } from "~/components"; + + + +## Integration prerequisites + +- A GCP account using Cloud Storage. +- For initial setup, access to the GCP account with permission to create a new Service Account with the scopes listed below. + +## Integration permissions + +For the GCP Cloud Storage integration to function, Cloudflare CASB requires the following access scopes via a Service Account: + +- `roles/viewer` +- `roles/storage.admin` + +These permissions follow the principle of least privilege to ensure that only the minimum required access is granted. To learn more about each permission scope, refer to the [GCP IAM roles for Cloud Storage documentation](https://cloud.google.com/storage/docs/access-control/iam-roles). + +## Compute account + +You can connect a GCP compute account to your CASB integration to perform [Data Loss Prevention](/cloudflare-one/policies/data-loss-prevention/) scans within your Cloud Storage bucket and avoid data egress. CASB will scan any objects that exist in the bucket at the time of configuration. + +### Add a compute account + +To connect a compute account to your GCP integration: + +1. In [Zero Trust](https://one.dash.cloudflare.com), go to **CASB** > **Integrations**. +2. Find and select your GCP integration. +3. Select **Open connection instructions**. +4. Follow the instructions provided to connect a new compute account. +5. Select **Refresh**. + +You can only connect one compute account to an integration. To remove a compute account, select **Manage compute accounts**. + +### Configure compute account scanning + +Once your GCP compute account has successfully connected to your CASB integration, you can configure where and how to scan for sensitive data: + +1. In [Zero Trust](https://one.dash.cloudflare.com), go to **CASB** > **Integrations**. +2. Find and select your GCP integration. +3. Select **Create new configuration**. +4. In **Resources**, choose the buckets you want to scan. Select **Continue**. +5. Choose the file types, sampling percentage, and [DLP profiles](/cloudflare-one/policies/data-loss-prevention/dlp-profiles/) to scan for. +6. (Optional) Configure additional settings, such as the limit of API calls over time for CASB to adhere to. +7. Select **Continue**. +8. Review the details of the scan, then select **Start scan**. + +CASB will take up to one hour to begin scanning. To view the scan results, go to **CASB** > **Content** > **Cloud**. + +To manage your resources, go to **CASB** > **Integrations**, then find and select your GCP integration. From here, you can pause all or individual scans, add or remove resources, and change scan settings. + +For more information, refer to [Content findings](/cloudflare-one/applications/casb/manage-findings/#content-findings). + +## Security findings + + + +### Cloud Storage Bucket security + +Flag security issues in Cloud Storage Buckets, including overpermissioning, access policies, and user security best practices. + +| Finding type | FindingTypeID | Severity | +| -------------------------------------------------------------------------------- | -------------------------------------- | -------- | +| Google Cloud Platform: GCS Bucket Allows Public Write | `4583f5a9-a343-4e2f-a8b3-9237a911f337` | Critical | +| Google Cloud Platform: GCS Bucket IAM Policy Allows Public Access | `032c1e88-0cff-47f6-8d75-046e0a7330de` | Critical | +| Google Cloud Platform: GCS Bucket Publicly Accessible | `cc028a95-46d4-4156-ac11-bc5713529824` | Critical | +| Google Cloud Platform: Public Access Prevention Enabled But Policy Grants Public | `cc02680e-9cc3-49d1-99d5-29d425bf142f` | Critical | +| Google Cloud Platform: GCS Bucket ACL Grants All Authenticated Users Access | `e1a588af-0500-482e-b59d-fd2693ce7fc0` | Critical | +| Google Cloud Platform: GCS Bucket ACL Grants All Users Public Access | `1904c004-8d4f-470e-9460-e77db23d6a86` | Critical | +| Google Cloud Platform: Public Access Prevention but ACL Grants allUsers | `fcf2e27e-673f-4cd2-9b76-ec89c4c5872c` | Critical | +| Google Cloud Platform: GCS Bucket Versioning Disabled | `bd66e214-f205-4e00-bd68-121dad0a7988` | High | +| Google Cloud Platform: GCS Bucket Without KMS Encryption | `0105d9c4-1a01-4b65-b33e-df6c55905147` | High | +| Google Cloud Platform: GCS Uniform Bucket-Level Access Disabled | `6960b459-aa9e-4b41-84f6-26cdb75a1995` | High | +| Google Cloud Platform: GCS Bucket IAM Policy Allows Public Read | `10420f34-8fdd-49cb-8d38-096a2de5824f` | High | +| Google Cloud Platform: GCS Bucket Lacks Lifecycle Rules | `edcd5a8b-b128-404b-8207-23a80f669b65` | Medium | +| Google Cloud Platform: GCS Bucket Logging Disabled | `d26f43c8-9406-481c-8c8b-1a7f05f3cc27` | Medium | +| Google Cloud Platform: GCS Bucket Not Using 'Soft Delete' | `5542ed8e-77a6-43c1-8b9e-935e66009d34` | Medium | +| Google Cloud Platform: GCS Bucket Retention Policy Disabled | `2d4a247c-8adb-4f2b-ae58-3568d633cb81` | Medium | +| Google Cloud Platform: GCS Bucket IAM Policy Not Version 3 | `ade2ede6-08c7-4962-b084-f6a29ee4a5b8` | Low | +| Google Cloud Platform: GCS Bucket IAM Policy Using Legacy Roles | `11a592b9-4f51-4a1a-9925-a48a5ed01521` | Low | diff --git a/src/content/docs/cloudflare-one/applications/casb/casb-integrations/index.mdx b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/index.mdx index 2d3e2ac9f00eab..f5382d9e199c8a 100644 --- a/src/content/docs/cloudflare-one/applications/casb/casb-integrations/index.mdx +++ b/src/content/docs/cloudflare-one/applications/casb/casb-integrations/index.mdx @@ -14,6 +14,7 @@ You can integrate the following SaaS applications and cloud environments with Cl - [Box](/cloudflare-one/applications/casb/casb-integrations/box/) - [Dropbox](/cloudflare-one/applications/casb/casb-integrations/dropbox/) - [GitHub](/cloudflare-one/applications/casb/casb-integrations/github/) +- [Google Cloud Platform (GCP) Cloud Storage](/cloudflare-one/applications/casb/casb-integrations/gcp-cloud-storage/) - [Google Workspace](/cloudflare-one/applications/casb/casb-integrations/google-workspace/) - [Google Drive](/cloudflare-one/applications/casb/casb-integrations/google-workspace/google-drive/) - [Gmail](/cloudflare-one/applications/casb/casb-integrations/google-workspace/gmail/) diff --git a/src/content/docs/cloudflare-one/applications/casb/index.mdx b/src/content/docs/cloudflare-one/applications/casb/index.mdx index 8fd85c96aaa943..bafae1ba80314c 100644 --- a/src/content/docs/cloudflare-one/applications/casb/index.mdx +++ b/src/content/docs/cloudflare-one/applications/casb/index.mdx @@ -3,6 +3,9 @@ pcx_content_type: how-to title: Cloud Access Security Broker sidebar: order: 3 +learning_center: + title: What is CASB? | Cloud access security brokers + link: https://www.cloudflare.com/learning/access-management/what-is-a-casb/ --- import { GlossaryTooltip, Render } from "~/components"; @@ -13,7 +16,7 @@ Available for all Zero Trust users. Free users can configure up to two CASB integrations. You must upgrade to an Enterprise plan to view the details of a finding instance. ::: -Cloudflare's API-driven Cloud Access Security Broker (CASB) integrates with SaaS applications and cloud environments to scan for misconfigurations, unauthorized user activity, shadow IT, and other data security issues that can occur after a user has successfully logged in. +Cloudflare's API-driven [Cloud Access Security Broker](https://www.cloudflare.com/learning/access-management/what-is-a-casb/) (CASB) integrates with SaaS applications and cloud environments to scan for misconfigurations, unauthorized user activity, shadow IT, and other data security issues that can occur after a user has successfully logged in. ## Manage CASB integrations diff --git a/src/content/docs/browser-rendering/get-started/index.mdx b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/index.mdx similarity index 63% rename from src/content/docs/browser-rendering/get-started/index.mdx rename to src/content/docs/cloudflare-one/applications/casb/troubleshooting/index.mdx index d64864ac0a09c0..a4c3f4bf12bfd3 100644 --- a/src/content/docs/browser-rendering/get-started/index.mdx +++ b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/index.mdx @@ -1,8 +1,8 @@ --- -pcx_content_type: navigation -title: Get started +pcx_content_type: troubleshooting +title: Troubleshooting sidebar: - order: 2 + order: 4 group: hideIndex: true --- diff --git a/src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-compute-accounts.mdx b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-compute-accounts.mdx new file mode 100644 index 00000000000000..3e8c43be0c6696 --- /dev/null +++ b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-compute-accounts.mdx @@ -0,0 +1,74 @@ +--- +pcx_content_type: troubleshooting +title: Troubleshoot compute accounts +sidebar: + order: 2 +--- + +import { Render } from "~/components"; + +Cloudflare CASB detects when compute accounts are unhealthy or outdated. Common compute account issues include security or functionality updates and API token misconfigurations. + +## Identify unhealthy compute accounts + +To identify unhealthy compute accounts: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **CASB** > **Integrations**. +2. Choose the integration you created for cloud scanning. +3. Select **Manage compute accounts**. + +CASB will display the status of each compute account next to its name. If a compute account is broken or outdated, CASB will set its status to **Unhealthy**. If the status is **Healthy**, no action is required. + +## Repair an unhealthy compute account + +When CASB marks a compute account as **Unhealthy**, CASB will not use new scan configuration changes and new scan results will not appear in the dashboard. + +To repair a compute account marked as **Unhealthy**, first [upgrade the compute account](#upgrade-a-compute-account). If the compute account is still unhealthy, [roll your API token](#roll-api-tokens). + +## Upgrade a compute account + +Upgrading a compute account applies the latest software features, bug fixes, and infrastructure changes to a cloud compute account. You should run upgrades periodically to keep the compute account software up to date or when recommended by Cloudflare to address an issue. CASB deploys compute account upgrades through Terraform updates. + +To upgrade a compute account: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **CASB** > **Integrations**. +2. Choose the integration you created for cloud scanning. +3. Select **Open connection instructions**. +4. Follow the instructions provided to validate your local Terraform and CLI configuration. +5. Under **Step 2: Deploy Terraform Configuration**, copy the template to your local configuration. This template will be the most up to date version of the integration's Terraform configuration. +6. In a local terminal, update the cached version of the CDS Terraform modules: + ```bash + terraform init --upgrade + ``` +7. Apply the upgraded Terraform configuration to your compute account: + ```bash + terraform apply + ``` + +## Roll API tokens + +:::caution +If you roll your API token in CASB but do not update it in your compute account, CASB will set your compute account's status as **Broken** and stop reporting scan results. +::: + +You may need to roll the Cloudflare API token used for your compute account if a security or operational issue appears, your API token is compromised, or your API token is removed from your compute account. + + + +4. Copy your API token. + +Once you roll your API token in Cloudflare, you can update the API token value in your secrets manager for [Amazon Web Services (AWS)](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_update-secret-value.html) or [Google Cloud Platform (GCP)](https://cloud.google.com/secret-manager/docs/edit-secrets). + +### Common token issues + +#### `cloudflare-cds-secrets` does not exist in the compute account's secrets manager + +To recreate the secret in your compute account: + +1. Validate that you selected the correct region. +2. [Upgrade the compute account](#upgrade-a-compute-account) to recreate the secret. +3. [Update the secret value](#roll-api-tokens) in your compute account. + +#### I no longer have access to the Cloudflare API token I created + +[Roll your Cloudflare API token](#roll-api-tokens) and add it to your compute account. If the [status of the compute account](#identify-unhealthy-compute-accounts) is set to **Healthy**, the issue has been solved. diff --git a/src/content/docs/cloudflare-one/applications/casb/troubleshooting.mdx b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-integrations.mdx similarity index 96% rename from src/content/docs/cloudflare-one/applications/casb/troubleshooting.mdx rename to src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-integrations.mdx index b003dd57d4facb..0cea3c9856f83a 100644 --- a/src/content/docs/cloudflare-one/applications/casb/troubleshooting.mdx +++ b/src/content/docs/cloudflare-one/applications/casb/troubleshooting/troubleshoot-integrations.mdx @@ -2,11 +2,9 @@ pcx_content_type: troubleshooting title: Troubleshoot integrations sidebar: - order: 3 + order: 1 --- -import { TabItem, Tabs } from "~/components"; - Cloudflare CASB detects when integrations are unhealthy or outdated. Common integration issues include changes to SaaS app or cloud environment configurations, user access, or permission scope. Integrations may need to be updated to support new features or permissions. diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/dash-sso-apps.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/dash-sso-apps.mdx index 24574815d79d91..a17df8a52b4708 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/dash-sso-apps.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/dash-sso-apps.mdx @@ -73,9 +73,8 @@ If there is an issue with your SSO IdP provider, you can add an alternate IdP us 1. [Add](/api/resources/zero_trust/subresources/identity_providers/methods/create/) one-time PIN login: ```bash title="cURL command" -curl 'https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers' \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/identity_providers' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "type": "onetimepin", @@ -86,9 +85,8 @@ curl 'https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity 2. [Get](/api/resources/zero_trust/subresources/access/subresources/applications/methods/list/) the `id` of the `dash_sso` Access application. You can use [`jq`](https://jqlang.github.io/jq/download/) to quickly find the correct application: ```bash title="cURL command" -curl 'https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps' \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ | jq '.result[] | select(.type == "dash_sso")' ``` @@ -106,9 +104,8 @@ curl 'https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps' \ ```bash title="cURL command" curl --request PUT \ -'https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/3537a672-e4d8-4d89-aab9-26cb622918a1' \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/3537a672-e4d8-4d89-aab9-26cb622918a1' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "id": "3537a672-e4d8-4d89-aab9-26cb622918a1", @@ -127,9 +124,8 @@ The following API calls will disable SSO enforcement for an account. This action 1. Get your SSO `connector_id`: ```bash title="cURL command" -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/sso/v2/connectors \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/sso/v2/connectors \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" ``` ```json title="Response" @@ -153,9 +149,8 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/sso/v2/connector ```bash title="cURL command" curl --request PATCH \ -'https://api.cloudflare.com/client/v4/accounts/{account_id}/sso/v2/connectors/2828' \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/sso/v2/connectors/2828' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "sso_connector_status": "DIS" diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas.mdx index 56b366b7d704a7..822a0d558bb334 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas.mdx @@ -3,8 +3,6 @@ pcx_content_type: how-to title: Generic OIDC application sidebar: order: 1 - badge: - text: Beta --- @@ -37,14 +35,7 @@ Some SaaS applications provide the Redirect URL after you [configure the SSO pro 6. Select **Add application**. -7. In **Scopes**, select the attributes that you want Access to send in the ID token. - - | Scope | Description | - | --------- | ---------------------------------------------------- | - | `openid` | Include a unique identifier for the user (required). | - | `email` | Include the user's email address. | - | `profile` | Include all custom OIDC claims from the IdP. | - | `groups` | Include the user's IdP group membership. | +7. In **Scopes**, select the user attributes that you want Access to send in the ID token. For more information about configuring OIDC scopes and claims, refer to [OIDC claims](#oidc-claims). 8. In **Redirect URLs**, enter the callback URL obtained from the SaaS application. @@ -62,7 +53,7 @@ Some SaaS applications provide the Redirect URL after you [configure the SSO pro | Key endpoint | Returns the current public keys used to [verify the Access JWT](/cloudflare-one/identity/authorization-cookie/validating-json/)
    `https://.cloudflareaccess.com/cdn-cgi/access/sso/oidc//jwks` | | User info endpoint | Returns all user claims in JSON format
    `https://.cloudflareaccess.com/cdn-cgi/access/sso/oidc//userinfo` | -11. Add [Access policies](/cloudflare-one/policies/access/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access. +11. 12. @@ -81,3 +72,62 @@ Next, configure your SaaS application to require users to log in through Cloudfl ## 4. Test the integration Open an incognito browser window and go to the SaaS application's login URL. You will be redirected to the Cloudflare Access login screen and prompted to sign in with your identity provider. + +## OIDC claims + +OIDC claims refer to the user identity characteristics that Cloudflare Access shares with your OIDC SaaS application upon successful authentication. An OIDC scope defines a set of OIDC claims. By default, Cloudflare Access passes all [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) that are included in the `openid`, `email`, `profile`, and `groups` scopes (if available). + + | Scope | Description | + | --------- | ---------------------------------------------------- | + | `openid` | Includes a unique identifier for the user (required). | + | `email` | Includes the user's email address. | + | `profile` | Includes the user's name and all custom OIDC claims from the IdP. | + | `groups` | Include the user's IdP group membership. | + +In your Access application, you can configure the OIDC scopes and claims that Access sends to the SaaS provider. For example, you can remove the `groups` scope if your SaaS application does not need to receive user group information. + +### Filter groups + +In **Group filter regex**, you can enter a regular expression to define the identity provider groups that you want to include in the `groups` scope. For example, if you enter the expression `(^TEAM-Engineering-.$)|(^TEAM-Product-.$)`, only groups with names like TEAM-Engineering-A or TEAM-Product-B would get passed to the SaaS application. + +### Add claims + +To add additional OIDC claims onto the ID token sent to your SaaS application, configure the following fields for each claim: + + - **Name**: OIDC claim name + - **Scope**: Select the OIDC scope where this claim should be included. In most cases, we recommend selecting `profile` since it already includes other custom claims from the IdP. + - **IdP claim**: The identity provider value that should map to this OIDC claim. You can select any [SAML attribute](/cloudflare-one/identity/idp-integration/generic-saml/#saml-headers-and-attributes) or [OIDC claim](/cloudflare-one/identity/idp-integration/generic-oidc/#oidc-claims) that was configured in a Zero Trust IdP integration. + - **Required**: If a claim is marked as required but is not provided by an IdP, Cloudflare will fail the authentication request and show an error page. + - **Add per IdP claim**: (Optional) If you turned on multiple identity providers for the SaaS application, you can choose different attribute mappings for each IdP. These values will override the parent **IdP claim**. + +## Advanced settings + +### Access token lifetime + +The OIDC Access token authorizes users to connect to the SaaS application through Cloudflare Access. You can set an **Access token lifetime** to determine the window in which the token can be used to establish authentication with the SaaS application — if it expires, the user must re-authenticate through Cloudflare Access. To balance security and user convenience, Cloudflare recommends configuring a short Access token lifetime in conjunction with a longer **Refresh token lifetime** (if supported by your application). When the access token expires, Cloudflare will use the refresh token to obtain a new access token after checking the user's identity against your Access policies. When the refresh token expires, the user will need to log back in to the identity provider. The refresh token lifetime should be less than your [global session duration](/cloudflare-one/identity/users/session-management/), otherwise the global session would take precedence. + +:::note + +::: + +### OIDC flows + +Some SaaS applications require SSO providers to provide tokens to the browser without backend authentication. Access for SaaS supports the following OIDC flows: + +- **No additional OIDC flows**: (Default) Recommended unless your application requires additional flows. +- **Hybrid flows**: Used by applications that require information from the ID token before authenticating the user. +- **Implicit flows**: (Not recommended) Typically used by frontend applications that cannot store secrets and which do not support **PKCE without client secret**. + +Cloudflare allows various `response_type` values in the authorization request depending on the selected flow. For example, the implicit flow allows Cloudflare to return the ID token, Access token, or both the ID token and Access token from the Authorization endpoint. + +| `response_type` values | Default flow | Hybrid flow | Implicit flow | +| -------------- | -- | -- | -- | +| `code` | ✅ | ✅ | ❌ | +| `id_token` | ❌ |✅ | ✅ | +| `token` | ❌| ✅ |✅ | + +To include `id_token` in the authorization request, turn on **Return ID Token from Authorization Endpoint**. To include `token`, turn on **Return Access Token from Authorization Endpoint** + +:::note +[Refresh tokens](#access-token-lifetime) are not supported with Hybrid or Implicit flows. +::: diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx index 5a207f5178194f..283e49f69daaa0 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx @@ -5,7 +5,7 @@ sidebar: order: 1 --- -import { Render } from "~/components"; +import { Render, Details } from "~/components"; This page provides generic instructions for setting up a SaaS application in Cloudflare Access using the SAML authentication protocol. @@ -39,16 +39,16 @@ Obtain the following URLs from your SaaS application account: 8. Select the **Name ID Format** expected by your SaaS application (usually _Email_). -9. Copy the **SSO endpoint**, **Access Entity ID or Issuer**, and **Public key**. +9. (Optional) Configure any additional [SAML attribute statements](#saml-attributes) required by your SaaS application. -10. If your SaaS application requires additional **SAML attribute statements**, add the mapping of your IdP's attributes you would like to include in the SAML statement sent to the SaaS application. +10. Copy the **SSO endpoint**, **Access Entity ID or Issuer**, and **Public key**. :::note[IdP groups] If you are using Okta, Microsoft Entra ID (formerly Azure AD), Google Workspace, or GitHub as your IdP, Access will automatically send a SAML attribute titled `groups` with all of the user's associated groups as attribute values. ::: -11. Add [Access policies](/cloudflare-one/policies/access/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access. +11. 12. @@ -77,3 +77,315 @@ When acting as a SAML identity provider, Cloudflare will sign both the SAML Resp ## 4. Test the integration Open an incognito browser window and go to the SaaS application's login URL. You will be redirected to the Cloudflare Access login screen and prompted to sign in with your identity provider. + +## SAML attributes + +[SAML attributes](/cloudflare-one/identity/idp-integration/generic-saml/#saml-headers-and-attributes) refer to the user identity characteristics that Cloudflare Access shares with your SAML SaaS application upon successful authentication. By default, Cloudflare Access passes the following attributes (if available) to the SaaS application: + +- `id` - UUID of the user's Access identity +- `name` - Full name of the user (for example, `John Doe`) +- `email` - User's email address +- `groups` - Identity provider group membership + +In Access for SaaS, you can add additional SAML attributes or customize the SAML statement sent to the SaaS application. This allows you to integrate SaaS applications which have specific SAML attribute requirements. + +### SAML attribute statements + +To send additional SAML attributes to your SaaS application, configure the following fields for each attribute: + + - **Name**: SAML attribute name + - **SAML friendly name**: (Optional) A human readable name for the SAML attribute + - **Name format**: Specify the **Name** format expected by the SaaS application: + - `Unspecified`: (default) No specific format required. + - `URI`: Name is in a format such as `urn:ietf:params:scim:schemas:core:2.0:User:userName` or `urn:oid:2.5.4.42`. + - `Basic`: Name is a normal string such as `userName`. + - **IdP claim**: The identity provider value that should map to this SAML attribute. You can select any [SAML attribute](/cloudflare-one/identity/idp-integration/generic-saml/#saml-headers-and-attributes) or [OIDC claim](/cloudflare-one/identity/idp-integration/generic-oidc/#oidc-claims) that was configured in a Zero Trust IdP integration. + - **Required**: If an attribute is marked as required but is not provided by an IdP, Cloudflare will fail the authentication request and show an error page. + - **Add per IdP claim**: (Optional) If you turned on multiple identity providers for the SaaS application, you can choose different attribute mappings for each IdP. These values will override the parent **IdP claim**. + +### JSONata transforms + +In **Advanced settings** > **Transformation**, you can enter a [JSONata](https://jsonata.org/) script that modifies a copy of the [User Registry identity](/cloudflare-one/insights/logs/users/). This is useful for setting default values, excluding email addresses, or ensuring usernames meet arbitrary criteria. Access will send the modified user identity to the SaaS application as SAML attributes. + +:::note +JSONata transformations are not compatible with [SAML attribute statements](#saml-attribute-statements). JSONata transformations will override any specified SAML attributes. +::: + +For example, the following JSONata script merges group names into a list and adds an `eduPersonPrincipalName` field which maps to the user email. + +```jsonata title = "JSONata expression" +$merge([$, {"groups": groups.name, 'eduPersonPrincipalName': email}]) +``` + +Here is an example of a user identity before applying the JSONata transform: + +```json title= "User identity before JSONata transform" +{ + "account_id": "699d98642c564d2e855e9661899b7252", + "amr": [ + "pwd" + ], + "auth_status": "NONE", + "common_name": "", + "device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "device_sessions": { + "49e653db-991e-11ee-af26-2243bf8c3428": { + "last_authenticated": 1703004275 + } + }, + "devicePosture": { + "8534a230-e85e-4183-8964-a4b7dcf72986": { + "rule_name": "Warp", + "success": true, + "type": "warp" + } + }, + "email": "jdoe@company.com", + "gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU", + "geo": { + "country": "US" + }, + "groups": [ + { + "id": "12fdf91a-fb23-41b3-995a-de2f72c61d0e", + "name": "IdentityProtection-RiskyUser-RiskLevel-low" + }, + { + "id": "12348f47-8234-4860-a03f-c2a1513f267b", + "name": "Global Administrator" + }, + { + "id": "11235980-87d7-4917-b0aa-74c01914c40e", + "name": "Application Administrator" + } + ], + "iat": 1659474397, + "id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M", + "idp": { + "id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47", + "type": "azureAD" + } +} +``` + +Result after applying the example JSONata script: + +```json output +{ + "account_id": "699d98642c564d2e855e9661899b7252", + "amr": [ + "pwd" + ], + "auth_status": "NONE", + "common_name": "", + "device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "device_sessions": { + "49e653db-991e-11ee-af26-2243bf8c3428": { + "last_authenticated": 1703004275 + } + }, + "devicePosture": { + "8534a230-e85e-4183-8964-a4b7dcf72986": { + "rule_name": "Warp", + "success": true, + "type": "warp" + } + }, + "email": "jdoe@company.com", + "gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU", + "geo": { + "country": "US" + }, + "groups": [ + "IdentityProtection-RiskyUser-RiskLevel-low", + "Global Administrator", + "Application Administrator" + ], + "iat": 1659474397, + "id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M", + "idp": { + "id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47", + "type": "azureAD" + }, + "eduPersonPrincipalName": "jdoe@company.com" +} +``` + +For more JSONata transform use cases, refer to the following examples. + +
    + +The following JSONata script removes the `groups` SAML attribute. This can be useful if your SaaS application does not need to receive user group information. + +```jsonata title="JSONata expression" +$ ~> |$|{}, ['groups']| +``` + +Result after applying the JSONata transform: +```json output +{ + "account_id": "699d98642c564d2e855e9661899b7252", + "amr": [ + "pwd" + ], + "auth_status": "NONE", + "common_name": "", + "device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "device_sessions": { + "49e653db-991e-11ee-af26-2243bf8c3428": { + "last_authenticated": 1703004275 + } + }, + "devicePosture": { + "8534a230-e85e-4183-8964-a4b7dcf72986": { + "rule_name": "Warp", + "success": true, + "type": "warp" + } + }, + "email": "jdoe@company.com", + "gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU", + "geo": { + "country": "US" + }, + "iat": 1659474397, + "id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M", + "idp": { + "id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47", + "type": "azureAD" + } +} +``` +
    + +
    + +The following JSONata script changes the `groups.name` field from `name` to `group_name` and removes the `groups.id` field: + +```jsonata title="JSONata expression" +{ + "account_id": account_id, + "amr": amr, + "auth_status": auth_status, + "common_name": common_name, + "devicePosture": devicePosture, + "device_id": device_id, + "device_sessions": device_sessions, + "email": email, + "gateway_account_id": gateway_account_id, + "geo": geo, + "groups": $map($.groups, function($group) { + {"group_name": $group.name}}), + "iat": iat, + "id": id, + "idp": idp +} +``` + +Result after applying the JSONata transform: + +```json output +{ + "account_id": "699d98642c564d2e855e9661899b7252", + "amr": [ + "pwd" + ], + "auth_status": "NONE", + "common_name": "", + "devicePosture": { + "8534a230-e85e-4183-8964-a4b7dcf72986": { + "rule_name": "Warp", + "success": true, + "type": "warp" + } + }, + "device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "device_sessions": { + "49e653db-991e-11ee-af26-2210bf8c3428": { + "last_authenticated": 1703004275 + } + }, + "email": "jdoe@company.com", + "gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU", + "geo": { + "country": "US" + }, + "groups": [ + { + "group_name": "IdentityProtection-RiskyUser-RiskLevel-low" + }, + { + "group_name": "Global Administrator" + }, + { + "group_name": "Application Administrator" + } + ], + "iat": 1659474397, + "id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M", + "idp": { + "id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47", + "type": "azureAD" + } +} +``` + +
    + +
    + +The following JSONata script filters groups to those that match a regular expression. + +```jsonata title="JSONata expression" +$merge([$, { "groups": $filter(groups, function($v) { $contains($v.name, /Administrator/) }) }]) +``` + +Result after applying the JSONata transform: + +```json output +{ + "account_id": "699d98642c564d2e855e9661899b7252", + "amr": [ + "pwd" + ], + "auth_status": "NONE", + "common_name": "", + "device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "device_sessions": { + "49e653db-991e-11ee-af26-2243bf8c3428": { + "last_authenticated": 1703004275 + } + }, + "devicePosture": { + "8534a230-e85e-4183-8964-a4b7dcf72986": { + "rule_name": "Warp", + "success": true, + "type": "warp" + } + }, + "email": "jdoe@company.com", + "gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU", + "geo": { + "country": "US" + }, + "groups": [ + { + "id": "12348f47-8234-4860-a03f-c2a1513f267b", + "name": "Global Administrator" + }, + { + "id": "11235980-87d7-4917-b0aa-74c01914c40e", + "name": "Application Administrator" + } + ], + "iat": 1659474397, + "id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M", + "idp": { + "id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47", + "type": "azureAD" + } +} +``` +
    + + diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-cloud-saas.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-cloud-saas.mdx index 9ae073c28f7242..ed6b261ecd0d53 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-cloud-saas.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-cloud-saas.mdx @@ -14,7 +14,7 @@ This guide covers how to configure [Google Cloud](https://support.google.com/clo When configuring Google Cloud with Access, the following limitations apply: -- Users will not be able to log in using [Google](/cloudflare-one/identity/idp-integration/google/) or [Google Workspace](/cloudflare-one/identity/idp-integration/gsuite/) as an identity provider after Google Cloud is configured with Access. +- Users will not be able to log in using [Google](/cloudflare-one/identity/idp-integration/google/) or [Google Workspace](/cloudflare-one/identity/idp-integration/google-workspace/) as an identity provider after Google Cloud is configured with Access. - The integration of Access as a single sign-on provider for your Google Cloud account does not work for Google super admins. It will work for other users. ::: diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-workspace-saas.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-workspace-saas.mdx index 83ca9b7e5caa8c..3cac01f4328a09 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-workspace-saas.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/google-workspace-saas.mdx @@ -35,7 +35,7 @@ The integration of Access as a single sign-on provider for your Google Workspace :::caution -When you put your Google Workspace behind Access, users will not be able to log in using [Google](/cloudflare-one/identity/idp-integration/google/) or [Google Workspace](/cloudflare-one/identity/idp-integration/gsuite/) as an identity provider. +When you put your Google Workspace behind Access, users will not be able to log in using [Google](/cloudflare-one/identity/idp-integration/google/) or [Google Workspace](/cloudflare-one/identity/idp-integration/google-workspace/) as an identity provider. ::: 4. [Create an Access policy](/cloudflare-one/policies/access/) for your application. For example, you could allow users with an `@your_domain.com` email address. diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx index 20650a40032156..33ec70d537cd3f 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx @@ -10,4 +10,6 @@ import { DirectoryListing } from "~/components" Cloudflare Access allows you to add an additional authentication layer to your SaaS applications. When you integrate a SaaS application with Access, users log in to the application with Cloudflare as the Single Sign-On provider. The user is then redirected to the configured identity providers for that application and are only granted access if they pass your Access policies. +Cloudflare integrates with the majority of SaaS applications that support the SAML or OIDC authentication protocol. If you do not see your application listed below, refer to our [generic SAML](/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas/) or [generic OIDC](/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas/) guide and consult your SaaS application's documentation. + diff --git a/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx b/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx index adc44fa635952f..ea8ebd5dde6473 100644 --- a/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx +++ b/src/content/docs/cloudflare-one/applications/configure-apps/self-hosted-public-app.mdx @@ -17,7 +17,7 @@ You can securely publish internal tools and applications by adding Cloudflare Ac ## 1. Add your application to Access - + ## 2. Connect your origin to Cloudflare @@ -37,12 +37,4 @@ Users can now connect to your self-hosted application after authenticating with ## Product compatibility -When using Access self-hosted applications, the majority of Cloudflare products will be compatible with your application. - -However, the following products are not supported: - -* [Automatic Signed Exchanges](/speed/optimization/other/signed-exchanges/) -* [Automatic Platform Optimization](/automatic-platform-optimization) -* [Zaraz](/zaraz) - -You can disable Automatic Signed Exchanges and Zaraz for a specific application - instead of across your entire zone - using a [Configuration Rule](/rules/configuration-rules/) scoped to the application domain. + \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/applications/non-http/browser-rendering.mdx b/src/content/docs/cloudflare-one/applications/non-http/browser-rendering.mdx index d0f7185f1944c1..839cfbdf6c1ef1 100644 --- a/src/content/docs/cloudflare-one/applications/non-http/browser-rendering.mdx +++ b/src/content/docs/cloudflare-one/applications/non-http/browser-rendering.mdx @@ -5,34 +5,44 @@ sidebar: order: 3 --- -Cloudflare can render certain non-web applications in your browser without the need for client software or end-user configuration changes. Cloudflare currently supports rendering a terminal for SSH and VNC connections in a user's browser. +import { Render } from "~/components"; -:::note -You can only enable browser rendering on domains and subdomains, not for specific paths. -::: +Cloudflare can render SSH, VNC, and RDP applications in a browser without the need for client software or end-user configuration changes. For SSH and VNC, user email prefixes must match their username on the server. RDP leverages your existing Windows usernames and passwords for authenticating to the Windows server; Cloudflare does not manage any credentials on the Windows server. -## Enable browser rendering +## Limitations -To enable browser rendering: +- Browser rendering is only supported for [self-hosted public applications](/cloudflare-one/applications/configure-apps/self-hosted-public-app/), not private IPs or hostnames. +- You can only render a browser-rendered terminal on domains and subdomains, not on specific paths. +- +- Cloudflare uses TLS to secure the egress RDP connection to your Windows server. We do not currently validate the chain of trust. -1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**. -2. Locate the SSH or VNC application you created when [connecting the server to Cloudflare](/cloudflare-one/connections/connect-networks/use-cases/ssh/). Select **Configure**. -3. In the **Policies** tab, ensure that only **Allow** or **Block** policies are present. **Bypass** and **Service Auth** are not supported for browser-rendered applications. -4. Go to **Advanced settings** > **Browser rendering settings**. -5. For **Browser rendering**, choose _SSH_ or _VNC_. +## Turn on browser rendering - :::note +### SSH and VNC - When connecting over SSH, Cloudflare supports following key exchange algorithms: - - - `curve25519-sha256@libssh.org` - - `curve25519-sha256` - - `ecdh-sha2-nistp256` - - `ecdh-sha2-nistp384` - - `ecdh-sha2-nistp521` - - ::: +To turn on browser rendering for an SSH or VNC application: +1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**. +2. Locate the SSH or VNC application you created when [connecting the server to Cloudflare](/cloudflare-one/connections/connect-networks/use-cases/ssh/). Select **Configure**. +3. In the **Policies** tab, ensure that only **Allow** or **Block** policies are present. **Bypass** and **Service Auth** are not supported for browser-rendered applications. +4. Go to **Advanced settings** > **Browser rendering settings**. +5. For **Browser rendering**, choose _SSH_ or _VNC_. 6. Select **Save application**. When users authenticate and visit the URL of the application, Cloudflare will render a terminal in their browser. + +### RDP + +To set up browser-rendering for RDP, refer to our [browser-based RDP guide](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser/). + +### SSH key exchange algorithms + +Cloudflare's browser-rendered SSH terminal supports the following Key Exchange (KEX) algorithms: + + - `curve25519-sha256@libssh.org` + - `curve25519-sha256` + - `ecdh-sha2-nistp256` + - `ecdh-sha2-nistp384` + - `ecdh-sha2-nistp521` + +For browser-rendered SSH connections to work, you may need to update the `sshd_config` file on your server to accept these algorithms. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/applications/non-http/index.mdx b/src/content/docs/cloudflare-one/applications/non-http/index.mdx index 3e040b8edadcf7..524fc807d74948 100644 --- a/src/content/docs/cloudflare-one/applications/non-http/index.mdx +++ b/src/content/docs/cloudflare-one/applications/non-http/index.mdx @@ -23,11 +23,11 @@ If you would like to define how users access specific infrastructure servers wit ## Clientless access -Clientless access methods are suited for organizations that cannot deploy the WARP client or need to support third-party contractors where installing a client is not possible. Clientless access requires onboarding a domain to Cloudflare and configuring a public hostname in order to make the server reachable. Command logging is not supported, and user email prefixes must match their username on the server. +Clientless access methods are suited for organizations that cannot deploy the WARP client or need to support third-party contractors where installing a client is not possible. Clientless access requires onboarding a domain to Cloudflare and configuring a public hostname in order to make the server reachable. Command logging is not supported. ### Browser-rendered terminal -Cloudflare's [browser-based terminal](/cloudflare-one/applications/non-http/browser-rendering/) allows users to connect over SSH and VNC without any configuration. When users visit the public hostname URL (for example, `https://ssh.example.com`) and log in with their Access credentials, Cloudflare will render a terminal in their browser. +Cloudflare's [browser-based terminal](/cloudflare-one/applications/non-http/browser-rendering/) allows users to connect over SSH, RDP, and VNC without any configuration. When users visit the public hostname URL (for example, `https://ssh.example.com`) and log in with their Access credentials, Cloudflare will render a terminal in their browser. For RDP connections, users must authenticate to the Windows server using their Windows username and password in addition to being authenticated by Cloudflare Access. ### Client-side cloudflared (legacy) diff --git a/src/content/docs/cloudflare-one/applications/non-http/infrastructure-apps.mdx b/src/content/docs/cloudflare-one/applications/non-http/infrastructure-apps.mdx index d757466c2d32d8..87c7922bb2ffad 100644 --- a/src/content/docs/cloudflare-one/applications/non-http/infrastructure-apps.mdx +++ b/src/content/docs/cloudflare-one/applications/non-http/infrastructure-apps.mdx @@ -6,8 +6,6 @@ sidebar: badge: variant: tip text: New -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must
    generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Badge, Details, Tabs, TabItem, Render } from "~/components"; @@ -42,7 +40,7 @@ Access for Infrastructure currently only supports [SSH](/cloudflare-one/connecti ## 1. Add a target - + ## 2. Add an infrastructure application diff --git a/src/content/docs/cloudflare-one/applications/non-http/self-hosted-private-app.mdx b/src/content/docs/cloudflare-one/applications/non-http/self-hosted-private-app.mdx index d4a7c6cab4334e..04368a06d043fb 100644 --- a/src/content/docs/cloudflare-one/applications/non-http/self-hosted-private-app.mdx +++ b/src/content/docs/cloudflare-one/applications/non-http/self-hosted-private-app.mdx @@ -18,21 +18,11 @@ This feature replaces the legacy [private network app type](/cloudflare-one/appl - Private IPs and hostnames are reachable over Cloudflare WARP, Magic WAN or Browser Isolation. For more details, refer to [Connect a private network](/cloudflare-one/connections/connect-networks/private-net/). - Private hostnames route to your custom DNS resolver through [Local Domain Fallback](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) or [Gateway resolver policies](/cloudflare-one/policies/gateway/resolver-policies/). -- [Gateway TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/) must be enabled if you would like to present a login page in the browser and issue an authorization JWT to your origin. Otherwise, users will receive a pop-up notification from the WARP client and all session management will be handled in the WARP client. +- (Optional) Turn on [Gateway TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/) if you want to use Access JWTs to manage [HTTPS application sessions](#https-applications). ## Add your application to Access -1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**. - -2. Select **Add an application**. - -3. Select **Self-hosted**. - -4. Enter any name for the application. - -5. In **Session Duration**, choose how often the user's [application token](/cloudflare-one/identity/authorization-cookie/application-token/) should expire. - - Cloudflare checks every HTTPS request to your application for a valid application token. If the user's application token (and global token) has expired, they will be prompted to reauthenticate with the IdP. For more information, refer to [Session management](/cloudflare-one/identity/users/session-management/). If the application is non-HTTPS or you do not have TLS decryption turned on, the session is tracked by the WARP client per application. + 6. Add the private IP and/or private hostname that represents the application. You can use [wildcards](/cloudflare-one/policies/access/app-paths/) with private hostnames to protect multiple parts of an application that share a root path. @@ -40,7 +30,7 @@ This feature replaces the legacy [private network app type](/cloudflare-one/appl Private hostnames are currently only available over port `443` over HTTPS and the application must have a valid Server Name Indicator (SNI). ::: -7. Add [Access policies](/cloudflare-one/policies/access/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access. +7. 8. Configure how users will authenticate: @@ -58,19 +48,28 @@ This feature replaces the legacy [private network app type](/cloudflare-one/appl 12. Select **Next**. -13. (Optional) Configure advanced settings. These settings only apply to private hostnames and require Gateway TLS decryption. +13. - - [**Cross-Origin Resource Sharing (CORS) settings**](/cloudflare-one/identity/authorization-cookie/cors/) - - [**Cookie settings**](/cloudflare-one/identity/authorization-cookie/#cookie-settings) - - **Browser rendering settings**: - - [Automatic `cloudflared` authentication](/cloudflare-one/applications/non-http/cloudflared-authentication/automatic-cloudflared-authentication/) - - [Browser rendering for SSH and VNC](/cloudflare-one/applications/non-http/browser-rendering/) - - **401 Response for Service Auth policies**: Return a `401` response code when a user (or machine) makes a request to the application without the correct [service token](/cloudflare-one/identity/service-tokens/). + These settings only apply to private hostnames and require [Gateway TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/). 14. Select **Save**. Users can now connect to your private application after authenticating with Cloudflare Access. +## Authentication flow + +### HTTPS applications + +If [Gateway TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/) is turned on and a user is accessing an HTTPS application on port `443`, Cloudflare Access will present a login page in the browser and issue an [application token](/cloudflare-one/identity/authorization-cookie/application-token/) to your origin. This is the same cookie-based authentication flow used by [self-hosted public apps](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). + +If [Gateway TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/) is turned off, session management is [handled in the WARP client](#non-https-applications) instead of in the browser. + +### Non-HTTPS applications + +The WARP client manages sessions for all non-HTTPS applications. Users will receive an `Authentication required` pop-up notification from the WARP client. When the user selects the notification, WARP will open a browser window with your Access login page. + + + ## Modify order of precedence in Gateway By default, Cloudflare will evaluate a private application's Access policies after evaluating all Gateway network policies. To evaluate Access private applications before or after specific Gateway policies, create the following [Gateway network policy](/cloudflare-one/policies/gateway/network-policies/): diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-https.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-https.mdx index 3b1b82d07142ff..7b3f599e084c18 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-https.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-https.mdx @@ -13,7 +13,7 @@ Location-based policies require that you send DNS requests to a [location-specif ## Filter DoH requests by location -Location-based policies require that you send DNS requests to a unique DoH endpoint assigned to the location: +Location-based policies require that you send DNS queries to a unique DoH endpoint assigned to the location: ```txt https://.cloudflare-gateway.com/dns-query @@ -105,6 +105,17 @@ For more information, refer to [Microsoft's DoH guide](https://learn.microsoft.c
    +### Use generic DoH endpoint + +You can send DoH requests to the generic Cloudflare DoH endpoint, `dns.cloudflare-gateway.com`. To specify a location in your request, include a header named `cf-dns-location` with a value of your location's DoH subdomain. For example: + +```http +GET /dns-query?name=example.com&type=A HTTP/2 +Host: dns.cloudflare-gateway.com +cf-dns-location: 9y65g5srsm +Accept: application/dns-message +``` + ## Filter DoH requests by user In order to filter DoH queries based on user identity, each query must include a user-specific authentication token. If you have several devices per user and want to apply device-specific policies, you will need to map each device to a different email. @@ -114,9 +125,8 @@ Currently, authentication tokens can only be generated through the API. You can ### 1. Create a service token for the account ```bash -curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/service_tokens" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/service_tokens" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{"name":"ACME Corporation service token"}' ``` @@ -148,12 +158,11 @@ Save the service token's `client_id`, `client_secret`, and `id`. ```bash curl --request PUT \ -"https://api.cloudflare.com/client/v4/accounts/{account_id}/access/organizations/doh/{service_token_id}" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " +"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations/doh/$SERVICE_TOKEN_ID" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" ``` -If you get an `access.api.error.service_token_not_found` error, check that `{service_token_id}` is the value of `id` and not `client_id`. +If you get an `access.api.error.service_token_not_found` error, check that `$SERVICE_TOKEN_ID` is the value of `id` and not `client_id`.
    @@ -181,9 +190,8 @@ If you get an `access.api.error.service_token_not_found` error, check that `{ser Create a new user and optionally add them to a group. ```bash -curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/users" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/users" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "John Doe", diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-tls.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-tls.mdx index c501e7bcf59432..c365c19af18a78 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-tls.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-tls.mdx @@ -7,35 +7,40 @@ sidebar: By default, DNS is sent over a plaintext connection. DNS over TLS (DoT) is a standard for encrypting DNS queries to keep them secure and private. DoT uses the same security protocol, TLS, that HTTPS websites use to encrypt and authenticate communications. -Cloudflare supports DoT on standard port `853` and is compliant with [RFC7858](https://tools.ietf.org/html/rfc7858). +Cloudflare supports DoT on standard port `853` over TLS 1.2 and TLS 1.3 in compliance with [RFC7858](https://tools.ietf.org/html/rfc7858). -## 1. Obtain your DoT hostname +## Configure DoT queries + +### 1. Obtain your DoT hostname Each Gateway DNS location has a unique DoT hostname. DNS locations and corresponding DoT hostnames have policies associated with them. 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Gateway** > **DNS locations**. -2. If you have more than one location set up, you will see a list of all your locations. -3. Expand the location card for the location whose DoT hostname you'd like to retrieve. -4. Get the **DoT hostname** for the location. - -In the example below, the DoT hostname is: `9y65g5srsm.cloudflare-gateway.com`. +2. [Add a new location](/cloudflare-one/connections/connect-devices/agentless/dns/locations/) or select an existing location from the list. +3. Under **DoT endpoint**, copy the value in **DoT addresses**. -![Getting the DoT hostname for a DNS location from the dashboard](~/assets/images/cloudflare-one/connections/get-unique-subdomain.png) +The DoT hostname contains your unique location name. For example, if the DoT hostname is `9y65g5srsm.cloudflare-gateway.com`, the location name is `9y65g5srsm`. -Next, configure your DoT client with the DoT hostname. +### 2. Configure your DoT client -## 2. Configure your DoT client +To configure a DoT client such as `dig`, specify the IP address and the DoT hostname for your location in your query. For example: -Depending on your operating system, you can choose from a variety of standalone DoT clients. +```txt +Hostname: 9y65g5srsm.cloudflare-gateway.com +IP address: 162.159.36.5 +``` -To configure your DoT client, enter the following IP address and the DoT hostname for your location (for example, `9y65g5srsm.cloudflare-gateway.com`): +Alternatively, you can use the generic DoT endpoint (`dns.cloudflare-gateway.com`) and include an `OPT` record with code `65011`. You can select a specific location for the value of the `OPT` record. For example: ```txt -Hostname: +Hostname: dns.cloudflare-gateway.com IP address: 162.159.36.5 +OPT Record: + - Code: 65011 + - Value: 9y65g5srsm ``` -Alternatively, stub resolvers (e.g., Unbound) support DoT natively. An example configuration is shown below. +Some stub resolvers support DoT natively. For example, you can configure Unbound to send a DoT query: ```txt # Unbound TLS Config @@ -44,15 +49,6 @@ tls-cert-bundle: "/etc/ssl/cert.pem" forward-zone: name: "." forward-tls-upstream: yes - forward-addr: 172.64.36.1@853#9y65g5srsm.cloudflare-gateway.com - forward-addr: # + forward-addr: 162.159.36.5@853#9y65g5srsm.cloudflare-gateway.com + forward-addr: 2001:db8:abcd::1234#9y65g5srsm.cloudflare-gateway.com ``` - -:::note - -Each DNS location has a unique DoT hostname and IPv6 address. Remember to substitute your location's values into the `` and `` fields. -::: - -## Supported TLS versions - -Cloudflare's DNS over TLS supports TLS 1.3 and TLS 1.2. diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/locations/index.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/locations/index.mdx index 0e8bf3f0c83917..f78875a0aec2e9 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/locations/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/dns/locations/index.mdx @@ -45,6 +45,23 @@ For more information, refer to [DNS over TLS](/cloudflare-one/connections/connec Gateway requires a DoH endpoint for default DNS locations. For more information, refer to [DNS over HTTPS](/cloudflare-one/connections/connect-devices/agentless/dns/dns-over-https/). +## Secure DNS locations + +Secure DNS locations provide additional protection against malicious domains for use in services such as [protective DNS (PDNS)](/reference-architecture/diagrams/sase/gateway-for-protective-dns/). For a DNS location to be considered secure, Gateway requires that: + +- Your IPv4 and IPv6 endpoints use your [BYOIP addresses](/cloudflare-one/connections/connect-devices/agentless/dns/locations/dns-resolver-ips/#bring-your-own-dns-resolver-ip) (if any). +- [Source network filtering](/cloudflare-one/policies/gateway/network-policies/) is configured for your IPv4, IPv6, and DoT endpoints. +- Source network filtering or token authentication are configured for your DoH endpoints. +- Any enabled endpoints for a DNS location meet security permissions. + +You can assign users the [**Cloudflare Zero Trust DNS Locations Write** role](/cloudflare-one/roles-permissions/#zero-trust-roles) to grant them the permission to create and edit secure DNS locations. To allow users to view locations, you must also assign the **Cloudflare Zero Trust Read Only** role. Users with these roles can view any DNS location, but can only create or edit secure locations. + +Roles that supersede **Cloudflare Zero Trust DNS Locations Write** include: + +- Cloudflare Gateway +- Cloudflare Zero Trust +- Super Administrator + ## Limitations ### Captive portals diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/index.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/index.mdx index 159f5f1c2e8787..0d2f77d28efca5 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/index.mdx @@ -9,7 +9,7 @@ If you are unable to install the WARP client on your devices (for example, Windo - **[Gateway DNS policies](/cloudflare-one/connections/connect-devices/agentless/dns/)** - **[Gateway HTTP policies](/cloudflare-one/connections/connect-devices/agentless/pac-files/)** without user identity and device posture -- **[Access policies](/cloudflare-one/policies/access/)** without device posture for [web applications](/cloudflare-one/applications/configure-apps/) and [browser-rendered](/cloudflare-one/applications/non-http/browser-rendering/) SSH and VNC connections +- **[Access policies](/cloudflare-one/policies/access/)** without device posture for [web applications](/cloudflare-one/applications/configure-apps/) and for [browser-rendered](/cloudflare-one/applications/non-http/browser-rendering/) SSH, RDP, and VNC connections - **[Remote Browser Isolation](/cloudflare-one/policies/browser-isolation/)** via an [Access policy](/cloudflare-one/policies/access/isolate-application/), [prefixed URLs](/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation/), or a [non-identity on-ramp](/cloudflare-one/policies/browser-isolation/setup/non-identity/) - **[Cloud Access Security Broker (CASB)](/cloudflare-one/applications/casb/)** - **[Data Loss Prevention (DLP)](/cloudflare-one/applications/casb/casb-dlp/)** for SaaS applications integrated with Cloudflare CASB diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/pac-files.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/pac-files.mdx index 825f92ec9c7526..67588bda576420 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/agentless/pac-files.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/agentless/pac-files.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -title: HTTP +title: PAC files sidebar: order: 1 --- @@ -11,7 +11,7 @@ import { Details, GlossaryDefinition, TabItem, Tabs } from "~/components"; Only available on Enterprise plans. ::: -You can apply Gateway HTTP and DNS policies at the browser level by configuring a Proxy Auto-Configuration (PAC) file. +You can apply Gateway HTTP and DNS policies at the browser level by configuring a Proxy Auto-Configuration (PAC) file to connect to a proxy endpoint. @@ -64,7 +64,7 @@ https://.proxy.cloudflare-gateway.com ```bash curl https://api.cloudflare.com/client/v4/accounts//gateway/proxy_endpoints \ - --header "Authorization: Bearer " \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{"name": "any_name", "ips": ["", "", ""]}' ``` @@ -211,8 +211,8 @@ To get the domain of a proxy endpoint: 1. Use the [List proxy endpoints](/api/resources/zero_trust/subresources/gateway/subresources/proxy_endpoints/methods/list/) operation to get a list of your proxy endpoints and their details. For example: ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/proxy_endpoints \ - --header "Authorization: Bearer " + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/proxy_endpoints \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" ``` ```json {8} output diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/automated-deployment.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/automated-deployment.mdx index 56fa0587ec0984..231663a2225a97 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/automated-deployment.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/automated-deployment.mdx @@ -5,8 +5,6 @@ sidebar: order: 1 head: [] description: Automatically deploy a root certificate on desktop devices. -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Details } from "~/components"; diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate.mdx index f4f1d7666f3d4c..84993080cc76cb 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate.mdx @@ -6,8 +6,6 @@ sidebar: head: [] description: Configure WARP to use a custom root certificate instead of the Cloudflare certificate. -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Render, Tabs, TabItem } from "~/components"; diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/index.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/index.mdx index 7c55150f7e8777..22f07462eb1d87 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/index.mdx @@ -3,8 +3,6 @@ pcx_content_type: get-started title: User-side certificates sidebar: order: 2 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Tabs, TabItem } from "~/components"; @@ -13,7 +11,7 @@ Advanced security features such as [HTTPS traffic inspection](/cloudflare-one/po Zero Trust [generates a unique root CA](#generate-a-cloudflare-root-certificate) for each account and deploys it across the Cloudflare global network. Alternatively, Enterprise users can upload and deploy their own [custom certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/). -:::caution[Default WARP certificate expired on 2025-02-02] +:::caution[Default certificate expired on 2025-02-02] The default Cloudflare certificate expired on 2025-02-02 at 16:05 UTC. Review how this change impacts certificate propagation to your end-user devices and how to address browser issues in [Troubleshooting](/cloudflare-one/faq/troubleshooting/#as-of-february-2-2025-my-end-user-devices-browser-is-returning-a-your-connection-is-not-private-warning). diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment.mdx index 043276202e6045..de131c55e8df17 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment.mdx @@ -6,8 +6,6 @@ sidebar: head: [] description: Manually add a Cloudflare certificate to mobile devices and individual applications. -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Details, Render, TabItem, Tabs } from "~/components"; @@ -177,6 +175,10 @@ Windows offers two locations to install the certificate, each impacting which us The root certificate is now installed and ready to be used. +:::caution +If your certificate is installed in the **Local Machine Store**, the [device posture check](/cloudflare-one/identity/devices/warp-client-checks/) looking for a certificate will fail. Install the certificate in the **Current User Store** to ensure a successful posture device check. +::: + ### Linux The location where the root certificate should be installed is different depending on your Linux distribution. Follow the specific instructions for your distribution. diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles.mdx index 504e5154d8bcde..7b4576bf1ecec6 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles.mdx @@ -35,9 +35,8 @@ Your profile will appear in the **Profile settings** list. You can rearrange the Send a `POST` request to the [Devices endpoint](/api/resources/zero_trust/subresources/devices/subresources/policies/subresources/custom/methods/create/): ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/policy \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "allow_mode_switch": false, diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/index.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/index.mdx index 3fee5e085fb03f..3a2eaba1f82a4c 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/index.mdx @@ -52,3 +52,31 @@ flowchart TD A@{ shape: in-out} n2@{ shape: proc} ``` + +## Add a DNS suffix + +Support for DNS suffix search lists in WARP is currently in development. You can manually configure DNS suffixes at the device level using the following instructions. + +### macOS + +To manually configure a DNS suffix on macOS: + +1. Open **System Settings** (or **System Preferences** on older macOS versions). +2. Go to **Network** and select your active connection (**Wi-Fi** or **Ethernet**). +3. Select **Details** (or **Advanced**). +4. Go to the **DNS** tab. +5. Under **Search Domains**, select the `+` button and add your DNS suffix. +6. Select **OK**, then **Apply**. + +### Windows + +To manually configure a DNS suffix on Windows: + +1. Open the **Search** bar in Windows, type **View network connections**, and select **Open**. +2. Right-click the network adapter (**Wi-Fi** or **Ethernet**) you want to modify and select **Properties**. (Admin privileges required.) +3. Double-click **Internet Protocol Version 4 (TCP/IPv4)**. +4. In the **Internet Protocol (TCP/IP) Properties** window, select **Advanced**. +5. Go to the **DNS** tab. +6. Select **Append these DNS suffixes (in order)**. +7. Select **Add**, enter your DNS suffix and select **Add**. +8. Select **OK** on all windows to apply changes. diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels.mdx index 70b8b266ac837c..7b6d0c53273d65 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels.mdx @@ -47,6 +47,13 @@ Many Cloudflare Zero Trust services rely on traffic going through WARP, such as - The application protected by the Access or Gateway policy - `edge.browser.run` if using [Browser Isolation](/cloudflare-one/policies/browser-isolation/) +## Cloudflare Zero Trust IP addresses + +In [Secure Web Gateway without DNS filtering](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/#secure-web-gateway-without-dns-filtering) WARP mode, you cannot [add domains](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains) to the Split Tunnel. If you are using Split Tunnels in Include mode, you must include the IPs that resolve to `.cloudflareaccess.com` instead: + +- `104.19.194.29` +- `104.19.195.29` + ## Domain-based Split Tunnels Domain-based split tunneling has a few ramifications you should be aware of before deploying in your organization:. diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/index.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/index.mdx index d32b92ad8ce3a1..a4f2dbf9847f85 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/index.mdx @@ -8,7 +8,7 @@ sidebar: import { Details, GlossaryTooltip, - InlineBadge, + Badge, Render, Tabs, TabItem, @@ -320,3 +320,26 @@ To turn on local network access in the WARP client: - WARP will only exclude local networks in the [RFC 1918](https://datatracker.ietf.org/doc/html/rfc1918) address space. Other IP addresses such as CGNAT are not supported. - The maximum excluded subnet size is `/24`. - If a device has multiple network interfaces with distinct local IP ranges, WARP will only exclude one of those networks. To access a specific local network, disable the other interfaces and disconnect/reconnect WARP. + +### WARP interface IP DNS registration + +
    + +| [WARP modes](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-modes/) | [Zero Trust plans](https://www.cloudflare.com/teams-pricing/) | +| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +|
    • Gateway with WARP
    • Secure Web Gateway without DNS filtering
    | All plans | + +| System | Availability | Minimum WARP version | +| -------- | ------------ | -------------------- | +| Windows | ✅ | 2025.2.460.1 | +| macOS | ❌ | | +| Linux | ❌ | | +| iOS | ❌ | | +| Android | ❌ | | +| ChromeOS | ❌ | | + +
    + +When `Enabled`, the operating system will register WARP's [local interface IP](#override-local-interface-ip) (CGNAT IP or `172.16.0.2`) with your on-premise DNS server when the DNS server is reachable. + +If you use on-premise DNS infrastructure (such as Active Directory), we recommend turning this setting on for remote [device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/) and turning it off for [managed network](/cloudflare-one/connections/connect-devices/warp/configure-warp/managed-networks/) device profiles. In this configuration, remote devices will register their WARP interface IP, while on-premise devices will only register their local DHCP address. This allows the on-premise DNS server to resolve device hostnames no matter where the device is located. diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/hexnode.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/hexnode.mdx index ba90a307f1542e..007a062df66cdb 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/hexnode.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/hexnode.mdx @@ -3,7 +3,7 @@ pcx_content_type: how-to title: Hexnode sidebar: order: 2 - +description: Deploy Cloudflare WARP with Hexnode MDM - Step-by-step guide for Windows, macOS, iOS, and Android. --- ## Windows diff --git a/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/kandji.mdx b/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/kandji.mdx index 6de4580f6632af..4d0b56ace0a903 100644 --- a/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/kandji.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/partners/kandji.mdx @@ -3,6 +3,7 @@ pcx_content_type: how-to title: Kandji sidebar: order: 2 +description: Deploy Cloudflare WARP with Kandji on macOS using a custom configuration profile. --- Kandji deploys Cloudflare WARP as a custom app. For an overview of how Kandji deploys custom apps, refer to their [knowledge base article](https://support.kandji.io/custom-apps-overview). diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx new file mode 100644 index 00000000000000..026c1fc2c39a35 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/index.mdx @@ -0,0 +1,150 @@ +--- +pcx_content_type: how-to +title: Configure cloudflared parameters +sidebar: + order: 1 +--- + +import { TabItem, Tabs, Render } from "~/components"; + +Remotely-managed tunnels run as a service on your OS. You can modify the Cloudflare Tunnel service with one or more [general-purpose tunnel parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/). + +:::note +For instructions on configuring a locally-managed tunnel, refer to the [configuration file documentation](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). +::: + +## Update tunnel run parameters + + + +On Linux, Cloudflare Tunnel installs itself as a system service using `systemctl`. By default, the service will be named `cloudflared.service`. To configure your tunnel on Linux: + +1. Open `cloudflared.service`. + + ```sh + sudo systemctl edit --full cloudflared.service + ``` + +2. Modify the `cloudflared tunnel run` command with the desired configuration flag. For example, + + ```txt null {8} + [Unit] + Description=Cloudflare Tunnel + After=network.target + + [Service] + TimeoutStartSec=0 + Type=notify + ExecStart=/usr/local/bin/cloudflared tunnel --loglevel debug --logfile /var/log/cloudflared/cloudflared.log run --token + Restart=on-failure + RestartSec=5s + + [Install] + WantedBy=multi-user.target + ``` + +3. Restart `cloudflared.service`: + + ```sh + sudo systemctl restart cloudflared + ``` + +4. To verify the new configuration, check the service status: + + ```sh + sudo systemctl status cloudflared + ``` + ```sh output + ● cloudflared.service - cloudflared + Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; preset: enabled) + Active: active (running) since Wed 2024-10-09 20:02:59 UTC; 2s ago + Main PID: 2157 (cloudflared) + Tasks: 8 (limit: 1136) + Memory: 16.3M + CPU: 136ms + CGroup: /system.slice/cloudflared.service + └─2157 /usr/bin/cloudflared tunnel --loglevel debug --logfile /var/log/cloudflared/cloudflared.log run --token eyJhIjoi... + ``` + + + +On macOS, Cloudflare Tunnel installs itself as a launch agent using `launchctl`. By default, the agent will be called `com.cloudflare.cloudflared`. To configure your tunnel on macOS: + +1. Stop the `cloudflared` service. + + ```sh + sudo launchctl stop com.cloudflare.cloudflared + ``` + +2. Unload the configuration file. + + ```sh + sudo launchctl unload /Library/LaunchDaemons/com.cloudflare.cloudflared.plist + ``` + +3. Open `/Library/LaunchDaemons/com.cloudflare.cloudflared.plist` in a text editor. + +4. Modify the `ProgramArguments` key with the desired configuration flag. For example, + + ```txt + + + Label + com.cloudflare.cloudflared + ProgramArguments + + /opt/homebrew/bin/cloudflared + tunnel + --logfile + + --loglevel + debug + run + --token + + + ``` + +5. Load the updated configuration file. + + ```sh + sudo launchctl load /Library/LaunchDaemons/com.cloudflare.cloudflared.plist + ``` + +6. Start the `cloudflared` service. + + ```sh + sudo launchctl start com.cloudflare.cloudflared + ``` + + + +On Windows, Cloudflare Tunnel installs itself as a system service using the Registry Editor. By default, the service will be named `cloudflared`. To configure your tunnel on Windows: + +1. Open the Registry Editor. + +2. Go to **HKEY_LOCAL_MACHINE** > **SYSTEM** > **CurrentControlSet** > **Services** > **cloudflared**. + +3. Double-click **ImagePath**. + +4. Modify **Value data** with the desired configuration flag. For example, + + ```txt + C:\Program Files (x86)\cloudflared\.\cloudflared.exe tunnel --loglevel debug --logfile run --token + ``` + +![Modify cloudflared service in the Registry Editor](~/assets/images/cloudflare-one/connections/connect-apps/remote-management-windows.png) + + + + +## Update origin configuration + +To configure how `cloudflared` sends requests to your [public hostname](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) services: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. +2. Choose a tunnel and select **Configure**. +3. Select the **Public Hostname** tab. +4. Choose a route and select **Edit**. +5. Under **Additional application settings**, modify one or more [origin configuration parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). +6. Select **Save hostname**. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx similarity index 85% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx index 48793581bb7512..554fa22b40f6d3 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters.mdx @@ -1,12 +1,12 @@ --- pcx_content_type: reference -title: Origin configuration +title: Origin configuration parameters sidebar: - order: 3 + order: 9 --- -Origin configuration parameters determine how `cloudflared` proxies traffic to your origin server. You can configure these settings [in the dashboard](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/#update-origin-configuration) for remotely-managed tunnels, or add them to your [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#origin-configuration) for locally-managed tunnels. +Origin configuration parameters determine how `cloudflared` proxies traffic to your origin server. If you are using remotely-managed tunnels (default), configure these settings [using the dashboard or API](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/#update-origin-configuration). If you are using [locally-managed tunnels](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/), add these parameters to your [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). ## TLS settings @@ -111,7 +111,7 @@ This configures what type of proxy will be started. Valid options are: :::note -For locally-managed tunnels only. +For locally-managed tunnels only. ::: | Default | UI name | @@ -125,7 +125,7 @@ This configures the listen address for that proxy. :::note -For locally-managed tunnels only. +For locally-managed tunnels only. ::: | Default | UI name | @@ -173,7 +173,7 @@ The timeout after which a TCP keepalive packet is sent on a connection between C Requires `cloudflared` to validate the [Cloudflare Access JWT](/cloudflare-one/identity/authorization-cookie/validating-json/) prior to proxying traffic to your origin. You can enforce this check on public hostname routes that are protected by an Access application. For all L7 requests to these hostnames, Access will send the JWT to `cloudflared` as a `Cf-Access-Jwt-Assertion` request header. -To enable this security control in a [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#origin-configuration), [get the AUD tag](/cloudflare-one/identity/authorization-cookie/validating-json/#get-your-aud-tag) for your Access application and add the following rule to `originRequest`: +To enable this security control in a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#origin-configuration), [get the AUD tag](/cloudflare-one/identity/authorization-cookie/validating-json/#get-your-aud-tag) for your Access application and add the following rule to `originRequest`: ```yml access: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters.mdx similarity index 86% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters.mdx index ccfcbbe8250c62..3cdbba15547e95 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters.mdx @@ -3,10 +3,13 @@ pcx_content_type: reference title: Tunnel run parameters sidebar: order: 4 - --- -This page lists general-purpose configuration options for a Cloudflare Tunnel. You can add these flags to the `cloudflared tunnel run` command for [remotely-managed](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/) and [locally-managed](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/) tunnels. These flags can also be added as key/value pairs to your [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/). +import { Render } from "~/components"; + +This page lists general-purpose configuration options that you can [add](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/#update-tunnel-run-parameters) to the `cloudflared tunnel run` command. + +Alternatively, if you are running a [locally-managed tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/) you can add these flags to your [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) as key/value pairs. ## `autoupdate-freq` @@ -29,7 +32,7 @@ For locally-managed tunnels only. | ------------------------------------------------------- | --------------------------- | | `cloudflared tunnel --config run ` | `~/.cloudflared/config.yml` | -Specifies the path to a [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) in YAML format. +Specifies the path to a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) in YAML format. ## `edge-bind-address` @@ -47,7 +50,7 @@ The IP version of `edge-bind-address` will override [`edge-ip-version`](#edge-ip | Syntax | Default | Environment Variable | | ------------------------------------------------------------------- | ------- | ------------------------ | -| `cloudflared tunnel --edge-ip-version run ` | `4` | `TUNNEL_EDGE_IP_VERSION` | +| `cloudflared tunnel --edge-ip-version run ` | `4` | `TUNNEL_EDGE_IP_VERSION` | Specifies the IP address version (IPv4 or IPv6) used to establish a connection between `cloudflared` and the Cloudflare global network. Available values are `auto`, `4`, and `6`. @@ -79,14 +82,20 @@ Specifies the verbosity of logging for the local `cloudflared` instance. Availab ## `metrics` -| Syntax | Default | Environment Variable | -| ----------------------------------------------------------- | ------------ | -------------------- | -| `cloudflared tunnel --metrics run ` | Refer to [Tunnel metrics](/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics/)| `TUNNEL_METRICS` | +| Syntax | Default | Environment Variable | +| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------- | +| `cloudflared tunnel --metrics run ` | Refer to [Tunnel metrics](/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics/) | `TUNNEL_METRICS` | Exposes a Prometheus endpoint on the specified IP address and port, which you can then query for [usage metrics](/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics/). ## `no-autoupdate` +:::note + +Does not apply if you installed `cloudflared` using a package manager. + +::: + | Syntax | Environment Variable | | ------------------------------------------------------- | -------------------- | | `cloudflared tunnel --no-autoupdate run ` | `NO_AUTOUPDATE` | @@ -104,7 +113,7 @@ For locally-managed tunnels only. | ----------------------------------------------------------- | ------------------------- | -------------------- | | `cloudflared tunnel --origincert run ` | `~/.cloudflared/cert.pem` | `TUNNEL_ORIGIN_CERT` | -Specifies the [account certificate](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions/) for one of your zones, authorizing the client to serve as an origin for that zone. You can obtain a certificate by using the `cloudflared tunnel login` command or by visiting `https://dash.cloudflare.com/argotunnel`. +Specifies the [account certificate](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions/) for one of your zones, authorizing the client to serve as an origin for that zone. You can obtain a certificate by using the `cloudflared tunnel login` command or by visiting `https://dash.cloudflare.com/argotunnel`. ## `pidfile` diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/index.mdx index 397f89dbdfde0b..2625e47e1f05ee 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/index.mdx @@ -3,9 +3,6 @@ title: Configure a tunnel pcx_content_type: navigation sidebar: order: 3 - + group: + hideIndex: true --- - -import { DirectoryListing } from "~/components" - - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/index.mdx deleted file mode 100644 index 21cc0dc7649721..00000000000000 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/index.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -pcx_content_type: navigation -title: Locally-managed tunnel -sidebar: - order: 2 - ---- - -import { DirectoryListing } from "~/components" - -If you set up your tunnel [through the CLI](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/), the tunnel runs as an instance of `cloudflared` on your machine. You can configure `cloudflared` properties by modifying [command line parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/) or by editing the tunnel configuration file. - -The CLI provides a quick way to handle configurations if you are connecting a single service through `cloudflared`. If you are connecting multiple services and you need to configure properties or exceptions for specific origins, you can do so by defining ingress rules in your configuration file. - - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management.mdx deleted file mode 100644 index 1929dbdb45b0ca..00000000000000 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management.mdx +++ /dev/null @@ -1,309 +0,0 @@ ---- -pcx_content_type: how-to -title: Remotely-managed tunnel -sidebar: - order: 1 ---- - -import { TabItem, Tabs, Render } from "~/components"; - -If you created a Cloudflare Tunnel [from the dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/), the tunnel runs as a service on your OS. - -## Add tunnel run parameters - -You can modify the Cloudflare Tunnel service with one or more [general-purpose tunnel parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/). - - - -On Linux, Cloudflare Tunnel installs itself as a system service using `systemctl`. By default, the service will be named `cloudflared.service`. To configure your tunnel on Linux: - -1. Open `cloudflared.service`. - - ```sh - sudo systemctl edit --full cloudflared.service - ``` - -2. Modify the `cloudflared tunnel run` command with the desired configuration flag. For example, - - ```txt null {8} - [Unit] - Description=Cloudflare Tunnel - After=network.target - - [Service] - TimeoutStartSec=0 - Type=notify - ExecStart=/usr/local/bin/cloudflared tunnel --loglevel debug --logfile /var/log/cloudflared/cloudflared.log run --token - Restart=on-failure - RestartSec=5s - - [Install] - WantedBy=multi-user.target - ``` - -3. Restart `cloudflared.service`: - - ```sh - sudo systemctl restart cloudflared - ``` - -4. To verify the new configuration, check the service status: - - ```sh - sudo systemctl status cloudflared - ``` - ```sh output - ● cloudflared.service - cloudflared - Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; preset: enabled) - Active: active (running) since Wed 2024-10-09 20:02:59 UTC; 2s ago - Main PID: 2157 (cloudflared) - Tasks: 8 (limit: 1136) - Memory: 16.3M - CPU: 136ms - CGroup: /system.slice/cloudflared.service - └─2157 /usr/bin/cloudflared tunnel --loglevel debug --logfile /var/log/cloudflared/cloudflared.log run --token eyJhIjoi... - ``` - - - -On macOS, Cloudflare Tunnel installs itself as a launch agent using `launchctl`. By default, the agent will be called `com.cloudflare.cloudflared`. To configure your tunnel on macOS: - -1. Stop the `cloudflared` service. - - ```sh - sudo launchctl stop com.cloudflare.cloudflared - ``` - -2. Unload the configuration file. - - ```sh - sudo launchctl unload /Library/LaunchDaemons/com.cloudflare.cloudflared.plist - ``` - -3. Open `/Library/LaunchDaemons/com.cloudflare.cloudflared.plist` in a text editor. - -4. Modify the `ProgramArguments` key with the desired configuration flag. For example, - - ```txt - - - Label - com.cloudflare.cloudflared - ProgramArguments - - /opt/homebrew/bin/cloudflared - tunnel - --logfile - - --loglevel - debug - run - --token - - - ``` - -5. Load the updated configuration file. - - ```sh - sudo launchctl load /Library/LaunchDaemons/com.cloudflare.cloudflared.plist - ``` - -6. Start the `cloudflared` service. - - ```sh - sudo launchctl start com.cloudflare.cloudflared - ``` - - - -On Windows, Cloudflare Tunnel installs itself as a system service using the Registry Editor. By default, the service will be named `cloudflared`. To configure your tunnel on Windows: - -1. Open the Registry Editor. - -2. Go to **HKEY_LOCAL_MACHINE** > **SYSTEM** > **CurrentControlSet** > **Services** > **cloudflared**. - -3. Double-click **ImagePath**. - -4. Modify **Value data** with the desired configuration flag. For example, - - ```txt - C:\Program Files (x86)\cloudflared\.\cloudflared.exe tunnel --loglevel debug --logfile run --token - ``` - -![Modify cloudflared service in the Registry Editor](~/assets/images/cloudflare-one/connections/connect-apps/remote-management-windows.png) - - - -## Update origin configuration - -To configure how `cloudflared` sends requests to your [public hostname](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) services: - -1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. -2. Choose a tunnel and select **Configure**. -3. Select the **Public Hostname** tab. -4. Choose a route and select **Edit**. -5. Under **Additional application settings**, modify one or more [origin configuration parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/). -6. Select **Save hostname**. - -## Tunnel permissions - -A remotely-managed tunnel only requires the tunnel token to run. Anyone with access to the token will be able to run the tunnel. - -### View the tunnel token - -To get the token for a remotely-managed tunnel: - - - -1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. -2. Select a `cloudflared` tunnel and select **Edit**. -3. Copy `cloudflared` installation command. -4. Paste the installation command into any text editor. The token value is of the form `eyJhIjoiNWFiNGU5Z...` - - - - -Make a `GET` request to the [Cloudflare Tunnel token](/api/resources/zero_trust/subresources/tunnels/subresources/token/methods/get/) endpoint. The token value can be found in the `result`: - -```sh output -{ - "success": true, - "errors": [], - "messages": [], - "result": "eyJhIjoiNWFiNGU5Z..." -} -``` - - - - -### Rotate a token without service disruption - -Cloudflare recommends rotating the tunnel token at a regular cadence to reduce the risk of token compromise. You can rotate a token with minimal disruption to users as long as the tunnel is served by at least two [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/). To ensure service availability, we recommend performing token rotations outside of working hours or in a maintenance window. - -To rotate a tunnel token: - -1. Refresh the token on Cloudflare: - - - - 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. - 2. Select a `cloudflared` tunnel and select **Edit**. - 3. Select **Refresh token**. - 4. Copy the `cloudflared` installation command for your operating system. This command contains the new token. - - - - - 1. Generate a random base64 string (minimum size 32 bytes) to use as a tunnel secret: - - ```sh - openssl rand -base64 32 - ``` - - ```sh output - AQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwg= - ``` - - 2. Make a `PATCH` request to the [Cloudflare Tunnel](/api/resources/zero_trust/subresources/tunnels/methods/edit/) endpoint: - ```sh - curl --request PATCH \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/cfd_tunnel/{tunnel_id} \ - --header 'Content-Type: application/json' \ - --header "Authorization: Bearer " \ - --data '{ - "name": "Example tunnel", - "tunnel_secret": "AQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwg=" - }' - ``` - - ```sh output {18} - { - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415", - "account_tag": "699d98642c564d2e855e9661899b7252", - "created_at": "2024-12-04T22:03:26.291225Z", - "deleted_at": null, - "name": "Example tunnel", - "connections": [], - "conns_active_at": null, - "conns_inactive_at": "2024-12-04T22:03:26.291225Z", - "tun_type": "cfd_tunnel", - "metadata": {}, - "status": "inactive", - "remote_config": true, - "token": "eyJhIjoiNWFiNGU5Z..." - } - } - ``` - 3. Copy the `token` value shown in the output. - - - - - After refreshing the token, `cloudflared` can no longer establish new connections to Cloudflare using the old token. However, existing connectors will remain active and the tunnel will continue serving traffic. - -2. On half of your `cloudflared` replicas, update `cloudflared` to use the new token. For example, on a Linux host: - - ```sh - sudo cloudflared service install - ``` - -3. Restart `cloudflared`: - - ```sh - sudo systemctl restart cloudflared.service - ``` - -4. Confirm that the service started correctly: - ```sh - sudo systemctl status cloudflared - ``` - - While these replicas are connecting to Cloudflare with the new token, traffic will automatically route through the other replicas. - -5. Wait 10 minutes for traffic to route through the new connectors. - -6. Repeat steps 2, 3, and 4 for the second half of the replicas. - -The tunnel token is now fully rotated. The old token is no longer in use. - -### Rotate a compromised token - -If your tunnel token is compromised, we recommend taking the following steps: - -1. Refresh the token using the dashboard or API. Refer to Step 1 of [Rotate a token without service disruption](#rotate-a-token-without-service-disruption). -2. [Delete all connections](/api/resources/zero_trust/subresources/tunnels/subresources/connections/methods/delete/) between `cloudflared` and Cloudflare: - ```sh - curl --request DELETE \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/cfd_tunnel/{tunnel_id}/connections \ - --header "Authorization: Bearer " - ``` - - This will clean up any unauthorized connections and prevent users from connecting to your network. - -3. On each `cloudflared` replica, update `cloudflared` to use the new token. For example, on a Linux host: - - ```sh - sudo cloudflared service install - ``` -4. Restart `cloudflared`: - - ```sh - sudo systemctl restart cloudflared.service - ``` - -5. Confirm that the service started correctly: - ```sh - sudo systemctl status cloudflared - ``` - -The tunnel token is now fully rotated. The old token is no longer in use. - -### Account-scoped roles - - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-tunnel-permissions.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-tunnel-permissions.mdx new file mode 100644 index 00000000000000..a94b5d28e07ba9 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/remote-tunnel-permissions.mdx @@ -0,0 +1,168 @@ +--- +pcx_content_type: how-to +title: Tunnel permissions +sidebar: + order: 10 +--- + +import { TabItem, Tabs, Render } from "~/components"; + +A remotely-managed tunnel only requires the tunnel token to run. Anyone with access to the token will be able to run the tunnel. + +## View the tunnel token + +To get the token for a remotely-managed tunnel: + + + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. +2. Select a `cloudflared` tunnel and select **Edit**. +3. Copy `cloudflared` installation command. +4. Paste the installation command into any text editor. The token value is of the form `eyJhIjoiNWFiNGU5Z...` + + + + +Make a `GET` request to the [Cloudflare Tunnel token](/api/resources/zero_trust/subresources/tunnels/subresources/token/methods/get/) endpoint. The token value can be found in the `result`: + +```sh output +{ + "success": true, + "errors": [], + "messages": [], + "result": "eyJhIjoiNWFiNGU5Z..." +} +``` + + + + +## Rotate a token without service disruption + +Cloudflare recommends rotating the tunnel token at a regular cadence to reduce the risk of token compromise. You can rotate a token with minimal disruption to users as long as the tunnel is served by at least two [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/). To ensure service availability, we recommend performing token rotations outside of working hours or in a maintenance window. + +To rotate a tunnel token: + +1. Refresh the token on Cloudflare: + + + + 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels**. + 2. Select a `cloudflared` tunnel and select **Edit**. + 3. Select **Refresh token**. + 4. Copy the `cloudflared` installation command for your operating system. This command contains the new token. + + + + + 1. Generate a random base64 string (minimum size 32 bytes) to use as a tunnel secret: + + ```sh + openssl rand -base64 32 + ``` + + ```sh output + AQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwg= + ``` + + 2. Make a `PATCH` request to the [Cloudflare Tunnel](/api/resources/zero_trust/subresources/tunnels/methods/edit/) endpoint: + ```sh + curl --request PATCH \ + https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel/$TUNNEL_ID \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + --data '{ + "name": "Example tunnel", + "tunnel_secret": "AQIDBAUGBwgBAgMEBQYHCAECAwQFBgcIAQIDBAUGBwg=" + }' + ``` + + ```sh output {18} + { + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f70ff985-a4ef-4643-bbbc-4a0ed4fc8415", + "account_tag": "699d98642c564d2e855e9661899b7252", + "created_at": "2024-12-04T22:03:26.291225Z", + "deleted_at": null, + "name": "Example tunnel", + "connections": [], + "conns_active_at": null, + "conns_inactive_at": "2024-12-04T22:03:26.291225Z", + "tun_type": "cfd_tunnel", + "metadata": {}, + "status": "inactive", + "remote_config": true, + "token": "eyJhIjoiNWFiNGU5Z..." + } + } + ``` + 3. Copy the `token` value shown in the output. + + + + + After refreshing the token, `cloudflared` can no longer establish new connections to Cloudflare using the old token. However, existing connectors will remain active and the tunnel will continue serving traffic. + +2. On half of your `cloudflared` replicas, update `cloudflared` to use the new token. For example, on a Linux host: + + ```sh + sudo cloudflared service install + ``` + +3. Restart `cloudflared`: + + ```sh + sudo systemctl restart cloudflared.service + ``` + +4. Confirm that the service started correctly: + ```sh + sudo systemctl status cloudflared + ``` + + While these replicas are connecting to Cloudflare with the new token, traffic will automatically route through the other replicas. + +5. Wait 10 minutes for traffic to route through the new connectors. + +6. Repeat steps 2, 3, and 4 for the second half of the replicas. + +The tunnel token is now fully rotated. The old token is no longer in use. + +## Rotate a compromised token + +If your tunnel token is compromised, we recommend taking the following steps: + +1. Refresh the token using the dashboard or API. Refer to Step 1 of [Rotate a token without service disruption](#rotate-a-token-without-service-disruption). +2. [Delete all connections](/api/resources/zero_trust/subresources/tunnels/subresources/connections/methods/delete/) between `cloudflared` and Cloudflare: + ```sh + curl --request DELETE \ + https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel/$TUNNEL_ID/connections \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" + ``` + + This will clean up any unauthorized connections and prevent users from connecting to your network. + +3. On each `cloudflared` replica, update `cloudflared` to use the new token. For example, on a Linux host: + + ```sh + sudo cloudflared service install + ``` +4. Restart `cloudflared`: + + ```sh + sudo systemctl restart cloudflared.service + ``` + +5. Confirm that the service started correctly: + ```sh + sudo systemctl status cloudflared + ``` + +The tunnel token is now fully rotated. The old token is no longer in use. + +## Account-scoped roles + + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/index.mdx similarity index 92% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/index.mdx index 4d538b610f61a7..3dc882e58ec5bc 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: Tunnel availability and failover sidebar: - order: 2 + order: 4 --- import { Details, GlossaryTooltip } from "~/components"; @@ -25,7 +25,7 @@ By design, replicas do not offer any level of traffic steering (random, hash, or To deploy multiple instances of `cloudflared`, you can create and configure one tunnel and run it on multiple hosts. If your tunnel runs as a service, only one `cloudflared` instance is allowed per host. -
    +
    1. To create a remotely-managed tunnel, follow the [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). 2. On the **Tunnels** page, select your newly created tunnel. The **Connectors** section shows all of the `cloudflared` instances for that tunnel. @@ -37,11 +37,11 @@ The new replica will appear on the **Connectors** list for the tunnel.
    -
    +
    -1. To create a locally-managed tunnel, complete Steps 1 through 5 in the [CLI setup guide](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/). +1. To create a locally-managed tunnel, complete Steps 1 through 5 in the [CLI setup guide](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/). -2. Next, run your newly created tunnel. +2. Run your newly created tunnel. ```sh cloudflared tunnel run @@ -57,7 +57,7 @@ The new replica will appear on the **Connectors** list for the tunnel. This will initialize another `cloudflared` instance and generate another `connector_id`. -4. Next, run `tunnel info` to show each `cloudflared` instance running your tunnel: +4. Run `tunnel info` to show each `cloudflared` instance running your tunnel: ```sh cloudflared tunnel info @@ -71,7 +71,7 @@ You can run the same tunnel across various `cloudflared` processes for up to 100 :::note[Deploy replicas with Kubernetes] -For information about running `cloudflared` instances in a Kubernetes deployment, refer to our guides for tunnels managed [remotely via the dashboard](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/kubernetes/) or [locally via the CLI](/cloudflare-one/tutorials/many-cfd-one-tunnel/). +For information about running `cloudflared` instances in a Kubernetes deployment, refer to our guides for tunnels managed [remotely via the dashboard](/cloudflare-one/connections/connect-networks/deployment-guides/kubernetes/) or [locally via the CLI](/cloudflare-one/tutorials/many-cfd-one-tunnel/). ::: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements.mdx similarity index 94% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements.mdx index ac47183eafcc5c..b8b758d62d2e08 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: System requirements sidebar: - order: 3 + order: 6 --- import { Render, TabItem, Tabs, TunnelCalculator } from "~/components"; @@ -13,7 +13,7 @@ Our connector, `cloudflared`, was designed to be lightweight and flexible enough For most use cases, we recommend the following baseline configuration: -- Run a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/#cloudflared-replicas) on two dedicated host machines per network location. Using two hosts enables server-side redundancy and traffic balancing. +- Run a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/#cloudflared-replicas) on two dedicated host machines per network location. Using two hosts enables server-side redundancy and traffic balancing. - Size each host with minimum 4GB of RAM and 4 CPU cores. - Allocate 50,000 [ports](#number-of-ports) to the `cloudflared` process on each host. @@ -104,4 +104,4 @@ To calculate your tunnel capacity: -You can use these results to determine if your tunnel is appropriately sized. To increase your tunnel capacity, add identical host machines running [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/#cloudflared-replicas). +You can use these results to determine if your tunnel is appropriately sized. To increase your tunnel capacity, add identical host machines running [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/#cloudflared-replicas). diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall.mdx similarity index 99% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall.mdx index 2b7281bcda2a84..f51a9f5012a995 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall.mdx @@ -2,7 +2,7 @@ pcx_content_type: reference title: Tunnel with firewall sidebar: - order: 1 + order: 3 tableOfContents: false --- @@ -36,7 +36,7 @@ Opening port 443 enables some optional features. Failure to allow these connecti | `api.cloudflare.com` | `104.19.192.29`
    `104.19.192.177`
    `104.19.192.175`
    `104.19.193.29`
    `104.19.192.174`
    `104.19.192.176` | `2606:4700:300a::6813:c0af`
    `2606:4700:300a::6813:c01d`
    `2606:4700:300a::6813:c0ae`
    `2606:4700:300a::6813:c11d`
    `2606:4700:300a::6813:c0b0`
    `2606:4700:300a::6813:c0b1` | 443 | TCP (HTTPS) | Allows `cloudflared` to query if software updates are available. | | `update.argotunnel.com` | `104.18.25.129`
    `104.18.24.129` | `2606:4700::6812:1881`
    `2606:4700::6812:1981` | 443 | TCP (HTTPS) | Allows `cloudflared` to query if software updates are available. | | `github.com` | [GitHub's IP addresses](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses) | [GitHub's IP addresses](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses) | 443 | TCP (HTTPS) | Allows `cloudflared` to download the latest release and perform a software update. | -| `.`
    `cloudflareaccess.com` | `104.19.194.29`
    `104.19.195.29` | `2606:4700:300a::6813:c31d`
    `2606:4700:300a::6813:c21d` | 443 | TCP (HTTPS) | Allows `cloudflared` to validate the Access JWT. Only required if the [`access`](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#access) setting is enabled. | +| `.`
    `cloudflareaccess.com` | `104.19.194.29`
    `104.19.195.29` | `2606:4700:300a::6813:c31d`
    `2606:4700:300a::6813:c21d` | 443 | TCP (HTTPS) | Allows `cloudflared` to validate the Access JWT. Only required if the [`access`](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#access) setting is enabled. | | `pqtunnels.`
    `cloudflareresearch.com` | `104.18.4.64`
    `104.18.5.64` | `2606:4700::6812:540`
    `2606:4700::6812:440` | 443 | TCP (HTTPS) | Allows `cloudflared` to report [post-quantum key exchange](https://blog.cloudflare.com/post-quantum-tunnel/) errors to Cloudflare. | ## Firewall configuration diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/index.mdx deleted file mode 100644 index 967bdf0a3fb021..00000000000000 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/index.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Deploy a tunnel -pcx_content_type: navigation -sidebar: - order: 3 - ---- - -import { DirectoryListing } from "~/components" - - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/ansible.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx similarity index 95% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/ansible.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx index 26ae236adf68ee..2427bf42af1384 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/ansible.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/ansible.mdx @@ -9,14 +9,14 @@ import { Render } from "~/components"; Ansible is a software tool that enables at scale management of infrastructure. Ansible is agentless — all it needs to function is the ability to SSH to the target and Python installed on the target. -Ansible works alongside Terraform to streamline the Cloudflare Tunnel setup process. In this guide, you will use Terraform to deploy an SSH server on Google Cloud and create a [locally-managed tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/) that makes the server available over the Internet. Terraform will automatically run an Ansible playbook that installs and configures `cloudflared` on the server. +Ansible works alongside Terraform to streamline the Cloudflare Tunnel setup process. In this guide, you will use Terraform to deploy an SSH server on Google Cloud and create a [locally-managed tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/) that makes the server available over the Internet. Terraform will automatically run an Ansible playbook that installs and configures `cloudflared` on the server. ## Prerequisites To complete the steps in this guide, you will need: - [A Google Cloud Project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project) and [GCP CLI installed and authenticated](https://cloud.google.com/sdk/docs/install). -- [Basic knowledge of Terraform](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/terraform/) and[Terraform installed](https://developer.hashicorp.com/terraform/tutorials/certification-associate-tutorials/install-cli). +- [Basic knowledge of Terraform](/cloudflare-one/connections/connect-networks/deployment-guides/terraform/) and[Terraform installed](https://developer.hashicorp.com/terraform/tutorials/certification-associate-tutorials/install-cli). - [A zone on Cloudflare](/fundamentals/setup/manage-domains/add-site/). - [A Cloudflare API token](/fundamentals/api/get-started/create-token/) with `Cloudflare Tunnel` and `DNS` permissions. @@ -140,7 +140,7 @@ The following configuration will modify settings in your Cloudflare account. ### Configure GCP resources -The following configuration defines the specifications for the GCP virtual machine and installs Python3 on the machine. Python3 allows Ansible to configure the GCP instance instead of having to run a [startup script](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/terraform/#create-a-startup-script) on boot. +The following configuration defines the specifications for the GCP virtual machine and installs Python3 on the machine. Python3 allows Ansible to configure the GCP instance instead of having to run a [startup script](/cloudflare-one/connections/connect-networks/deployment-guides/terraform/#create-a-startup-script) on boot. 1. In your configuration directory, create a `.tf` file: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/aws.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx similarity index 87% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/aws.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx index 5a15cfee882ec4..e1efa8d1c1ca09 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/aws.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/aws.mdx @@ -9,6 +9,7 @@ head: --- import { Render } from "~/components"; +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; This guide covers how to connect an Amazon Web Services (AWS) virtual machine to Cloudflare using our lightweight connector, `cloudflared`. @@ -98,7 +99,20 @@ EOF [Private network routes](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) allow users to connect to your virtual private cloud (VPC) using the WARP client. To add a private network route for your Cloudflare Tunnel: 1. In the **Private Network** tab, enter the **Private IPv4 address** of your AWS instance (for example, `172.31.19.0`). You can expand the IP range later if necessary. -2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the private IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `172.16.0.0/12`. We recommend re-adding the IPs that are not explicitly used by your AWS instance -- you can use [this calculator](https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/) to determine which IP addresses to re-add. +2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the private IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `172.16.0.0/12`. We recommend re-adding the IPs that are not explicitly used by your AWS instance. + + To determine which IP addresses to re-add, subtract your AWS instance IPs from `172.16.0.0/12`: + + + + Add the results back to your Split Tunnel Exclude mode list. + 3. To test on a user device: 1. [Log in to the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/manual-deployment/). @@ -115,7 +129,7 @@ You can optionally [create Gateway network policies](/cloudflare-one/connections ## Firewall configuration -To secure your AWS instance, you can configure your [Security Group rules](https://docs.aws.amazon.com/vpc/latest/userguide/security-group-rules.html) to deny all inbound traffic and allow only outbound traffic to the [Cloudflare Tunnel IP addresses](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). All Security Group rules are Allow rules; traffic that does not match a rule is blocked. Therefore, you can delete all inbound rules and leave only the relevant outbound rules. +To secure your AWS instance, you can configure your [Security Group rules](https://docs.aws.amazon.com/vpc/latest/userguide/security-group-rules.html) to deny all inbound traffic and allow only outbound traffic to the [Cloudflare Tunnel IP addresses](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). All Security Group rules are Allow rules; traffic that does not match a rule is blocked. Therefore, you can delete all inbound rules and leave only the relevant outbound rules. :::note diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/azure.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/azure.mdx similarity index 100% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/azure.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/azure.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/google-cloud-platform.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx similarity index 86% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/google-cloud-platform.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx index 91fef839c8b5dd..cc0742d11a8b9e 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/google-cloud-platform.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/google-cloud-platform.mdx @@ -6,6 +6,7 @@ sidebar: --- import { Render } from "~/components"; +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; This guide covers how to connect a Google Cloud Project (GCP) virtual machine to Cloudflare using our lightweight connector, `cloudflared`. @@ -77,7 +78,19 @@ To complete the following procedure, you will need to: To configure a private network route for your Cloudflare Tunnel: 1. In the **Private Network** tab, enter the **Internal IP** of your GCP VM instance (for example, `10.0.0.2`). You can expand the IP range later if necessary. -2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the internal IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `10.0.0.0/8`. We recommend re-adding the IPs that are not explicitly used by your GCP VM -- you can use [this calculator](https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/) to determine which IP addresses to re-add. +2. In your [Split Tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#add-a-route), make sure the internal IP is routing through WARP. For example, if you are using Split Tunnels in Exclude mode, delete `10.0.0.0/8`. We recommend re-adding the IPs that are not explicitly used by your GCP VM. + + To determine which IP addresses to re-add, subtract your GCP instance IPs from `10.0.0.0/8`: + + + + Add the results back to your Split Tunnel Exclude mode list. 3. To test on a user device: 1. [Log in to the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/manual-deployment/). @@ -97,7 +110,7 @@ You can optionally [create Gateway network policies](/cloudflare-one/connections ## Firewall configuration -To secure your VM instance, you can [configure your VPC firewall rules](https://cloud.google.com/firewall/docs/using-firewalls) to deny all ingress traffic and allow only egress traffic to the [Cloudflare Tunnel IP addresses](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). Since GCP denies ingress traffic by [default](https://cloud.google.com/firewall/docs/firewalls#default_firewall_rules), you can delete all ingress rules and leave only the relevant egress rules. +To secure your VM instance, you can [configure your VPC firewall rules](https://cloud.google.com/firewall/docs/using-firewalls) to deny all ingress traffic and allow only egress traffic to the [Cloudflare Tunnel IP addresses](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). Since GCP denies ingress traffic by [default](https://cloud.google.com/firewall/docs/firewalls#default_firewall_rules), you can delete all ingress rules and leave only the relevant egress rules. :::note diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/index.mdx similarity index 69% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/index.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/index.mdx index a796eba3642b8a..c2001e98cc2686 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/index.mdx @@ -3,9 +3,10 @@ pcx_content_type: navigation title: Environments sidebar: order: 6 - --- import { DirectoryListing } from "~/components" +Learn how to deploy Cloudflare Tunnel in specific environments: + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/kubernetes.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/kubernetes.mdx similarity index 100% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/kubernetes.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/kubernetes.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/terraform.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx similarity index 100% rename from src/content/docs/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/terraform.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/deployment-guides/terraform.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/index.mdx index 37dd0dbea55f04..1c02f368a5e678 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Do more with Tunnel sidebar: - order: 7 + order: 11 --- diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/index.mdx similarity index 100% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/index.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/index.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/linux.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/linux.mdx similarity index 67% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/linux.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/linux.mdx index 5a2d6b007b8c8f..efa511a00897f1 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/linux.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/linux.mdx @@ -12,11 +12,11 @@ You can install `cloudflared` as a system service on Linux. ## Prerequisites -Before you install Cloudflare Tunnel as a service on Linux, follow Steps 1 through 4 of the [Tunnel CLI setup guide](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/). At this point you should have a named tunnel and a `config.yml` file in your `.cloudflared` directory. +Before you install Cloudflare Tunnel as a service on Linux, follow Steps 1 through 4 of the [Tunnel CLI setup guide](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/). At this point you should have a named tunnel and a `config.yml` file in your `.cloudflared` directory. ## 1. Configure `cloudflared` as a service -By default, Cloudflare Tunnel expects all of the configuration to exist in the `$HOME/.cloudflared/config.yml` [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: +By default, Cloudflare Tunnel expects all of the configuration to exist in the `$HOME/.cloudflared/config.yml` [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: | Argument | Description | | ------------------ | ---------------------------------------------------- | @@ -45,7 +45,7 @@ By default, Cloudflare Tunnel expects all of the configuration to exist in the ` ## Next steps -You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: +You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: ```sh systemctl restart cloudflared diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/macos.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/macos.mdx similarity index 75% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/macos.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/macos.mdx index acd721b1ccf877..3073fb92344c4e 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/macos.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/macos.mdx @@ -12,11 +12,11 @@ You can install `cloudflared` as a system service on macOS. ## Prerequisites -Before you install Cloudflare Tunnel as a service on your OS, follow Steps 1 through 4 of the [Tunnel CLI setup guide](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/). At this point you should have a named tunnel and a `config.yml` file in your `$HOME/.cloudflared` directory. +Before you install Cloudflare Tunnel as a service on your OS, follow Steps 1 through 4 of the [Tunnel CLI setup guide](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/). At this point you should have a named tunnel and a `config.yml` file in your `$HOME/.cloudflared` directory. ## 1. Configure `cloudflared` as a service -By default, Cloudflare Tunnel expects all of the configuration to exist in the `$HOME/.cloudflared/config.yml` [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: +By default, Cloudflare Tunnel expects all of the configuration to exist in the `$HOME/.cloudflared/config.yml` [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: | Argument | Description | | ------------------ | ---------------------------------------------------- | @@ -59,7 +59,7 @@ The output will be logged to `/Library/Logs/com.cloudflare.cloudflared.err.log` ## Next steps -You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: +You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: ```sh sudo launchctl stop com.cloudflare.cloudflared diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/windows.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/windows.mdx similarity index 85% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/windows.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/windows.mdx index 2851280cbee09e..f26ee642961376 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/windows.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/windows.mdx @@ -13,7 +13,7 @@ You can install `cloudflared` as a system service on Windows. ## Configure `cloudflared` as a service -By default, Cloudflare Tunnel expects all of the configuration to exist in the `%USERPROFILE%\.cloudflared\config.yml` [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: +By default, Cloudflare Tunnel expects all of the configuration to exist in the `%USERPROFILE%\.cloudflared\config.yml` [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). At a minimum you must specify the following arguments to run as a service: | Argument | Description | | ------------------ | ---------------------------------------------------- | @@ -64,9 +64,9 @@ By default, Cloudflare Tunnel expects all of the configuration to exist in the ` cloudflared.exe tunnel create ``` - This will generate a [credentials file](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#credentials-file) in `.json` format. + This will generate a [credentials file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#credentials-file) in `.json` format. -10. [Create a configuration file](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#4-create-a-configuration-file) with the following content: +10. [Create a configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#4-create-a-configuration-file) with the following content: ```txt tunnel: @@ -125,7 +125,7 @@ By default, Cloudflare Tunnel expects all of the configuration to exist in the ` ## Next steps -You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: +You can now [route traffic through your tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#5-start-routing-traffic). If you add IP routes or otherwise change the configuration, restart the service to load the new configuration: ```bash sc stop cloudflared diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file.mdx similarity index 87% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file.mdx index 83e4cf427888e5..a494696e4c8005 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file.mdx @@ -11,7 +11,9 @@ sidebar: ::: -The tunnel [configuration file](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#4-create-a-configuration-file) allows you to have fine-grained control over how an instance of `cloudflared` will operate. In your configuration file, you can specify top-level properties for your `cloudflared` instance as well as configure [origin-specific properties](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/). For a full list of configuration options, type `cloudflared tunnel help` in your terminal. +Locally-managed tunnels run as an instance of `cloudflared` on your machine. You can configure `cloudflared` properties by modifying [command line parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/) or by editing the tunnel [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#4-create-a-configuration-file). + +The CLI provides a quick way to handle configurations if you are connecting a single service through `cloudflared`. The tunnel configuration file is useful if you are connecting multiple services and need to configure properties or exceptions for specific origins. In the configuration file, you can define top-level properties for your `cloudflared` instance as well as [origin-specific properties](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/). For a full list of configuration options, type `cloudflared tunnel help` in your terminal. In the absence of a configuration file, `cloudflared` will proxy outbound traffic through port `8080`. @@ -115,7 +117,7 @@ ingress: ### Origin configuration -If you need to proxy traffic to multiple origins within one instance of `cloudflared`, you can define the way `cloudflared` sends requests to each service by specifying [configuration options](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/) as part of your ingress rules. +If you need to proxy traffic to multiple origins within one instance of `cloudflared`, you can define the way `cloudflared` sends requests to each service by specifying [configuration options](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/) as part of your ingress rules. In the following example, the top-level configuration `connectTimeout: 30s` sets a 30-second connection timeout for all services within that instance of `cloudflared`. The ingress rule for `service: localhost:8002` then configures an exception to the top-level configuration by setting `connectTimeout` for that service at `10s`. The 30-second connection timeout still applies to all other services. @@ -169,7 +171,7 @@ Matched rule #3 ## Update a configuration file -When making changes to the configuration file for a given tunnel, we suggest relying on [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) to propagate the new configuration with minimal downtime. +When making changes to the configuration file for a given tunnel, we suggest relying on [`cloudflared` replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) to propagate the new configuration with minimal downtime. 1. Have a `cloudflared` instance running with the original version of the configuration file. 2. Start a `cloudflared` replica running with the updated version of the configuration file. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel.mdx similarity index 87% rename from src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel.mdx index 4932292c38fb69..0e88f7428ba1e4 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel.mdx @@ -1,8 +1,8 @@ --- -title: Create a locally-managed tunnel (CLI) +title: Create a locally-managed tunnel pcx_content_type: how-to sidebar: - order: 2 + order: 1 --- import { Render, TabItem, Tabs } from "~/components"; @@ -105,7 +105,7 @@ cloudflared tunnel login Running this command will: - Open a browser window and prompt you to log in to your Cloudflare account. After logging in to your account, select your hostname. -- Generate an account certificate, the [cert.pem file](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#certpem), in the [default `cloudflared` directory](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#default-cloudflared-directory). +- Generate an account certificate, the [cert.pem file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#certpem), in the [default `cloudflared` directory](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#default-cloudflared-directory). ## 3. Create a tunnel and give it a name @@ -116,7 +116,7 @@ cloudflared tunnel create Running this command will: - Create a tunnel by establishing a persistent relationship between the [name you provide](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#tunnel-name) and a [UUID](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#tunnel-uuid) for your tunnel. At this point, no connection is active within the tunnel yet. -- Generate a [tunnel credentials file](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#credentials-file) in the [default `cloudflared` directory](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#default-cloudflared-directory). +- Generate a [tunnel credentials file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#credentials-file) in the [default `cloudflared` directory](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#certpem). - Create a subdomain of `.cfargotunnel.com`. From the output of the command, take note of the tunnel's UUID and the path to your tunnel's credentials file. @@ -129,7 +129,7 @@ cloudflared tunnel list ## 4. Create a configuration file -1. In your `.cloudflared` directory, create a [`config.yml` file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) using any text editor. This file will configure the tunnel to route traffic from a given origin to the hostname of your choice. +1. In your `.cloudflared` directory, create a [`config.yml` file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) using any text editor. This file will configure the tunnel to route traffic from a given origin to the hostname of your choice. 2. Add the following fields to the file: @@ -194,7 +194,7 @@ cloudflared tunnel --config /path/your-config-file.yml run :::note -Cloudflare Tunnel can install itself as a system service on Linux and Windows and as a launch agent on macOS. For more information, refer to [run as a service](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/). +Cloudflare Tunnel can install itself as a system service on Linux and Windows and as a launch agent on macOS. For more information, refer to [run as a service](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/). ::: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/index.mdx new file mode 100644 index 00000000000000..3b8828cd295aef --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/index.mdx @@ -0,0 +1,18 @@ +--- +pcx_content_type: navigation +title: Locally-managed tunnels +sidebar: + order: 2 + +--- + +import { DirectoryListing } from "~/components" + + +A loocally-managed tunnel is a Cloudflare Tunnel created by running `cloudflared tunnel create ` on the command line. Tunnel configuration is stored in your local [cloudflared directory](#default-cloudflared-directory). + +:::note +Cloudflare recommends setting up a [remotely-managed tunnel](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). Remotely-managed configurations are stored on Cloudflare, which allows you to manage the tunnel from any machine using the dashboard, API, or Terraform. +::: + + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms.mdx new file mode 100644 index 00000000000000..a56a2acab8b39c --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms.mdx @@ -0,0 +1,35 @@ +--- +pcx_content_type: reference +title: Useful terms +sidebar: + order: 10 +--- + +This page contains terminology specific to locally-managed Cloudflare Tunnels. For general Tunnel terminology, refer to the [Get started section](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/). + +## Default `cloudflared` directory + +`cloudflared` uses a default directory when storing credentials files for your tunnels, as well as the `cert.pem` file it generates when you run `cloudflared login`. The default directory is also where `cloudflared` will look for a [configuration file](#configuration-file) if no other file path is specified when running a tunnel. + +| OS | Path to default directory | +| --------------------------- | -------------------------------------------------------------------------------------- | +| Windows | `%USERPROFILE%\.cloudflared` | +| macOS and Unix-like systems | `~/.cloudflared`, `/etc/cloudflared`, and `/usr/local/etc/cloudflared`, in this order. | + +## Configuration file + +This is a YAML file that functions as the operating manual for `cloudflared`. `cloudflared` will automatically look for the configuration file in the [default `cloudflared` directory](#default-cloudflared-directory), but you can store your configuration file in any directory. It is recommended to always specify the file path for your configuration file whenever you reference it. By creating a configuration file, you can have fine-grained control over how their instance of `cloudflared` will operate. This includes operations like what you want `cloudflared` to do with traffic (for example, proxy websockets to port `xxxx` or SSH to port `yyyy`), where `cloudflared` should search for authorization (credentials file, tunnel token), and what mode it should run in (for example, [`warp-routing`](/cloudflare-one/connections/connect-networks/private-net/)). In the absence of a configuration file, cloudflared will proxy outbound traffic through port `8080`. For more information on how to create, store, and structure a configuration file, refer to the [dedicated instructions](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). + +## Cert.pem + +This is the certificate file issued by Cloudflare when you run `cloudflared tunnel login`. This file uses a certificate to authenticate your instance of `cloudflared` and it is required when you create new tunnels, delete existing tunnels, change DNS records, or configure tunnel routing from cloudflared. This file is not required to perform actions such as running an existing tunnel or managing tunnel routing from the Cloudflare dashboard. Refer to the [Tunnel permissions page](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions/) for more details on when this file is needed. + +The `cert.pem` origin certificate is valid for at least 10 years, and the service token it contains is valid until revoked. + +## Credentials file + +This file is created when you run `cloudflared tunnel create `. It stores your tunnel's credentials in JSON format, and is unique to each tunnel. This file functions as a token authenticating the tunnel it is associated with. Refer to the [Tunnel permissions page](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions/) for more details on when this file is needed. + +## Ingress rule + +Ingress rules let you specify which local services traffic should be proxied to. If a rule does not specify a path, all paths will be matched. Ingress rules can be listed in your [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) or when running `cloudflared tunnel ingress`. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions.mdx similarity index 100% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-permissions.mdx diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-useful-commands.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-useful-commands.mdx similarity index 98% rename from src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-useful-commands.mdx rename to src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-useful-commands.mdx index e3e4bbbe6d0307..30bcc1addae328 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-useful-commands.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-useful-commands.mdx @@ -26,7 +26,7 @@ To view all CLI commands, refer to the CLI help text in your terminal. For examp | `cloudflared tunnel --config path/config.yaml run ` | Runs a tunnel, creating highly available connections between your server and the Cloudflare edge. You can provide name or UUID of the tunnel to run either as the last command line argument or in the configuration file using `tunnel: `. | | `cloudflared tunnel info ` | Displays details about the active connectors for a given tunnel identified by name of UUID. | | `cloudflared tunnel cleanup ` | Deletes connections for tunnels with the given UUIDs or names. This is useful if you get an error trying to delete or run a tunnel after `cloudflared` is not shut down gracefully (for example, if a `kill` command is issued). | -| `cloudflared tunnel cleanup --connector-id ` | Disconnects and deletes a [cloudflared replica](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) with the given connector ID. You can view all replicas for a tunnel by running `cloudflared tunnel info `. | +| `cloudflared tunnel cleanup --connector-id ` | Disconnects and deletes a [cloudflared replica](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) with the given connector ID. You can view all replicas for a tunnel by running `cloudflared tunnel info `. | | `cloudflared tunnel delete ` | Deletes tunnels with the given name or UUID. A tunnel cannot be deleted if it has active connections. To delete the tunnel unconditionally, use the `-f` flag. | | `cloudflared tunnel vnet add ` | Creates a Virtual Network to which IP routes can be assigned. To make this Virtual Network the default for your Zero Trust organization, use the `-d` flag. | | `cloudflared tunnel vnet delete ` | Deletes the Virtual Network with the given name or UUID. Before you can delete a Virtual Network, you must first delete all IP routes assigned to the Virtual Network. | diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels.mdx index cc3bd1491a58f6..34861c011fde78 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels.mdx @@ -34,7 +34,7 @@ To migrate your legacy tunnels to the named tunnels architecture: 2. Obtain a new origin certificate by running `cloudflared login`. While named tunnels are scoped to an account, for legacy reasons the login page requires selecting a zone. -3. [Create a tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#3-create-a-tunnel-and-give-it-a-name). +3. [Create a tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#3-create-a-tunnel-and-give-it-a-name). ```sh cloudflared tunnel create @@ -54,7 +54,7 @@ To migrate your legacy tunnels to the named tunnels architecture: cloudflared tunnel route lb ``` -5. Next, create a [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) with ingress rules. The ingress rules describe how to dispatch requests to your origins based on hostname and path. For example, if in the past you used to run `cloudflared tunnel --hostname tunnel.example.com --url https://localhost:3000`, you should add an equivalent ingress rule to your configuration file: +5. Next, create a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) with ingress rules. The ingress rules describe how to dispatch requests to your origins based on hostname and path. For example, if in the past you used to run `cloudflared tunnel --hostname tunnel.example.com --url https://localhost:3000`, you should add an equivalent ingress rule to your configuration file: ```yml ingress: @@ -64,7 +64,7 @@ To migrate your legacy tunnels to the named tunnels architecture: # Note that the last rule is the catch-all rule and is required. ``` -6. [Run your tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#6-run-the-tunnel). +6. [Run your tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#6-run-the-tunnel). ## Make sure everything works diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/downloads/update-cloudflared.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/downloads/update-cloudflared.mdx index 4b728a5963a52c..9ea0e712994ec9 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/downloads/update-cloudflared.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/downloads/update-cloudflared.mdx @@ -5,7 +5,7 @@ sidebar: order: 5 --- -import { TabItem, Tabs } from "~/components"; +import { TabItem, Tabs, Render } from "~/components"; Updates will cause `cloudflared` to restart which will impact traffic currently being served. You can perform zero-downtime upgrades by using Cloudflare's [Load Balancer product](/cloudflare-one/connections/connect-networks/downloads/update-cloudflared/#update-with-cloudflare-load-balancer) or by using [multiple `cloudflared` instances](/cloudflare-one/connections/connect-networks/downloads/update-cloudflared/#update-with-multiple-cloudflared-instances). @@ -21,7 +21,11 @@ Run the following command: cloudflared update ``` -This updates `cloudflared` and automatically restarts the service. +After running `cloudflared update` to update `cloudflared`, you must restart the service for it to take effect. Run: + +```powershell +net start cloudflared +``` @@ -58,7 +62,7 @@ sudo systemctl restart cloudflared.service **If installed manually via `dpkg -i`:** -You can check if `cloudflared` was installed by a package manager by running `ls -la /usr/local/etc/cloudflared/` and looking for `.installedFromPackageManager` in the output. + 1. Update the `cloudflared` package: @@ -103,7 +107,7 @@ If you installed `cloudflared` from GitHub-provided binaries or from source, run cloudflared update ``` -If you installed `cloudflared` with a package manager, you must update it using the same package manager. You can check if `cloudflared` was installed by a package manager by running `ls -la /usr/local/etc/cloudflared/` and looking for `.installedFromPackageManager` in the output. +If you installed `cloudflared` with a package manager, you must update it using the same package manager. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx new file mode 100644 index 00000000000000..e445b2188b1240 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel-api.mdx @@ -0,0 +1,262 @@ +--- +title: Create a tunnel (API) +pcx_content_type: how-to +sidebar: + order: 2 +--- + +import { Tabs, TabItem } from "~/components"; + +Follow this guide to set up a Cloudflare Tunnel using the API. + +## 1. Create an API token + +[Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: + +| Type | Item | Permission | +| ------- | ----------------- | ---------- | +| Account | Cloudflare Tunnel | Edit | +| Zone | DNS | Edit | + +## 2. Create a tunnel + +Make a `POST` request to the [Cloudflare Tunnel](/api/resources/zero_trust/subresources/tunnels/subresources/cloudflared/methods/create/) endpoint: + +```sh +curl 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel' \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "api-tunnel", + "config_src": "cloudflare" +}' +``` + +```sh output +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "account_tag": "699d98642c564d2e855e9661899b7252", + "created_at": "2025-02-18T22:41:43.534395Z", + "deleted_at": null, + "name": "example-tunnel", + "connections": [], + "conns_active_at": null, + "conns_inactive_at": "2025-02-18T22:41:43.534395Z", + "tun_type": "cfd_tunnel", + "metadata": {}, + "status": "inactive", + "remote_config": true, + "credentials_file": { + "AccountTag": "699d98642c564d2e855e9661899b7252", + "TunnelID": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "TunnelName": "api-tunnel", + "TunnelSecret": "bTSquyUGwLQjYJn8cI8S1h6M6wUc2ajIeT7JotlxI7TqNqdKFhuQwX3O8irSnb==" + }, + "token": "eyJhIjoiNWFiNGU5Z..." + } +} +``` + +Copy the `id` and `token` values shown in the output. You will need these values to configure and run the tunnel. + +The next steps depend on whether you want to [connect an application](#3a-connect-an-application) or [connect a network](#3b-connect-a-network). + +## 3a. Connect an application + +Before you connect an application through your tunnel, you must: + +- [Add a website to Cloudflare](/fundamentals/setup/manage-domains/add-site/). +- [Change your domain nameservers to Cloudflare](/dns/zone-setups/full-setup/setup/). + +Follow these steps to connect an application through your tunnel. If you are looking to connect a network, skip to the [Connect a network section](#3b-connect-a-network). + +1. Make a [`PUT` request](/api/resources/zero_trust/subresources/tunnels/subresources/cloudflared/subresources/configurations/methods/update/) to route your local service URL to a public hostname. For example, + + ```sh + curl --request PUT \ + 'https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel/c1744f8b-faa1-48a4-9e5c-02ac921467fa/configurations' \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + --data '{ + "config": { + "ingress": [ + { + "hostname": "app.example.com", + "service": "http://localhost:8001", + "originRequest": {} + }, + { + "service": "http_status:404" + } + ] + } + }' + ``` + + :::note + If you add a multi-level subdomain (more than one level of subdomain), you must [order an Advanced Certificate for the hostname](/cloudflare-one/faq/troubleshooting/#i-see-this-site-cant-provide-a-secure-connection). + ::: + + Your ingress rules must include a catch-all rule at the end. In this example, `cloudflared` will respond with a 404 status code when the request does not match any of the previous hostnames. + +2. [Create a DNS record](/api/resources/dns/subresources/records/methods/create/) for your application: + + ```sh + curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + --data '{ + "type": "CNAME", + "proxied": true, + "name": "app.example.com", + "content": "c1744f8b-faa1-48a4-9e5c-02ac921467fa.cfargotunnel.com" + }' + ``` + + This DNS record allows Cloudflare to proxy `app.example.com` traffic to your Cloudflare Tunnel (`.cfargotunnel.com`). + +This application will be publicly available on the Internet once you [run the tunnel](#4-install-and-run-the-tunnel). To allow or block specific users, [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). + +## 3b. Connect a network + +To connect a private network through your tunnel, [add a tunnel route](/api/resources/zero_trust/subresources/networks/subresources/routes/methods/create/): + +```sh +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/routes \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "network": "172.16.0.0/16", + "tunnel_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "comment": "Example private network route" +}' +``` + +To configure Zero Trust policies and connect as a user, refer to [Connect private networks](/cloudflare-one/connections/connect-networks/private-net/cloudflared/). + +## 4. Install and run the tunnel + +Install `cloudflared` on your server and run the tunnel using the `token` value obtained in [2. Create a tunnel](#2-create-a-tunnel). You can also get the tunnel token using the [Cloudflare Tunnel token](/api/resources/zero_trust/subresources/tunnels/subresources/cloudflared/subresources/token/methods/get/) endpoint. + + + +1. [Download and install](/cloudflare-one/connections/connect-networks/downloads/#windows) `cloudflared`. + +2. Open Command Prompt as administrator. + +3. Run the following command: + + ```txt + cloudflared.exe service install + ``` + + + +1. [Download and install](/cloudflare-one/connections/connect-networks/downloads/#macos) `cloudflared`. + +2. Run the following command: + + ```sh + sudo cloudflared service install + ``` + + + +1. [Download and install](https://pkg.cloudflare.com/index.html) `cloudflared`. + +2. Run the following command: + + ```sh + sudo cloudflared service install + ``` + + + +1. Open a terminal window. + +2. Run the following command: + + ```sh + docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token + ``` + + + +## 5. Verify tunnel status + +To check if the tunnel is serving traffic: + +```sh +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/cfd_tunnel/c1744f8b-faa1-48a4-9e5c-02ac921467fa \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" +``` + +```sh output +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa", + "account_tag": "699d98642c564d2e855e9661899b7252", + "created_at": "2025-02-18T22:41:43.534395Z", + "deleted_at": null, + "name": "example-tunnel", + "connections": [ + { + "colo_name": "bos01", + "uuid": "2xz99mfm-a59e-4924-gyh9-z9vafaw6k0i2", + "id": "2xz99mfm-a59e-4924-gyh9-z9vafaw6k0i2", + "is_pending_reconnect": false, + "origin_ip": "10.1.0.137", + "opened_at": "2025-02-19T19:11:12.101642Z", + "client_id": "4xh4eb3f-cz0j-2aso-hu6i-36207018771a", + "client_version": "2025.2.0" + }, + { + "colo_name": "phl01", + "uuid": "axe2socu-2fb5-3akx-b860-898zyes3cs9q", + "id": "axe2socu-2fb5-3akx-b860-898zyes3cs9q", + "is_pending_reconnect": false, + "origin_ip": "10.1.0.137", + "opened_at": "2025-02-19T19:11:12.006297Z", + "client_id": "4xh4eb3f-cz0j-2aso-hu6i-36207018771a", + "client_version": "2025.2.0" + }, + { + "colo_name": "phl01", + "uuid": "9b5y0wm9-ca7f-ibq6-8ff4-sm53xekfyym1", + "id": "9b5y0wm9-ca7f-ibq6-8ff4-sm53xekfyym1", + "is_pending_reconnect": false, + "origin_ip": "10.1.0.137", + "opened_at": "2025-02-19T19:11:12.004721Z", + "client_id": "4xh4eb3f-cz0j-2aso-hu6i-36207018771a", + "client_version": "2025.2.0" + }, + { + "colo_name": "bos01", + "uuid": "g6cdeiz1-80f5-3akx-b18b-3y0ggktoxwkd", + "id": "g6cdeiz1-80f5-3akx-b18b-3y0ggktoxwkd", + "is_pending_reconnect": false, + "origin_ip": "10.1.0.137", + "opened_at": "2025-02-19T19:11:12.110765Z", + "client_id": "4xh4eb3f-cz0j-2aso-hu6i-36207018771a", + "client_version": "2025.2.0" + } + ], + "conns_active_at": "2025-02-19T19:11:12.004721Z", + "conns_inactive_at": null, + "tun_type": "cfd_tunnel", + "metadata": {}, + "status": "healthy", + "remote_config": true + } +} +``` + +A healthy tunnel will have four connections to Cloudflare's network. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx index e3f91cbe5ff87a..967529acb49b8a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel.mdx @@ -1,5 +1,5 @@ --- -title: Create a remotely-managed tunnel (dashboard) +title: Create a tunnel (dashboard) pcx_content_type: how-to sidebar: order: 1 @@ -7,7 +7,7 @@ sidebar: import { Render } from "~/components"; -Follow this step-by-step guide to get your first tunnel up and running using Zero Trust. +Follow this step-by-step guide to create your first [remotely-managed tunnel](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#remotely-managed-tunnel) using Zero Trust. ## 1. Create a tunnel @@ -26,8 +26,6 @@ Follow these steps to connect an application through your tunnel. If you are loo -If you add a multi-level subdomain (more than one level of subdomain), you must [order an Advanced Certificate for the hostname](/cloudflare-one/faq/troubleshooting/#i-see-this-site-cant-provide-a-secure-connection). - The application is now publicly available on the Internet. To allow or block specific users, [create an Access application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/). ## 2b. Connect a network diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/index.mdx index 99594af411ebac..c013e2b4bc20b9 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/index.mdx @@ -13,6 +13,4 @@ import { DirectoryListing, GlossaryTooltip } from "~/components" To create and manage tunnels, you will need to install and authenticate cloudflared on your origin server. `cloudflared` is what connects your server to Cloudflare's global network. -You have the option of creating a tunnel [via the dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) or [via the command line](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/). We recommend getting started with the dashboard, since it will allow you to manage the tunnel from any machine. - diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms.mdx index 0ccef5a20767a4..dd716fa7d05ac0 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms.mdx @@ -33,34 +33,7 @@ A remotely-managed tunnel is a [tunnel](#tunnel) that was created in [Zero Trust ## Locally-managed tunnel -A locally-managed tunnel is a [tunnel](#tunnel) that was created by running `cloudflared tunnel create ` on the command line. Tunnel configuration is stored in your local [cloudflared directory](#default-cloudflared-directory). - -### Default `cloudflared` directory - -`cloudflared` uses a default directory when storing credentials files for your tunnels, as well as the `cert.pem` file it generates when you run `cloudflared login`. The default directory is also where `cloudflared` will look for a [configuration file](#configuration-file) if no other file path is specified when running a tunnel. - -| OS | Path to default directory | -| --------------------------- | -------------------------------------------------------------------------------------- | -| Windows | `%USERPROFILE%\.cloudflared` | -| macOS and Unix-like systems | `~/.cloudflared`, `/etc/cloudflared`, and `/usr/local/etc/cloudflared`, in this order. | - -### Configuration file - -This is a YAML file that functions as the operating manual for `cloudflared`. `cloudflared` will automatically look for the configuration file in the [default `cloudflared` directory](#default-cloudflared-directory), but you can store your configuration file in any directory. It is recommended to always specify the file path for your configuration file whenever you reference it. By creating a configuration file, you can have fine-grained control over how their instance of `cloudflared` will operate. This includes operations like what you want `cloudflared` to do with traffic (for example, proxy websockets to port `xxxx` or SSH to port `yyyy`), where `cloudflared` should search for authorization (credentials file, tunnel token), and what mode it should run in (for example, [`warp-routing`](/cloudflare-one/connections/connect-networks/private-net/)). In the absence of a configuration file, cloudflared will proxy outbound traffic through port `8080`. For more information on how to create, store, and structure a configuration file, refer to the [dedicated instructions](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/). - -### Cert.pem - -This is the certificate file issued by Cloudflare when you run `cloudflared tunnel login`. This file uses a certificate to authenticate your instance of `cloudflared` and it is required when you create new tunnels, delete existing tunnels, change DNS records, or configure tunnel routing from cloudflared. This file is not required to perform actions such as running an existing tunnel or managing tunnel routing from the Cloudflare dashboard. Refer to the [Tunnel permissions page](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions/) for more details on when this file is needed. - -The `cert.pem` origin certificate is valid for at least 10 years, and the service token it contains is valid until revoked. - -### Credentials file - -This file is created when you run `cloudflared tunnel create `. It stores your tunnel's credentials in JSON format, and is unique to each tunnel. This file functions as a token authenticating the tunnel it is associated with. Refer to the [Tunnel permissions page](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/tunnel-permissions/) for more details on when this file is needed. - -### Ingress rule - -Ingress rules let you specify which local services traffic should be proxied to. If a rule does not specify a path, all paths will be matched. Ingress rules can be listed in your [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) or when running `cloudflared tunnel ingress`. +A locally-managed tunnel is a [tunnel](#tunnel) that was created by running `cloudflared tunnel create ` on the command line. Tunnel configuration is stored in your local [cloudflared directory](#default-cloudflared-directory). For terminology specific to locally-managed tunnels, refer to the [Locally-managed tunnel glossary](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/). ## Quick tunnels diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/index.mdx index 094637e601bd67..a6ba333ef5b74e 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Monitor tunnels sidebar: - order: 6 + order: 9 --- diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/logs.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/logs.mdx index 3eb0b4f45ed7bf..84b9c1ca42e729 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/logs.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/logs.mdx @@ -12,7 +12,7 @@ Tunnel logs record all activity between a `cloudflared` instance and Cloudflare' ## View logs on the server -If you have access to the origin server, you can use the [`--loglevel` flag](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#loglevel) to enable logging when you start the tunnel. By default, `cloudflared` prints logs to stdout and does not store logs on the server. You can optionally use the [`--logfile` flag](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#logfile) to write your logs to a file. +If you have access to the origin server, you can use the [`--loglevel` flag](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#loglevel) to enable logging when you start the tunnel. By default, `cloudflared` prints logs to stdout and does not store logs on the server. You can optionally use the [`--logfile` flag](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#logfile) to write your logs to a file. To enable logs for a locally-managed tunnel: @@ -20,7 +20,7 @@ To enable logs for a locally-managed tunnel: cloudflared tunnel --loglevel debug --logfile cloudflared.log run ``` -To enable logs for a remotely-managed tunnel, add `--loglevel debug` and `--logfile ` to your system service as shown in [Add tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/#add-tunnel-run-parameters). +To enable logs for a remotely-managed tunnel, add `--loglevel debug` and `--logfile ` to your system service as shown in [Add tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/#update-tunnel-run-parameters). ## View logs on your local machine @@ -69,13 +69,13 @@ cloudflared tail --level debug | Flag | Description | Allowed values | Default value | | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------- | | `--event` | Filter by the type of event / request. | `cloudflared`, `http`, `tcp`, `udp` | All events | -| `--level` | Return logs at this level and above. Works independently of the [`--loglevel`](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#loglevel) setting on the server. | `debug`, `info`, `warn`, `error`, `fatal` | `debug` | +| `--level` | Return logs at this level and above. Works independently of the [`--loglevel`](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#loglevel) setting on the server. | `debug`, `info`, `warn`, `error`, `fatal` | `debug` | | `--sampling` | Sample a fraction of the total logs. | Number from `0.0` to `1.0` | `1.0` | | | | | | #### View logs for a replica -If you are running multiple `cloudflared` instances for the same tunnel (also known as [replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/)), you must specify an individual instance to stream logs from: +If you are running multiple `cloudflared` instances for the same tunnel (also known as [replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/)), you must specify an individual instance to stream logs from: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Networks** > **Tunnels** and select your tunnel. 2. Find the **Connector ID** for the `cloudflared` instance you want to view. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics.mdx index c4e0e26732ff7f..7f373009656222 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics.mdx @@ -24,13 +24,13 @@ To determine the default port being used by a `cloudflared` instance, you can ch To serve metrics on a custom IP address and port, perform these steps on the `cloudflared` host: -1. Run the tunnel using the [--metrics](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#metrics) flag. Here is an example command for a locally-managed tunnel: +1. Run the tunnel using the [--metrics](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#metrics) flag. Here is an example command for a locally-managed tunnel: ```sh cloudflared tunnel --metrics 127.0.0.1:60123 run my-tunnel ``` - To learn how to add the `--metrics` flag to a remotely-managed tunnel, refer to [Configure a remotely-managed tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/#add-tunnel-run-parameters). + To learn how to add the `--metrics` flag to a remotely-managed tunnel, refer to [Configure a remotely-managed tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/#update-tunnel-run-parameters). :::note If you plan to fetch metrics from another machine on the local network, replace `127.0.0.1` with the internal IP of the `cloudflared` server (for example, `198.168.x.x`). To serve metrics on all available network interfaces, use `0.0.0.0`. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx index 0f7a040557307b..090c5ce74af888 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/index.mdx @@ -19,7 +19,8 @@ To enable remote access to your private network, follow the guide below. To connect your infrastructure with Cloudflare Tunnel: -1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the connect an application step and go straight to connecting a network. + + 2. In the **Private Networks** tab for the tunnel, enter the IP/CIDR range that you wish to route through the tunnel (for example `10.0.0.0/8`). ## 2. Set up the client diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx index e7a7b5fc958129..7ba2feb7061b38 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns.mdx @@ -23,7 +23,7 @@ Ensure that **Split Tunnels** are configured to [include traffic to private IPs ::: -5. Finally, ensure that your tunnel uses QUIC as the default [transport protocol](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#protocol). This will enable `cloudflared` to proxy UDP-based traffic which is required in most cases to resolve DNS queries. +5. Finally, ensure that your tunnel uses QUIC as the default [transport protocol](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#protocol). This will enable `cloudflared` to proxy UDP-based traffic which is required in most cases to resolve DNS queries. The WARP client will now resolve requests through the internal DNS server you set up in your private network. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx index 9d5b79ff00ebf6..e39ef7ebcc1656 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks.mdx @@ -38,7 +38,7 @@ Here are a few scenarios where virtual networks may prove useful: ## Prerequisites -- [Install `cloudflared`](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#1-download-and-install-cloudflared) on each private network. +- [Install `cloudflared`](/cloudflare-one/connections/connect-networks/downloads/) on each private network. - [Deploy the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/) on user devices. ## Create a virtual network @@ -137,7 +137,7 @@ The following example demonstrates how to add two overlapping IP routes to Cloud We now have two overlapping IP addresses routed over `staging-vnet` and `production-vnet` respectively. - 6. Within your staging environment, create a [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) for `staging-tunnel`. The configuration file will be structured as follows: + 6. Within your staging environment, create a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) for `staging-tunnel`. The configuration file will be structured as follows: ```txt tunnel: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx index 9418c9f194e678..554f09cc4b6775 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: Private networks sidebar: - order: 5 + order: 7 --- With Cloudflare Zero Trust, you can connect private networks and the services running in those networks to Cloudflare's global network. This involves installing a [connector](#connectors) on the private network, and then [setting up routes](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#2b-connect-a-network) which define the IP addresses available in that environment. Unlike [public hostname routes](/cloudflare-one/connections/connect-networks/routing-to-tunnel/), private network routes can expose both HTTP and non-HTTP resources. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx index 7a1384001f7d2e..74ef08215e0c92 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/private-net/warp-connector/index.mdx @@ -32,7 +32,7 @@ import { Render, Details} from "~/components"; WARP Connector is not currently supported in accounts that have [Magic WAN](/magic-wan/) enabled. ::: -Cloudflare WARP Connector is a software client[^1] that enables site-to-site, bidirectional, and mesh networking connectivity without requiring changes to underlying network routing infrastructure. WARP Connector establishes a secure Layer 3 proxy between a private network and Cloudflare, allowing you to: +Cloudflare WARP Connector (beta) is a software client[^1] that enables site-to-site, bidirectional, and mesh networking connectivity without requiring changes to underlying network routing infrastructure. WARP Connector establishes a secure Layer 3 proxy between a private network and Cloudflare, allowing you to: - Connect two or more private networks to each other. - Connect IoT devices that cannot run external software, such as printers and IP phones. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns.mdx index 478bae62254b12..e4bc17309a199a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns.mdx @@ -44,7 +44,7 @@ This command create a `CNAME` record that points to the tunnel subdomain, but wi :::note -To create DNS records using `cloudflared`, the [`cert.pem`](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#certpem) file must be installed on your system. +To create DNS records using `cloudflared`, the [`cert.pem`](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#certpem) file must be installed on your system. ::: diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx index f2648387b3b398..64bc9606108510 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: Public hostnames sidebar: - order: 5 + order: 8 --- diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb.mdx index f82cb681185afa..ba541d47870c87 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb.mdx @@ -39,7 +39,7 @@ This command creates an LB DNS record that points the specified hostname to the :::note -To create DNS records using `cloudflared`, the [`cert.pem`](/cloudflare-one/connections/connect-networks/get-started/tunnel-useful-terms/#certpem) file must be installed on your system. +To create DNS records using `cloudflared`, the [`cert.pem`](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/local-tunnel-terms/#certpem) file must be installed on your system. ::: @@ -56,11 +56,11 @@ The application will default to the Cloudflare settings for the load balancer ho If you have a tunnel to a port or SSH port, do not run a TCP health check. -Instead, set up a health check endpoint in `cloudflared` — for example, an [ingress entry rule](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames) that returns a fixed HTTP status response — and create an **HTTP** [monitor](/load-balancing/monitors/) for that endpoint. The monitor will only verify that your server is reachable. It does not check whether the server is running and accepting requests. +Instead, set up a health check endpoint in `cloudflared` — for example, an [ingress entry rule](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames) that returns a fixed HTTP status response — and create an **HTTP** [monitor](/load-balancing/monitors/) for that endpoint. The monitor will only verify that your server is reachable. It does not check whether the server is running and accepting requests. ### Session affinity and replicas -The load balancer does not distinguish between [replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) of the same tunnel. If you run the same tunnel UUID on two separate hosts, the load balancer treats both hosts as a single endpoint. To maintain [session affinity](/load-balancing/understand-basics/session-affinity/) between a client and a particular host, you will need to connect each host to Cloudflare using a different tunnel UUID. +The load balancer does not distinguish between [replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) of the same tunnel. If you run the same tunnel UUID on two separate hosts, the load balancer treats both hosts as a single endpoint. To maintain [session affinity](/load-balancing/understand-basics/session-affinity/) between a client and a particular host, you will need to connect each host to Cloudflare using a different tunnel UUID. ### Local connection preference @@ -68,4 +68,4 @@ If you notice traffic imbalances across endpoints in different locations, you ma `cloudflared` connections give preference to tunnels that terminate in the same Cloudflare data center. This behavior can impact how connections are weighted and traffic is distributed. -The solution depends on the type of tunnel being used. If running [legacy tunnels](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels/), put your origins in different pools. If running [Cloudflare tunnel replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) (using a shared ID), switch to separate Cloudflare tunnels as distinct origins. +The solution depends on the type of tunnel being used. If running [legacy tunnels](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/migrate-legacy-tunnels/), put your origins in different pools. If running [Cloudflare tunnel replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) (using a shared ID), switch to separate Cloudflare tunnels as distinct origins. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/common-errors.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/common-errors.mdx index 225bd5e76e3da4..6ac2ac9890e977 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/common-errors.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/common-errors.mdx @@ -54,14 +54,14 @@ This means the origin is using a certificate that `cloudflared` does not trust. An error 1033 indicates your tunnel is not connected to Cloudflare's edge. First, run `cloudflared tunnel list` to see whether your tunnel is listed as active. If it isn't, check the following: -1. Make sure you correctly routed traffic to your tunnel (step 5 in the [Tunnel guide](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#5-start-routing-traffic)) by assigning a CNAME record to point traffic to your tunnel. Alternatively, check [this guide](/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb/) to route traffic to your tunnel using load balancers. -2. Make sure you run your tunnel (step 6 in the [Tunnel guide](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#6-run-the-tunnel)). +1. Make sure you correctly routed traffic to your tunnel (step 5 in the [Tunnel guide](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#5-start-routing-traffic)) by assigning a CNAME record to point traffic to your tunnel. Alternatively, check [this guide](/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb/) to route traffic to your tunnel using load balancers. +2. Make sure you run your tunnel (step 6 in the [Tunnel guide](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#6-run-the-tunnel)). For more information, here is a [comprehensive list](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors/) of Cloudflare 1xxx errors. ## I see `ERR_TOO_MANY_REDIRECTS` when attempting to connect to an Access self-hosted app. -This error occurs when `cloudflared` does not recognize the SSL/TLS certificate presented by your origin. To resolve the issue, set the [origin server name](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#originservername) parameter to the hostname on your origin certificate. Here is an example of a locally-managed tunnel configuration: +This error occurs when `cloudflared` does not recognize the SSL/TLS certificate presented by your origin. To resolve the issue, set the [origin server name](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#originservername) parameter to the hostname on your origin certificate. Here is an example of a locally-managed tunnel configuration: ```txt ingress: @@ -102,7 +102,7 @@ If `cloudflared` returns error `error="remote error: tls: handshake failure"`, c ## Tunnel connections fail with `Too many open files` error. -If your [Cloudflare Tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) returns a `socket: too many open files` error, it means that `cloudflared` has exhausted the open files limit on your machine. The maximum number of open files, or file descriptors, is an operating system setting that determines how many files a process is allowed to open. To increase the open file limit, you will need to [configure ulimit settings](/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/#ulimits) on the machine running `cloudflared`. +If your [Cloudflare Tunnel logs](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/) returns a `socket: too many open files` error, it means that `cloudflared` has exhausted the open files limit on your machine. The maximum number of open files, or file descriptors, is an operating system setting that determines how many files a process is allowed to open. To increase the open file limit, you will need to [configure ulimit settings](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/#ulimits) on the machine running `cloudflared`. ## I see `failed to sufficiently increase receive buffer size` in my cloudflared logs. @@ -173,3 +173,6 @@ By default the [`cloudflared` Docker container](https://github.com/cloudflare/cl +## Cloudflare Tunnel is buffering my streaming response instead of streaming it live. + +Proxied traffic through Cloudflare Tunnel is buffered by default unless the origin server includes the response header `Content-Type: text/event-stream`. The `Content-Type: text/event-stream` response header tells `cloudflared` to stream data as it arrives instead of buffering the entire response. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/diag-logs.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/diag-logs.mdx index 413ba535014e78..7606ab666dbf67 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/diag-logs.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/diag-logs.mdx @@ -135,7 +135,7 @@ The `cloudflared-diag-YYYY-MM-DDThh-mm-ss.zip` archive contains the files listed | File name | Description | Instance | | -| - | - | -| `cli-configuration.json`| [Tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/) used when starting the tunnel | diagnosee| +| `cli-configuration.json`| [Tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/) used when starting the tunnel | diagnosee| | `cloudflared_logs.txt` | [Tunnel log file](/cloudflare-one/connections/connect-networks/monitor-tunnels/logs/)[^1] | diagnosee| | `configuration.json` | Tunnel configuration parameters | diagnosee| | `goroutine.pprof` | goroutine profile made available by `pprof` | diagnosee| diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/index.mdx index 23f72ff9af12ab..1dd6edca659a47 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/index.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Troubleshoot tunnels sidebar: - order: 6 + order: 10 --- diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx index 277c1731f8a694..e2813000b24eea 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/grpc.mdx @@ -32,9 +32,9 @@ Server started, listening on 50051 To establish a secure, outbound-only connection to Cloudflare: -1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the connect an application step and go straight to connecting a network. + -2. In the **Private Networks** tab for the tunnel, enter the private IP address of your server (or a range that includes the server IP). +2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. ## 3. Route private network IPs through WARP diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp.mdx deleted file mode 100644 index 92650f044cdec2..00000000000000 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp.mdx +++ /dev/null @@ -1,126 +0,0 @@ ---- -pcx_content_type: how-to -title: RDP -sidebar: - order: 2 ---- - -import { Render } from "~/components"; - -The Remote Desktop Protocol (RDP) provides a graphical interface for users to connect to a computer remotely. RDP is most commonly used to facilitate simple remote access to machines or workstations which users cannot physically access. However, this also makes RDP connections the frequent subject of attacks, since a misconfiguration can inadvertently allow unauthorized access to the machine. - -With Cloudflare Zero Trust, you can enjoy the convenience of making your RDP server available over the Internet without the risk of opening any inbound ports on your local server. - -Cloudflare Zero Trust offers two solutions to provide secure access to RDP servers: - -- [Private subnet routing with Cloudflare WARP to Tunnel](#connect-to-rdp-server-with-warp-to-tunnel) -- [Public hostname routing with `cloudflared access`](#connect-to-rdp-server-with-cloudflared-access) - -## Set up an RDP server in GCP - -This example walks through how to set up an RDP server on a Google Cloud Platform (GCP) virtual machine (VM), but you can use any machine that supports RDP connections. - -1. In your [Google Cloud Console](https://console.cloud.google.com/), [create a new project](https://developers.google.com/workspace/guides/create-project). -2. Go to **Compute Engine** > **VM instances**. -3. Select **Create instance**. -4. Name your VM instance, for example `windows-rdp-server`. -5. Configure your VM instance: - 1. Scroll down to **Boot Disk** and select **Change**. - 2. For **Operating system**, select _Windows Server_. - 3. Choose a **Version** with Desktop Experience, for example _Windows Server 2016 Datacenter_. -6. Once your VM is running, open the dropdown next to **RDP** and select _View gcloud command to reset password_. -7. Select **Run in Cloud Shell**. -8. Run the command in the Cloud Shell terminal. You will be asked to confirm the password reset. -9. Copy the auto-generated password and username to a safe place. - -## Install Microsoft Remote Desktop - -You can use any RDP client to access and configure the RDP server. - -To access the server through Microsoft Remote Desktop: - -1. Download and install [Microsoft Remote Desktop](https://apps.microsoft.com/store/detail/microsoft-remote-desktop/9WZDNCRFJ3PS). -2. Once downloaded, open Microsoft Remote Desktop and select **Add a PC**. -3. For **PC name**, enter the public IP address of your RDP server. In GCP, this is the **External IP** of the VM instance. -4. For **User account**, select **Add User Account** and enter your auto-generated password and username. -5. Select **Add**. The PC will display in Microsoft Remote Desktop. -6. To test basic connectivity, double-click the newly added PC. -7. When asked if you want to continue, select **Continue**. - -You can now remotely access and configure your RDP server. - -:::note - -By default, Internet Explorer will be installed and configured in [Enhanced Security mode](https://learn.microsoft.com/en-us/troubleshoot/developer/browsers/security-privacy/enhanced-security-configuration-faq#internet-explorer-enhanced-security-configuration). If the browser is slow or unable to load, you can turn off Enhanced Security and install an alternate browser such as Google Chrome. -::: - -## Connect to RDP server with WARP to Tunnel - - - -### 1. Connect the server to Cloudflare - - - -### 2. Set up the client - - - -### 3. Route private network IPs through WARP - - - -### 4. Connect as a user - -Once the WARP client is configured, you can use your RDP client to connect to the server's private IP address (instead of the public IP address used initially). - -To connect in Microsoft Remote Desktop: - -1. Open Microsoft Remote Desktop and select **Add a PC**. -2. For **PC name**, enter the private IP address of your RDP server. In GCP, this is the **Internal IP** of the VM instance. -3. For **User account**, enter your RDP server username and password. -4. To test Zero Trust connectivity, double-click the newly added PC. -5. When asked if you want to continue, select **Continue**. - -You now have secure, remote access to the RDP server. - -## Connect to RDP server with `cloudflared access` - - - -### 1. Connect the server to Cloudflare - -1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). - -2. In the **Public Hostnames** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). - -3. For **Service**, select _RDP_ and enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server (for example, `localhost:3389`). It will likely be port `3389`. - -4. Select **Save hostname**. - -5. (Recommended) Add a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) to Cloudflare Access in order to manage access to your server. - -### 2. Connect as a user - -1. [Install `cloudflared`](/cloudflare-one/connections/connect-networks/downloads/) on the client machine. -2. Run this command to open an RDP listening port: - - ```sh - cloudflared access rdp --hostname rdp.example.com --url rdp://localhost:3389 - ``` - - This process will need to be configured to stay alive and autostart. If the process is killed, users will not be able to connect. - -:::note - -If the client machine is running Windows, port `3389` may already be consumed locally. Select an alternative port to `3389` that is not being used. -::: - -3. While `cloudflared access` is running, connect from an RDP client such as Microsoft Remote Desktop: - 1. Open Microsoft Remote Desktop and select **Add a PC**. - 2. For **PC name**, enter `localhost:3389`. - 3. For **User account**, enter your RDP server username and password. - 4. Double-click the newly added PC. - 5. When asked if you want to continue, select **Continue**. - -When the client launches, a browser window will open and prompt the user to authenticate themselves. diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/index.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/index.mdx new file mode 100644 index 00000000000000..96b169ad5835bc --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/index.mdx @@ -0,0 +1,17 @@ +--- +pcx_content_type: navigation +title: RDP +sidebar: + order: 2 +tableOfContents: false +--- + +The Remote Desktop Protocol (RDP) provides a graphical interface for users to connect to a computer remotely. RDP is most commonly used to facilitate simple remote access to machines or workstations which users cannot physically access. However, this also makes RDP connections the frequent subject of attacks, since a misconfiguration can inadvertently allow unauthorized access to the machine. + +With Cloudflare Zero Trust, you can make your RDP server available over the Internet without the risk of opening any inbound ports on your local server. + +Cloudflare offers three ways to secure RDP: + +- [Browser-based RDP](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser/) +- [RDP with WARP client](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel/) +- [RDP with client-side cloudflared](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication/) \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser.mdx new file mode 100644 index 00000000000000..b7f75ae4943a8f --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser.mdx @@ -0,0 +1,126 @@ +--- +pcx_content_type: how-to +title: Connect to RDP in a browser +sidebar: + order: 2 + label: Browser-based RDP + badge: + text: Beta +--- + +import { Render, GlossaryTooltip } from "~/components" + +:::note[Availability] +Browser-based RDP is currently available in closed beta to Enterprise customers. To request access, contact your account team. +::: + +With Cloudflare Zero Trust, users can connect to an RDP server without installing an RDP client or the [WARP client](/cloudflare-one/connections/connect-devices/warp/) on their device. Browser-based RDP leverages [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/), which creates a secure, outbound-only connection from your RDP server to Cloudflare's global network. Setup involves running the `cloudflared` daemon on the RDP server (or any other host machine within the private network) and routing RDP traffic over a public hostname. + +There are two ways for users to [reach the RDP server in their browser](#4-connect-as-a-user): +- **App Launcher**: Users can log in to the [Access App Launcher](/cloudflare-one/applications/app-launcher/) with their Cloudflare Access credentials and then initiate an RDP connection within the browser to their Windows machine. Users will authenticate to the Windows machine using their pre-configured Windows username and password. Cloudflare does not manage any credentials on the Windows server. +- **Direct URL**: A user may also navigate directly to the Windows server using a public URL. The authentication flow is the same as for the App Launcher; first users must log in to Cloudflare Access and then use their Windows credentials to authenticate to the Windows machine. + +Browser-based RDP can be used in conjunction with [routing over WARP](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel/) so that there are multiple ways to connect to the server. You can reuse the same Cloudflare Tunnel when configuring each connection method. + +## Prerequisites + +- An [active domain on Cloudflare](/fundamentals/setup/manage-domains/add-site/) +- Domain uses either a [full setup](/dns/zone-setups/full-setup/) or a [partial (`CNAME`) setup](/dns/zone-setups/partial-setup/) +- Windows machine supports RDP connections. For a list of supported operating systems, refer to the [Windows documentation](https://learn.microsoft.com/windows-server/remote/remote-desktop-services/remotepc/remote-desktop-supported-config). + +## 1. Connect the server to Cloudflare + + + + + +## 2. Add a target + + + +## 3. Create an Access application + + + +6. Select **Add public hostname**. + + :::note + Browser-based RDP is only compatible with public hostnames. If you add a private hostname or IP, RDP functionality will not be available in this application. + ::: + +7. + + :::note + You can only enable browser-based RDP on domains and subdomains, not for specific paths. + ::: + +8. Expand **Browser rendering settings**. In the **Browser rendering** dropdown, select _RDP_. + +9. In **Target criteria**, select the [target hostname(s)](#2-add-a-target) that define your RDP servers. The application definition will apply to all targets that share the selected target hostname, including any targets added in the future. + +10. In **Port**, enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server. It will likely be port `3389`. + +11. (Optional) If you run RDP on more than one port, select **Add new target criteria** and reconfigure the same target hostname(s) with the different port number. + +12. + +:::note +Ensure that only **Allow** or **Block** policies are present. **Bypass** and **Service Auth** are not supported for browser-rendered applications. +::: + +13. + +14. Select **Next**. + +15. (Recommended) Turn on **Show application in App Launcher** and configure [App Launcher settings](/cloudflare-one/applications/app-launcher/) for the application. The App Launcher allows users to view the Windows servers that they can access using browser-based RDP. Without the App Launcher, users will need to know each target's direct URL. + + :::note + Ensure that users match an Allow rule in your [App Launcher policies](/cloudflare-one/applications/app-launcher/#enable-the-app-launcher). + ::: + +16. + +17. Select **Next**. + +18. + +19. Select **Save**. + +## 4. Create a DNS record + +In the [Cloudflare dashboard](https://dash.cloudflare.com/login), go to **DNS** > **Records** and verify that a [DNS record](/dns/manage-dns-records/how-to/create-dns-records/) exists for your domain. The DNS record allows Cloudflare to proxy browser-based RDP traffic to your private network. Any arbitrary DNS record will work. + +If you do not already have a DNS record, [create a new DNS record](/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records). For example, you could create a `CNAME` record that points your Access application public hostname (`app.example.com`) to your Cloudflare Tunnel (`.cfargotunnel.com`): + +- **Type**: _CNAME_ +- **Name**: `app` +- **Target**: `c1744f8b-faa1-48a4-9e5c-02ac921467fa.cfargotunnel.com` +- **Proxy status**: On + +## 5. Connect as a user + +To connect to a Windows machine over RDP: + +1. Open a browser and go to your App Launcher URL: + + ```text + https://.cloudflareaccess.com + ``` + + Replace `` with your Zero Trust team name. +2. Follow the prompts to log in to your identity provider. + + Once you have authenticated, the App Launcher will display tiles showing the applications that you are authorized to use. Windows servers (targets) available through browser-based RDP will also appear as tiles. If a target is reachable through multiple Access applications, the target will have a tile per Access application. +3. Select the target you want to connect to. + + The App Launcher tile will launch a URL of the form `https:///rdp///`. You may also navigate directly to this URL. +4. Select the port that you want to connect to. The port selection screen only appears if the Access application allows RDP traffic on multiple ports (for example, port `3389` and port `65321`). +5. Enter your Windows username and password. + +You now have access to the remote Windows desktop. + +## Product compatibility + + + + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx new file mode 100644 index 00000000000000..586c6147dd6535 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-cloudflared-authentication.mdx @@ -0,0 +1,52 @@ +--- +pcx_content_type: how-to +title: Connect to RDP with client-side cloudflared +sidebar: + order: 5 + label: RDP with client-side cloudflared +--- + +import { Render } from "~/components"; + +End users can connect to an RDP server without the WARP client by authenticating through `cloudflared` in their native terminal. This method requires having `cloudflared` installed on both the server machine and on the client machine, as well as an active zone on Cloudflare. The traffic is proxied over this connection, and the user logs in to the server with their Cloudflare Access credentials. + +Client-side `cloudflared` can be used in conjunction with [routing over WARP](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel/) and [Browser-based RDP](/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-browser/) so that there are multiple ways to connect to the server. You can reuse the same Cloudflare Tunnel when configuring each connection method. + +## 1. Connect the server to Cloudflare + +1. Create a Cloudflare Tunnel by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). + +2. In the **Public Hostnames** tab, choose a domain from the drop-down menu and specify any subdomain (for example, `rdp.example.com`). + +3. For **Service**, select _RDP_ and enter the [RDP listening port](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/change-listening-port) of your server (for example, `localhost:3389`). It will likely be port `3389`. + +4. Select **Save hostname**. + +## 2. (Recommended) Create an Access application + +By default, anyone on the Internet can connect to the server using its public hostname. To allow or block specific users, create a [self-hosted application](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in Cloudflare Access. + +## 3. Connect as a user + +1. [Install `cloudflared`](/cloudflare-one/connections/connect-networks/downloads/) on the client machine. +2. Run this command to open an RDP listening port: + + ```sh + cloudflared access rdp --hostname rdp.example.com --url rdp://localhost:3389 + ``` + + This process will need to be configured to stay alive and autostart. If the process is killed, users will not be able to connect. + +:::note + +If the client machine is running Windows, port `3389` may already be consumed locally. Select an alternative port to `3389` that is not being used. +::: + +3. While `cloudflared access` is running, connect from an RDP client such as Microsoft Remote Desktop: + 1. Open Microsoft Remote Desktop and select **Add a PC**. + 2. For **PC name**, enter `localhost:3389`. + 3. For **User account**, enter your RDP server username and password. + 4. Double-click the newly added PC. + 5. When asked if you want to continue, select **Continue**. + +When the client launches, a browser window will open and prompt the user to authenticate with Cloudflare Access. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx new file mode 100644 index 00000000000000..b4cf0deff5f042 --- /dev/null +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/rdp/rdp-warp-to-tunnel.mdx @@ -0,0 +1,79 @@ +--- +pcx_content_type: how-to +title: Connect to RDP using WARP +sidebar: + order: 2 + label: RDP with WARP client +--- + +import { Render } from "~/components"; + +Cloudflare WARP to Tunnel allows users to connect to RDP servers using their preferred RDP client. Cloudflare Tunnel creates a secure, outbound-only connection from your RDP server to Cloudflare's global network; this requires running the `cloudflared` daemon on the server (or any other host machine within the private network). Users install the [Cloudflare WARP client](/cloudflare-one/connections/connect-devices/warp/) on their device and enroll in your Zero Trust organization. Remote devices will be able to connect as if they were on your private network. By default, all devices enrolled in your organization can connect to the RDP server unless you build policies to allow or block specific users. + +This example walks through how to set up an RDP server on a Google Cloud Platform (GCP) virtual machine (VM), but you can use any machine that supports RDP connections. + +## 1. Set up an RDP server in GCP + +1. In your [Google Cloud Console](https://console.cloud.google.com/), [create a new project](https://developers.google.com/workspace/guides/create-project). +2. Go to **Compute Engine** > **VM instances**. +3. Select **Create instance**. +4. Name your VM instance, for example `windows-rdp-server`. +5. Configure your VM instance: + 1. Scroll down to **Boot Disk** and select **Change**. + 2. For **Operating system**, select _Windows Server_. + 3. Choose a **Version** with Desktop Experience, for example _Windows Server 2016 Datacenter_. +6. Once your VM is running, open the dropdown next to **RDP** and select _View gcloud command to reset password_. +7. Select **Run in Cloud Shell**. +8. Run the command in the Cloud Shell terminal. You will be asked to confirm the password reset. +9. Copy the auto-generated password and username to a safe place. + +## 2. Install Microsoft Remote Desktop + +You can use any RDP client to access and configure the RDP server. + +To access the server through Microsoft Remote Desktop: + +1. Download and install [Microsoft Remote Desktop](https://apps.microsoft.com/store/detail/microsoft-remote-desktop/9WZDNCRFJ3PS). +2. Once downloaded, open Microsoft Remote Desktop and select **Add a PC**. +3. For **PC name**, enter the public IP address of your RDP server. In GCP, this is the **External IP** of the VM instance. +4. For **User account**, select **Add User Account** and enter your auto-generated password and username. +5. Select **Add**. The PC will display in Microsoft Remote Desktop. +6. To test basic connectivity, double-click the newly added PC. +7. When asked if you want to continue, select **Continue**. + +You can now remotely access the RDP server using its public IP. The next steps will configure access to the server using its private IP. + +:::note + +By default, Internet Explorer will be installed and configured in [Enhanced Security mode](https://learn.microsoft.com/troubleshoot/developer/browsers/security-privacy/enhanced-security-configuration-faq#internet-explorer-enhanced-security-configuration). If the browser is slow or unable to load, you can turn off Enhanced Security and install an alternate browser such as Google Chrome. +::: + +## 3. Connect the server to Cloudflare + + + +2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. + +3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. + +## 4. Set up the client + + + +## 5. Route private network IPs through WARP + + + +## 6. Connect as a user + +Once the WARP client is configured, you can use your RDP client to connect to the server's private IP address (instead of the public IP address used initially). + +To connect in Microsoft Remote Desktop: + +1. Open Microsoft Remote Desktop and select **Add a PC**. +2. For **PC name**, enter the private IP address of your RDP server. In GCP, this is the **Internal IP** of the VM instance. +3. For **User account**, enter your RDP server username and password. +4. To test Zero Trust connectivity, double-click the newly added PC. +5. When asked if you want to continue, select **Continue**. + +You now have secure, remote access to the RDP server. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx index 8c099811d2aafe..deb7934716b605 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/smb.mdx @@ -20,14 +20,13 @@ While SMB was developed for Microsoft Windows, Samba provides SMB connectivity f ## Connect to SMB server with WARP to Tunnel - +You can use Cloudflare Tunnel to create a secure, outbound-only connection from your server to Cloudflare's global network. This requires running the `cloudflared` daemon on the server. Users reach the service by installing the [Cloudflare WARP client](/cloudflare-one/connections/connect-devices/warp/) on their device and enrolling in your Zero Trust organization. Remote devices will be able to connect as if they were on your private network. By default, all devices enrolled in your organization can access the service unless you build policies to allow or block specific users. ### 1. Connect the server to Cloudflare -1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the connect an application step and go straight to connecting a network. - -2. In the **Private Networks** tab for the tunnel, enter the private IP address of your server (or a range that includes the server IP). + +2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. 3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. ### 2. Set up the client @@ -60,7 +59,9 @@ While SMB was developed for Microsoft Windows, Samba provides SMB connectivity f ## Connect to SMB server with `cloudflared access` - +Cloudflare Tunnel can also route applications through a public hostname, which allows users to connect to the application without the WARP client. This method requires having `cloudflared` installed on both the server machine and on the client machine, as well as an active zone on Cloudflare. The traffic is proxied over this connection, and the user logs in to the server with their Cloudflare Access credentials. + +The public hostname method can be implemented in conjunction with routing over WARP so that there are multiple ways to connect to the server. You can reuse the same tunnel for both the private network and public hostname routes. ### 1. Connect the server to Cloudflare diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access.mdx index fc5cd97702ebe7..03c3b7a2c80579 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access.mdx @@ -13,13 +13,16 @@ import { Tabs, TabItem, Badge, Render } from "~/components"; [Access for Infrastructure](/cloudflare-one/applications/non-http/infrastructure-apps/) provides granular control over how users can connect to your SSH servers. This feature uses the same deployment model as [WARP-to-Tunnel](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel/) but unlocks more policy options and command logging functionality. - + ## 1. Connect the server to Cloudflare -1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the connect an application step and go straight to connecting a network. + -2. In the **Private Networks** tab for the tunnel, enter the IP address of your server (or a range that includes the server IP). Typically this would be a private IP, but public IPs are also allowed. + ## 2. Set up the client @@ -31,12 +34,11 @@ To connect your devices to Cloudflare: ## 3. Route server IPs through WARP - - + ## 4. Add a target - + ## 5. Add an infrastructure application @@ -55,9 +57,11 @@ To generate a Cloudflare SSH CA and get its public key: ### Save the public key + ### Modify your SSHD config + :::note @@ -66,9 +70,11 @@ For certain distributions, such as Amazon Linux 1 (based on RHEL), the certifica ```sh chmod 600 /etc/ssh/ca.pub ``` + ::: ### Restart your SSH server + ## 7. Connect as a user @@ -112,13 +118,13 @@ Cloudflare will stop logging SSH commands to your targets, as well as any comman To delete the SSH encryption public key using the [API](/api/resources/zero_trust/subresources/gateway/subresources/audit_ssh_settings/methods/update/): ```sh -curl --request PUT https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/audit_ssh_settings \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl --request PUT https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/audit_ssh_settings \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "public_key": "" }' ``` + diff --git a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx index e1b87ef1cd3b5b..3866ba385beb7a 100644 --- a/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx +++ b/src/content/docs/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-warp-to-tunnel.mdx @@ -59,7 +59,11 @@ In order to be able to establish an SSH connection, do not enable [OS Login](htt ## 3. Connect the server to Cloudflare - + + +2. In the **Private Networks** tab for the tunnel, enter the private IP or CIDR address of your server. In GCP, the server IP is the **Internal IP** of the VM instance. + +3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. ## 4. Set up the client diff --git a/src/content/docs/cloudflare-one/email-security/auto-moves.mdx b/src/content/docs/cloudflare-one/email-security/auto-moves.mdx index fa3def428af957..a983174fe3f452 100644 --- a/src/content/docs/cloudflare-one/email-security/auto-moves.mdx +++ b/src/content/docs/cloudflare-one/email-security/auto-moves.mdx @@ -2,7 +2,7 @@ title: Auto-move events pcx_content_type: how-to sidebar: - order: 4 + order: 5 --- Auto-move events are events where emails are automatically moved to different inboxes based on the disposition Email Security assigned to them. diff --git a/src/content/docs/cloudflare-one/email-security/detection-settings/index.mdx b/src/content/docs/cloudflare-one/email-security/detection-settings/index.mdx index e5ae7eff6656a2..866d1a60aea00c 100644 --- a/src/content/docs/cloudflare-one/email-security/detection-settings/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/detection-settings/index.mdx @@ -2,7 +2,9 @@ pcx_content_type: navigation title: Detection settings sidebar: - order: 3 + order: 4 + group: + hideIndex: true --- import { DirectoryListing } from "~/components" diff --git a/src/content/docs/cloudflare-one/email-security/directories/index.mdx b/src/content/docs/cloudflare-one/email-security/directories/index.mdx index a2d4cce3697ccd..3c60ef54027118 100644 --- a/src/content/docs/cloudflare-one/email-security/directories/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/directories/index.mdx @@ -2,7 +2,7 @@ title: Directories pcx_content_type: how-to sidebar: - order: 2 + order: 3 --- Directories are folders to store user data. Email Security allows you to manage directories from the Cloudflare dashboard. diff --git a/src/content/docs/cloudflare-one/email-security/directories/manage-es-directories.mdx b/src/content/docs/cloudflare-one/email-security/directories/manage-es-directories.mdx index d67086428b530f..d255ab794fa25b 100644 --- a/src/content/docs/cloudflare-one/email-security/directories/manage-es-directories.mdx +++ b/src/content/docs/cloudflare-one/email-security/directories/manage-es-directories.mdx @@ -5,13 +5,13 @@ sidebar: order: 5 --- -You can manage your Email Security directory by adding, editing and deleting added users. +You can manage your Email Security directory by editing and deleting added users. :::note[Registered users] The Email Security directory contains registered users only. A registered user is a user added to the [impersonation registry](/cloudflare-one/email-security/detection-settings/impersonation-registry/). ::: -To manually add, modify or delete users: +To modify or delete users: 1. Log in to [Zero Trust](https://one.dash.cloudflare.com/). 2. Select **Email security**. diff --git a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/index.mdx b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/index.mdx similarity index 65% rename from src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/index.mdx rename to src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/index.mdx index d7d936f368ec45..862fe0e2f31cfa 100644 --- a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/index.mdx @@ -1,14 +1,14 @@ --- -title: Manage Microsoft directories +title: Manage integrated directories pcx_content_type: how-to sidebar: order: 2 --- -To manage a Microsoft directory: +To manage an integrated directory: 1. Log in to [Zero Trust](https://one.dash.cloudflare.com/). 2. Select **Email security**. 3. Select **Directories**. -4. Under **Directory name**, select **MS directory**. +4. Under **Directory name**, select your directory. 5. From here, you can manage **Groups** or **Users** directories. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory.mdx b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory.mdx similarity index 95% rename from src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory.mdx rename to src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory.mdx index ac8f92c27e46cc..67b06a1954deec 100644 --- a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory.mdx +++ b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory.mdx @@ -7,7 +7,7 @@ sidebar: Email Security allows you to view and manage your groups directory and their [impersonation registry](/cloudflare-one/email-security/detection-settings/impersonation-registry/). When a group is added to the registry, all members are registered by default. -To manage your group directory, on the **MS directory** page, select **Groups**. +To manage your group directory, go to your directory and select **Groups**. ## Add groups to registry diff --git a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-users-directory.mdx b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-users-directory.mdx similarity index 97% rename from src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-users-directory.mdx rename to src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-users-directory.mdx index 5ce609a2c14e50..1fa696eca9dd8e 100644 --- a/src/content/docs/cloudflare-one/email-security/directories/manage-ms-directories/manage-users-directory.mdx +++ b/src/content/docs/cloudflare-one/email-security/directories/manage-integrated-directories/manage-users-directory.mdx @@ -7,7 +7,7 @@ sidebar: Email Security allows you to view and manage the [impersonation registry](/cloudflare-one/email-security/detection-settings/impersonation-registry/) status of your users directory. -On the **MS directory** page, select **Users**. +Go to your directory and select **Users**. ## Add users to registry diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/download-disposition-report.mdx b/src/content/docs/cloudflare-one/email-security/email-monitoring/download-disposition-report.mdx similarity index 100% rename from src/content/docs/cloudflare-one/insights/email-monitoring/download-disposition-report.mdx rename to src/content/docs/cloudflare-one/email-security/email-monitoring/download-disposition-report.mdx diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/index.mdx b/src/content/docs/cloudflare-one/email-security/email-monitoring/index.mdx similarity index 94% rename from src/content/docs/cloudflare-one/insights/email-monitoring/index.mdx rename to src/content/docs/cloudflare-one/email-security/email-monitoring/index.mdx index 9e93d2cd0dc1af..df423d025a6e28 100644 --- a/src/content/docs/cloudflare-one/insights/email-monitoring/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/email-monitoring/index.mdx @@ -2,7 +2,7 @@ title: Email monitoring pcx_content_type: how-to sidebar: - order: 1 + order: 2 --- import { GlossaryTooltip, Render } from "~/components" @@ -10,7 +10,7 @@ import { GlossaryTooltip, Render } from "~/components" Once you have chosen a [domain to scan](/cloudflare-one/email-security/setup/post-delivery-deployment/api/office365-api/#connect-your-domains), Email Security allows you to monitor the traffic scanned from your email inboxes. :::note -With Email Security, you can enable logs to send detection data to an endpoint of your choice. Refer to [Email Security logs](/cloudflare-one/insights/email-monitoring/enable-logs/) for more information. +With Email Security, you can enable logs to send detection data to an endpoint of your choice. Refer to [Enable Email Security logs](/cloudflare-one/insights/logs/enable-logs/) for more information. ::: To monitor your inbox: @@ -25,7 +25,7 @@ The dashboard will display the following metrics: - [Disposition evaluation](/cloudflare-one/email-security/reference/dispositions-and-attributes/) - Detection details - [Impersonations](/cloudflare-one/email-security/detection-settings/impersonation-registry/) -- [Phish submissions](/cloudflare-one/insights/email-monitoring/phish-submissions/) +- [Phish submissions](/cloudflare-one/email-security/phish-submissions/) - [Auto-move events](/cloudflare-one/email-security/auto-moves/) - [Detection settings metrics](/cloudflare-one/email-security/detection-settings/) @@ -78,7 +78,7 @@ Refer to [Trusted domains](/cloudflare-one/email-security/detection-settings/tru Phishing is a type of attack that involves stealing sensitive information with the aim of using and selling the information. -A phish submission happens when a user or an administrator reports a phishing attack. Refer to [Phish submissions](/cloudflare-one/insights/email-monitoring/phish-submissions/) to learn how to submit a phish. +A phish submission happens when a user or an administrator reports a phishing attack. Refer to [Phish submissions](/cloudflare-one/email-security/phish-submissions/) to learn how to submit a phish. Phish submissions displays the following information: diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/search-email.mdx b/src/content/docs/cloudflare-one/email-security/email-monitoring/search-email.mdx similarity index 78% rename from src/content/docs/cloudflare-one/insights/email-monitoring/search-email.mdx rename to src/content/docs/cloudflare-one/email-security/email-monitoring/search-email.mdx index 7c4fb702d0ffeb..56b15981ea004b 100644 --- a/src/content/docs/cloudflare-one/insights/email-monitoring/search-email.mdx +++ b/src/content/docs/cloudflare-one/email-security/email-monitoring/search-email.mdx @@ -146,7 +146,7 @@ To escalate a reclassification: ## Move messages -Moving messages allows you to move messages to a specific folder. +Moving messages allows you to move messages to a specific folder. You can move up to 1,000 messages at a time. To move messages: @@ -187,13 +187,57 @@ To view status and actions for each email: 1. On the **Investigation** page, select the three dots. 2. Selecting the three dots will show you the following options: - If the email is quarantined: - - **View details**: Refer to [Email details](/cloudflare-one/insights/email-monitoring/email-details/) to learn more. + - **View details**: Refer to [Email details](/cloudflare-one/email-security/email-monitoring/search-email/#email-details) to learn more. - **View similar emails**: Find similar emails based on the `value_edf_hash` (Electronic Detection Fingerprint hash). - **Release**: Email Security will no longer quarantine your chosen messages. - - **Reclassify**: Choose the dispositions of your messages if they are incorrect. Refer to [Reclassify messages](/cloudflare-one/insights/email-monitoring/search-email/#reclassify-messages) to learn more. + - **Reclassify**: Choose the dispositions of your messages if they are incorrect. Refer to [Reclassify messages](/cloudflare-one/email-security/email-monitoring/search-email/#reclassify-messages) to learn more. 3. If the email is not quarantined: - **View details**. - **View similar emails**. - **View submission detail**. - [Move](/cloudflare-one/email-security/auto-moves/) (only available if you authorized moves). - - [Reclassify](/cloudflare-one/insights/email-monitoring/search-email/#reclassify-messages). \ No newline at end of file + - [Reclassify](/cloudflare-one/email-security/email-monitoring/search-email/#reclassify-messages). + +## Email details + +Email Security shows you the following email detail information: + +- Details +- Action log +- Raw message +- Mail trace + +### Details + +Email Security displays the following details: + +1. **Threat type**: Threat type of the email, for example, [credential harvester](/cloudflare-one/email-security/reference/how-es-detects-phish/#credential-harvesters), and [IP-based spam](/cloudflare-one/email-security/reference/how-es-detects-phish/#ip-based-spam). +2. **Validation**: Email validation methods [SPF](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/), [DKIM](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/), [DMARC](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/). +3. **Sender details**: Information include: + - IP address + - Registered domain + - Autonomous sys number: This number identifies your [autonomous system (AS)](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-an-autonomous-system/). + - Autonomous sys name: This name identifies your autonomous system (AS). + - Country +4. **Links identified**: A list of malicious links identified by Email Security. +5. **Attachments**: If an email has an attachment, the dashboard will display the filename, and the disposition assigned. +6. **Reasons for disposition**: Description of why the email was deemed as malicious, suspicious, or spam. + +### Action log + +Action log allows you to review post-delivery actions performed on your selected message. The action log displays: + +- **Date**: Date when the post-delivery action was performed. +- **Activity**: The activity taken on an email. For example, moving the email to the trash folder, releasing a quarantined email, and more. + +### Raw message + +Raw message allows you to view the raw details of the message. You can also choose to download the email message. To download the message, select **Download .EML**. + +### Mail trace + +Mail trace allows you to track the path your selected message took from the sender to the recipient. Mail trace displays: + +- **Date**: The date and time when the mail was tracked. +- **Type**: An email can be inbound (email sent to you from another email), or outbound (emails sent from your email address). +- **Activity**: The activity taken on an email. For example, moving the email to the trash folder, releasing a quarantined email, and more. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/index.mdx b/src/content/docs/cloudflare-one/email-security/index.mdx index ebf7814cd65595..d0644355077084 100644 --- a/src/content/docs/cloudflare-one/email-security/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/index.mdx @@ -22,4 +22,4 @@ Email Security allows you to: - Configure [allow policies](/cloudflare-one/email-security/detection-settings/allow-policies/), [blocked senders](/cloudflare-one/email-security/detection-settings/blocked-senders/), [trusted domains](/cloudflare-one/email-security/detection-settings/trusted-domains/), and [additional detections](/cloudflare-one/email-security/detection-settings/additional-detections/). - [Automatically move messages](/cloudflare-one/email-security/auto-moves/) to specific folders based on a [certain disposition](/cloudflare-one/email-security/reference/dispositions-and-attributes/). - [Manage directories](/cloudflare-one/email-security/directories/). -- [Monitor your inbox](/cloudflare-one/insights/email-monitoring/), perform a thorough [search of your email](/cloudflare-one/insights/email-monitoring/search-email/), and download a [disposition report](/cloudflare-one/insights/email-monitoring/download-disposition-report/). \ No newline at end of file +- [Monitor your inbox](/cloudflare-one/email-security/email-monitoring/), perform a thorough [search of your email](/cloudflare-one/email-security/email-monitoring/search-email/), and download a [disposition report](/cloudflare-one/email-security/email-monitoring/download-disposition-report/). \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/outbound-dlp.mdx b/src/content/docs/cloudflare-one/email-security/outbound-dlp.mdx index df98f96f9594e3..cdef9be9a4dc2a 100644 --- a/src/content/docs/cloudflare-one/email-security/outbound-dlp.mdx +++ b/src/content/docs/cloudflare-one/email-security/outbound-dlp.mdx @@ -2,9 +2,7 @@ title: Outbound Data Loss Prevention (DLP) pcx_content_type: how-to sidebar: - order: 6 - badge: - text: Beta + order: 7 --- diff --git a/src/content/docs/cloudflare-one/email-security/phish-guard.mdx b/src/content/docs/cloudflare-one/email-security/phish-guard.mdx index 8b228234b1cc92..301d3889daabae 100644 --- a/src/content/docs/cloudflare-one/email-security/phish-guard.mdx +++ b/src/content/docs/cloudflare-one/email-security/phish-guard.mdx @@ -2,7 +2,7 @@ title: PhishGuard pcx_content_type: how-to sidebar: - order: 5 + order: 8 --- PhishGuard is a managed email security service that provides resources for end-to-end phish and targeted attack management and response. With PhishGuard, you can preemptively block [phishing attacks](https://www.cloudflare.com/en-gb/learning/access-management/phishing-attack/), [malware](https://www.cloudflare.com/en-gb/learning/ddos/glossary/malware/), [Business Email Compromise (BEC)](https://www.cloudflare.com/en-gb/learning/email-security/business-email-compromise-bec/), and vendor email fraud. @@ -61,7 +61,7 @@ Managed email security operations allows you to review the results of phish subm It displays the following: -- Total [phish submissions](/cloudflare-one/insights/email-monitoring/phish-submissions/) +- Total [phish submissions](/cloudflare-one/email-security/phish-submissions/) - Tracked incidents - Median time to resolve - Resolved track incidents diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/phish-submissions.mdx b/src/content/docs/cloudflare-one/email-security/phish-submissions.mdx similarity index 75% rename from src/content/docs/cloudflare-one/insights/email-monitoring/phish-submissions.mdx rename to src/content/docs/cloudflare-one/email-security/phish-submissions.mdx index 1d058dd936dd53..055b0054eda4ae 100644 --- a/src/content/docs/cloudflare-one/insights/email-monitoring/phish-submissions.mdx +++ b/src/content/docs/cloudflare-one/email-security/phish-submissions.mdx @@ -2,7 +2,7 @@ title: Phish submissions pcx_content_type: how-to sidebar: - order: 4 + order: 6 --- import { GlossaryTooltip, Render } from "~/components" @@ -11,14 +11,18 @@ As part of your continuous email security posture, administrators and security a Submitting missed phish samples to Cloudflare is of paramount importance and necessary for continuous protection. Submitting missed phish samples helps Cloudflare improve our machine learning (ML) models, and alerts us of new attack vectors before they become prevalent. -## How to submit phish +There are three routes you can use to report an email as a phish: -To submit a phish: +- Via Investigation, by [reclassifying an email](/cloudflare-one/email-security/phish-submissions/#reclassify-an-email). +- Via [PhishNet O365](/cloudflare-one/email-security/phish-submissions/#phishnet-o365) or [PhishNet for Google Workspace](/cloudflare-one/email-security/phish-submissions/#phishnet-for-google-workspace), depending on your email provider. +- Via [Submission addresses](/cloudflare-one/email-security/phish-submissions/#submission-addresses). + +## Reclassify an email 1. Log in to [Zero Trust](https://one.dash.cloudflare.com/). -2. Select **Email Security**. -3. Select **Settings**. -4. Under **Phish submission**, select **View**. +2. Select **Email Security** > **Investigation**. +3. On the **Investigation** page, under **Your matching messages**, select the message you want to reclassify. Select the three dots, then select **Reclassify**. By selecting **Reclassify**, you are requesting a new disposition for the message. +4. Select the new disposition, then select **Save**. ## PhishNet O365 @@ -28,7 +32,7 @@ To set up PhishNet O365: 1. Log in to the [Microsoft admin panel](https://admin.microsoft.com/). Go to **Microsoft 365 admin center** > **Settings** > **Integrated Apps**. 2. Select **Upload custom apps**. -3. Choose **Provide link to manifest file** and paste the the following URL: +3. Choose **Provide link to manifest file** and paste the following URL: ```txt https://phishnet-o365.area1cloudflare-webapps.workers.dev?clientId=ODcxNDA0MjMyNDM3NTA4NjQwNDk1Mzc3MDIxNzE0OTcxNTg0Njk5NDEyOTE2NDU5ODQyNjU5NzYzNjYyNDQ3NjEwMzIxODEyMDk1NQ ``` diff --git a/src/content/docs/cloudflare-one/email-security/reference/index.mdx b/src/content/docs/cloudflare-one/email-security/reference/index.mdx index be40cb7084513e..12b32f8c9477cc 100644 --- a/src/content/docs/cloudflare-one/email-security/reference/index.mdx +++ b/src/content/docs/cloudflare-one/email-security/reference/index.mdx @@ -2,7 +2,7 @@ title: Reference pcx_content_type: navigation sidebar: - order: 8 + order: 9 group: hideIndex: true --- diff --git a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/api/office365-api.mdx b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/api/office365-api.mdx index 9a5221688b88ea..04b0881423f5f7 100644 --- a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/api/office365-api.mdx +++ b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/api/office365-api.mdx @@ -5,6 +5,8 @@ sidebar: order: 3 --- +import { Render } from "~/components" + This guide will instruct you through setting up Microsoft Office 365 with Email Security via the Cloudflare dashboard. ## Prerequisites @@ -73,4 +75,8 @@ To view the integration for each connected domain: 1. Select a domain. 2. Select the three dots > **View integration**. -Once you have set up Email Security to scan through your inbox, Email Security will display detailed information about your inbox. Refer to [Monitor your inbox](/cloudflare-one/insights/email-monitoring/) to learn more. \ No newline at end of file +Once you have set up Email Security to scan through your inbox, Email Security will display detailed information about your inbox. Refer to [Monitor your inbox](/cloudflare-one/email-security/email-monitoring/) to learn more. + +## Next steps + + \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/bcc-microsoft-exchange.mdx b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/bcc-microsoft-exchange.mdx index 74374ad71a2fbd..d43351ebe53509 100644 --- a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/bcc-microsoft-exchange.mdx +++ b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/bcc-microsoft-exchange.mdx @@ -73,4 +73,8 @@ If you have multiple rules, you may need to change the order of the BCC rule and ## Email processing and reports -In BCC mode, all emails are put through automated phishing detections by Email Security. Emails that trigger phishing detections are logged for reporting via product portal, email and Slack. Emails that do not trigger any detections are deleted. \ No newline at end of file +In BCC mode, all emails are put through automated phishing detections by Email Security. Emails that trigger phishing detections are logged for reporting via product portal, email and Slack. Emails that do not trigger any detections are deleted. + +## Next steps + + \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/enable-gmail-integration.mdx b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/enable-gmail-integration.mdx index f6aee0f5c83a70..5d283f264d3fe7 100644 --- a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/enable-gmail-integration.mdx +++ b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/enable-gmail-integration.mdx @@ -7,13 +7,11 @@ sidebar: To enable Gmail BCC integration: -1. Log in to [Zero Trust](https://one.dash.cloudflare.com/). -2. Select **Zero Trust** > **Settings**. -3. Select **SaaS Integrations**. -4. Select **Add integration** > **Google Workspace**. -5. Select **Select Integration**. - -## Create an integration +1. Log in to [Zero Trust](https://one.dash.cloudflare.com/), select **Email Security**, then select **Settings**. +2. Go to **Integrated domains** and select **View**. +3. Select **Connect a domain**. +4. Select **BCC/Journaling**. +5. Choose **Integrate with Google**, and select **Authorize**. Name your integration, then select **Next**. @@ -23,22 +21,10 @@ Name your integration, then select **Next**. 2. On the [Google Cloud Console](https://console.cloud.google.com/welcome/new), go to the sidebar, select **APIs & Services**, then select **Credentials**. 3. Select **CREATE CREDENTIALS** > **Service account**. 4. Fill in the details to create a service account: - - **Service account name**: Enter `Message Retraction Service Account`. - - **Service account ID**: Enter `message-retraction-service-acc`. - - **Service account description**: Enter `Email Security Message Retraction`. + - **Service account name**: Enter `Cloudflare Google Integration`. + - **Service account ID**: Enter `cloudflare-google-integration`. + - **Service account description**: Enter `Cloudflare Google Integration`. - Select **CREATE AND CONTINUE**. -5. In **Grant this service account access to project**, select **Select a role** > Choose **Owner**. Select **CONTINUE**, then select **DONE**. -6. Go back to **Credentials** on the sidebar, and select your service account under **Service Accounts**. In **Details**, take note of the **Unique ID**. -7. Select **Advanced settings** > **VIEW GOOGLE WORKSPACE ADMIN CONSOLE**, then enter your password. This will redirect you to the Google admin portal. -8. On the sidebar, select **Security** > **Access and data control** > **API controls** > Select **MANAGE DOMAIN WIDE DELEGATION**. -9. Select **Add new** > Add a new client ID: - - **Client ID**: Enter the **Unique ID** you took note of in step 5. - - **OAuth scopes**: Enter the following URLs: - - ```txt - https://www.googleapis.com/auth/admin.directory.user.readonly, https://www.googleapis.com/auth/admin.directory.group.readonly, https://www.googleapis.com/auth/admin.directory.user.alias.readonly, https://www.googleapis.com/auth/gmail.labels, https://mail.google.com/ - ``` - - Select **AUTHORIZE**. ### 2. Create a JSON Key for your Service Account @@ -82,6 +68,24 @@ Enter the email associated with the Google Workspace Administrator account. Your 2. Once you created your integration, you will be redirected to the **Review details** page, where you will be able to review **Integration details**. 3. Review your details, then select **Complete Email Security set up** > **Continue to Email Security**. +## Verify integration + +To verify that the integration has been successful: + +1. Go to **Settings** (the gear icon) > **SaaS integrations**. +2. Go to your integration, and ensure that the integration displays **CASB+EMAIL** under **Type**. + +:::note +If you do not reach the step to complete Email Security set up: + +1. Go to **Settings** (the gear icon) > **SaaS Integrations**. +2. Delete the integration, if present. Locate your integration, select **Configure**, then select **Delete**. +3. Follow the steps from the beginning to enable Gmail BCC integration. +::: + ## Next steps -Now that you have created an integration, you will need to [connect your domains](/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/connect-domains/) for Email Security to start scanning your inbox. \ No newline at end of file +Now that you have created an integration: + +- [Connect your domains](/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/bcc-setup/gmail-bcc-setup/connect-domains/) for Email Security to start scanning your inbox. +- [Enable logs](/cloudflare-one/insights/logs/enable-logs/) to send detection data to an endpoint of your choice. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/journaling-setup/office365-journaling.mdx b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/journaling-setup/office365-journaling.mdx index 8bbe072aece88e..ab2d01b7afd7a6 100644 --- a/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/journaling-setup/office365-journaling.mdx +++ b/src/content/docs/cloudflare-one/email-security/setup/post-delivery-deployment/bcc-journaling/journaling-setup/office365-journaling.mdx @@ -5,7 +5,7 @@ sidebar: order: 2 --- -import { GlossaryTooltip } from "~/components" +import { GlossaryTooltip, Render } from "~/components" When you receive an email, the email lands on your Microsoft O365 inbox, and then Email Security receives a copy of that email. The following email flow shows how this works: @@ -51,4 +51,8 @@ Your domains are now added successfully. To view your connected domains: 1. Go to **Settings**. -2. Locate your domain, select the three dots > **View domain**. Selecting **View domain** will display information about your domain. \ No newline at end of file +2. Locate your domain, select the three dots > **View domain**. Selecting **View domain** will display information about your domain. + +## Next steps + + \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/faq/cloudflare-tunnels-faq.mdx b/src/content/docs/cloudflare-one/faq/cloudflare-tunnels-faq.mdx index 72899b069ca721..248efdb8240383 100644 --- a/src/content/docs/cloudflare-one/faq/cloudflare-tunnels-faq.mdx +++ b/src/content/docs/cloudflare-one/faq/cloudflare-tunnels-faq.mdx @@ -83,6 +83,6 @@ Before contacting the Cloudflare support team: 3. Gather any relevant error/access logs from your server. -4. (Locally-managed tunnels only) Set [`--loglevel`](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#loglevel) to `debug`, so the Cloudflare support team can get more info from the `cloudflared.log` file. +4. (Locally-managed tunnels only) Set [`--loglevel`](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#loglevel) to `debug`, so the Cloudflare support team can get more info from the `cloudflared.log` file. 5. Include your [Cloudflare Tunnel diagnostic logs](/cloudflare-one/connections/connect-networks/troubleshoot-tunnels/diag-logs/) (`cloudflared-diag-YYYY-MM-DDThh-mm-ss.zip`). diff --git a/src/content/docs/cloudflare-one/faq/index.mdx b/src/content/docs/cloudflare-one/faq/index.mdx index 86f29e471b314c..9bfc8d613c3e78 100644 --- a/src/content/docs/cloudflare-one/faq/index.mdx +++ b/src/content/docs/cloudflare-one/faq/index.mdx @@ -9,9 +9,9 @@ sidebar: import { LinkButton } from "~/components"; -Below you'll find answers to the most commonly asked questions on Cloudflare Zero Trust, as well as a troubleshooting section to help you solve common issues and errors you may come across. +Review answers to the most commonly asked questions on Cloudflare Zero Trust, as well as a troubleshooting section to help you solve common issues and errors you may come across. -If you can't find the answer you're looking for, feel free to head over to our [community page](https://community.cloudflare.com/) and post your question there. +If you cannot find the answer you are looking for, go to our [community page](https://community.cloudflare.com/) and post your question there. --- @@ -68,7 +68,7 @@ For questions on connecting applications with Tunnels. ## Troubleshooting -Got an unexpected error? See if it's covered in our troubleshooting section. +Got an unexpected error? Check if it is covered in our troubleshooting section. Troubleshooting ❯ diff --git a/src/content/docs/cloudflare-one/faq/troubleshooting.mdx b/src/content/docs/cloudflare-one/faq/troubleshooting.mdx index e17b46c5cad19e..8dc6b5115000cd 100644 --- a/src/content/docs/cloudflare-one/faq/troubleshooting.mdx +++ b/src/content/docs/cloudflare-one/faq/troubleshooting.mdx @@ -111,7 +111,7 @@ Cloudflare dashboard SSO does not currently support team domain changes. Contact ## WARP on Linux shows `DNS connectivity check failed`. -This error means that the `systemd-resolved` service on Linux is not allowing WARP to resolve DNS requests. +This error means that the `systemd-resolved` service on Linux is not allowing WARP to resolve DNS requests. You can identify this issue in the [`daemon.log`](/cloudflare-one/connections/connect-devices/warp/troubleshooting/warp-logs/#warp-diag-logs:~:text=the%20WARP%20client.-,daemon.log,-Detailed%20log%20of) file of the `warp diag` logs, where the error message appears as `ERROR main_loop: warp::warp::connectivity_check: DNS connectivity check failed to resolve host="warp-svc."`. To solve the issue: @@ -284,7 +284,7 @@ If admin generates an override code with a timeout of three hours at **9:30 AM** However, if the user attempts to enter the override code at **10:00 AM**, the override code will only be valid until **12:00 PM** (a two hour duration). The override code was generated at **9:30 AM** and one hour of its total three hour validity was counted as used in the 9:00 AM to 10:00 AM hour. -### Scenariot three: Admin generates an override code at 12:30 PM with a timeout of 24 hours. +### Scenario three: Admin generates an override code at 12:30 PM with a timeout of 24 hours. If admin generates an override code with a timeout of 24 hours at **12:30 PM** and the user inputs the override code in their device at **12:59 PM** the same day, the user will be able to toggle WARP on and off until **12:59 PM** the next day (a 24 hour duration.) @@ -297,3 +297,25 @@ If the user attempts to enter the override code at **11:59 AM** the next day, th If you are using an [Admin override](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/#admin-override) code with [Auto connect](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/#auto-connect) also enabled, WARP will turn on automatically according to the Timeout set for **Auto connect**. Using an override code to override the WARP lock switch will not disable Auto connect. As best practice, review your Auto connect settings before sending the override code to the user. To prevent WARP from auto connecting while using an admin override code, disable Auto connect or set a longer **Timeout** for **Auto connect**. Note the changes you make to Auto connect while the end user is using the admin override code if you need to revert these changes later. + +## I am getting the error `Failed to fetch user/group information from the identity provider`. + +This error is returned when proper API permissions are not set up in the identity provider. When Cloudflare attempts to fetch user/group information from the identity provider and proper API permissions have not been configured, the `Failed to fetch user/group information from the identity provider` error will appear. Review the [SSO integration](/cloudflare-one/identity/idp-integration/) guide for your identity provider to ensure your application has the appropriate API permissions. + +For example, [Microsoft Entra](/cloudflare-one/identity/idp-integration/entra-id/#2-configure-api-permissions-in-entra-id) and [Okta]() have required permissions stated in their integration guides. + +You can also examine logs in your identity provider to identify any denied requests related to API access. + +## WSL2 is losing connectivity when using WARP. + +If your WSL2 environment is losing connectivity while using WARP, check your [split tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/). + +The issue may arise because the IP range that the WSL environment uses to communicate with the host device is included in the split tunnel configuration. Excluding the WSL environment’s IP range should restore connectivity. + +You must ensure the host device is included in the WARP tunnel while excluding the WSL environment to prevent connectivity issues between WSL and the host device. + +### To debug this issue: + +1. Review the WSL2 environment's IP address and compare it with the laptop’s IP. +2. Check if the WSL network is [included in the split tunnel configuration](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#change-split-tunnels-mode). +3. If the WSL network is included, exclude it from the split tunnel to prevent connectivity issues. diff --git a/src/content/docs/cloudflare-one/identity/authorization-cookie/application-token.mdx b/src/content/docs/cloudflare-one/identity/authorization-cookie/application-token.mdx index 8d0f8af84942ee..12294719c8c382 100644 --- a/src/content/docs/cloudflare-one/identity/authorization-cookie/application-token.mdx +++ b/src/content/docs/cloudflare-one/identity/authorization-cookie/application-token.mdx @@ -3,6 +3,7 @@ pcx_content_type: reference title: Application token sidebar: order: 2 +description: Learn how Cloudflare Access uses application tokens to secure your origin. Understand JWT structure and payloads. --- Cloudflare Access includes the application token with all authenticated requests to your origin. A typical JWT looks like this: diff --git a/src/content/docs/cloudflare-one/identity/authorization-cookie/cors.mdx b/src/content/docs/cloudflare-one/identity/authorization-cookie/cors.mdx index c2669a612f7646..250cebafb4eebb 100644 --- a/src/content/docs/cloudflare-one/identity/authorization-cookie/cors.mdx +++ b/src/content/docs/cloudflare-one/identity/authorization-cookie/cors.mdx @@ -158,7 +158,7 @@ This will prompt you to install the [`create-cloudflare`](https://www.npmjs.com/ product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/cloudflare-one/identity/authorization-cookie/index.mdx b/src/content/docs/cloudflare-one/identity/authorization-cookie/index.mdx index 0b5fce86c4636d..e8d48956484cb5 100644 --- a/src/content/docs/cloudflare-one/identity/authorization-cookie/index.mdx +++ b/src/content/docs/cloudflare-one/identity/authorization-cookie/index.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: concept title: Authorization cookie +description: Learn how Cloudflare Access uses CF_Authorization cookies to secure self-hosted web applications. sidebar: order: 12 @@ -9,7 +10,6 @@ sidebar: import { Details, GlossaryTooltip } from "~/components" When you protect a site with Cloudflare Access, Cloudflare checks every HTTP request bound for that site to ensure that the request has a valid `CF_Authorization` cookie. If a request does not include the cookie, Access will block the request. - ## Access JWTs The `CF_Authorization` cookie contains the user's identity in the form of a JSON Web Token (JWT). Cloudflare securely creates these tokens through the OAUTH or SAML integration between Cloudflare Access and the configured identity provider. diff --git a/src/content/docs/cloudflare-one/identity/authorization-cookie/validating-json.mdx b/src/content/docs/cloudflare-one/identity/authorization-cookie/validating-json.mdx index d3a995afc72141..253e32f9648d58 100644 --- a/src/content/docs/cloudflare-one/identity/authorization-cookie/validating-json.mdx +++ b/src/content/docs/cloudflare-one/identity/authorization-cookie/validating-json.mdx @@ -3,10 +3,9 @@ pcx_content_type: how-to title: Validate JWTs sidebar: order: 1 - --- -import { GlossaryTooltip } from "~/components" +import { GlossaryTooltip } from "~/components"; When Cloudflare sends a request to your origin, the request will include an [application token](/cloudflare-one/identity/authorization-cookie/application-token/) as a `Cf-Access-Jwt-Assertion` request header and as a `CF_Authorization` cookie. @@ -22,9 +21,9 @@ You can also manually rotate the key using the [API](/api/resources/zero_trust/s As shown in the example below, `https://.cloudflareaccess.com/cdn-cgi/access/certs` contains two public keys: the current key used to sign all new tokens, and the previous key that has been rotated out. -* `keys`: both keys in JWK format -* `public_cert`: current key in PEM format -* `public_certs`: both keys in PEM format +- `keys`: both keys in JWK format +- `public_cert`: current key in PEM format +- `public_certs`: both keys in PEM format ```txt { @@ -65,9 +64,8 @@ As shown in the example below, `https://.cloudflareaccess.com/cd :::note[Avoid key rotation issues] - -* Validate tokens using the external endpoint rather than saving the public key as a hard-coded value. -* Do not fetch the current key from `public_cert`, since your origin may inadvertently read an expired value from an outdated cache. Instead, match the `kid` value in the JWT to the corresponding certificate in `public_certs`. +- Validate tokens using the external endpoint rather than saving the public key as a hard-coded value. +- Do not fetch the current key from `public_cert`, since your origin may inadvertently read an expired value from an outdated cache. Instead, match the `kid` value in the JWT to the corresponding certificate in `public_certs`. ::: ## Verify the JWT manually @@ -175,10 +173,10 @@ func main() { `pip` install the following: -* flask -* requests -* PyJWT -* cryptography +- flask +- requests +- PyJWT +- cryptography ```python from flask import Flask, request @@ -251,8 +249,8 @@ if __name__ == '__main__': ### JavaScript example ```javascript -const express = require('express'); -const jose = require('jose'); +const express = require("express"); +const jose = require("jose"); // The Application Audience (AUD) tag for your application const AUD = process.env.POLICY_AUD; @@ -265,33 +263,36 @@ const JWKS = jose.createRemoteJWKSet(new URL(CERTS_URL)); // verifyToken is a middleware to verify a CF authorization token const verifyToken = async (req, res, next) => { - const token = req.headers['cf-access-jwt-assertion']; - - // Make sure that the incoming request has our token header - if (!token) { - return res.status(403).send({ - status: false, - message: 'missing required cf authorization token', - }); - } - - const result = await jose.jwtVerify(token, JWKS, { - issuer: TEAM_DOMAIN, - audience: AUD, - }); - - req.user = result.payload; - next(); + const token = req.headers["cf-access-jwt-assertion"]; + + // Make sure that the incoming request has our token header + if (!token) { + return res.status(403).send({ + status: false, + message: "missing required cf authorization token", + }); + } + + const result = await jose.jwtVerify(token, JWKS, { + issuer: TEAM_DOMAIN, + audience: AUD, + }); + + req.user = result.payload; + next(); }; const app = express(); app.use(verifyToken); -app.get('/', (req, res) => { - res.send('Hello World!'); +app.get("/", (req, res) => { + res.send("Hello World!"); }); app.listen(3333); - ``` + +## Related resources + +- [Verifying JWTs in Cloudflare Workers](https://kinde.com/blog/engineering/verifying-jwts-in-cloudflare-workers/) - Implement JWT verification in Cloudflare Workers. diff --git a/src/content/docs/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication.mdx b/src/content/docs/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication.mdx index e2a8df40633e8f..88d2af11768fe2 100644 --- a/src/content/docs/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication.mdx @@ -248,7 +248,6 @@ You will need to add the CRL to your server or enforce the revocation in a Cloud mTLS does not currently work for: -- HTTP/3 traffic - Cloudflare Pages site served on a [custom domain](/pages/configuration/custom-domains/) - Cloudflare R2 public bucket served on a [custom domain](/r2/buckets/public-buckets/#connect-a-bucket-to-a-custom-domain) diff --git a/src/content/docs/cloudflare-one/identity/devices/index.mdx b/src/content/docs/cloudflare-one/identity/devices/index.mdx index 2cf298d04f93ee..d5b5b8776ff702 100644 --- a/src/content/docs/cloudflare-one/identity/devices/index.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/index.mdx @@ -55,6 +55,14 @@ C --5 min--> E[Cache] --> F[Gateway policy] A --> G[Service provider] --interval--> C ``` +:::caution + +Gateway does not terminate an [active session](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-sessions/#configure-warp-sessions-in-gateway) even if a subsequent posture check fails during that session. Gateway only evaluates posture checks at the beginning of a session, and ongoing sessions will remain uninterrupted. + +For example, if you establish an SSH session based on a successful posture check, but a posture requirement fails after the session has started, the session will remain active. + +::: + ### Expiration By default, the posture result on Cloudflare remains valid until it is overwritten by new data. You can specify an `expiration` time using our [API](/api/resources/zero_trust/subresources/devices/subresources/posture/methods/update/). We recommend setting the expiration to be longer than the [polling frequency](#polling-frequency). diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/crowdstrike.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/crowdstrike.mdx index 9b70d40cc0b114..cb5f9b9e9d969f 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/crowdstrike.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/crowdstrike.mdx @@ -33,32 +33,27 @@ To retrieve those values: 1. Log in to your Falcon Dashboard. 2. Go to **Support and resources** > **API Clients and Keys**. -3. Select **Add new API client** and enter any name for the client. -4. Enable the **Read** API Scope for **Zero Trust Assessment**, **Hosts**, **Detections**, **Event Streams**, and **User Management**. -5. Select **Add**. +3. Select **Create API client** and enter any name for the client. +4. Turn on the following API permissions: + | Scope | Permission | + | ----- | ---------- | + | Detections | Read | + | Hosts | Read | + | Event Streams | Read | + | User Management | Read | + | Zero Trust Assessment | Read | +5. Select **Create**. 6. Copy the **Client ID**, **Client Secret**, and **Base URL** to a safe place. -7. Go to **Host setup and management** > **Sensor downloads** and copy your Customer ID. -8. Get an auth token from your CrowdStrike API endpoint: - - ```bash - curl -X POST "/oauth2/token" \ - -H "accept: application/json" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "client_id=&client_secret=" - ``` - - This POST request authorizes Cloudflare Zero Trust to [add CrowdStrike as a service provider](#2-add-crowdstrike-as-a-service-provider). For more information, refer to the Crowdstrike [auth token documentation](https://falcon.us-2.crowdstrike.com/documentation/93/oauth2-auth-token-apis). +7. Go to **Host setup and management** > **Sensor downloads** and copy your **Customer ID**. ### 2. Add CrowdStrike as a service provider 5. Enter the **Client ID** and **Client secret** you noted down above. -6. Enter your **Rest API URL**. +6. In **Rest API URL**, enter your **Base URL**. 7. Enter your **Customer ID**. 8. Choose a **Polling frequency** for how often Cloudflare Zero Trust should query CrowdStrike for information. -9. Select **Save**. - - +9. Select **Test and save**. ### 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/custom.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/custom.mdx index e73bbb39ac389f..0ef8752d0fc00e 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/custom.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/custom.mdx @@ -5,6 +5,8 @@ sidebar: label: Custom integration order: 1 +description: Configure custom device posture checks in Cloudflare Zero Trust using a service-to-service integration. + --- import { Render } from "~/components" @@ -21,7 +23,6 @@ sequenceDiagram WARP->>External API: JSON with user and device identity External API-->>WARP: JSON with 0-100 result ``` - ## External API requirements The custom service provider integration works with any API service that meets the following specifications. For an example of a custom device posture integration API, refer to our [Cloudflare Workers sample code](https://github.com/cloudflare/custom-device-posture-integration-example-worker). diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/kolide.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/kolide.mdx index 9618ba6a3a342e..63876bae4304ec 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/kolide.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/kolide.mdx @@ -30,9 +30,7 @@ import { Render } from "~/components" 5. Enter the **Client secret** you noted down above. 6. Choose a **Polling frequency** for how often Cloudflare Zero Trust should query Kolide for information. -7. Select **Save**. - - +7. Select **Test and save**. ### 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/microsoft.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/microsoft.mdx index 12355fee93a31e..3b286de0dc9851 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/microsoft.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/microsoft.mdx @@ -46,9 +46,7 @@ To retrieve those values: 5. Enter the **Client ID**, **Client secret** and **Customer ID** as you noted down above. 6. Select a **Polling frequency** for how often Cloudflare Zero Trust should query Microsoft Graph API for information. -7. Select **Save**. - - +7. Select **Test and save**. ## 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/sentinelone.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/sentinelone.mdx index f664676c753636..fd1e302d718ae9 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/sentinelone.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/sentinelone.mdx @@ -45,9 +45,7 @@ To retrieve those values: 5. In **Client Secret**, enter your **API Token**. 6. In **Rest API URL**, enter `https://.sentinelone.net`. 7. Choose a **Polling frequency** for how often Cloudflare Zero Trust should query SentinelOne for information. -8. Select **Save**. - - +8. Select **Test and save**. ### 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/taniums2s.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/taniums2s.mdx index 4e2d65a916efa3..ecfff09f660651 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/taniums2s.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/taniums2s.mdx @@ -43,9 +43,7 @@ To retrieve those values: 5. Enter the **Client Secret** and **Rest API URL** you noted down above. 6. Choose a **Polling frequency** for how often Cloudflare Zero Trust should query Tanium for information. -7. Select **Save**. - - +7. Select **Test and save**. ### 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/uptycs.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/uptycs.mdx index bed35d08795356..f344d0a3118459 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/uptycs.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/uptycs.mdx @@ -34,9 +34,7 @@ To obtain these values: 5. Enter the **Client ID**, **Client secret** and **Customer ID** as you noted down above. 6. Select a **Polling frequency** for how often Cloudflare Zero Trust should query Uptycs for information. -7. Select **Save**. - - +7. Select **Test and save**. ## 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/service-providers/workspace-one.mdx b/src/content/docs/cloudflare-one/identity/devices/service-providers/workspace-one.mdx index 82e3e1ce83e3a3..b27ead8cb99d7e 100644 --- a/src/content/docs/cloudflare-one/identity/devices/service-providers/workspace-one.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/service-providers/workspace-one.mdx @@ -44,9 +44,7 @@ To retrieve those values: 5. Enter the **Client ID** and **Client secret** you noted down above. 6. Select a **Polling frequency** for how often Cloudflare Zero Trust should query Workspace ONE for information. 7. Enter the **Region-specific token URL** and **REST API URL** you noted down above. -8. Select **Save**. - - +8. Select **Test and save**. ## 3. Configure the posture check diff --git a/src/content/docs/cloudflare-one/identity/devices/warp-client-checks/client-certificate.mdx b/src/content/docs/cloudflare-one/identity/devices/warp-client-checks/client-certificate.mdx index af477a0f4621b0..280373c79e9be9 100644 --- a/src/content/docs/cloudflare-one/identity/devices/warp-client-checks/client-certificate.mdx +++ b/src/content/docs/cloudflare-one/identity/devices/warp-client-checks/client-certificate.mdx @@ -31,7 +31,7 @@ The Client Certificate device posture attribute checks if the device has a valid - A CA that issues client certificates for your devices. WARP does not evaluate the certificate trust chain; this needs to be the issuing certificate. - Cloudflare WARP client is [deployed](/cloudflare-one/connections/connect-devices/warp/deployment/) on the device. -- A client certificate is [installed and trusted](#how-warp-checks-for-a-client-certificate) on the device. +- A client certificate is [installed and trusted](#configure-the-client-certificate-check) on the device. :::note diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/adfs.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/adfs.mdx index 76049cd16258ff..aa2e7e5a6db90e 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/adfs.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/adfs.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: how-to title: Active Directory (SAML) +description: Integrate Active Directory with Cloudflare Zero Trust for secure identity management. --- import { GlossaryTooltip } from "~/components"; @@ -12,7 +13,6 @@ To set up the Microsoft Entra ID IdP integration with Zero Trust, refer to [Micr ::: Active Directory is a directory service developed by Microsoft for Windows domain networks. It is included in most Windows Server operating systems as a set of processes and services. Active Directory integrates with Cloudflare Access using Security Assertion Markup Language (SAML). - ## Before you start To get started, you need: diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/centrify-saml.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/centrify-saml.mdx index 745b96a7fc2b18..48b5385635697f 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/centrify-saml.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/centrify-saml.mdx @@ -1,10 +1,10 @@ --- pcx_content_type: how-to title: Centrify (SAML) +description: Learn how to integrate Centrify as a SAML identity provider with Cloudflare Zero Trust. --- Centrify secures access to infrastructure, DevOps, cloud, and other modern enterprise so you can prevent the number one cause of breaches: privileged access abuse. - ## Set up Centrify as a SAML provider ## 1. Create an application in Centrify diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/entra-id.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/entra-id.mdx index 5631cf3814eee1..0468ee5f1511fa 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/entra-id.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/entra-id.mdx @@ -19,31 +19,31 @@ The following Entra ID values are required to set up the integration: To retrieve those values: -1. Log in to the [Azure dashboard](https://portal.azure.com/). +1. Log in to the [Azure dashboard](https://portal.azure.com/). -2. Go to **All services** > **Microsoft Entra ID**. +2. Go to **All services** > **Microsoft Entra ID**. -3. In the sidebar, go to **Manage** > **Enterprise applications**. +3. In the sidebar, go to **Manage** > **Enterprise applications**. -4. Select **New application**, then select **Create your own application**. +4. Select **New application**, then select **Create your own application**. -5. Name your application. +5. Name your application. -6. Select **Register an application to integrate with Microsoft Entra ID (App you're developing)** and then select **Create**. +6. Select **Register an application to integrate with Microsoft Entra ID (App you're developing)** and then select **Create**. -7. Under **Redirect URI**, select the _Web_ platform and enter the following URL: +7. Under **Redirect URI**, select the _Web_ platform and enter the following URL: - ```txt - https://.cloudflareaccess.com/cdn-cgi/access/callback - ``` + ```txt + https://.cloudflareaccess.com/cdn-cgi/access/callback + ``` - You can find your team name in Zero Trust under **Settings** > **Custom Pages**. + You can find your team name in Zero Trust under **Settings** > **Custom Pages**. - ![Registering an application in Azure](~/assets/images/cloudflare-one/identity/azure/name-app.png) + ![Registering an application in Azure](~/assets/images/cloudflare-one/identity/azure/name-app.png) -8. Select **Register**. +8. Select **Register**. -9. Next, return to Microsoft Entra ID and go to go to **Manage** > **App registrations**. +9. Next, return to Microsoft Entra ID and go to go to **Manage** > **App registrations**. 10. Select the app you just created. Copy the **Application (client) ID** and **Directory (tenant) ID**. @@ -53,11 +53,9 @@ To retrieve those values: 12. Name the client secret and choose an expiration period. -:::note - -When the client secret expires, users will be unable to log in through Access. Take note of your expiry date to prevent login errors and renew your client secret when necessary. - -::: + :::note + When the client secret expires, users will be unable to log in through Access. Take note of your expiry date to prevent login errors and renew your client secret when necessary. + ::: 13. After the client secret is created, copy its **Value** field. Store the client secret in a safe place, as it can only be viewed immediately after creation. @@ -118,27 +116,28 @@ To [test](/cloudflare-one/identity/idp-integration/#test-idps-in-zero-trust) tha -1. [Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: - | Type | Item | Permission | - | ------- | ---------------- | ---------- | - | Account | Access: Organizations, Identity Providers, and Groups | Edit | - -2. Make a `POST` request to the [Identity Providers](/api/resources/zero_trust/subresources/identity_providers/methods/create/) endpoint: - - ```sh - curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/identity_providers \ - --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ - --data '{ - "name": "Entra ID example", - "type": "azureAD", - "config": { - "client_id": "", - "client_secret": "", - "directory_id": "", - "support_groups": true - } - }' - ``` +1. [Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: + + | Type | Item | Permission | + | ------- | ----------------------------------------------------- | ---------- | + | Account | Access: Organizations, Identity Providers, and Groups | Edit | + +2. Make a `POST` request to the [Identity Providers](/api/resources/zero_trust/subresources/identity_providers/methods/create/) endpoint: + + ```sh + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/identity_providers \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + --data '{ + "name": "Entra ID example", + "type": "azureAD", + "config": { + "client_id": "", + "client_secret": "", + "directory_id": "", + "support_groups": true + } + }' + ``` @@ -146,12 +145,13 @@ To [test](/cloudflare-one/identity/idp-integration/#test-idps-in-zero-trust) tha The following example requires Cloudflare provider version `>=4.40.0`. ::: -1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_token): - - `Access: Organizations, Identity Providers, and Groups Write` +1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_token): + + - `Access: Organizations, Identity Providers, and Groups Write` -2. Configure the [`cloudflare_zero_trust_access_identity_provider`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_identity_provider) resource: +2. Configure the [`cloudflare_zero_trust_access_identity_provider`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_identity_provider) resource: - + @@ -185,7 +185,7 @@ The Microsoft Entra ID integration allows you to synchronize IdP groups and auto ### 2. Configure SCIM in Entra ID @@ -274,11 +274,12 @@ Access and Gateway policies for an Entra group will also apply to all [nested gr You can require users to re-enter their credentials into Entra ID whenever they [re-authenticate their WARP session](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-sessions/). To configure this setting: 1. Make a `GET` request to the [Identity Providers endpoint](/api/resources/zero_trust/subresources/identity_providers/) and copy the response for the Entra ID identity provider. -2. [Update the Entra ID identity provider](/api/resources/zero_trust/subresources/identity_providers/methods/update/) using a `PUT` request. In the request body, include all existing configurations and set the `prompt` parameter to either `login` or `select_account`. For example, +2. [Update the Entra ID identity provider](/api/resources/zero_trust/subresources/identity_providers/methods/update/) using a `PUT` request. In the request body, include all existing configurations and set the `prompt` parameter to either `login` or `select_account`. For example: + ```sh {17} curl --request PUT \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/access/identity_providers/{identity_provider_id} \ - --header "Authorization: Bearer " \ + https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/identity_providers/$IDENTITY_PROVIDER_ID \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/generic-oidc.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/generic-oidc.mdx index 34abd6e287f9ac..03a347bcab65c0 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/generic-oidc.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/generic-oidc.mdx @@ -129,14 +129,14 @@ Your identity provider must support SCIM version 2.0. ### 2. Configure SCIM in the IdP -Setup instructions vary depending on the identity provider. In your identity provider, you will either need to edit the [original SSO application](/cloudflare-one/identity/idp-integration/generic-oidc/#set-up-a-generic-oidc) or create a new SCIM application. Refer to your identity provider's documentation for more details. For example instructions, refer to our [Okta](/cloudflare-one/identity/idp-integration/okta/#synchronize-users-and-groups) or [Jumpcloud](/cloudflare-one/identity/idp-integration/jumpcloud-saml/#synchronize-users-and-groups) guides. +Setup instructions vary depending on the identity provider. In your identity provider, you will either need to edit the [original SSO application](/cloudflare-one/identity/idp-integration/generic-oidc/#1-create-an-application-in-your-identity-provider) or create a new SCIM application. Refer to your identity provider's documentation for more details. For example instructions, refer to our [Okta](/cloudflare-one/identity/idp-integration/okta/#synchronize-users-and-groups) or [Jumpcloud](/cloudflare-one/identity/idp-integration/jumpcloud-saml/#synchronize-users-and-groups) guides. #### IdP groups If you would like to build policies based on IdP groups: - Ensure that your IdP sends a `groups` field. The naming must match exactly (case insensitive). All other values will be sent as a OIDC claim. -- If your IdP requires creating a new SCIM application, ensure that the groups in the SCIM application match the groups in the [original SSO application](/cloudflare-one/identity/idp-integration/generic-oidc/#set-up-a-generic-oidc). Because SCIM group membership updates will overwrite any groups in a user's identity, assigning the same groups to each app ensures consistent policy evaluation. +- If your IdP requires creating a new SCIM application, ensure that the groups in the SCIM application match the groups in the [original SSO application](/cloudflare-one/identity/idp-integration/generic-oidc/#1-create-an-application-in-your-identity-provider). Because SCIM group membership updates will overwrite any groups in a user's identity, assigning the same groups to each app ensures consistent policy evaluation. ### 3. Verify SCIM provisioning diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/generic-saml.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/generic-saml.mdx index 8ae65f5117478b..0ae1ec07b29c73 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/generic-saml.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/generic-saml.mdx @@ -5,7 +5,7 @@ sidebar: order: 2 --- -import { Tabs, TabItem, Render } from '~/components'; +import { Tabs, TabItem, Render } from "~/components"; Cloudflare Zero Trust integrates with any identity provider that supports SAML 2.0. If your identity provider is not listed in the integration list of login methods in Zero Trust, it can be configured using SAML 2.0 (or OpenID if OIDC based). Generic SAML can also be used if you would like to pass additional SAML headers or claims for an IdP in the integration list. @@ -43,7 +43,6 @@ To download the SAML metadata file, copy-paste the metadata endpoint into a web ## 2. Add a SAML identity provider to Zero Trust - 1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Settings** > **Authentication** > **Login methods**. @@ -60,28 +59,36 @@ To download the SAML metadata file, copy-paste the metadata endpoint into a web The following example requires Cloudflare provider version `>=4.40.0`. ::: -1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_token): +1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_token): + - `Access: Organizations, Identity Providers, and Groups Write` -2. Configure the [`cloudflare_zero_trust_access_identity_provider`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_identity_provider) resource: - - ```tf - resource "cloudflare_zero_trust_access_identity_provider" "generic_saml_example" { - account_id = var.cloudflare_account_id - name = "Generic SAML example" - type = "saml" - config { - sso_target_url = "https://example.com/1234/sso/saml" - issuer_url = "https://example.com/1234" - idp_public_cert = "-----BEGIN CERTIFICATE-----\nXXXXX\n-----END CERTIFICATE-----" - sign_request = false - email_attribute_name = "email" - attributes = ["employeeID", "groups"] - } - } - ``` +2. Configure the [`cloudflare_zero_trust_access_identity_provider`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/zero_trust_access_identity_provider) resource: + + ```tf + resource "cloudflare_zero_trust_access_identity_provider" "generic_saml_example" { + account_id = var.cloudflare_account_id + name = "Generic SAML example" + type = "saml" + config { + sso_target_url = "https://example.com/1234/sso/saml" + issuer_url = "https://example.com/1234" + idp_public_cert = "-----BEGIN CERTIFICATE-----\nXXXXX\n-----END CERTIFICATE-----" + sign_request = false + email_attribute_name = "email" + attributes = ["employeeID", "groups"] + } + } + ``` + +:::caution + +Set a reminder for the expiry date of the signing certificate obtained from your generic SAML identity provider. After the certificate expires, you will need to generate a new signing certificate and re-add it to your Cloudflare configuration via the Cloudflare dashboard or Terraform. + +::: + ## 3. Test the connection You can now [test the IdP integration](/cloudflare-one/identity/idp-integration/#test-idps-in-zero-trust). A success response should return the configured SAML attributes. @@ -96,10 +103,7 @@ Your identity provider must support SCIM version 2.0. ### 1. Enable SCIM in Zero Trust - + ### 2. Configure SCIM in the IdP @@ -114,7 +118,7 @@ If you would like to build policies based on IdP groups: ### 3. Verify SCIM provisioning - + ## Optional configurations diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/google-workspace.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/google-workspace.mdx new file mode 100644 index 00000000000000..157b88072e20c4 --- /dev/null +++ b/src/content/docs/cloudflare-one/identity/idp-integration/google-workspace.mdx @@ -0,0 +1,120 @@ +--- +pcx_content_type: how-to +title: Google Workspace +--- + +import { GlossaryTooltip, Render } from "~/components"; + +:::note + +The Google Workspace IdP integration is not supported if your Google Workspace account is protected by Access. +::: + +You can integrate a Google Workspace (formerly G Suite) account with Cloudflare Access. Unlike the instructions for [generic Google authentication](/cloudflare-one/identity/idp-integration/google/), the steps below will allow you to pull group membership information from your Google Workspace account. + +Once integrated, users will log in with their Google Workspace credentials to reach resources protected by Cloudflare Access or to enroll their device into Cloudflare Gateway. + +You do not need to be a Google Cloud Platform user to integrate Google Workspace as an identity provider with Cloudflare Zero Trust. You will only need to open the Google Cloud Platform to configure IdP integration settings. + +## Set up Google Workspace as an identity provider + +### 1. Configure Google Workspace + +1. Log in to the Google Cloud Platform [console](https://console.cloud.google.com/). This is separate from your Google Workspace console. + +2. A Google Cloud project is required to enable Google Workspace APIs. If you do not already have a Google Cloud project, go to **IAM & Admin** > **Create Project**. Name the project and select **Create**. + +3. Go to **APIs & Services** and select **Enable APIs and Services**. The API Library will load. + +4. In the API Library, search for `admin` and select **Admin SDK API**. + +5. **Enable** the Admin SDK API. + +6. Return to the **APIs & Services** page and go to **Credentials**. + +7. Select **Configure Consent Screen**. + + ![Location to configure a Consent Screen in the Google Cloud Platform console.](~/assets/images/cloudflare-one/identity/google/configure-consent-screen.png) + +8. To configure the consent screen: + + 1. Select **Get Started**. + 2. Enter an **App name** and a **User support email**. + 3. Choose **Internal** as the Audience Type. This Audience Type limits authorization requests to users in your Google Workspace and blocks users who have regular Gmail addresses. + 4. Enter your **Contact Information**. Google Cloud Platform requires an email in your account. + 5. Agree to Google's user data policy and select **Continue**. + 6. Select **Create**. + +9. The OAuth overview page will load. Select **Create OAuth Client**. + + ![Location to create an OAuth client in the Google Cloud Platform console.](~/assets/images/cloudflare-one/identity/google/create-oauth-client.png) + +10. Choose _Web application_ as the **Application type** and give your OAuth Client ID a name. + +11. Under **Authorized JavaScript origins**, in the **URIs** field, enter your team domain: + + ```txt + https://.cloudflareaccess.com + ``` + + You can find your team name in [Zero Trust](https://one.dash.cloudflare.com/) under **Settings** > **Custom Pages**. + +12. Under **Authorized redirect URIs**, in the **URIs** field, enter the following URL: + + ```txt + https://.cloudflareaccess.com/cdn-cgi/access/callback + ``` + +13. After creating the OAuth client, select the OAuth client that you just created. Google will present the **OAuth Client ID** value and **Client secret** value. The client secret field functions like a password and should not be shared. Copy both the **OAuth Client ID** value and **Client secret** value. + +14. On your [Google Admin console](https://admin.google.com), go to **Security** > **Access and data control** > **API controls**. + +15. In **API Controls**, select **Settings**. + +16. Select **Internal apps** and check the box next to **Trust internal apps** to enable this option. The **Trust internal apps** setting is disabled by default and must be enabled for Cloudflare Access to work correctly. + + ![Location to trust internal apps in the Google Cloud Platform console.](~/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png) + +### 2. Add Google Workspace to Zero Trust + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Settings** > **Authentication**. + +2. Under **Login methods**, select **Add new** and choose **Google Workspace**. + +3. Input the Client ID (**App ID** in the Cloudflare dashboard) and Client Secret fields generated previously. Additionally, enter the domain of your Google Workspace account. + +4. (Optional) Enable [Proof of Key Exchange (PKCE)](https://www.oauth.com/oauth2-servers/pkce/). PKCE will be performed on all login attempts. + +5. (Optional) Under **Optional configurations**, enter [custom OIDC claims](/cloudflare-one/identity/idp-integration/generic-oidc/#oidc-claims) that you wish to add to your Access [application token](/cloudflare-one/identity/authorization-cookie/application-token/). + +6. Select **Save**. To complete setup, you must visit the generated link. If you are not the Google Workspace administrator, share the link with the administrator. + +7. The generated link will prompt you to log in to your Google admin account and to authorize Cloudflare Access to view group information. After allowing permissions, you will see a success page from Cloudflare Access. + +To test that your connection is working, go to **Authentication** > **Login methods** and select **Test** next to Google Workspace. Your user identity and group membership should return. + +:::note[`Failed to fetch group information from the identity provider` error] + +To test successfully, you must [finish setup](https://community.cloudflare.com/t/google-workspace-failed-to-fetch-group-information-from-the-identity-provider/313361/2). Testing before finishing setup will result in a [`Failed to fetch user/group information from the identity provider` error](/cloudflare-one/faq/troubleshooting/#i-am-getting-the-error-failed-to-fetch-usergroup-information-from-the-identity). + +::: + +## Example API Configuration + +```json +{ + "config": { + "client_id": "", + "client_secret": "", + "apps_domain": "mycompany.com" + }, + "type": "google-apps", + "name": "my example idp" +} +``` + +## Troubleshooting + +### `Error 401: deleted_client` + + diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/google.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/google.mdx index 95e1797c4e241f..aa9d9908113726 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/google.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/google.mdx @@ -5,30 +5,34 @@ title: Google import { GlossaryTooltip, Render } from "~/components"; -You can integrate Google authentication with Cloudflare Access without a Google Workspace account. The integration allows any user with a Google account to log in (if the [Access policy](/cloudflare-one/policies/access/) allows them to reach the resource). Unlike the instructions for [Google Workspace](/cloudflare-one/identity/idp-integration/gsuite/), the steps below will not allow you to pull group membership information from a Google Workspace account. +You can integrate Google authentication with Cloudflare Access without a Google Workspace account. The integration allows any user with a Google account to log in (if the [Access policy](/cloudflare-one/policies/access/) allows them to reach the resource). Unlike the instructions for [Google Workspace](/cloudflare-one/identity/idp-integration/google-workspace/), the steps below will not allow you to pull group membership information from a Google Workspace account. -You do not need to be a Google Cloud Platform user to integrate Google Suite as an identity provider with Cloudflare Zero Trust. You will only need to open the Google Cloud Platform to configure IdP integration settings. +You do not need to be a Google Cloud Platform user to integrate Google as an identity provider with Cloudflare Zero Trust. You will only need to open the Google Cloud Platform to configure IdP integration settings. ## Set up Google as an identity provider -1. Visit the Google Cloud Platform console. Create a new project, name the project, and select **Create**. +1. Log in to the Google Cloud Platform [console](https://console.cloud.google.com/). Create a new project, name the project, and select **Create**. -2. On the project home page, go to **APIs & Services** on the sidebar and select **Dashboard**. +2. On the project home page, go to **APIs & Services** and on the sidebar select **Credentials**. -3. On the sidebar, go to **Credentials** and select **Configure Consent Screen** at the top of the page. +3. Select **Configure Consent Screen**. - ![Location of credential settings at the top of the Google Cloud Platform dashboard.](~/assets/images/cloudflare-one/identity/google/click-configure-consent.png) + ![Location to configure a Consent Screen in the Google Cloud Platform console.](~/assets/images/cloudflare-one/identity/google/configure-consent-screen.png) -4. Choose `External` as the User Type. Since this application is not being created in a Google Workspace account, any user with a Gmail address can login. +4. To configure the consent screen: -5. Name the application, add a support email, and input contact fields. Google Cloud Platform requires an email in your account. - :::note - In the **Scopes** section, we recommend adding the `userinfo.email` scope. This is not required for the integration, but shows authenticating users what information is being gathered. You do not need to add test users. - ::: + 1. Select **Get started**. + 2. Enter an **App name** and a **User support email**. + 3. Choose **External** as the Audience Type. Since this application is not being created in a Google Workspace account, any user with a Gmail address can log in. + 4. Enter your **Contact Information**. Google Cloud Platform requires an email in your account. + 5. Agree to Google's user data policy and select **Continue**. + 6. Select **Create**. -6. Return to the **APIs & Services** page, select **Create Credentials** > **OAuth client ID**, and name the application. +5. The OAuth overview page will load. On the OAuth overview screen, select **Create OAuth client**. - ![Location of OAuth client ID settings on Google Cloud Platform credentials page.](~/assets/images/cloudflare-one/identity/google/create-oauth.png) + ![Location to create an OAuth client in the Google Cloud Platform console.](~/assets/images/cloudflare-one/identity/google/create-oauth-client.png) + +6. Choose _Web application_ as the **Application type** and give your OAuth Client ID a name. 7. Under **Authorized JavaScript origins**, in the **URIs** field, enter your team domain: @@ -36,7 +40,7 @@ You do not need to be a Google Cloud Platform user to integrate Google Suite as https://.cloudflareaccess.com ``` - You can find your team name in Zero Trust under **Settings** > **Custom Pages**. + You can find your team name in [Zero Trust](https://one.dash.cloudflare.com/) under **Settings** > **Custom Pages**. 8. Under **Authorized redirect URIs**, in the **URIs** field, enter the following URL: @@ -44,13 +48,13 @@ You do not need to be a Google Cloud Platform user to integrate Google Suite as https://.cloudflareaccess.com/cdn-cgi/access/callback ``` -9. Google will present the OAuth Client ID and Secret values. The secret field functions like a password and should not be shared. Copy both values. +9. After creating the OAuth client, select the OAuth client that you just created. Google will present the **OAuth Client ID** value and **Client secret** value. The client secret field functions like a password and should not be shared. Copy both the **OAuth Client ID** value and **Client secret** value. 10. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Settings** > **Authentication**. 11. Under **Login methods**, select **Add new**. Choose **Google** on the next page. -12. Input the Client ID and Client Secret fields generated previously. +12. Input the Client ID (**App ID** in the Cloudflare dashboard) and Client Secret fields generated previously. 13. (Optional) Enable [Proof of Key Exchange (PKCE)](https://www.oauth.com/oauth2-servers/pkce/). PKCE will be performed on all login attempts. diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/gsuite.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/gsuite.mdx deleted file mode 100644 index b4b6a7488a1224..00000000000000 --- a/src/content/docs/cloudflare-one/identity/idp-integration/gsuite.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -pcx_content_type: how-to -title: Google Workspace ---- - -import { GlossaryTooltip, Render } from "~/components"; - -:::note - -The Google Workspace IdP integration is not supported if your Google Workspace account is protected by Access. -::: - -You can integrate a Google Workspace (formerly Google Suite) account with Cloudflare Access. Unlike the instructions for [generic Google authentication](/cloudflare-one/identity/idp-integration/google/), the steps below will allow you to pull group membership information from your Google Workspace account. - -Once integrated, users will log in with their Google Workspace credentials to reach resources protected by Cloudflare Access or to enroll their device into Cloudflare Gateway. - -You do not need to be a Google Cloud Platform user to integrate Google Workspace as an identity provider with Cloudflare Zero Trust. You will only need to open the Google Cloud Platform to configure IdP integration settings. - -## Set up Google Workspace as an identity provider - -### 1. Configure Google Workspace - -1. Log in to the Google Cloud Platform [console](https://console.cloud.google.com/). This is separate from your Google Workspace console. - -2. A Google Cloud project is required to enable Google Workspace APIs. If you do not already have a Google Cloud project, go to **IAM & Admin** > **Create Project**. Name the project and select **Create**. - -3. Go to **APIs & Services** and select **+ Enable APIs and Services**. The API Library will load. - -4. In the API Library, search for `admin` and select _Admin SDK API_. - -5. **Enable** the Admin SDK API. - -6. Return to the **APIs & Services** page and go to **Credentials**. - - ![Location of credential settings at the top of the Google Cloud Platform dashboard.](~/assets/images/cloudflare-one/identity/google/click-configure-consent.png) - -7. You will see a warning that you need to configure a consent screen. Select **Configure Consent Screen**. - -8. To configure the consent screen: - - 1. Choose **Internal** as the User Type. This limits authorization requests to users in your Google Workspace and blocks users who have regular Gmail addresses. - 2. Name the application, add a support email, and input contact fields. Google Cloud Platform requires an email in your account. - 3. The **Scopes** page can be left blank. - 4. The summary page will load and you can save and exit. - -9. Return to the **Credentials** page and select **+ Create Credentials** > **OAuth client ID**. - - ![Location of OAuth client ID settings on Google Cloud Platform credentials page.](~/assets/images/cloudflare-one/identity/google/create-oauth.png) - -10. Choose _Web application_ as the Application type. - -11. Under **Authorized JavaScript origins**, in the **URIs** field, enter your team domain: - - ```txt - https://.cloudflareaccess.com - ``` - - You can find your team name in Zero Trust under **Settings** > **Custom Pages**. - -12. Under **Authorized redirect URIs**, in the **URIs** field, enter the following URL: - - ```txt - https://.cloudflareaccess.com/cdn-cgi/access/callback - ``` - -13. Google will present the OAuth Client ID and Secret values. The secret field functions like a password and should not be shared. Copy both values. - -14. On your [Google Admin console](https://admin.google.com), go to **Security** > **Access and data control** > **API controls**. - ![Location of Trust internal apps setting in the Google Admin dashboard](~/assets/images/cloudflare-one/identity/gsuite/trust-internal-apps.png) - -15. Enable the **Trust internal, domain-owned apps** option. This setting is disabled by default and must be enabled for Cloudflare Access to work correctly. - -### 2. Add Google Workspace to Zero Trust - -1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Settings** > **Authentication**. - -2. Under **Login methods**, select **Add new** and choose **Google Workspace**. - -3. Input the Client ID and Client Secret fields generated previously. Additionally, input the domain of your Google Workspace account. - -4. (Optional) Enable [Proof of Key Exchange (PKCE)](https://www.oauth.com/oauth2-servers/pkce/). PKCE will be performed on all login attempts. - -5. (Optional) Under **Optional configurations**, enter [custom OIDC claims](/cloudflare-one/identity/idp-integration/generic-oidc/#oidc-claims) that you wish to add to your Access [application token](/cloudflare-one/identity/authorization-cookie/application-token/). - -6. Select **Save**. To complete setup, you must visit the generated link. If you are not the Google Workspace administrator, share the link with the administrator. - -7. The generated link will prompt you to log in to your Google admin account and to authorize Cloudflare Access to view group information. After allowing permissions, you will see a success page from Cloudflare Access. - -To test that your connection is working, go to **Authentication** > **Login methods** and select **Test** next to Google Workspace. Your user identity and group membership should return. - -## Example API Configuration - -```json -{ - "config": { - "client_id": "", - "client_secret": "", - "apps_domain": "mycompany.com" - }, - "type": "google-apps", - "name": "my example idp" -} -``` - -## Troubleshooting - -### `Error 401: deleted_client` - - diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/okta-saml.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/okta-saml.mdx index a14b86cf11dde5..8af703f56fdcfa 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/okta-saml.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/okta-saml.mdx @@ -1,10 +1,10 @@ --- pcx_content_type: how-to title: Okta (SAML) +description: Integrate Okta as a SAML identity provider with Cloudflare Zero Trust. --- Cloudflare Zero Trust can integrate SAML with Okta as an identity provider. - ## Set up Okta as a SAML provider To set up SAML with Okta as your identity provider: diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/okta.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/okta.mdx index 051bf61ca19ae8..bf8470160e8290 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/okta.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/okta.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: how-to title: Okta +description: Integrate Okta as an identity provider for Cloudflare Zero Trust. --- import { Render } from "~/components"; @@ -8,7 +9,6 @@ import { Render } from "~/components"; Okta provides cloud software that helps companies manage and secure user authentication to modern applications, and helps developers build identity controls into applications, website web services, and devices. You can integrate Okta with Cloudflare Zero Trust and build rules based on user identity and group membership. Cloudflare Zero Trust supports Okta integrations using either the OIDC (default) or [SAML](/cloudflare-one/identity/idp-integration/okta-saml/) protocol. Additionally, you can configure Okta to use risk information from Zero Trust [user risk scores](/cloudflare-one/insights/risk-score/) to create SSO-level policies. For more information, refer to [Send risk score to Okta](/cloudflare-one/insights/risk-score/#send-risk-score-to-okta). - ## Set up Okta as an OIDC provider 1. On your Okta admin dashboard, go to **Applications** > **Applications**. diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/onelogin-saml.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/onelogin-saml.mdx index 0fb8da65b69dd2..f264b4d3186e7a 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/onelogin-saml.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/onelogin-saml.mdx @@ -1,10 +1,10 @@ --- pcx_content_type: how-to title: OneLogin (SAML) +description: Integrate OneLogin as a SAML identity provider for Cloudflare Zero Trust. --- OneLogin provides SSO identity management. Cloudflare Access supports OneLogin as an SAML identity provider. - ## Set up OneLogin as a SAML provider ## 1. Create an application in OneLogin diff --git a/src/content/docs/cloudflare-one/identity/idp-integration/pingone-saml.mdx b/src/content/docs/cloudflare-one/identity/idp-integration/pingone-saml.mdx index 323e4640d30af1..0d2305ac59a742 100644 --- a/src/content/docs/cloudflare-one/identity/idp-integration/pingone-saml.mdx +++ b/src/content/docs/cloudflare-one/identity/idp-integration/pingone-saml.mdx @@ -1,12 +1,12 @@ --- pcx_content_type: how-to title: PingOne (SAML) +description: Learn how to integrate PingOne as a SAML identity provider with Cloudflare Zero Trust. --- import { GlossaryTooltip } from "~/components"; The PingOne cloud platform from PingIdentity provides SSO identity management. Cloudflare Access supports PingOne as a SAML identity provider. - ## Set up PingOne as a SAML provider ## 1. Create an application in PingOne diff --git a/src/content/docs/cloudflare-one/identity/one-time-pin.mdx b/src/content/docs/cloudflare-one/identity/one-time-pin.mdx index 79684e82588baa..53e602bb4384e4 100644 --- a/src/content/docs/cloudflare-one/identity/one-time-pin.mdx +++ b/src/content/docs/cloudflare-one/identity/one-time-pin.mdx @@ -88,6 +88,6 @@ By design, blocked users will not receive an email. The login page will always s :::note -Access only logs an authentication attempt after the user enters a code. If the user enters their email but never submits a code, the event will not appear in your [audit logs](/cloudflare-one/insights/logs/audit-logs/#authentication-audit-logs). +Access only logs an authentication attempt after the user enters a code. If the user enters their email but never submits a code, the event will not appear in your [audit logs](/cloudflare-one/insights/logs/audit-logs/#authentication-logs). ::: diff --git a/src/content/docs/cloudflare-one/identity/users/seat-management.mdx b/src/content/docs/cloudflare-one/identity/users/seat-management.mdx index 13e9b29d50d528..4ecaed821137ac 100644 --- a/src/content/docs/cloudflare-one/identity/users/seat-management.mdx +++ b/src/content/docs/cloudflare-one/identity/users/seat-management.mdx @@ -5,7 +5,7 @@ sidebar: order: 4 --- -Cloudflare Zero Trust subscriptions consist of seats that active users in your account consume. Active users are added to Zero Trust through any [authentication event](#authentication-event). +Cloudflare Zero Trust subscriptions consist of seats that active users in your account consume. Active users are added to Zero Trust through any [authentication event](#authentication-events). The amount of seats available in your Zero Trust account depends on the amount of users you purchase. If you want to increase the number of seats available, you will have to purchase more users. Learn more about adding and removing seats from your account in the [Zero Trust FAQ](/cloudflare-one/faq/getting-started-faq/#how-do-i-change-my-subscription-plan). diff --git a/src/content/docs/cloudflare-one/identity/users/session-management.mdx b/src/content/docs/cloudflare-one/identity/users/session-management.mdx index 2d9ad22312f474..bd677d73491f28 100644 --- a/src/content/docs/cloudflare-one/identity/users/session-management.mdx +++ b/src/content/docs/cloudflare-one/identity/users/session-management.mdx @@ -47,9 +47,13 @@ You can set an application session duration for self-hosted and private Access a The application token will expire after this period of time (unless you have set a [policy session duration](#set-policy-session-duration)). -#### SaaS application sessions +#### SaaS applications -Access session durations only control the front door to a SaaS app; Access does not control how long the user can stay in the SaaS app itself. For example, if the user logs out of the SaaS app and then comes back to it, a valid Access application token allows them to re-authenticate without another login. The SaaS app issues its own authorization cookie that manages the user's session within the app. + + +#### SSH, RDP, and VNC + + ### Set policy session duration diff --git a/src/content/docs/cloudflare-one/index.mdx b/src/content/docs/cloudflare-one/index.mdx index 0982cfda426f4b..f7b967877d9e53 100644 --- a/src/content/docs/cloudflare-one/index.mdx +++ b/src/content/docs/cloudflare-one/index.mdx @@ -1,12 +1,12 @@ --- -title: Overview +title: Cloudflare Zero Trust type: overview pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Zero Trust + content: Overview --- import { GlossaryTooltip, Render } from "~/components"; diff --git a/src/content/docs/cloudflare-one/insights/analytics/gateway.mdx b/src/content/docs/cloudflare-one/insights/analytics/gateway.mdx index 83e64b8e571652..fff34ee6004254 100644 --- a/src/content/docs/cloudflare-one/insights/analytics/gateway.mdx +++ b/src/content/docs/cloudflare-one/insights/analytics/gateway.mdx @@ -14,4 +14,47 @@ To see the top Allowed and Blocked requests across all of your DNS locations, go ## GraphQL queries -You can use the [GraphQL Analytics API](/analytics/graphql-api/) to query your Gateway Analytics data. For more information on the Gateway Analytics dataset, refer to the [available datasets](/analytics/graphql-api/features/data-sets/) table and use the [GraphiQL client](/analytics/graphql-api/getting-started/explore-graphql-schema/) to explore the schema. +You can use the [GraphQL Analytics API](/analytics/graphql-api/) to query your Gateway Analytics data. Available [datasets](/analytics/graphql-api/features/data-sets/) for Gateway include: + +| Dataset | Description | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `gatewayL4DownstreamSessionsAdaptiveGroups` | Metrics for Gateway network sessions from user devices to the Cloudflare global network. | +| `gatewayL4UpstreamSessionsAdaptiveGroups` | Metrics for Gateway network sessions from the Cloudflare global network to user devices. | +| `gatewayL4SessionsAdaptiveGroups` | Metrics for Gateway network sessions with adaptive sampling. | +| `gatewayL7RequestsAdaptiveGroups` | Metrics for Gateway HTTP requests with adaptive sampling. | +| `gatewayResolverQueriesAdaptiveGroups` | Metrics for Gateway DNS queries with adaptive sampling. | +| `gatewayResolverByRuleExecutionPerformanceAdaptiveGroups` | Time to execute Gateway DNS policies on the Cloudflare global network. | +| `gatewayResolverByCustomResolverGroups` | Metrics for Gateway DNS queries resolved using custom resolvers. | +| `gatewayResolverByCategoryAdaptiveGroups` | Metrics for Gateway DNS queries sorted by [domain category](/cloudflare-one/policies/gateway/domain-categories/) with adaptive sampling. | + +To explore the schema, you can use a GraphQL client such as [GraphiQL](https://github.com/graphql/graphiql/tree/main/packages/graphiql#readme) or [Altair](https://altairgraphql.dev/). + +1. [Create an API token](/analytics/graphql-api/getting-started/authentication/api-token-auth/) with the following permissions: + + | Type | Item | Permission | + | ------- | ----------------- | ---------- | + | Account | Account Analytics | Read | + +2. In your GraphQL client, [add your API token](/analytics/graphql-api/getting-started/authentication/graphql-client-headers/) as an Authorization header. +3. Compose a query to access your Gateway Analytics datasets. For example, you can query the `gatewayResolverQueriesAdaptiveGroups` dataset to return the adaptive groups of DNS queries resolved by Gateway: + + ```graphql + { + viewer { + accounts(filter: { accountTag: "" }) { + gatewayResolverQueriesAdaptiveGroups( + filter: { datetime_gt: "2025-02-28T00:00:00Z" } + limit: 10 + ) { + count + dimensions { + queryNameReversed + resolverDecision + } + } + } + } + } + ``` + +For more information, refer to [Compose a query in GraphiQL](/analytics/graphql-api/getting-started/compose-graphql-query/). diff --git a/src/content/docs/cloudflare-one/insights/dex/index.mdx b/src/content/docs/cloudflare-one/insights/dex/index.mdx index 4834b1c26fdfb7..56c9bfc0fcb357 100644 --- a/src/content/docs/cloudflare-one/insights/dex/index.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Digital Experience Monitoring sidebar: - order: 2 + order: 1 --- import { DirectoryListing } from "~/components"; diff --git a/src/content/docs/cloudflare-one/insights/dex/ip-visibility.mdx b/src/content/docs/cloudflare-one/insights/dex/ip-visibility.mdx index de52a0da3ca0f2..cc31272d8b4293 100644 --- a/src/content/docs/cloudflare-one/insights/dex/ip-visibility.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/ip-visibility.mdx @@ -5,7 +5,20 @@ sidebar: order: 7 --- -import { Render } from "~/components"; +import { Render, Details } from "~/components"; + +
    + +| System | Availability | Minimum WARP version | +| -------- | ------------ | -------------------- | +| Windows | ✅ | 2025.1.861.0 | +| macOS | ✅ | 2025.1.861.0 | +| Linux | ✅ | 2025.1.861.0 | +| iOS | ❌ | | +| Android | ❌ | | +| ChromeOS | ❌ | | + +
    DEX's IP visibility gives administrators insight into three different IP types per device: diff --git a/src/content/docs/cloudflare-one/insights/dex/monitoring.mdx b/src/content/docs/cloudflare-one/insights/dex/monitoring.mdx index a111edc828507c..950ef03d18b76e 100644 --- a/src/content/docs/cloudflare-one/insights/dex/monitoring.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/monitoring.mdx @@ -2,7 +2,7 @@ pcx_content_type: reference title: Monitoring sidebar: - order: 1 + order: 2 --- Monitor performance and network status for your organization's [fleet](/cloudflare-one/insights/dex/monitoring/#fleet-status) or individual [user devices](/cloudflare-one/insights/dex/monitoring/#device-monitoring). diff --git a/src/content/docs/cloudflare-one/insights/dex/notifications.mdx b/src/content/docs/cloudflare-one/insights/dex/notifications.mdx index c784810126e13a..6a54f892fe7a4e 100644 --- a/src/content/docs/cloudflare-one/insights/dex/notifications.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/notifications.mdx @@ -2,14 +2,13 @@ pcx_content_type: reference title: Notifications sidebar: - order: 5 + order: 6 head: - tag: title content: DEX notifications - --- -import { AvailableNotifications } from "~/components" +import { AvailableNotifications } from "~/components"; Administrators can receive alerts when Cloudflare detects connectivity issues with the WARP client or degraded application performance. Notifications can be delivered via email, webhook, and third-party services. diff --git a/src/content/docs/cloudflare-one/insights/dex/remote-captures.mdx b/src/content/docs/cloudflare-one/insights/dex/remote-captures.mdx index ecb5c9dbdd0e40..15f30b976a6ddb 100644 --- a/src/content/docs/cloudflare-one/insights/dex/remote-captures.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/remote-captures.mdx @@ -2,7 +2,7 @@ pcx_content_type: reference title: Remote captures sidebar: - order: 4 + order: 5 --- import { Details } from "~/components"; @@ -45,7 +45,8 @@ DEX will now send capture requests to the configured devices. If the WARP client ## Check remote capture status To view a list of captures, go to **DEX** > **Remote captures**. The **Status** column displays one of the following options: -- **Success**: The capture is complete and ready for download. Any partially successful captures will still upload to Cloudflare. For example, there could be a scenario where the PCAP succeeds on the primary network interface but fails on the WARP tunnel interface. You can [review PCAP results](/cloudflare-one/insights/dex/remote-captures/#download-remote-captures) to determine which PCAPs succeeded or failed. + +- **Success**: The capture is complete and ready for download. Any partially successful captures will still upload to Cloudflare. For example, there could be a scenario where the PCAP succeeds on the primary network interface but fails on the WARP tunnel interface. You can [review PCAP results](/cloudflare-one/insights/dex/remote-captures/#download-remote-captures) to determine which PCAPs succeeded or failed. - **Running**: The capture is in progress on the device. - **Pending Upload**: The capture is complete but not yet ready for download. - **Failed**: The capture has either timed out or encountered an error. To retry the capture, check the WARP client version and [connectivity status](/cloudflare-one/insights/dex/monitoring/#fleet-status), then start a [new capture](/cloudflare-one/insights/dex/remote-captures/#start-a-remote-capture). diff --git a/src/content/docs/cloudflare-one/insights/dex/rules.mdx b/src/content/docs/cloudflare-one/insights/dex/rules.mdx new file mode 100644 index 00000000000000..f7f2fc158e1bd6 --- /dev/null +++ b/src/content/docs/cloudflare-one/insights/dex/rules.mdx @@ -0,0 +1,76 @@ +--- +pcx_content_type: reference +title: Rules +sidebar: + order: 4 +--- + +DEX rules allow you to create and manage testing policies for targeted user groups within your [fleet](/cloudflare-one/insights/dex/tests/). After creating a rule, you can use it to define the scope of a [test](/cloudflare-one/insights/dex/tests/) to specific groups such as departments (like finance or sales), devices, and/or users. You can apply and reuse rules on your desired tests. + +DEX rules are ideal for admins who want to define the scope of a test to a specific group within their fleet to allow for more precise problem detection and resolution. + +## Create a rule + +To create a rule: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Rules**. +2. Select **Add a rule**. +3. Give your rule a name and build your desired expressions. +4. Select **Create rule** to finalize your rule. + +### Selectors + +Selectors are required categories in a DEX rule expression that define a group within a fleet. The selector(s) you have defined in a rule will determine which group a test will impact. + +Review the available selectors and their scope in the following list. + +| Selector | Description | +| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| **User email** | For specifying [user emails](/cloudflare-one/policies/gateway/identity-selectors/#user-email). | +| **User group emails** | For specifying [group emails](/cloudflare-one/policies/gateway/identity-selectors/#user-group-email). | +| **User group IDs** | For specifying [group IDs](/cloudflare-one/policies/gateway/identity-selectors/#user-group-ids). | +| **User group names** | For specifying a [group name](/cloudflare-one/policies/gateway/identity-selectors/#user-group-names). | +| **Operating systems** | For specifying operating systems. | +| **Operating system version** | For specifying an operating system version (use Operator `in`) or versions (use Operator `is`). | +| **Managed network** | For specifying users accessing the network from the office (managed network) compared to those accessing remotely. | +| **SAML attributes** | For specifying a value from the [SAML Attribute Assertion](/cloudflare-one/policies/gateway/identity-selectors/#saml-attributes). | +| **Colos** | For specifying a Cloudflare data center location users are connected to. | + +## Add a rule to a test + +After you have created a rule, you can add it to a test. If you do not add a rule to a test, the test will run on your entire device fleet. + +To add a rule to a test: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Tests**. +2. Choose an existing test and select **Edit**, or select **Add a test** to make a new test. +3. Under **Select DEX rules**, select the rule you would like to apply. +4. Select **Save test** for an existing rule or **Add rule** for the new test. + +:::note +When applying or removing rules from an existing test, your change can take up to 24 hours to propagate. +::: + +To view which tests a rule is being applied to: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Rules**. +2. Select a rule > **Edit**. +3. Select the **DEX tests** tab and review the list of tests that include your selected rule. + +## Create a test using a rule + +You can create a new test from the [DEX test dashboard as described above](/cloudflare-one/insights/dex/rules/#add-a-rule-to-a-test) or directly from the DEX rules dashboard. + +To create a new test using a rule from DEX rules: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Rules**. +2. Select a rule > **Edit**. +3. Select the **DEX tests** tab. +4. You will be able to review all the tests that currently include this rule. To create a new test, select **Create a test using this rule**. +5. Enter all required information, making sure that the box next to your rule name is checked. +6. Select **Add test**. + +## Related resources + +- [DEX HTTP test](/cloudflare-one/insights/dex/tests/http/) - Assess the accessibility of a web application. +- [DEX Traceroute test](/cloudflare-one/insights/dex/tests/traceroute/) - Measure the network path of an IP packet from an end-user device to a server. diff --git a/src/content/docs/cloudflare-one/insights/dex/tests/http.mdx b/src/content/docs/cloudflare-one/insights/dex/tests/http.mdx index d170545e1bee8f..84b8d776096ef9 100644 --- a/src/content/docs/cloudflare-one/insights/dex/tests/http.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/tests/http.mdx @@ -3,11 +3,9 @@ pcx_content_type: reference title: HTTP test sidebar: order: 1 - --- - -import { Details } from "~/components" +import { Details } from "~/components";
    @@ -17,13 +15,12 @@ import { Details } from "~/components" | System | Availability | Minimum WARP version | | -------- | ------------ | -------------------- | -| Windows | ✅ | 2023.3.381 | -| macOS | ✅ | 2023.3.381 | -| Linux | ✅ | 2023.3.398 | -| iOS | ❌ | | -| Android | ✅ | 1.0 | -| ChromeOS | ✅ | 1.0 | - +| Windows | ✅ | 2023.3.381 | +| macOS | ✅ | 2023.3.381 | +| Linux | ✅ | 2023.3.398 | +| iOS | ❌ | | +| Android | ✅ | 1.0 | +| ChromeOS | ✅ | 1.0 |
    @@ -36,11 +33,11 @@ To set up an HTTP test for an application: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Tests**. 2. Select **Add a Test**. 3. Fill in the following fields: - * **Name**: Enter any name for the test. - * **Target**: Enter the URL of the website or application that you want to test (for example, `https://jira.site.com`). Both public and private hostnames are supported. If testing a private hostname, ensure that the domain is on your [local domain fallback](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) list. - * **Source device profiles**: (Optional) Select the [WARP device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/) that you want to run the test on. If no profiles are selected, the test will run on all supported devices connected to your Zero Trust organization. - * **Test type**: Select *HTTP Get*. - * **Test frequency**: Specify how often the test will run. Input a minute value between 5 and 60. + - **Name**: Enter any name for the test. + - **Target**: Enter the URL of the website or application that you want to test (for example, `https://jira.site.com`). Both public and private hostnames are supported. If testing a private hostname, ensure that the domain is on your [local domain fallback](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/) list. + - **Source device profiles**: (Optional) Select the [WARP device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/) that you want to run the test on. If no profiles are selected, the test will run on all supported devices connected to your Zero Trust organization. + - **Test type**: Select _HTTP Get_. + - **Test frequency**: Specify how often the test will run. Input a minute value between 5 and 60. 4. Select **Add test**. Next, [view the results](/cloudflare-one/insights/dex/tests/view-results/) of your test. @@ -55,3 +52,7 @@ An HTTP test measures the following data: | Server response time | Round-trip time for the device to receive a response from the target. | | DNS response time | Round-trip time for the DNS query to resolve. | | HTTP status codes | [Status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) returned by the target. | + +## Related resources + +- [DEX rules](/cloudflare-one/insights/dex/rules/) - Specify the target group of a test. diff --git a/src/content/docs/cloudflare-one/insights/dex/tests/index.mdx b/src/content/docs/cloudflare-one/insights/dex/tests/index.mdx index 704c964e5e1653..6c6d919b4bce1c 100644 --- a/src/content/docs/cloudflare-one/insights/dex/tests/index.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/tests/index.mdx @@ -2,11 +2,15 @@ pcx_content_type: navigation title: Tests sidebar: - order: 2 + order: 3 --- import { DirectoryListing } from "~/components"; -With Digital Experience Monitoring (DEX), you can test if your devices can connect to a private or public endpoint through the WARP client. This tool allows you to monitor availability for a given application and investigate performance issues reported by your end users. DEX tests will only run when the WARP client is turned on, whereas [fleet status](/cloudflare-one/insights/dex/monitoring/#fleet-status) metrics are always available. +With Digital Experience Monitoring (DEX), you can test if your devices can connect to a private or public endpoint through the WARP client. Tests allow you to monitor availability for a given application and investigate performance issues reported by your end users. + +DEX tests will only run when the WARP client is turned on, whereas [fleet status](/cloudflare-one/insights/dex/monitoring/#fleet-status) metrics are always available. + +To specify the target group of a test, use [DEX rules](/cloudflare-one/insights/dex/rules/). diff --git a/src/content/docs/cloudflare-one/insights/dex/tests/traceroute.mdx b/src/content/docs/cloudflare-one/insights/dex/tests/traceroute.mdx index 7e246f062f4488..86647c14a8d5d8 100644 --- a/src/content/docs/cloudflare-one/insights/dex/tests/traceroute.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/tests/traceroute.mdx @@ -3,11 +3,9 @@ pcx_content_type: reference title: Traceroute test sidebar: order: 2 - --- - -import { Details } from "~/components" +import { Details } from "~/components";
    @@ -17,13 +15,12 @@ import { Details } from "~/components" | System | Availability | Minimum WARP version | | -------- | ------------ | -------------------- | -| Windows | ✅ | 2023.5.587 | -| macOS | ✅ | 2023.5.589 | -| Linux | ❌ | | -| iOS | ❌ | | -| Android | ✅ | 1.0 | -| ChromeOS | ✅ | 1.0 | - +| Windows | ✅ | 2023.5.587 | +| macOS | ✅ | 2023.5.589 | +| Linux | ❌ | | +| iOS | ❌ | | +| Android | ✅ | 1.0 | +| ChromeOS | ✅ | 1.0 |
    @@ -36,11 +33,11 @@ To set up a traceroute test for an application: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **DEX** > **Tests**. 2. Select **Add a Test**. 3. Fill in the following fields: - * **Name**: Enter any name for the test. - * **Target**: Enter the IP address of the server you want to test (for example, `192.0.2.0`). You can test either a public-facing endpoint or a private endpoint you have connected to Cloudflare. - * **Source device profiles**: (Optional) Select the [WARP device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/) that you want to run the test on. If no profiles are selected, the test will run on all supported devices connected to your Zero Trust organization. - * **Test type**: Select *Traceroute*. - * **Test frequency**: Specify how often the test will run. Input a minute value between 5 and 60. + - **Name**: Enter any name for the test. + - **Target**: Enter the IP address of the server you want to test (for example, `192.0.2.0`). You can test either a public-facing endpoint or a private endpoint you have connected to Cloudflare. + - **Source device profiles**: (Optional) Select the [WARP device profiles](/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/) that you want to run the test on. If no profiles are selected, the test will run on all supported devices connected to your Zero Trust organization. + - **Test type**: Select _Traceroute_. + - **Test frequency**: Specify how often the test will run. Input a minute value between 5 and 60. 4. Select **Add test**. Next, [view the results](/cloudflare-one/insights/dex/tests/view-results/) of your test. @@ -49,11 +46,15 @@ Next, [view the results](/cloudflare-one/insights/dex/tests/view-results/) of yo A traceroute test measures the following data: -| Data | Description | -| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Network path | IP address, average response time, and packet loss for each hop between the device and the target. | -| Round trip time | Time between sending out a packet and receiving a response from the target. | -| Number of hops | Number of routers encountered between the device and the target. | -| Packet loss | Percentage of IP packets that failed to receive a response. | -| Availability | Percentage of tests where at least one packet reached the destination. | -| Last seen ISP | The Internet Service Provider that is managing the connection from the device to Cloudflare. (Only available on macOS and Windows.)

    DEX looks up the IP address of the ISP in the [MaxMind GeoIP2 database](https://www.maxmind.com/en/geoip2-services-and-databases) and returns the corresponding [ASO and ASN](https://www.cloudflare.com/learning/network-layer/what-is-an-autonomous-system/). If the ASO and ASN are `Unknown`, it means this information is unavailable in MaxMind. | +| Data | Description | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Network path | IP address, average response time, and packet loss for each hop between the device and the target. | +| Round trip time | Time between sending out a packet and receiving a response from the target. | +| Number of hops | Number of routers encountered between the device and the target. | +| Packet loss | Percentage of IP packets that failed to receive a response. | +| Availability | Percentage of tests where at least one packet reached the destination. | +| Last seen ISP | The Internet Service Provider that is managing the connection from the device to Cloudflare. (Only available on macOS and Windows.)

    DEX looks up the IP address of the ISP in the [MaxMind GeoIP2 database](https://www.maxmind.com/en/geoip2-services-and-databases) and returns the corresponding [ASO and ASN](https://www.cloudflare.com/learning/network-layer/what-is-an-autonomous-system/). If the ASO and ASN are `Unknown`, it means this information is unavailable in MaxMind. | + +## Related resources + +- [DEX rules](/cloudflare-one/insights/dex/rules/) - Specify the target group of a test. diff --git a/src/content/docs/cloudflare-one/insights/dex/tests/view-results.mdx b/src/content/docs/cloudflare-one/insights/dex/tests/view-results.mdx index ac48343beadc2a..2193c3581ff5fb 100644 --- a/src/content/docs/cloudflare-one/insights/dex/tests/view-results.mdx +++ b/src/content/docs/cloudflare-one/insights/dex/tests/view-results.mdx @@ -3,15 +3,14 @@ pcx_content_type: how-to title: View test results sidebar: order: 3 - --- -You can use the results of a DEX test to monitor availability and performance for a specific application. DEX will store test results according to our [log retention policy](/cloudflare-one/insights/logs/#log-retention). +Use the results of a DEX test to monitor availability and performance for a specific application. DEX will store test results according to our [log retention policy](/cloudflare-one/insights/logs/#log-retention). ## Prerequisites -* At least one test has been created under **DEX** > **Tests**. -* Admins must have at least the [Cloudflare Zero Trust Reporting role](/cloudflare-one/roles-permissions/#zero-trust-roles). +- At least one [test](/cloudflare-one/insights/dex/tests/) has been created under **DEX** > **Tests**. +- Admins must have at least the [Cloudflare Zero Trust Reporting role](/cloudflare-one/roles-permissions/#zero-trust-roles). ## View results for all devices @@ -28,4 +27,10 @@ To view analytics on a per-device level: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **My Team** > **Devices**. 2. Select the device you want to view, and then select **View details**. 3. Select the **Tests** tab. -4. Select a test to view detailed results. \ No newline at end of file +4. Select a test to view detailed results. + +## Related resources + +- [DEX HTTP test](/cloudflare-one/insights/dex/tests/http/) - Assess the accessibility of a web application. +- [DEX Traceroute test](/cloudflare-one/insights/dex/tests/traceroute/) - Measure the network path of an IP packet from an end-user device to a server. +- [DEX rules](/cloudflare-one/insights/dex/rules/) - Specify the target group of a test. diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/email-details.mdx b/src/content/docs/cloudflare-one/insights/email-monitoring/email-details.mdx deleted file mode 100644 index 0a7d5ef58876c2..00000000000000 --- a/src/content/docs/cloudflare-one/insights/email-monitoring/email-details.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Email details -pcx_content_type: reference -sidebar: - order: 6 ---- - -Email Security shows you the following email detail information: - -- Details -- Action log -- Raw message -- Mail trace - -### Details - -Email Security displays the following details: - -1. **Threat type**: Threat type of the email, for example, [credential harvester](/cloudflare-one/email-security/reference/how-es-detects-phish/#credential-harvesters), and [IP-based spam](/cloudflare-one/email-security/reference/how-es-detects-phish/#ip-based-spam). -2. **Validation**: Email validation methods [SPF](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/), [DKIM](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/), [DMARC](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/). -3. **Sender details**: Information include: - - IP address - - Registered domain - - Autonomous sys number: This number identifies your [autonomous system (AS)](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-an-autonomous-system/). - - Autonomous sys name: This name identifies your autonomous system (AS). - - Country -4. **Links identified**: A list of malicious links identified by Email Security. -5. **Reasons for disposition**: Description of why the email was deemed as malicious, suspicious, or spam. - -### Action log - -Action log allows you to review post-delivery actions performed on your selected message. The action log displays: - -- **Date**: Date when the post-delivery action was performed. -- **Activity**: The activity taken on an email. For example, moving the email to the trash folder, releasing a quarantined email, and more. - -### Raw message - -Raw message allows you to view the raw details of the message. You can also choose to download the email message. To download the message, select **Download .EML**. - -### Mail trace - -Mail trace allows you to track the path your selected message took from the sender to the recipient. Mail trace displays: - -- **Date**: The date and time when the mail was tracked. -- **Type**: An email can be inbound (email sent to you from another email), or outbound (emails sent from your email address). -- **Activity**: The activity taken on an email. For example, moving the email to the trash folder, releasing a quarantined email, and more. \ No newline at end of file diff --git a/src/content/docs/cloudflare-one/insights/logs/audit-logs.mdx b/src/content/docs/cloudflare-one/insights/logs/audit-logs.mdx index 241ae71f36cd7e..fba100ca701bb3 100644 --- a/src/content/docs/cloudflare-one/insights/logs/audit-logs.mdx +++ b/src/content/docs/cloudflare-one/insights/logs/audit-logs.mdx @@ -43,9 +43,8 @@ To view logs for identity-based authentication events: The [Access authentication logs](/api/resources/zero_trust/subresources/access/subresources/logs/subresources/access_requests/methods/list/) API endpoint provides a custom URL to export audit log events for your account. ```bash title="Request" -curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/logs/access_requests?limit=25&direction=desc&since=2020-07-01T05:20:00Z&until=2020-10-01T05:20:00Z" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/logs/access_requests?limit=25&direction=desc&since=2020-07-01T05:20:00Z&until=2020-10-01T05:20:00Z" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" ``` ```json title="Response" @@ -77,32 +76,32 @@ Identity-based authentication logs contain the following fields: ##### Basic information -| Field | Description | -| -------------- | --------------------------------------------------------- | -| **App** | Name of the Access application. | -| **User email** | Email address of the authenticating user. | -| **User ID** | UUID of the authenticating user. | -| **IP address** | IP address of the authenticating user. | -| **App UID** | UUID of the Access application. | -| **App domain** | URL of the Access application. | -| **App type** | The type specifies if the Access application is self-hosted, SaaS, or infrastructure. | -| **Event** | Type of authentication event, such as a login attempt. | -| **Connection** | IdP used to authenticate. | -| **Allow** | Result of the authentication event. | -| **Request time** | Timestamp of the authentication event. | -| **Ray ID** | A unique identifier for every request through Cloudflare. | -| **Country** | Country associated with the user's IP address. | +| Field | Description | +| ---------------- | ------------------------------------------------------------------------------------- | +| **App** | Name of the Access application. | +| **User email** | Email address of the authenticating user. | +| **User ID** | UUID of the authenticating user. | +| **IP address** | IP address of the authenticating user. | +| **App UID** | UUID of the Access application. | +| **App domain** | URL of the Access application. | +| **App type** | Specifies the type of Access application: self-hosted, browser SSH, browser VNC, browser RDP, SaaS, or infrastructure. | +| **Event** | Type of authentication event, such as a login attempt. | +| **Connection** | IdP used to authenticate. | +| **Allow** | Result of the authentication event. | +| **Request time** | Timestamp of the authentication event. | +| **Ray ID** | A unique identifier for every request through Cloudflare. | +| **Country** | Country associated with the user's IP address. | ##### Infrastructure applications Cloudflare Access logs the following information when the user authenticates to an [infrastructure application](/cloudflare-one/applications/non-http/infrastructure-apps/): -| Field | Description | -| -------------- | --------------------------------------------------------- | -| **Hostname** | Hostname of the infrastructure target. | -| **Target ID** | UUID of the infrastructure target. | -| **SSH user** | The UNIX user, such as `root`, that the authenticating user specified when connecting to the infrastructure target. | -| **SSH logs** | SSH commands that the user ran on the target. Requires configuring an [SSH encryption key](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/#ssh-command-logs) before the session begins. | +| Field | Description | +| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Hostname** | Hostname of the infrastructure target. | +| **Target ID** | UUID of the infrastructure target. | +| **SSH user** | The UNIX user, such as `root`, that the authenticating user specified when connecting to the infrastructure target. | +| **SSH logs** | SSH commands that the user ran on the target. Requires configuring an [SSH encryption key](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/#ssh-command-logs) before the session begins. | ### Non-identity authentication diff --git a/src/content/docs/cloudflare-one/insights/email-monitoring/enable-logs.mdx b/src/content/docs/cloudflare-one/insights/logs/enable-logs.mdx similarity index 88% rename from src/content/docs/cloudflare-one/insights/email-monitoring/enable-logs.mdx rename to src/content/docs/cloudflare-one/insights/logs/enable-logs.mdx index bd914f7e719f15..9c2d7c2bd0532d 100644 --- a/src/content/docs/cloudflare-one/insights/email-monitoring/enable-logs.mdx +++ b/src/content/docs/cloudflare-one/insights/logs/enable-logs.mdx @@ -2,7 +2,7 @@ title: Enable Email Security logs pcx_content_type: how-to sidebar: - order: 5 + order: 9 --- Email Security allows you to configure Logpush to send detection data to an endpoint of your choice. @@ -11,9 +11,9 @@ Email Security allows you to configure Logpush to send detection data to an endp Before you can audit logs for Email Security, you will have to enable logpush jobs to your storage destination. Refer to [Enable destinations](/logs/get-started/enable-destinations/) to enable logs on destinations such as Cloudflare R2, HTTP, Amazon S3, and more. -## Audit logs +## Enable detection logs -Once you have configured your destination, you can audit logs: +Once you have configured your destination, you can set up audit logs for detections: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/). 2. Select **Analytics & Logs** > **Logpush**. diff --git a/src/content/docs/cloudflare-one/insights/logs/index.mdx b/src/content/docs/cloudflare-one/insights/logs/index.mdx index c230f8e3aa57c7..e5e9b5b450537e 100644 --- a/src/content/docs/cloudflare-one/insights/logs/index.mdx +++ b/src/content/docs/cloudflare-one/insights/logs/index.mdx @@ -8,7 +8,7 @@ head: content: Zero Trust logs --- -import { DirectoryListing } from "~/components"; +import { DirectoryListing, Badge, Render } from "~/components"; Review detailed logs for your Zero Trust organization. @@ -18,19 +18,25 @@ Review detailed logs for your Zero Trust organization. Cloudflare Zero Trust logs are stored for a varying period of time based on the service used and plan type: -| | Free | Standard | Access | Gateway | Enterprise | -| ----| ------ | ------ | ------ | ------ | -------- | -| **Admin logs** | 18 months | 18 months | 18 months | 18 months | 18 months | 18 months | -| **Access logs** | 24 hours | 30 days | 30 days | 24 hours | 180 days | -| **DNS logs** | 24 hours | 30 days | 24 hours | 30 days | 180 days1 | -| **Network logs** | 24 hours | 30 days | 24 hours | 30 days | 30 days | -| **HTTP logs** | 24 hours | 30 days | 24 hours | 30 days | 30 days | -| **DEX logs** | 7 days | 7 days | 7 days | 7 days | 7 days | -| **Device posture logs** | 30 days | 30 days | 30 days | 30 days | 30 days | - -1 Enterprise users on per query plans cannot store DNS logs via Cloudflare. -You can still export logs via [Logpush](/cloudflare-one/insights/logs/logpush/). -For more information, contact your account team. +| | Free | Standard | Access | Gateway | Enterprise | +| ----------------------- | --------- | --------- | --------- | --------- | ------------ | +| **Admin logs** | 18 months | 18 months | 18 months | 18 months | 18 months | +| **Access logs** | 24 hours | 30 days | 30 days | 24 hours | 180 days | +| **DNS logs** | 24 hours | 30 days | 24 hours | 30 days | 180 days[^1] | +| **Network logs** | 24 hours | 30 days | 24 hours | 30 days | 30 days | +| **HTTP logs** | 24 hours | 30 days | 24 hours | 30 days | 30 days | +| **DEX logs** | 7 days | 7 days | 7 days | 7 days | 7 days | +| **Device posture logs** | 30 days | 30 days | 30 days | 30 days | 30 days | + +[^1]: Enterprise users on per query plans cannot store DNS logs via Cloudflare. You can still export logs via [Logpush](/cloudflare-one/insights/logs/logpush/). For more information, contact your account team. + +## Log Explorer + +Log Explorer users can store Zero Trust logs directly within Cloudflare in an [R2 bucket](/r2/) and access them with the dashboard or API. Log Explorer supports the following Zero Trust datasets: + + + +For more information, refer to [Log Explorer](/logs/log-explorer/). ## Customer Metadata Boundary diff --git a/src/content/docs/cloudflare-one/insights/logs/logpush.mdx b/src/content/docs/cloudflare-one/insights/logs/logpush.mdx index 53c456e24de49a..6920418c7d7519 100644 --- a/src/content/docs/cloudflare-one/insights/logs/logpush.mdx +++ b/src/content/docs/cloudflare-one/insights/logs/logpush.mdx @@ -17,15 +17,15 @@ With Cloudflare's [Logpush](/logs/about/) service, you can configure the automat Zero Trust does not support configuring [Cloudflare R2](/logs/get-started/enable-destinations/r2/) as a Logpush destination in the dashboard. To use R2 as a destination for Zero Trust logs, configure your Logpush jobs [with the API](/logs/get-started/enable-destinations/r2/#manage-via-api). ::: -To enable Logpush for Zero Trust logs: +To configure Logpush for Zero Trust logs: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Logs** > **Logpush**. -2. Select **Add Logpush job**. -3. Select **Create a Logpush job**. -4. In **Select a destination**, select the service you want to export your logs to. +2. If this is your first Logpush job, select **Add a Logpush job**. Otherwise, select **Go to logpush configurations**. +3. In Logpush, select **Create a Logpush job**. +4. Choose a [Logpush destination](/logs/get-started/enable-destinations/). 5. Follow the service-specific instructions to configure and validate your destination. -6. Choose the [**Zero Trust datasets**](#zero-trust-datasets) you would like to export. -7. Enter a **Job name**, any [filters](/logs/reference/filters/) you would like to add, and the data fields you want to include in the log. +6. Choose the [Zero Trust datasets](#zero-trust-datasets) to export. +7. Enter a **Job name**, any [filters](/logs/reference/filters/) you would like to add, and the data fields you want to include in the logs. 8. (Optional) In **Advanced settings**, choose the timestamp format you prefer and whether you want to enable log sampling. 9. Select **Submit**. @@ -35,19 +35,21 @@ You can configure multiple destinations and add additional fields to your logs b ## Zero Trust datasets -Refer to the Logpush documentation for a list of available fields. - -| Dataset | Description | -| ------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| [Gateway DNS](/logs/reference/log-fields/account/gateway_dns/) | DNS queries inspected by Cloudflare Gateway | -| [Gateway HTTP](/logs/reference/log-fields/account/gateway_http/) | HTTP requests inspected by Cloudflare Gateway | -| [Gateway Network](/logs/reference/log-fields/account/gateway_network/) | Network packets inspected by Cloudflare Gateway | -| [Audit Logs](/logs/reference/log-fields/account/audit_logs/) | Authentication events through Cloudflare Access | -| [Access Requests](/logs/reference/log-fields/account/access_requests/) | HTTP requests to sites protected by Cloudflare Access | -| [CASB Findings](/logs/reference/log-fields/account/casb_findings/) | Security issues detected by Cloudflare CASB | -| [Device Posture](/logs/reference/log-fields/account/device_posture_results/) | Device posture status from the WARP client | -| [Session Logs](/logs/reference/log-fields/account/zero_trust_network_sessions/) | Network session logs for traffic proxied by Cloudflare Gateway | -| [SSH Logs](/logs/reference/log-fields/account/ssh_logs/) | SSH command logs for [Access for Infrastructure targets](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/) | +Refer to [Logpush log fields](/logs/reference/log-fields/) for a list of all available fields. + +| Dataset | Description | +| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Access Requests](/logs/reference/log-fields/account/access_requests/) | HTTP requests to sites protected by Cloudflare Access | +| [Audit Logs](/logs/reference/log-fields/account/audit_logs/) | Authentication events through Cloudflare Access | +| [Browser Isolation User Actions](/logs/reference/log-fields/account/biso_user_actions/) | Data transfer actions performed by a user in the remote browser | +| [CASB Findings](/logs/reference/log-fields/account/casb_findings/) | Security issues detected by Cloudflare CASB | +| [Device Posture Results](/logs/reference/log-fields/account/device_posture_results/) | Device posture status from the WARP client | +| [DLP Forensic Copies](/logs/reference/log-fields/account/dlp_forensic_copies/) | Entire HTTP requests or payloads of HTTP requests captured by [Cloudflare DLP](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/) | +| [Gateway DNS](/logs/reference/log-fields/account/gateway_dns/) | DNS queries inspected by Cloudflare Gateway | +| [Gateway HTTP](/logs/reference/log-fields/account/gateway_http/) | HTTP requests inspected by Cloudflare Gateway | +| [Gateway Network](/logs/reference/log-fields/account/gateway_network/) | Network packets inspected by Cloudflare Gateway | +| [SSH Logs](/logs/reference/log-fields/account/ssh_logs/) | SSH command logs for [Access for Infrastructure targets](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/) | +| [Zero Trust Network Session Logs](/logs/reference/log-fields/account/zero_trust_network_sessions/) | Network session logs for traffic proxied by Cloudflare Gateway | ## Parse DNS logs diff --git a/src/content/docs/cloudflare-one/policies/access/index.mdx b/src/content/docs/cloudflare-one/policies/access/index.mdx index c22caaf39c2883..fe949c309607a7 100644 --- a/src/content/docs/cloudflare-one/policies/access/index.mdx +++ b/src/content/docs/cloudflare-one/policies/access/index.mdx @@ -55,17 +55,21 @@ For example, this configuration blocks every request to the application, except :::caution[Warning] -Bypass does not enforce any Access security controls and requests are not logged. This should be tested before deploying to production. Consider using Service Auth if you would like to enforce policies and maintain logging without requiring user authentication. +Bypass does not enforce any Access security controls and requests are not logged. Bypass policies should be tested before deploying to production. Consider using [Service Auth](/cloudflare-one/policies/access/#service-auth) if you would like to enforce policies and maintain logging without requiring user authentication. + +As Bypass does not enforce Access security controls, Bypass policies do not support identity-based [rule types](/cloudflare-one/policies/access/#rule-types). When making Bypass policies, you will not be able to apply certain identity-based [selectors](/cloudflare-one/policies/access/#selectors) (such as email, or IP). ::: -The Bypass action disables any Access enforcement for traffic that meets the defined rule criteria. Bypass is typically used to enable applications that require specific endpoints to be public. For example, some applications have an endpoint under the `/admin` route that must be publicly routable. In this situation, you could create an Access application for the domain `test.example.com/admin/` and add the following Bypass policy: +The Bypass action disables any Access enforcement for traffic that meets the defined rule criteria. Bypass is typically used to enable applications that require specific endpoints to be public. + +For example, some applications have an endpoint under the `/admin` route that must be publicly routable. In this situation, you could create an Access application for the domain `test.example.com/admin/` and add the following Bypass policy: | Action | Rule type | Selector | Value | | ------ | --------- | -------- | ---------- | | Bypass | Include | Everyone | `Everyone` | -As part of implementing a Zero Trust security model, we do not recommend using Bypass to grant direct permanent access to your internal applications. To enable seamless and secure access for on-network employees, use Cloudflare Tunnel to [connect your private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) and have users connect through WARP. +As part of implementing a Zero Trust security model, Cloudflare does not recommend using Bypass to grant direct permanent access to your internal applications. To enable seamless and secure access for on-network employees, use Cloudflare Tunnel to [connect your private network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/) and have users connect through WARP. :::note @@ -110,18 +114,18 @@ the policy will only grant access to people reaching the application from both t To require only one country and one email ending: -1. [Create a rule group](/cloudflare-one/policies/access/groups/) that includes users in Portugal OR in the United States: +1. [Create a rule group](/cloudflare-one/policies/access/groups/) that includes users in Portugal OR in the United States: - | Rule type | Selector | Value | - | --------- | -------- | --------------------------- | - | Include | Country | `United States`, `Portugal` | + | Rule type | Selector | Value | + | --------- | -------- | --------------------------- | + | Include | Country | `United States`, `Portugal` | -2. Create a policy that requires the rule group, and that also includes users with emails ending in either `@cloudflare.com` OR `@contractors.com`: +2. Create a policy that requires the rule group, and that also includes users with emails ending in either `@cloudflare.com` OR `@contractors.com`: - | Action | Rule type | Selector | Value | - | ------ | --------- | ----------------- | ------------------------------------- | - | Allow | Require | Rule group | `Country requirements` | - | | Include | Emails ending in | `@cloudflare.com`, `@contractors.com` | + | Action | Rule type | Selector | Value | + | ------ | --------- | ----------------- | ------------------------------------- | + | Allow | Require | Rule group | `Country requirements` | + | | Include | Emails ending in | `@cloudflare.com`, `@contractors.com` | ## Selectors @@ -129,26 +133,26 @@ When you add a rule to your policy, you will be asked to specify the criteria/at Identity-based attributes are only checked when a user authenticates to Access, whereas non-identity attributes are polled continuously for changes during the [user session](/cloudflare-one/identity/users/session-management/). If you have configured [SCIM provisioning](/cloudflare-one/identity/users/scim/), you can force a user to re-attest all attributes with Access whenever you revoke the user in the IdP or update their IdP group membership. -| Selector | Description | Checked at login | Checked continuously1 | -| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------------------------------- | -| Emails | `you@company.com` | ✅ | ❌ | -| Emails ending in | `@company.com` | ✅ | ❌ | -| External Evaluation | Allows or denies access based on [custom logic](/cloudflare-one/policies/access/external-evaluation/) in an external API. | ✅ | ❌ | -| IP ranges | `192.168.100.1/24` (supports IPv4/IPv6 addresses and CIDR ranges) | ✅ | ✅ | -| Country | Uses the IP address to determine country. | ✅ | ✅ | -| Everyone | Allows, denies, or bypasses access to everyone. | ✅ | ❌ | -| Common Name | The request will need to present a valid certificate with an expected common name. | ✅ | ✅ | -| Valid Certificate | The request will need to present any valid client certificate. | ✅ | ✅ | -| Service Token | The request will need to present the correct service token headers configured for the specific application. | ✅ | ✅ | -| Any Access Service Token | The request will need to present the headers for any [service token](/cloudflare-one/identity/service-tokens/) created for this account. | ✅ | ✅ | -| Login Methods | Checks the identity provider used at the time of login. | ✅ | ❌ | -| Authentication Method | Checks the [multifactor authentication](/cloudflare-one/policies/access/mfa-requirements/) method used by the user, if supported by the identity provider. | ✅ | ❌ | -| Identity provider group | Checks the user groups configured with your identity provider (IdP). This selector only displays if you use Microsoft Entra ID, GitHub, Google, Okta, or an IdP that provisions groups with [SCIM](/cloudflare-one/identity/users/scim/). | ✅ | ❌ | -| SAML Group | Checks a SAML attribute name / value pair. This selector only displays if you use a [generic SAML](/cloudflare-one/identity/idp-integration/generic-saml/) identity provider. | ✅ | ❌ | -| OIDC Claim | Checks an OIDC claim name / value pair. This selector only displays if you use a [generic OIDC](/cloudflare-one/identity/idp-integration/generic-oidc/) identity provider. | ✅ | ❌ | -| Device posture | Checks [device posture signals](/cloudflare-one/identity/devices/) from the WARP client or a third-party service provider. | ✅ | ✅ | -| Warp | Checks that the device is connected to WARP, including the consumer version. | ✅ | ✅ | -| Gateway | Checks that the device is connected to your Zero Trust instance through the [WARP client](/cloudflare-one/connections/connect-devices/warp/). | ✅ | ✅ | +| Selector | Description | Checked at login | Checked continuously1 | +| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------------------------------- | +| Emails | `you@company.com` | ✅ | ❌ | +| Emails ending in | `@company.com` | ✅ | ❌ | +| External Evaluation | Allows or denies access based on [custom logic](/cloudflare-one/policies/access/external-evaluation/) in an external API. | ✅ | ❌ | +| IP ranges | `192.168.100.1/24` (supports IPv4/IPv6 addresses and CIDR ranges) | ✅ | ✅ | +| Country | Uses the IP address to determine country. | ✅ | ✅ | +| Everyone | Allows, denies, or bypasses access to everyone. | ✅ | ❌ | +| Common Name | The request will need to present a valid certificate with an expected common name. | ✅ | ✅ | +| Valid Certificate | The request will need to present any valid client certificate. | ✅ | ✅ | +| Service Token | The request will need to present the correct service token headers configured for the specific application. | ✅ | ✅ | +| Any Access Service Token | The request will need to present the headers for any [service token](/cloudflare-one/identity/service-tokens/) created for this account. | ✅ | ✅ | +| Login Methods | Checks the identity provider used at the time of login. | ✅ | ❌ | +| Authentication Method | Checks the [multifactor authentication](/cloudflare-one/policies/access/mfa-requirements/) method used by the user, if supported by the identity provider. | ✅ | ❌ | +| Identity provider group | Checks the user groups configured with your identity provider (IdP). This selector only displays if you use Microsoft Entra ID, GitHub, Google, Okta, or an IdP that provisions groups with [SCIM](/cloudflare-one/identity/users/scim/). | ✅ | ❌ | +| SAML Group | Checks a SAML attribute name / value pair. This selector only displays if you use a [generic SAML](/cloudflare-one/identity/idp-integration/generic-saml/) identity provider. | ✅ | ❌ | +| OIDC Claim | Checks an OIDC claim name / value pair. This selector only displays if you use a [generic OIDC](/cloudflare-one/identity/idp-integration/generic-oidc/) identity provider. | ✅ | ❌ | +| Device posture | Checks [device posture signals](/cloudflare-one/identity/devices/) from the WARP client or a third-party service provider. | ✅ | ✅ | +| Warp | Checks that the device is connected to WARP, including the consumer version. | ✅ | ✅ | +| Gateway | Checks that the device is connected to your Zero Trust instance through the [WARP client](/cloudflare-one/connections/connect-devices/warp/). | ✅ | ✅ | 1 For SaaS applications, Access can only enforce policies at the time of initial sign on and when reissuing the SaaS session. Once the user has diff --git a/src/content/docs/cloudflare-one/policies/access/policy-management.mdx b/src/content/docs/cloudflare-one/policies/access/policy-management.mdx index f24c4ae0f0295d..d092495c2a54ce 100644 --- a/src/content/docs/cloudflare-one/policies/access/policy-management.mdx +++ b/src/content/docs/cloudflare-one/policies/access/policy-management.mdx @@ -3,10 +3,9 @@ pcx_content_type: how-to title: Manage Access policies sidebar: order: 2 - --- -import {Tabs, TabItem } from "~/components"; +import { Tabs, TabItem } from "~/components"; Access policies define the users who can log in to your Access applications. You can create, edit, or delete policies at any time and reuse policies across multiple applications. @@ -21,9 +20,9 @@ To create a reusable Access policy: 5. Choose a [**Session duration**](/cloudflare-one/identity/users/session-management/) for the policy. 6. Configure as many [**Rules**](/cloudflare-one/policies/access/#rule-types) as needed. 7. (Optional) Configure additional settings for users who match this policy: - - [Isolate application](/cloudflare-one/policies/access/isolate-application/). - - [Purpose justificaton](/cloudflare-one/policies/access/require-purpose-justification/) - - [Temporary authentication](/cloudflare-one/policies/access/temporary-auth/) + - [Isolate application](/cloudflare-one/policies/access/isolate-application/). + - [Purpose justificaton](/cloudflare-one/policies/access/require-purpose-justification/) + - [Temporary authentication](/cloudflare-one/policies/access/temporary-auth/) 8. Select **Save**. You can now add this policy to an [Access application](/cloudflare-one/applications/). @@ -49,20 +48,42 @@ To delete a reusable Access policy: ## Test your policies -You can test your policies against an existing user identity to see if they would be granted access. For the policy tester to work, the user must have logged into the [App Launcher](/cloudflare-one/applications/app-launcher/) or any other Access application at some point in time. +You can test your Access policies against all existing user identities in your Zero Trust organization. For the policy tester to work, users must have logged into the [App Launcher](/cloudflare-one/applications/app-launcher/) or any other Access application at some point in time. + +### Test a single policy + +The Access policy builder allows you to test your rules before saving any changes. + +To test an individual Access policy: + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Access** > **Policies**. +2. Locate the policy you want to test and select **Configure**. +3. Go to **Policy tester** and select **Test policies**. + +The policy tester reports the percentage of active users who are allowed or denied access to an application based on this policy. You can expand the test results to view a list of allowed or blocked users. + +### Test all policies in an application -To check if a user has access to an application: +You can test your Access application policies against your user population before deploying changes to your users. After saving your changes, you can also perform a more detailed policy test for a specific user. + +To test if users have access to an application: 1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Access** > **Applications**. 2. Locate the application you want to test and select **Configure**. -3. Go to the **Policies** tab and select **Test policies**. -4. Enter the user's email address and select **Test policies**. +3. Go to **Policies** > **Policy tester**. +4. To test all active users in your organization, select **Test policies**. + + The policy tester reports the percentage of users who are allowed or denied access to this application based on all configured policies. You can expand the test results to view a list of allowed or blocked users. -The policy tester reports the following information: +5. To perform a detailed test on a single user: + a. If you made any changes to your policies, first save the application. + b. Select **testing a single user**. + c. Enter their email address and select **Test policies**. -* Whether the user is allowed or denied access to the application based on all configured policies. -* The user's identity from their most recent Access login attempt. -* Whether the user matches individual Allow, Block, or Bypass policies. + The single user test results will show: + - Whether the user is allowed or denied access to this application based on all configured policies. + - The user's identity from their most recent Access login attempt. + - Whether the user matches individual Allow, Block, or Bypass policies. ## Legacy policies @@ -83,8 +104,8 @@ You can use the API to convert a legacy policy into a reusable policy. To conver ```bash curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id}/policies/{policy_id}/make_reusable \ ---header "Authorization: Bearer " +https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID/policies/$POLICY_ID/make_reusable \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" ``` -The policy is now removed from the applications endpoint (`/access/apps/{app_id}/policies`) and managed using the [reusable policies endpoints](/api/resources/zero_trust/subresources/access/subresources/policies/)(`/access/policies/{policy_id}`). \ No newline at end of file +The policy is now removed from the applications endpoint (`/access/apps/$APP_ID/policies`) and managed using the [reusable policies endpoints](/api/resources/zero_trust/subresources/access/subresources/policies/)(`/access/policies/$POLICY_ID`). diff --git a/src/content/docs/cloudflare-one/policies/browser-isolation/index.mdx b/src/content/docs/cloudflare-one/policies/browser-isolation/index.mdx index 269d8710d4bc0b..aa605a5e7bd419 100644 --- a/src/content/docs/cloudflare-one/policies/browser-isolation/index.mdx +++ b/src/content/docs/cloudflare-one/policies/browser-isolation/index.mdx @@ -3,8 +3,6 @@ pcx_content_type: concept title: Browser Isolation sidebar: order: 5 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- :::note diff --git a/src/content/docs/cloudflare-one/policies/browser-isolation/isolation-policies.mdx b/src/content/docs/cloudflare-one/policies/browser-isolation/isolation-policies.mdx index bc8feefac6f359..9ecaafc85dacd9 100644 --- a/src/content/docs/cloudflare-one/policies/browser-isolation/isolation-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/browser-isolation/isolation-policies.mdx @@ -134,9 +134,9 @@ Isolate security threats such as malware and phishing. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Isolate all security threats", "description": "Isolate security threats such as malware and phishing", @@ -168,9 +168,9 @@ Isolate high risk content categories such as newly registered domains. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Isolate high risk content", "description": "Isolate high risk content categories such as newly registered domains", @@ -202,9 +202,9 @@ Isolate news and media sites, which are targets for malvertising attacks. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Isolate news and media", "description": "Isolate news and media sites, which are targets for malvertising attacks", @@ -236,9 +236,9 @@ Isolate content that has not been categorized by [Cloudflare Radar](/radar/). ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Isolate uncategorized content", "description": "Isolate content not categorized by Cloudflare Radar", @@ -272,9 +272,9 @@ In **Configure policy settings**, you can customize restrictions for ChatGPT. Fo ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Isolate ChatGPT", "description": "Isolate the use of ChatGPT", diff --git a/src/content/docs/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation.mdx b/src/content/docs/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation.mdx index 5f57c06901590b..ffaa7385ea417f 100644 --- a/src/content/docs/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation.mdx +++ b/src/content/docs/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation.mdx @@ -106,6 +106,7 @@ To turn on or off the address bar, users can right-click on any isolated page an - **Authentication events**: User login events are available in [Access audit logs](/cloudflare-one/insights/logs/audit-logs/). - **HTTP requests**: Traffic from the remote browser to the Internet is logged in [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). - **DNS queries**: DNS queries from the remote browser are shown in [Gateway activity logs](/cloudflare-one/insights/logs/gateway-logs/). +- **User actions**: Track copy/paste, download/upload, and print actions initiated by users in the remote browser (only available in [Logpush](/cloudflare-one/insights/logs/logpush/)). ## Redirect traffic to the remote browser diff --git a/src/content/docs/cloudflare-one/policies/data-loss-prevention/datasets.mdx b/src/content/docs/cloudflare-one/policies/data-loss-prevention/datasets.mdx index af2204b84aa296..41efd816bdaa20 100644 --- a/src/content/docs/cloudflare-one/policies/data-loss-prevention/datasets.mdx +++ b/src/content/docs/cloudflare-one/policies/data-loss-prevention/datasets.mdx @@ -7,7 +7,7 @@ sidebar: import { Details } from "~/components"; -Cloudflare DLP can scan your web traffic and SaaS applications for specific data defined in a custom dataset. Sensitive data can be hashed before reaching Cloudflare and redacted from matches in [payload logs](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules/). +Cloudflare DLP can scan your web traffic and SaaS applications for specific data defined in a custom dataset. Sensitive data can be hashed before reaching Cloudflare and redacted from matches in [payload logs](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules). ## DLP dataset types diff --git a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/index.mdx b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/index.mdx index 903cb2c889fb1d..d6d6679fd18655 100644 --- a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/index.mdx @@ -11,8 +11,8 @@ You can scan HTTP traffic for sensitive data through Secure Web Gateway policies ## Prerequisites - Set up [Gateway HTTP filtering](/cloudflare-one/policies/gateway/initial-setup/http/). - - HTTP filtering requires turning on the [Gateway proxy](/cloudflare-one/policies/gateway/proxy/#enable-the-gateway-proxy) for TCP traffic. -- Turn on [TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#enable-tls-decryption). + - HTTP filtering requires turning on the [Gateway proxy](/cloudflare-one/policies/gateway/proxy/#turn-on-the-gateway-proxy) for TCP traffic. +- Turn on [TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#turn-on-tls-decryption). ## 1. Configure a DLP profile diff --git a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options.mdx b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options.mdx index 0beaa46bbe68dd..710448bb57483b 100644 --- a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options.mdx +++ b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options.mdx @@ -66,13 +66,16 @@ Gateway allows you to send copies of entire HTTP requests matched in DLP policie To set up the DLP Forensic Copy Logpush job: -1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Logs** > **Logpush**. Select **Add a Logpush job**. -2. Set up a [Logpush destination](/logs/get-started/enable-destinations/) with the DLP Forensic Copy Logpush job. -3. Return to Zero Trust and go to **Gateway** > **Firewall policies** > **HTTP**. -4. Edit an existing Allow or Block DLP policy, or [create a new policy](/cloudflare-one/policies/data-loss-prevention/dlp-policies/#2-create-a-dlp-policy). -5. In the policy builder, scroll down to **Configure policy settings** and turn on **Send copy to storage**. -6. Select a storage destination. Gateway will list any configured Logpush jobs or integrations that can receive HTTP requests. -7. Select **Save**. +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Logs** > **Logpush**. +2. If this is your first Logpush job, select **Add a Logpush job**. Otherwise, select **Go to logpush configurations**. +3. In Logpush, select **Create a Logpush job**. +4. Choose a [Logpush destination](/logs/get-started/enable-destinations/). +5. In **Configure logpush job**, choose the _DLP forensic copies_ dataset. Select **Create Logpush job**. +6. Return to Zero Trust and go to **Gateway** > **Firewall policies** > **HTTP**. +7. Edit an existing Allow or Block DLP policy, or [create a new policy](/cloudflare-one/policies/data-loss-prevention/dlp-policies/#2-create-a-dlp-policy). +8. In the policy builder, scroll down to **Configure policy settings** and turn on **Send copy to storage**. +9. Select a storage destination. Gateway will list any configured Logpush jobs or integrations that can receive HTTP requests. +10. Select **Save policy**. DLP will now send a copy of HTTP requests that match this policy to your Logpush destination. diff --git a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-profiles/index.mdx b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-profiles/index.mdx index 0fd82adcca08c7..178a917dcf7440 100644 --- a/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-profiles/index.mdx +++ b/src/content/docs/cloudflare-one/policies/data-loss-prevention/dlp-profiles/index.mdx @@ -8,7 +8,7 @@ sidebar: import { Render } from "~/components"; -A DLP profile is a collection of regular expressions (also known as detection entries) that define the data patterns you want to detect. Cloudflare DLP provides predefined profiles for common detections, or you can build custom DLP profiles specific to your data, organization, and risk tolerance. +A DLP profile is a collection of detection entries (regular expressions and [DLP datasets](/cloudflare-one/policies/data-loss-prevention/datasets/)) that define the data patterns you want to detect. Cloudflare DLP provides predefined profiles for common detections, or you can build custom DLP profiles specific to your data, organization, and risk tolerance. ## Configure a predefined profile diff --git a/src/content/docs/cloudflare-one/policies/data-loss-prevention/index.mdx b/src/content/docs/cloudflare-one/policies/data-loss-prevention/index.mdx index 6bf35c36ad26a7..edab3a2e0c7e3c 100644 --- a/src/content/docs/cloudflare-one/policies/data-loss-prevention/index.mdx +++ b/src/content/docs/cloudflare-one/policies/data-loss-prevention/index.mdx @@ -3,8 +3,9 @@ pcx_content_type: concept title: Data Loss Prevention sidebar: order: 5 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. +learning_center: + title: What is DLP (data loss prevention)? + link: https://www.cloudflare.com/learning/access-management/what-is-dlp/ --- import { GlossaryDefinition } from "~/components"; @@ -12,7 +13,7 @@ import { GlossaryDefinition } from "~/components"; :::note[Availability] Available as an add-on to Zero Trust Enterprise plans. -Users on Zero Trust Free and Pay-as-you-go plans can use the [Financial Information](/cloudflare-one/policies/data-loss-prevention/dlp-profiles/predefined-profiles/#financial-information) and [Social Security, Insurance, Tax, and Identifier Numbers](/cloudflare-one/policies/data-loss-prevention/dlp-profiles/predefined-profiles/#social-security-insurance-tax-and-identifier-numbers) predefined profiles, [payload logging](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules/), and [false positive reporting](/cloudflare-one/policies/data-loss-prevention/dlp-policies/#report-false-positives). +Users on Zero Trust Free and Pay-as-you-go plans can use the [Financial Information](/cloudflare-one/policies/data-loss-prevention/dlp-profiles/predefined-profiles/#financial-information) and [Social Security, Insurance, Tax, and Identifier Numbers](/cloudflare-one/policies/data-loss-prevention/dlp-profiles/predefined-profiles/#social-security-insurance-tax-and-identifier-numbers) predefined profiles, [payload logging](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules), and [false positive reporting](/cloudflare-one/policies/data-loss-prevention/dlp-policies/#report-false-positives). ::: diff --git a/src/content/docs/cloudflare-one/policies/gateway/application-app-types.mdx b/src/content/docs/cloudflare-one/policies/gateway/application-app-types.mdx index 4b7c9ac1392fe0..5b2351733765df 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/application-app-types.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/application-app-types.mdx @@ -58,7 +58,7 @@ Applications can be incompatible with [TLS decryption](/cloudflare-one/policies/ #### Application grouping -Gateway automatically groups applications incompatible with TLS decryption into the _Do Not Inspect_ app type. As Cloudflare identifies incompatible applications, Gateway will periodically update this app type to add new applications. To ensure Gateway does not intercept any current or future incompatible traffic, you can [create a Do Not Inspect HTTP policy](/cloudflare-one/policies/gateway/initial-setup/http/#bypass-inspection-for-incompatible-applications) with the entire _Do Not Inspect_ app type selected. +Gateway automatically groups applications incompatible with TLS decryption into the _Do Not Inspect_ app type. As Cloudflare identifies incompatible applications, Gateway will periodically update this app type to add new applications. To ensure Gateway does not intercept any current or future incompatible traffic, you can [create a Do Not Inspect HTTP policy](/cloudflare-one/policies/gateway/http-policies/#do-not-inspect) with the entire _Do Not Inspect_ app type selected. :::note[Install Cloudflare certificate manually to allow TLS decryption] diff --git a/src/content/docs/cloudflare-one/policies/gateway/block-page.mdx b/src/content/docs/cloudflare-one/policies/gateway/block-page.mdx index 3972268233fc83..56e44df0b2510f 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/block-page.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/block-page.mdx @@ -3,8 +3,6 @@ pcx_content_type: how-to title: Block page sidebar: order: 14 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Render } from "~/components"; diff --git a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/common-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/common-policies.mdx index b822d87d1d2640..82777d2468f5c7 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/common-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/common-policies.mdx @@ -29,9 +29,9 @@ This policy allows users to access official corporate domains. By deploying the ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Allow corporate domains", "description": "Allow any internal corporate domains added to a list", @@ -92,9 +92,9 @@ You can implement policies to block websites hosted in countries categorized as ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block banned countries", "description": "Block access to banned countries", @@ -127,9 +127,9 @@ Blocking [frequently misused](https://www.spamhaus.org/statistics/tlds/) top-lev ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block top-level domains", "description": "Block top-level domains that are frequently used for malicious practices", @@ -161,9 +161,9 @@ To protect against [sophisticated phishing attacks](https://blog.cloudflare.com/ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block phishing attacks", "description": "Block attempts to phish specific domains targeting your organization", @@ -196,9 +196,9 @@ To safeguard user privacy, some organizations will block tracking domains such a ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block online tracking", "description": "Block domains used for tracking at an OS level", @@ -231,9 +231,9 @@ Block specific IP addresses that are known to be malicious or pose a threat to y ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block malicious IPs", "description": "Block specific IP addresses that are known to be malicious or pose a threat to your organization", @@ -266,9 +266,9 @@ The CIPA (Children's Internet Protection Act) Filter is a collection of subcateg ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Turn on CIPA filter", "description": "Block access to unwanted or harmful online content for children", @@ -299,9 +299,9 @@ SafeSearch is a feature of search engines that helps you filter explicit or offe ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Hide explicit search results", "description": "Force SafeSearch on search engines to filter explicit or offensive content", @@ -333,9 +333,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Check user identity", "description": "Filter traffic based on a user identity group name", @@ -371,9 +371,9 @@ The following example includes two policies. The first policy allows the specifi ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Allow social media for Marketing", "description": "Allow access to social media sites for users in the Marketing group", @@ -403,9 +403,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block social media", "description": "Block social media for all other users", @@ -424,7 +424,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ## Control IP version -Enterprise users can pair these policies with an [egress policy](/cloudflare-one/policies/gateway/egress-policies/) to control which IP address is used to egress to the origin server. +Enterprise users can pair these policies with an [egress policy](/cloudflare-one/policies/gateway/egress-policies/) to control which IP version is used to egress to the origin server. + +Optionally, you can use the Domain selector to control the IP version for specific sites. :::note To ensure traffic routes through your preferred IP version, disable **Display block page**. @@ -436,19 +438,18 @@ Force users to connect with IPv4 by blocking IPv6 resolution. -| Selector | Operator | Value | Logic | Action | -| ----------------- | -------- | ------------- | ----- | ------ | -| Query Record Type | is | _AAAA_ | And | Block | -| Domain | is | `example.com` | | | +| Selector | Operator | Value | Action | +| ----------------- | -------- | ------ | ------ | +| Query Record Type | is | _AAAA_ | Block | ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Force IPv4", "description": "Force users to connect with IPv4 by blocking IPv6 resolution", @@ -457,7 +458,7 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ "filters": [ "dns" ], - "traffic": "dns.query_rtype == \"AAAA\" and any(dns.domains[*] == \"example.com\")", + "traffic": "dns.query_rtype == \"AAAA\"", "identity": "" }' ``` @@ -470,19 +471,18 @@ Force users to connect with IPv6 by blocking IPv4 resolution. -| Selector | Operator | Value | Logic | Action | -| ----------------- | -------- | ------------- | ----- | ------ | -| Query Record Type | is | _A_ | And | Block | -| Domain | is | `example.com` | | | +| Selector | Operator | Value | Action | +| ----------------- | -------- | ----- | ------ | +| Query Record Type | is | _A_ | Block | ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Force IPv6", "description": "Force users to connect with IPv6 by blocking IPv4 resolution", @@ -491,7 +491,7 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ "filters": [ "dns" ], - "traffic": "dns.query_rtype == \"A\" and any(dns.domains[*] == \"example.com\")", + "traffic": "dns.query_rtype == \"A\"", "identity": "" }' ``` diff --git a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/index.mdx index 300f855405984d..5f16451a0b7ad1 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/index.mdx @@ -24,6 +24,8 @@ When creating a DNS policy, you can select as many security risk categories and params={{ type: "query", example: "Source IP", example2: "Resolved IP" }} /> + + ## Actions Just like actions in HTTP policies, actions in DNS policies allow you to choose what to do with a given set of elements. You can assign one action per policy. @@ -79,9 +81,9 @@ API value: `allow` Policies with Allow actions allow DNS queries to reach destinations you specify within the Selector and Value fields. For example, the following configuration allows DNS queries to reach domains we categorize as belonging to the Education content category: -| Selector | Operator | Value | Action | -| ------------------ | -------- | --------- | ------ | -| Content Categories | in | Education | Allow | +| Selector | Operator | Value | Action | +| ------------------ | -------- | ----------- | ------ | +| Content Categories | in | _Education_ | Allow | #### Disable DNSSEC validation @@ -130,9 +132,9 @@ API value: `block` Policies with Block actions block DNS queries to reach destinations you specify within the Selector and Value fields. For example, the following configuration blocks DNS queries from reaching domains we categorize as belonging to the Adult Themes content category: -| Selector | Operator | Value | Action | -| ------------------ | -------- | ------------ | ------ | -| Content Categories | in | Adult Themes | Block | +| Selector | Operator | Value | Action | +| ------------------ | -------- | -------------- | ------ | +| Content Categories | in | _Adult Themes_ | Block | #### Custom block page @@ -140,7 +142,7 @@ When choosing the Block action, turn on **Display custom block page** to respond #### WARP client block notifications - + ### Override @@ -347,6 +349,8 @@ Use this selector to filter DNS responses by their `TXT` records. + + ### Location diff --git a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/timed-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/timed-policies.mdx index 75a6e0c5754dfc..c3028eec98b0f8 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/dns-policies/timed-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/dns-policies/timed-policies.mdx @@ -50,9 +50,8 @@ If you [do not specify a time zone](#example-users-time-zone), Gateway will enab The following command creates a DNS policy to block `facebook.com` only on weekdays from 8:00 AM - 12:30 PM and 1:30 PM - 5:00 PM in the Chicago, USA time zone. ```bash -curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "office-no-facebook-policy", @@ -77,9 +76,8 @@ Refer to [this table](https://en.wikipedia.org/wiki/List_of_tz_database_time_zon The following command creates a DNS policy to block `clockin.com` only on weekends in the time zone where the user is currently located. ```bash -curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "clock-in-policy", diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips.mdx index 65b365007f2089..285ed104b56234 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips.mdx @@ -43,7 +43,7 @@ When testing against another origin, you may see either an IPv4 or IPv6 address. ### Concurrent connections -Each dedicated egress IP assigned to your organization supports 40,000 concurrent connections per origin. You can configure multiple origins for each combination of dedicated egress IP and source port. +Each dedicated egress IP assigned to your organization supports 40,000 concurrent connections per destination and port. You can configure multiple origins for each combination of dedicated egress IP and source port. ### Unsupported traffic diff --git a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx index e1074b01a0df81..77d1575cee47ea 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/egress-policies/index.mdx @@ -18,6 +18,8 @@ Egress policies allow you to control which dedicated egress IP is used and when, Cloudflare does not publish WARP egress IP ranges. WARP egress IPs are not documented at [Cloudflare's IP Ranges](https://cloudflare.com/ips). To obtain a dedicated WARP egress IP, contact your account team. + + ## Force IP version To control whether only IPv4 or IPv6 is used to egress, ensure you are [filtering DNS traffic](/cloudflare-one/policies/gateway/initial-setup/dns/), then create a DNS policy to [block AAAA or A records](/cloudflare-one/policies/gateway/dns-policies/common-policies/#control-ip-version). diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/antivirus-scanning.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/antivirus-scanning.mdx index f695b6eafa17b0..20afe76eae3639 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/antivirus-scanning.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/antivirus-scanning.mdx @@ -3,8 +3,6 @@ pcx_content_type: concept title: AV scanning sidebar: order: 5 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Render, Details } from "~/components"; @@ -107,7 +105,7 @@ Gateway cannot scan [certain archive files](#non-scannable-files) regardless of Gateway cannot scan all files for malware. When Gateway encounters a non-scannable file, you can configure AV scanning whether to fail open (allow the file to pass through unscanned) or to fail closed (deny the file transfer). - + - Password protected archives - Archives with more than three recursion levels diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/common-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/common-policies.mdx index 80b2c161bcb151..98c9a9143f7c44 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/common-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/common-policies.mdx @@ -6,8 +6,6 @@ sidebar: head: - tag: title content: Common HTTP policies -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Render, Tabs, TabItem } from "~/components"; @@ -35,9 +33,9 @@ Block all subdomains that use a host. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block sites by hostname", "description": "Block all subdomains that use a specific hostname", @@ -69,9 +67,9 @@ Block a section of a site without blocking the entire site. For example, you can ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block sites by URL", "description": "Block specific parts of a site without blocking the hostname", @@ -122,9 +120,9 @@ Block content categories which go against your organization's acceptable use pol ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Check user identity", "description": "Block access to Salesforce by temporary employees and contractors", @@ -158,9 +156,9 @@ Gateway [evaluates Do Not Inspect policies first](/cloudflare-one/policies/gatew ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Bypass incompatible applications", "description": "Skip TLS decryption for applications that are incompatible with Gateway", @@ -200,9 +198,9 @@ Perform an [OS version check](/cloudflare-one/identity/devices/warp-client-check ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Require OS version", "description": "Perform an OS version check for minimum version", @@ -239,9 +237,9 @@ Since the file path will be different for each operating system, you can configu ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Check for specific file", "description": "Ensure users have a specific file on their device regardless of operating system", @@ -283,9 +281,9 @@ When accessing origin servers with certificates not signed by a public certifica ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Bypass internal site inspection", "description": "Bypass TLS decryption for internal sites with self-signed certificates", @@ -310,7 +308,7 @@ For more information on supported file types, refer to [Download and Upload File ## Block Google services -To enable Gateway inspection for Google Drive traffic, you must [add a Cloudflare certificate to Google Drive](/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment/#google-drive-for-desktop). +To enable Gateway inspection for Google Drive traffic, you must [add a Cloudflare certificate to Google Drive](/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment/#google-drive). ### Block Google Drive downloads @@ -328,9 +326,9 @@ Block file downloads from Google Drive. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block Google Drive downloads", "description": "Block file downloads from Google Drive", @@ -399,9 +397,9 @@ Block file downloads from Gmail. ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block Gmail downloads", "description": "Block file downloads from Gmail", diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/file-sandboxing.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/file-sandboxing.mdx index da8b86c2279a2b..2d0658de477713 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/file-sandboxing.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/file-sandboxing.mdx @@ -3,8 +3,6 @@ pcx_content_type: concept title: File sandboxing sidebar: order: 6 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Render, Details } from "~/components"; @@ -83,4 +81,4 @@ Gateway will quarantine and scan the file, display an interstitial status page i ### Non-scannable files - + diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/http3.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/http3.mdx index 0bc565de7f94bc..ac001f1b980d90 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/http3.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/http3.mdx @@ -3,8 +3,6 @@ pcx_content_type: concept title: HTTP/3 inspection sidebar: order: 3 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Details } from "~/components"; diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/index.mdx index b14951779ed709..a21459966fc5dd 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/index.mdx @@ -3,8 +3,6 @@ pcx_content_type: configuration title: HTTP policies sidebar: order: 4 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { Details, InlineBadge, Render } from "~/components"; @@ -28,6 +26,8 @@ An HTTP policy consists of an **Action** as well as a logical expression that de params={{ type: "query", example: "Source IP", example2: "Resolved IP" }} /> + + ## Actions Actions in HTTP policies allow you to choose what to do with a given set of elements (domains, IP addresses, file types, and so on). You can assign one action per policy. @@ -89,17 +89,13 @@ The Allow action allows outbound traffic to reach destinations you specify withi #### Untrusted certificates -:::note -To use this feature, deploy a [custom root certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/). -::: - The **Untrusted certificate action** determines how to handle insecure requests. -| Option | Action | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Error | Display Gateway error page. Matches the default behavior when no action is configured. | -| Block | Display [block page](/cloudflare-one/policies/gateway/block-page/) as set in Zero Trust. | -| Pass through | Bypass insecure connection warnings and seamlessly connect to the upstream. To use this feature, deploy a [custom root certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/). For more information on what statuses are bypassed, refer to the [troubleshooting FAQ](/cloudflare-one/faq/troubleshooting/#i-see-error-526-when-browsing-to-a-website). | +| Option | Action | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Error | Display Gateway error page. Matches the default behavior when no action is configured. | +| Block | Display [block page](/cloudflare-one/policies/gateway/block-page/) as set in Zero Trust. | +| Pass through | Bypass insecure connection warnings and seamlessly connect to the upstream. For more information on what statuses are bypassed, refer to the [troubleshooting FAQ](/cloudflare-one/faq/troubleshooting/#i-see-error-526-when-browsing-to-a-website). | ### Block @@ -159,7 +155,7 @@ The Block action blocks outbound traffic from reaching destinations you specify #### WARP client block notifications - + ### Isolate diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/tenant-control.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/tenant-control.mdx index 7c8292aeb7458f..255cd950c38986 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/tenant-control.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/tenant-control.mdx @@ -3,8 +3,6 @@ pcx_content_type: how-to title: Tenant control sidebar: order: 4 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- With Gateway tenant control, you can allow your users access to corporate SaaS applications while blocking access to personal applications. This helps prevent the loss of sensitive or confidential data from a corporate network. @@ -87,6 +85,22 @@ For more information, refer to the [Slack documentation](https://slack.com/help/ For more information, refer to the [Dropbox documentation](https://help.dropbox.com/security/network-control). +## Exempt users in Cloudflare WAF + +You can include custom headers in an HTTP policy to allow your users through [Cloudflare WAF](/waf/). This is useful for allowing only WARP users through your WAF. + +1. Create an Allow policy for an internal domain behind your WAF with a custom header. + + | Selector | Operator | Value | Action | + | -------- | -------- | ----------------- | ------ | + | Domain | in | `internalapp.com` | Allow | + + | Custom header name | Custom header value | + | ------------------ | ------------------- | + | `X-Example-Header` | `example-value` | + +2. In Cloudflare WAF, [create a custom rule](/waf/custom-rules/) to [require the same HTTP header](/waf/custom-rules/use-cases/require-specific-headers/#example-2-require-http-header-with-a-specific-value). + ## Use tenant control with Browser Isolation You can configure [Browser Isolation](/cloudflare-one/policies/browser-isolation/) to send custom headers. This is useful for implementing tenant control for isolated SaaS applications or sending arbitrary custom request headers to isolated websites. diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/tls-decryption.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/tls-decryption.mdx index 979c665db33a00..99487e5af32906 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/tls-decryption.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/tls-decryption.mdx @@ -3,8 +3,6 @@ pcx_content_type: concept title: TLS decryption sidebar: order: 2 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- import { @@ -19,7 +17,7 @@ Cloudflare Gateway can perform [SSL/TLS decryption](https://www.cloudflare.com/l When you turn on TLS decryption, Gateway will decrypt all traffic sent over HTTPS, apply your HTTP policies, and then re-encrypt the request with a [user-side certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/). -Cloudflare prevents interference by decrypting, inspecting, and re-encrypting HTTPS requests in its data centers in memory only. Gateway only stores eligible cache content at rest. All cache disks are encrypted at rest. You can configure where TLS decryption takes place with [Regional Services](/data-localization/regional-services/) in the [Cloudflare Data Localization Suite (DLS)](/data-localization/). +Cloudflare prevents traffic interference by decrypting, inspecting, and re-encrypting HTTPS requests in its data centers in memory only. Gateway only stores eligible cache content at rest. All cache disks are encrypted at rest. You can configure where TLS decryption takes place with [Regional Services](/data-localization/regional-services/) in the [Cloudflare Data Localization Suite (DLS)](/data-localization/). To further control what data centers traffic egresses from, you can use [dedicated egress IPs](/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/). Cloudflare supports connections from users to Gateway over TLS 1.1, 1.2, and 1.3. @@ -91,7 +89,7 @@ Chrome Enterprise users can turn off automatic HTTPS upgrades for all URLs with ### ESNI and ECH -Websites that adhere to [ESNI or ECH standards](https://blog.cloudflare.com/encrypted-client-hello/) encrypt the Server Name Indicator (SNI) during the TLS handshake and are therefore incompatible with HTTP inspection. This is because Gateway relies on the SNI to match an HTTP request to a policy. +Websites that adhere to [ESNI or Encrypted Client Hello (ECH) standards](https://blog.cloudflare.com/encrypted-client-hello/) encrypt the Server Name Indicator (SNI) during the TLS handshake and are therefore incompatible with HTTP inspection. This is because Gateway relies on the SNI to match an HTTP request to a policy. If the ECH fails, browsers will retry the TLS handshake using the unencrypted SNI from the initial request. To avoid this behavior, you can disable ECH in your users' browsers. You can still apply all [network policy filters](/cloudflare-one/policies/gateway/network-policies/#selectors) except for SNI and SNI Domain. To restrict ESNI and ECH traffic, an option is to filter out all port `80` and `443` traffic that does not include an SNI header. @@ -99,6 +97,8 @@ You can still apply all [network policy filters](/cloudflare-one/policies/gatewa Gateway supports post-quantum cryptography using a hybrid key exchange with X25519 and MLKEM768 over TLS 1.3. Once the key exchange is complete, Gateway uses AES-128-GCM to encrypt traffic. +Refer to [Post-quantum cryptography](/ssl/post-quantum-cryptography/) to learn more. + ## FIPS compliance By default, TLS decryption can use both TLS version 1.2 and 1.3. However, some environments such as FedRAMP may require cipher suites and TLS versions compliant with FIPS 140-2. FIPS compliance currently requires TLS version 1.2. @@ -115,9 +115,9 @@ When FIPS compliance is enabled, Gateway will only choose [FIPS-compliant cipher FIPS-compliant traffic defaults to [HTTP/3](/cloudflare-one/policies/gateway/http-policies/http3/). To enforce HTTP policies for UDP traffic, you must turn on the [Gateway proxy for UDP](/cloudflare-one/policies/gateway/http-policies/http3/#enable-http3-inspection). -### Cipher suites +## Cipher suites - + The following table lists the default cipher suites Gateway uses for TLS decryption. diff --git a/src/content/docs/cloudflare-one/policies/gateway/http-policies/websocket.mdx b/src/content/docs/cloudflare-one/policies/gateway/http-policies/websocket.mdx index 617de4457d91d8..e0cba0a7dd2b77 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/http-policies/websocket.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/http-policies/websocket.mdx @@ -3,12 +3,10 @@ pcx_content_type: how-to title: WebSocket traffic sidebar: order: 7 -banner: - content: The default global Cloudflare root certificate expired on 2025-02-02. If you installed the default Cloudflare certificate before 2024-10-17, you must generate a new certificate and activate it for your Zero Trust organization to avoid inspection errors. --- Gateway does not inspect or log [WebSocket](https://datatracker.ietf.org/doc/html/rfc6455) traffic. Instead, Gateway will only log the HTTP details used to make the WebSocket connection, as well as [network session information](/logs/reference/log-fields/account/zero_trust_network_sessions/). To filter your WebSocket traffic, create a policy with the `101` HTTP response code. -| Selector | Operator | Value | Action | -| ------------- | -------- | ----------------------- | ------ | -| HTTP Response | is | 101 SWITCHING_PROTOCOLS | Allow | +| Selector | Operator | Value | Action | +| ------------- | -------- | ------------------------- | ------ | +| HTTP Response | is | _101 SWITCHING_PROTOCOLS_ | Allow | diff --git a/src/content/docs/cloudflare-one/policies/gateway/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/index.mdx index 9f92bd2baba4c5..f95d151661a405 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/index.mdx @@ -8,7 +8,7 @@ head: content: Gateway policies --- -Cloudflare Gateway, our comprehensive Secure Web Gateway, allows you to set up policies to inspect DNS, Network, HTTP, and Egress traffic. +Cloudflare Gateway, our comprehensive [Secure Web Gateway](https://www.cloudflare.com/learning/access-management/what-is-a-secure-web-gateway/), allows you to set up policies to inspect DNS, Network, HTTP, and Egress traffic. - **DNS policies** inspect DNS queries. You can block domains and IP addresses from resolving on your devices. For more information on DNS filtering, refer to our [Learning Center article](https://www.cloudflare.com/learning/access-management/what-is-dns-filtering/). - **Network policies** inspect individual TCP/UDP/GRE packets. You can block access to specific ports on your origin server, including non-HTTP resources. diff --git a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/dns.mdx b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/dns.mdx index 84efb4e20549ac..da36348972c104 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/dns.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/dns.mdx @@ -6,6 +6,9 @@ sidebar: head: - tag: title content: Set up DNS filtering +learning_center: + title: What is DNS filtering? | Secure DNS servers + link: https://www.cloudflare.com/learning/access-management/what-is-dns-filtering/ --- import { GlossaryTooltip, Render } from "~/components"; @@ -13,7 +16,6 @@ import { GlossaryTooltip, Render } from "~/components"; Secure Web Gateway allows you to inspect DNS traffic and control which websites users can visit. :::note - For a more detailed guide to filtering DNS queries and other traffic for your organization, refer to the [Secure your Internet traffic and SaaS apps](/learning-paths/secure-internet-traffic/concepts/) implementation guide. ::: diff --git a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/http.mdx b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/http.mdx index 2794fbbe6c005a..9a3ee2b7ad5549 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/http.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/http.mdx @@ -6,6 +6,9 @@ sidebar: head: - tag: title content: Set up HTTP filtering +learning_center: + title: What is URL filtering? | Web filtering + link: https://www.cloudflare.com/learning/access-management/what-is-url-filtering/ --- import { GlossaryTooltip, Render } from "~/components"; @@ -13,7 +16,6 @@ import { GlossaryTooltip, Render } from "~/components"; Secure Web Gateway allows you to inspect HTTP traffic and control which websites users can visit. :::note - For a more detailed guide to filtering HTTP requests and other traffic for your organization, refer to the [Secure your Internet traffic and SaaS apps](/learning-paths/secure-internet-traffic/concepts/) implementation guide. ::: @@ -24,8 +26,8 @@ To filter HTTP requests from a device: 1. [Install the Cloudflare root certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/) on your device. 2. [Install the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/) on your device. 3. In the WARP client Settings, log in to your organization's Zero Trust instance. -4. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#enable-the-gateway-proxy) for TCP. Optionally, you can enable the UDP proxy to inspect all port 443 UDP traffic. -5. To inspect HTTPS traffic, [enable TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#enable-tls-decryption). +4. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#turn-on-the-gateway-proxy) for TCP. Optionally, you can enable the UDP proxy to inspect all port 443 UDP traffic. +5. To inspect HTTPS traffic, [enable TLS decryption](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#turn-on-tls-decryption). 6. (Optional) To scan file uploads and downloads for malware, [enable anti-virus scanning](/cloudflare-one/policies/gateway/http-policies/antivirus-scanning/). ## 2. Verify device connectivity diff --git a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/network.mdx b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/network.mdx index 834c9dd60b0470..8b83052e002dff 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/initial-setup/network.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/initial-setup/network.mdx @@ -13,7 +13,6 @@ import { GlossaryTooltip, Render } from "~/components"; Secure Web Gateway allows you to apply policies at the network level (Layers 3 and 4) to control which websites and non-HTTP applications users can access. :::note - For a more detailed guide to filtering network traffic and more for your organization, refer to the [Secure your Internet traffic and SaaS apps](/learning-paths/secure-internet-traffic/concepts/) implementation guide. ::: @@ -26,7 +25,7 @@ To filter network traffic from a device such as a laptop or phone: 1. [Install the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/) on your device. 2. In the WARP client Settings, log in to your organization's Zero Trust instance. 3. (Optional) If you want to display a [custom block page](/cloudflare-one/policies/gateway/block-page/), [install the Cloudflare root certificate](/cloudflare-one/connections/connect-devices/user-side-certificates/) on your device . -4. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#enable-the-gateway-proxy) for TCP. Optionally, you can enable the UDP proxy to inspect all port 443 UDP traffic. +4. [Enable the Gateway proxy](/cloudflare-one/policies/gateway/proxy/#turn-on-the-gateway-proxy) for TCP. Optionally, you can enable the UDP proxy to inspect all port 443 UDP traffic. ### Connect private networks diff --git a/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx index 0a59858c0af0b4..02282b56b97824 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/network-policies/common-policies.mdx @@ -29,9 +29,9 @@ Refer to the [network policies page](/cloudflare-one/policies/gateway/network-po ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block unauthorized applications", "description": "Block access to unauthorized AI applications", @@ -64,9 +64,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Check user identity", "description": "Block access to Salesforce by temporary employees and contractors", @@ -114,9 +114,9 @@ Restrict user access to only the specific sites or applications configured in yo ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Allow HTTP and HTTPS traffic", "description": "Restrict traffic to HTTP and HTTPS traffic", @@ -146,9 +146,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block all other traffic", "description": "Block all other traffic that is not HTTP or HTTPS", @@ -185,9 +185,9 @@ The following example consists of two policies: the first allows specific users ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Allow company employees", "description": "Allow any users with an organization email to reach the application", @@ -217,9 +217,9 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block everyone else", "description": "Block any other users from accessing the application", @@ -256,9 +256,9 @@ Override traffic directed toward a specific IP address with a different IP addre ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rule \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ ---header "Authorization: Bearer " \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Override example.com with 1.1.1.1", "description": "Override a site'\''s IP address with another IP", diff --git a/src/content/docs/cloudflare-one/policies/gateway/network-policies/index.mdx b/src/content/docs/cloudflare-one/policies/gateway/network-policies/index.mdx index b2666fe06a3293..b38e82eb33bac3 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/network-policies/index.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/network-policies/index.mdx @@ -26,6 +26,8 @@ A network policy consists of an **Action** as well as a logical expression that params={{ type: "query", example: "Source IP", example2: "Resolved IP" }} /> + + ## Actions Like actions in DNS and HTTP policies, actions in network policies define which decision you want to apply to a given set of elements. You can assign one action per policy. @@ -38,7 +40,7 @@ API value: `allow` **Traffic** -- [All Access Private Apps](#all-access-private-apps) +- [All Access Private Apps](#all-access-private-app-destinations) - [All Access App Targets](#all-access-app-targets) - [Application](#application) - [Content Categories](#content-categories) @@ -177,7 +179,7 @@ Policies with Block actions block network traffic from reaching certain IPs or p #### WARP client block notifications - + ### Network Override diff --git a/src/content/docs/cloudflare-one/policies/gateway/resolver-policies.mdx b/src/content/docs/cloudflare-one/policies/gateway/resolver-policies.mdx index bcde3a3126a82b..5f0ceb97523685 100644 --- a/src/content/docs/cloudflare-one/policies/gateway/resolver-policies.mdx +++ b/src/content/docs/cloudflare-one/policies/gateway/resolver-policies.mdx @@ -52,7 +52,7 @@ You can protect your authoritative nameservers from DDoS attacks by enabling [DN ### Cloudflare Tunnel -You can configure connections to a private resolver connected to Cloudflare with [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/). To ensure `cloudflared` can route UDP traffic to your resolver, connect your tunnel via [QUIC](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#protocol). +You can configure connections to a private resolver connected to Cloudflare with [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/). To ensure `cloudflared` can route UDP traffic to your resolver, connect your tunnel via [QUIC](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#protocol). For more information on connecting a private DNS resolver to Cloudflare with Cloudflare Tunnel, refer to [Private DNS](/cloudflare-one/connections/connect-networks/private-net/cloudflared/private-dns/). @@ -79,6 +79,8 @@ Gateway will filter, resolve, and log your queries regardless of endpoint. For more information on creating a DNS policy, refer to [DNS policies](/cloudflare-one/policies/gateway/dns-policies/). + + ## Selectors ### Content Categories diff --git a/src/content/docs/cloudflare-one/roles-permissions.mdx b/src/content/docs/cloudflare-one/roles-permissions.mdx index 781094c2d91580..56f989c3caef86 100644 --- a/src/content/docs/cloudflare-one/roles-permissions.mdx +++ b/src/content/docs/cloudflare-one/roles-permissions.mdx @@ -13,19 +13,20 @@ To check the list of members in your account, or to manage roles and permissions Only Super Administrators will be able to assign or remove the following roles from users in their account. Scroll to the right to see a full list of permissions for each role. -| | Access Read | Access Edit | Gateway Read | Gateway Edit | Gateway Report | Billing Read | Billing Edit | DEX Read | DEX Edit | -| ------------------------------- | ----------- | ----------- | ------------ | ------------ | -------------- | ------------ | ------------ | -------- | -------- | -| Super Administrator | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| Cloudflare Zero Trust | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | -| Cloudflare Access | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | -| Cloudflare Gateway | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | -| Cloudflare Zero Trust Read Only | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | -| Cloudflare Zero Trust Reporting | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | -| Cloudflare DEX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | - -:::note -The Cloudflare Zero Trust role grants administrator access to all Zero Trust products including Access, Gateway, WARP, Tunnel, Browser Isolation, CASB, DLP, DEX, and Email Security. -::: +| | Access Read | Access Edit | Gateway Read | Gateway Edit | Gateway Report | DNS Location Read | DNS Location Edit | Billing Read | Billing Edit | DEX Read | DEX Edit | +| --------------------------------------------- | ----------- | ----------- | ------------ | ------------ | -------------- | ----------------- | ----------------- | ------------ | ------------ | -------- | -------- | +| Super Administrator | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Cloudflare Zero Trust[^1] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | +| Cloudflare Access | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| Cloudflare Gateway | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | +| Cloudflare Zero Trust Read Only | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | +| Cloudflare Zero Trust Reporting | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | +| Cloudflare Zero Trust DNS Locations Write[^2] | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | +| Cloudflare DEX | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | + +[^1]: The **Cloudflare Zero Trust** role grants administrator access to all Zero Trust products including Access, Gateway, WARP, Tunnel, Browser Isolation, CASB, DLP, DEX, and Email Security. + +[^2]: Users with the **Cloudflare Zero Trust DNS Locations Write** role can view all DNS locations for an organization but can only create and edit [secure DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/#secure-dns-locations). ### Cloudflare Zero Trust PII diff --git a/src/content/docs/cloudflare-one/tutorials/access-workers.mdx b/src/content/docs/cloudflare-one/tutorials/access-workers.mdx index 73d3a7b75844dd..048ae9d17efd65 100644 --- a/src/content/docs/cloudflare-one/tutorials/access-workers.mdx +++ b/src/content/docs/cloudflare-one/tutorials/access-workers.mdx @@ -2,7 +2,6 @@ updated: 2023-11-27 category: 🔐 Access difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Create custom headers for Cloudflare Access-protected origins with Workers products: diff --git a/src/content/docs/cloudflare-one/tutorials/extend-sso-with-workers.mdx b/src/content/docs/cloudflare-one/tutorials/extend-sso-with-workers.mdx index b0456fcefd2bfe..b6d49e6654201b 100644 --- a/src/content/docs/cloudflare-one/tutorials/extend-sso-with-workers.mdx +++ b/src/content/docs/cloudflare-one/tutorials/extend-sso-with-workers.mdx @@ -52,7 +52,7 @@ This approach allows you to: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -72,7 +72,7 @@ This approach allows you to: async fetch(request, env, ctx) { // The name of the cookie const COOKIE_NAME = "CF_Authorization"; - const CF_GET_IDENTITY = "https://.cloudflareaccess.com>/cdn-cgi/access/get-identity"; + const CF_GET_IDENTITY = "https://.cloudflareaccess.com/cdn-cgi/access/get-identity"; const cookie = parse(request.headers.get("Cookie") || ""); if (cookie[COOKIE_NAME] != null) { try { diff --git a/src/content/docs/cloudflare-one/tutorials/gitlab.mdx b/src/content/docs/cloudflare-one/tutorials/gitlab.mdx index b1fb35b936e7d5..f4335bd257db72 100644 --- a/src/content/docs/cloudflare-one/tutorials/gitlab.mdx +++ b/src/content/docs/cloudflare-one/tutorials/gitlab.mdx @@ -310,3 +310,13 @@ Cloudflare Tunnel will continue to run outbound-only connections and I can avoid ## View logs You can also view logs of the events that are allowed and blocked. Open the `Access` page of the `Logs` section in Zero Trust. + +## Troubleshooting + +If you are using Git Large File Storage (LFS), note that Git LFS is not automatically supported by `cloudflared`. To access repositories protected by Cloudflare Access, you need to authenticate manually by running: + +```sh +cloudflared access login +``` + +Replace `` with the Cloudflare Access-protected URL. diff --git a/src/content/docs/cloudflare-one/tutorials/grafana.mdx b/src/content/docs/cloudflare-one/tutorials/grafana.mdx index 4a8074e4cc8f98..bf1f25c85a817b 100644 --- a/src/content/docs/cloudflare-one/tutorials/grafana.mdx +++ b/src/content/docs/cloudflare-one/tutorials/grafana.mdx @@ -36,7 +36,7 @@ If your tunnel was created via the CLI, run the following command on the `cloudf cloudflared tunnel --metrics 192.168.1.1:60123 run my-tunnel ``` -If your tunnel was created via the dashboard, the [--metrics](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#metrics) flag must be added to your `cloudflared` system service configuration. Refer to [Add tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-management/#add-tunnel-run-parameters) for instructions on how to do this. +If your tunnel was created via the dashboard, the [--metrics](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#metrics) flag must be added to your `cloudflared` system service configuration. Refer to [Add tunnel run parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/#update-tunnel-run-parameters) for instructions on how to do this. ## Set up Prometheus diff --git a/src/content/docs/cloudflare-one/tutorials/kubectl.mdx b/src/content/docs/cloudflare-one/tutorials/kubectl.mdx index f44ceed780499a..2fc8777f6f0294 100644 --- a/src/content/docs/cloudflare-one/tutorials/kubectl.mdx +++ b/src/content/docs/cloudflare-one/tutorials/kubectl.mdx @@ -69,7 +69,7 @@ cloudflared tunnel list ## Configure the Tunnel -You can now [configure the tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/#4-create-a-configuration-file) to serve traffic. +You can now [configure the tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/#4-create-a-configuration-file) to serve traffic. Create a `YAML` file that `cloudflared` can reach. By default, `cloudflared` will look for the file in the same folder where `cloudflared` has been installed. @@ -95,7 +95,7 @@ ingress: ## Route to the Tunnel -You can now create a DNS record that will route traffic to this Tunnel. Multiple DNS records can point to a single Tunnel and will send traffic to the configured service as long as the hostname is defined with an [ingress rule](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames). +You can now create a DNS record that will route traffic to this Tunnel. Multiple DNS records can point to a single Tunnel and will send traffic to the configured service as long as the hostname is defined with an [ingress rule](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames). 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. Select your domain and go to **DNS**. @@ -117,7 +117,7 @@ You can now run the Tunnel to connect the target service to Cloudflare. Use the cloudflared tunnel run ``` -We recommend that you run `cloudflared` [as a service](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/as-a-service/) that is configured to launch on start. +We recommend that you run `cloudflared` [as a service](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/as-a-service/) that is configured to launch on start. ## Connect from a client machine diff --git a/src/content/docs/cloudflare-one/tutorials/migrate-lb-tunnel.mdx b/src/content/docs/cloudflare-one/tutorials/migrate-lb-tunnel.mdx index afd83494f0185c..bf054ce7ce987b 100644 --- a/src/content/docs/cloudflare-one/tutorials/migrate-lb-tunnel.mdx +++ b/src/content/docs/cloudflare-one/tutorials/migrate-lb-tunnel.mdx @@ -22,7 +22,7 @@ If you are using Legacy Tunnel today you can migrate to Named Tunnel deployment 10 minutes -See additional documentation for working with [Kubernetes](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/kubernetes/). +See additional documentation for working with [Kubernetes](/cloudflare-one/connections/connect-networks/deployment-guides/kubernetes/). --- @@ -82,7 +82,7 @@ This command will create a Tunnel object in your Cloudflare account that is repr ## Create a configuration file -Next, configure your Tunnel. The example below consists of a web service that is available at port 8000. The ingress rule will send traffic that `cloudflared` receives for the specified hostname to that port. You can also connect [multiple services](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames) with a single instance of `cloudflared`. +Next, configure your Tunnel. The example below consists of a web service that is available at port 8000. The ingress rule will send traffic that `cloudflared` receives for the specified hostname to that port. You can also connect [multiple services](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#file-structure-for-public-hostnames) with a single instance of `cloudflared`. In the configuration file, you must specify the location of the credentials file generated previously when you created the Tunnel. diff --git a/src/content/docs/cloudflare-one/tutorials/mongodb-tunnel.mdx b/src/content/docs/cloudflare-one/tutorials/mongodb-tunnel.mdx index 505d0e204901f6..8b18c4b2869871 100644 --- a/src/content/docs/cloudflare-one/tutorials/mongodb-tunnel.mdx +++ b/src/content/docs/cloudflare-one/tutorials/mongodb-tunnel.mdx @@ -196,7 +196,7 @@ done; ## Configure Cloudflare Tunnel -Next, you can use `cloudflared` to connect to Cloudflare's Edge using Cloudflare Tunnel. Start by [downloading and installing](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/) the Cloudflare Tunnel daemon, `cloudflared`. +Next, you can use `cloudflared` to connect to Cloudflare's Edge using Cloudflare Tunnel. Start by [downloading and installing](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/) the Cloudflare Tunnel daemon, `cloudflared`. Once installed, run the following command to authenticate the instance of `cloudflared` into your Cloudflare account. @@ -214,7 +214,7 @@ You can now use `cloudflared` to control Cloudflare Tunnel connections in your C ### Create a Tunnel -You can now [create a Tunnel](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/) that will connect `cloudflared` to Cloudflare's edge. You'll configure the details of that Tunnel in the next step. +You can now [create a Tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/) that will connect `cloudflared` to Cloudflare's edge. You'll configure the details of that Tunnel in the next step. Run the following command to create a Tunnel. You can replace `mongodb` with any name that you choose. This command requires the `cert.pem` file. diff --git a/src/content/docs/cloudflare-one/tutorials/r2-logs.mdx b/src/content/docs/cloudflare-one/tutorials/r2-logs.mdx index 6229b320217b12..13bd9d1cd1b4b2 100644 --- a/src/content/docs/cloudflare-one/tutorials/r2-logs.mdx +++ b/src/content/docs/cloudflare-one/tutorials/r2-logs.mdx @@ -6,7 +6,6 @@ pcx_content_type: tutorial title: Use Cloudflare R2 as a Zero Trust log destination products: - R2 -content_type: 📝 Tutorial --- diff --git a/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx b/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx index 5b1087208a1092..f02c4aff27e28f 100644 --- a/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx +++ b/src/content/docs/cloudflare-one/tutorials/user-selectable-egress-ips.mdx @@ -49,8 +49,8 @@ First, create [virtual networks](/cloudflare-one/connections/connect-networks/pr 1. Create a [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) corresponding to one of your dedicated egress IPs. We recommend using a name related to the location of the corresponding dedicated egress IP. For example, if your users will egress from the Americas, you can name the virtual network `vnet-AMER`. ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/teamnet/virtual_networks \ - --header "Authorization: Bearer " \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/virtual_networks \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "comment": "Virtual network to egress from the Americas", @@ -90,8 +90,8 @@ After creating your virtual networks, route your private network CIDRs over each ```bash curl --request PATCH \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/teamnet/routes/{route_id} \ - --header "Authorization: Bearer " \ + https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/routes/$ROUTE_ID \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "network": "10.0.0.0/8", @@ -106,8 +106,8 @@ After creating your virtual networks, route your private network CIDRs over each ```bash curl --request PATCH \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/teamnet/routes/{route_id} \ - --header "Authorization: Bearer " \ + https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/routes/$ROUTE_ID \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "network": "10.0.0.0/8", @@ -160,8 +160,8 @@ Next, assign your dedicated egress IPs to each virtual network using Gateway egr 1. Add a Gateway egress policy that matches the corresponding virtual network. For example: ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ - --header "Authorization: Bearer " \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "egress", diff --git a/src/content/docs/cloudflare-one/tutorials/vnc-client-in-browser.mdx b/src/content/docs/cloudflare-one/tutorials/vnc-client-in-browser.mdx index 37ad5aa5b2bf9b..1be132d6cdbf06 100644 --- a/src/content/docs/cloudflare-one/tutorials/vnc-client-in-browser.mdx +++ b/src/content/docs/cloudflare-one/tutorials/vnc-client-in-browser.mdx @@ -135,7 +135,7 @@ At this point, you have a VNC server ready to test with browser-based VNC. We re cloudflared tunnel --config path/config.yaml run ``` -8. Follow [this guide](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/) to open outbound connections for Cloudflare Tunnel if you have a firewall enabled. +8. Follow [this guide](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/) to open outbound connections for Cloudflare Tunnel if you have a firewall enabled. At this point you have a running VNC server and a Cloudflare Tunnel on your machine ready to accept inbound VNC requests. diff --git a/src/content/docs/cloudflare-one/video-tutorials.mdx b/src/content/docs/cloudflare-one/video-tutorials.mdx new file mode 100644 index 00000000000000..3483b82ca82c99 --- /dev/null +++ b/src/content/docs/cloudflare-one/video-tutorials.mdx @@ -0,0 +1,16 @@ +--- +pcx_content_type: navigation +title: Videos +sidebar: + order: 11 +--- + +import { CardGrid, LinkCard } from "~/components"; + + + + diff --git a/src/content/docs/d1/best-practices/query-d1.mdx b/src/content/docs/d1/best-practices/query-d1.mdx index 8f0387f6b16de3..801cdd29156c6e 100644 --- a/src/content/docs/d1/best-practices/query-d1.mdx +++ b/src/content/docs/d1/best-practices/query-d1.mdx @@ -19,7 +19,7 @@ D1 understands SQLite semantics, which allows you to query a database using SQL ### Use foreign key relationships -When using SQL with D1, you may wish to define and and enforce foreign key constraints across tables in a database. Foreign key constraints allow you to enforce relationships across tables, or prevent you from deleting rows that reference rows in other tables. An example of a foreign key relationship is shown below. +When using SQL with D1, you may wish to define and enforce foreign key constraints across tables in a database. Foreign key constraints allow you to enforce relationships across tables, or prevent you from deleting rows that reference rows in other tables. An example of a foreign key relationship is shown below. ```sql CREATE TABLE users ( diff --git a/src/content/docs/d1/examples/d1-and-hono.mdx b/src/content/docs/d1/examples/d1-and-hono.mdx index 52fe30888509aa..0552626134e146 100644 --- a/src/content/docs/d1/examples/d1-and-hono.mdx +++ b/src/content/docs/d1/examples/d1-and-hono.mdx @@ -3,24 +3,22 @@ type: example summary: Query D1 from the Hono web framework tags: - Hono - - D1 pcx_content_type: example title: Query D1 from Hono sidebar: order: 3 description: Query D1 from the Hono web framework - --- -import { TabItem, Tabs } from "~/components" +import { TabItem, Tabs } from "~/components"; Hono is a fast web framework for building API-first applications, and it includes first-class support for both [Workers](/workers/) and [Pages](/pages/). When using Workers: -* Ensure you have configured your [Wrangler configuration file](/d1/get-started/#3-bind-your-worker-to-your-d1-database) to bind your D1 database to your Worker. -* You can access your D1 databases via Hono's [`Context`](https://hono.dev/api/context) parameter: [bindings](https://hono.dev/getting-started/cloudflare-workers#bindings) are exposed on `context.env`. If you configured a [binding](/pages/functions/bindings/#d1-databases) named `DB`, then you would access [D1 Workers Binding API](/d1/worker-api/prepared-statements/) methods via `c.env.DB`. -* Refer to the Hono documentation for [Cloudflare Workers](https://hono.dev/getting-started/cloudflare-workers). +- Ensure you have configured your [Wrangler configuration file](/d1/get-started/#3-bind-your-worker-to-your-d1-database) to bind your D1 database to your Worker. +- You can access your D1 databases via Hono's [`Context`](https://hono.dev/api/context) parameter: [bindings](https://hono.dev/getting-started/cloudflare-workers#bindings) are exposed on `context.env`. If you configured a [binding](/pages/functions/bindings/#d1-databases) named `DB`, then you would access [D1 Workers Binding API](/d1/worker-api/prepared-statements/) methods via `c.env.DB`. +- Refer to the Hono documentation for [Cloudflare Workers](https://hono.dev/getting-started/cloudflare-workers). If you are using [Pages Functions](/pages/functions/): @@ -37,24 +35,24 @@ import { Hono } from "hono"; // This ensures c.env.DB is correctly typed type Bindings = { - DB: D1Database; + DB: D1Database; }; const app = new Hono<{ Bindings: Bindings }>(); // Accessing D1 is via the c.env.YOUR_BINDING property app.get("/query/users/:id", async (c) => { - const userId = c.req.param("id"); - try { - let { results } = await c.env.DB.prepare( - "SELECT * FROM users WHERE user_id = ?", - ) - .bind(userId) - .all(); - return c.json(results); - } catch (e) { - return c.json({ err: e.message }, 500); - } + const userId = c.req.param("id"); + try { + let { results } = await c.env.DB.prepare( + "SELECT * FROM users WHERE user_id = ?", + ) + .bind(userId) + .all(); + return c.json(results); + } catch (e) { + return c.json({ err: e.message }, 500); + } }); // Export our Hono app: Hono automatically exports a @@ -72,17 +70,17 @@ const app = new Hono().basePath("/api"); // Accessing D1 is via the c.env.YOUR_BINDING property app.get("/query/users/:id", async (c) => { - const userId = c.req.param("id"); - try { - let { results } = await c.env.DB.prepare( - "SELECT * FROM users WHERE user_id = ?", - ) - .bind(userId) - .all(); - return c.json(results); - } catch (e) { - return c.json({ err: e.message }, 500); - } + const userId = c.req.param("id"); + try { + let { results } = await c.env.DB.prepare( + "SELECT * FROM users WHERE user_id = ?", + ) + .bind(userId) + .all(); + return c.json(results); + } catch (e) { + return c.json({ err: e.message }, 500); + } }); // Export the Hono instance as a Pages onRequest function diff --git a/src/content/docs/d1/examples/d1-and-remix.mdx b/src/content/docs/d1/examples/d1-and-remix.mdx index 884afaad5fc09f..f61b7bb83ad2a0 100644 --- a/src/content/docs/d1/examples/d1-and-remix.mdx +++ b/src/content/docs/d1/examples/d1-and-remix.mdx @@ -3,16 +3,14 @@ type: example summary: Query your D1 database from a Remix application. tags: - Remix - - D1 pcx_content_type: example title: Query D1 from Remix sidebar: order: 2 description: Query your D1 database from a Remix application. - --- -import { TabItem, Tabs } from "~/components" +import { TabItem, Tabs } from "~/components"; Remix is a full-stack web framework that operates on both client and server. You can query your D1 database(s) from Remix using Remix's [data loading](https://remix.run/docs/en/main/guides/data-loading) API with the [`useLoaderData`](https://remix.run/docs/en/main/hooks/use-loader-data) hook. @@ -24,8 +22,8 @@ To set up a new Remix site on Cloudflare Pages that can query D1: The following example shows you how to define a Remix [`loader`](https://remix.run/docs/en/main/route/loader) that has a binding to a D1 database. -* Bindings are passed through on the `context.env` parameter passed to a `LoaderFunction`. -* If you configured a [binding](/pages/functions/bindings/#d1-databases) named `DB`, then you would access [D1 Workers Binding API](/d1/worker-api/prepared-statements/) methods via `context.env.DB`. +- Bindings are passed through on the `context.env` parameter passed to a `LoaderFunction`. +- If you configured a [binding](/pages/functions/bindings/#d1-databases) named `DB`, then you would access [D1 Workers Binding API](/d1/worker-api/prepared-statements/) methods via `context.env.DB`. diff --git a/src/content/docs/d1/examples/d1-and-sveltekit.mdx b/src/content/docs/d1/examples/d1-and-sveltekit.mdx index c7ae97a184f723..6482cb36ce087f 100644 --- a/src/content/docs/d1/examples/d1-and-sveltekit.mdx +++ b/src/content/docs/d1/examples/d1-and-sveltekit.mdx @@ -4,16 +4,14 @@ summary: Query a D1 database from a SvelteKit application. tags: - SvelteKit - Svelte - - D1 pcx_content_type: example title: Query D1 from SvelteKit sidebar: order: 3 description: Query a D1 database from a SvelteKit application. - --- -import { TabItem, Tabs } from "~/components" +import { TabItem, Tabs } from "~/components"; [SvelteKit](https://kit.svelte.dev/) is a full-stack framework that combines the Svelte front-end framework with Vite for server-side capabilities and rendering. You can query D1 from SvelteKit by configuring a [server endpoint](https://kit.svelte.dev/docs/routing#server) with a binding to your D1 database(s). @@ -26,8 +24,8 @@ To set up a new SvelteKit site on Cloudflare Pages that can query D1: The following example shows you how to create a server endpoint configured to query D1. -* Bindings are available on the `platform` parameter passed to each endpoint, via `platform.env.BINDING_NAME`. -* With SvelteKit's [file-based routing](https://kit.svelte.dev/docs/routing), the server endpoint defined in `src/routes/api/users/+server.ts` is available at `/api/users` within your SvelteKit app. +- Bindings are available on the `platform` parameter passed to each endpoint, via `platform.env.BINDING_NAME`. +- With SvelteKit's [file-based routing](https://kit.svelte.dev/docs/routing), the server endpoint defined in `src/routes/api/users/+server.ts` is available at `/api/users` within your SvelteKit app. The example also shows you how to configure both your app-wide types within `src/app.d.ts` to recognize your `D1Database` binding, import the `@sveltejs/adapter-cloudflare` adapter into `svelte.config.js`, and configure it to apply to all of your routes. @@ -38,10 +36,10 @@ import type { RequestHandler } from "@sveltejs/kit"; /** @type {import('@sveltejs/kit').RequestHandler} */ export async function GET({ request, platform }) { - let result = await platform.env.DB.prepare( - "SELECT * FROM users LIMIT 5" - ).run(); - return new Response(JSON.stringify(result)); + let result = await platform.env.DB.prepare( + "SELECT * FROM users LIMIT 5", + ).run(); + return new Response(JSON.stringify(result)); } ``` @@ -49,40 +47,39 @@ export async function GET({ request, platform }) { // See https://kit.svelte.dev/docs/types#app // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - interface Platform { - env: { - DB: D1Database; - }; - context: { - waitUntil(promise: Promise): void; - }; - caches: CacheStorage & { default: Cache }; - } - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + interface Platform { + env: { + DB: D1Database; + }; + context: { + waitUntil(promise: Promise): void; + }; + caches: CacheStorage & { default: Cache }; + } + } } export {}; ``` ```js -import adapter from '@sveltejs/adapter-cloudflare'; +import adapter from "@sveltejs/adapter-cloudflare"; export default { - kit: { - adapter: adapter({ - // See below for an explanation of these options - routes: { - include: ['/*'], - exclude: [''] - } - }) - } + kit: { + adapter: adapter({ + // See below for an explanation of these options + routes: { + include: ["/*"], + exclude: [""], + }, + }), + }, }; - ``` diff --git a/src/content/docs/d1/examples/query-d1-from-python-workers.mdx b/src/content/docs/d1/examples/query-d1-from-python-workers.mdx index 112aaebd81e514..712e9929c7d8a9 100644 --- a/src/content/docs/d1/examples/query-d1-from-python-workers.mdx +++ b/src/content/docs/d1/examples/query-d1-from-python-workers.mdx @@ -1,9 +1,8 @@ --- type: example summary: Learn how to query D1 from a Python Worker -tags: +languages: - Python - - D1 pcx_content_type: example title: Query D1 from Python Workers sidebar: diff --git a/src/content/docs/d1/get-started.mdx b/src/content/docs/d1/get-started.mdx index 7e11737a4f54a5..6fcf23ccae110f 100644 --- a/src/content/docs/d1/get-started.mdx +++ b/src/content/docs/d1/get-started.mdx @@ -1,5 +1,5 @@ --- -title: Get started +title: Getting started pcx_content_type: get-started updated: 2024-08-28 sidebar: @@ -49,7 +49,7 @@ Create a new Worker as the means to query your database. product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -73,7 +73,7 @@ Create a new Worker as the means to query your database. Your new `d1-tutorial` directory includes: - A `"Hello World"` [Worker](/workers/get-started/guide/#3-write-code) in `index.ts`. - - A [[Wrangler configuration file](/workers/wrangler/configuration/)](/workers/wrangler/configuration/). This file is how your `d1-tutorial` Worker accesses your D1 database. + - A [Wrangler configuration file](/workers/wrangler/configuration/). This file is how your `d1-tutorial` Worker accesses your D1 database. diff --git a/src/content/docs/d1/index.mdx b/src/content/docs/d1/index.mdx index f6992adcf96740..611ef085c6e6bf 100644 --- a/src/content/docs/d1/index.mdx +++ b/src/content/docs/d1/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare D1 order: 0 type: overview pcx_content_type: overview @@ -7,8 +7,7 @@ sidebar: order: 1 head: - tag: title - content: Cloudflare D1 - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/d1/platform/alpha-migration.mdx b/src/content/docs/d1/platform/alpha-migration.mdx index a0bac59a560ba5..2ea032f6873093 100644 --- a/src/content/docs/d1/platform/alpha-migration.mdx +++ b/src/content/docs/d1/platform/alpha-migration.mdx @@ -18,8 +18,8 @@ This guide will instruct you to recreate alpha D1 databases on our production-re ## Prerequisites 1. You have the [`wrangler` command-line tool](/workers/wrangler/install-and-update/) installed -2. You are using `wrangler` version `3.33.0` or later (released March 2024) as earlier versions do not have the [`--remote` flag](/d1/platform/changelog/#2024-03-12) required as part of this guide -3. An 'alpha' D1 database. All databases created before July 27th, 2023 ([release notes](/d1/platform/changelog/#2024-03-12)) use the alpha storage backend, which is no longer supported and was not recommended for production. +2. You are using `wrangler` version `3.33.0` or later (released March 2024) as earlier versions do not have the [`--remote` flag](/d1/platform/release-notes/#2024-03-12) required as part of this guide +3. An 'alpha' D1 database. All databases created before July 27th, 2023 ([release notes](/d1/platform/release-notes/#2024-03-12)) use the alpha storage backend, which is no longer supported and was not recommended for production. ## 1. Verify that a database is alpha diff --git a/src/content/docs/d1/platform/changelog.mdx b/src/content/docs/d1/platform/release-notes.mdx similarity index 95% rename from src/content/docs/d1/platform/changelog.mdx rename to src/content/docs/d1/platform/release-notes.mdx index ed1eef1a959bbb..a5dccb0a376f27 100644 --- a/src/content/docs/d1/platform/changelog.mdx +++ b/src/content/docs/d1/platform/release-notes.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: changelog -title: Changelog +title: Release notes release_notes_file_name: - d1 sidebar: diff --git a/src/content/docs/d1/tutorials/build-a-comments-api/index.mdx b/src/content/docs/d1/tutorials/build-a-comments-api/index.mdx index 68fcadf9e04de6..70129551bee5c8 100644 --- a/src/content/docs/d1/tutorials/build-a-comments-api/index.mdx +++ b/src/content/docs/d1/tutorials/build-a-comments-api/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-10-01 difficulty: Intermediate -content_type: 🎥 Video pcx_content_type: tutorial title: Build a Comments API products: @@ -28,7 +27,7 @@ Use [C3](https://developers.cloudflare.com/learning-paths/workers/get-started/c3 product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -42,9 +41,9 @@ cd d1-example ## Video Tutorial ## 1. Install Hono @@ -82,7 +81,7 @@ export default app; ## 3. Create a database -You will now create a D1 database. In Wrangler v2, there is support for the `wrangler d1` subcommand, which allows you to create and query your D1 databases directly from the command line. Create a new database with `wrangler d1 create`: +You will now create a D1 database. In Wrangler, there is support for the `wrangler d1` subcommand, which allows you to create and query your D1 databases directly from the command line. Create a new database with `wrangler d1 create`: ```sh npx wrangler d1 create d1-example diff --git a/src/content/docs/d1/tutorials/build-a-staff-directory-app/index.mdx b/src/content/docs/d1/tutorials/build-a-staff-directory-app/index.mdx index 44a6aa5b53910a..b6d7e774007bcf 100644 --- a/src/content/docs/d1/tutorials/build-a-staff-directory-app/index.mdx +++ b/src/content/docs/d1/tutorials/build-a-staff-directory-app/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-03-21 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a Staff Directory Application products: diff --git a/src/content/docs/d1/tutorials/build-an-api-to-access-d1/index.mdx b/src/content/docs/d1/tutorials/build-an-api-to-access-d1/index.mdx index d69f1becdea36b..16ceedc186015b 100644 --- a/src/content/docs/d1/tutorials/build-an-api-to-access-d1/index.mdx +++ b/src/content/docs/d1/tutorials/build-an-api-to-access-d1/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-09-20 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build an API to access D1 using a proxy Worker products: @@ -56,7 +55,7 @@ Create a new Worker to create and deploy your API. product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/data-localization/compatibility.mdx b/src/content/docs/data-localization/compatibility.mdx index 274c405609cb9a..e272e7dba8b9df 100644 --- a/src/content/docs/data-localization/compatibility.mdx +++ b/src/content/docs/data-localization/compatibility.mdx @@ -32,6 +32,7 @@ The table below provides a summary of the Data Localization Suite product's beha | Tiered Caching | ✅ | 🚧 [^2] | 🚧 [^30] | | Trace | ✘ | ✘ | ✘ | | Waiting Room | ⚫️ | ✅ | ✅ | +| Web Analytics / Real User Monitoring (RUM) | ⚫️ | ⚫️ | ✘ [^43] | | Zaraz | ✅ | ✅ | ✅ | *** @@ -126,10 +127,10 @@ The table below provides a summary of the Data Localization Suite product's beha [^12]: Logpull not available when using Customer Metadata Boundary outside US region. Logs may be stored and retrieved with [Logs Engine](https://blog.cloudflare.com/announcing-logs-engine/) which is adding region support in 2025. [^13]: Logpush available with Customer Metadata Boundary for [these datasets](/data-localization/metadata-boundary/logpush-datasets/). Contact your account team if you need another dataset. [^14]: Access App SSL keys can use Geo Key Manager. [Access JWT](/cloudflare-one/identity/authorization-cookie/validating-json/) is not yet localized. -[^15]: Can be localized to US FedRAMP region only. More regions coming in 2024. +[^15]: Can be localized to US FedRAMP Moderate Domestic region only. [^16]: Customer Metadata Boundary can be used to limit data transfer outside region, but Access User Logs will not be available outside US region. [^17]: Currently may only be used with US FedRAMP region. -[^18]: The only connectivity option is [US FedRAMP region](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#region). Regional Services only applies when using [Public Hostnames](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) set to a region. +[^18]: The only connectivity option is [US FedRAMP Moderate Domestic region](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region). Regional Services only applies when using [Public Hostnames](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) set to a region. [^19]: Uses Gateway HTTP and CASB. [^20]: You can [bring your own certificate](https://blog.cloudflare.com/bring-your-certificates-cloudflare-gateway/) to Gateway but these cannot yet be restricted to a specific region. [^21]: Gateway HTTP supports Regional Services. Gateway DNS does not yet support regionalization.
    ICMP proxy and WARP-to-WARP proxy are not available to Regional Services users. @@ -151,3 +152,4 @@ The table below provides a summary of the Data Localization Suite product's beha [^40]: Jurisdictional Restrictions ([data location](/d1/configuration/data-location/) / storage) options are not supported today. [^41]: Logs / Analytics not available outside US region when using Customer Metadata Boundary. Use Logpush instead. [^42]: Only applies to HTTP/S Spectrum applications. +[^43]: Web Analytics collects the [minimum amount of information](/web-analytics/data-metrics/data-origin-and-collection/). Alternatively, you can [exclude EU Visitors from RUM](/speed/speed-test/rum-beacon/#rum-excluding-eeaeu). diff --git a/src/content/docs/data-localization/how-to/workers.mdx b/src/content/docs/data-localization/how-to/workers.mdx index 01db2776ea7930..b35388eabac07f 100644 --- a/src/content/docs/data-localization/how-to/workers.mdx +++ b/src/content/docs/data-localization/how-to/workers.mdx @@ -28,7 +28,7 @@ Regional Services does not apply to other Worker triggers, like [Queues](/queues ## Customer Metadata Boundary -Customer Metadata Boundary applies to the custom domain configured, as well as the [`*.workers.dev`](/workers/configuration/routing/routes/#routes-with-workersdev) subdomain. +Customer Metadata Boundary applies to the custom domain configured, as well as the [`*.workers.dev`](/workers/configuration/routing/workers-dev/) subdomain. Workers [Metrics and Analytics](/workers/observability/metrics-and-analytics/) are not available outside the US region when using Customer Metadata Boundary. diff --git a/src/content/docs/data-localization/how-to/zero-trust.mdx b/src/content/docs/data-localization/how-to/zero-trust.mdx index 270415f55f029a..952e1cfaa0c7d3 100644 --- a/src/content/docs/data-localization/how-to/zero-trust.mdx +++ b/src/content/docs/data-localization/how-to/zero-trust.mdx @@ -27,7 +27,7 @@ As part of Regional Services, Cloudflare Gateway will only perform [TLS decrypti #### Data Loss Prevention (DLP) -You are able to [log the payload of matched DLP rules](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules/) and encrypt them with your public key so that only you can examine them later. +You are able to [log the payload of matched DLP rules](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#log-the-payload-of-matched-rules) and encrypt them with your public key so that only you can examine them later. [Cloudflare cannot decrypt encrypted payloads](/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#data-privacy). @@ -60,7 +60,7 @@ To ensure that all reverse proxy requests for applications protected by Cloudfla ## Cloudflare Tunnel -You can [configure Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/#region) to only connect to data centers within the United States, regardless of where the software was deployed. +You can [configure Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/run-parameters/#region) to only connect to data centers within the United States, regardless of where the software was deployed. ## WARP settings diff --git a/src/content/docs/data-localization/metadata-boundary/faq.mdx b/src/content/docs/data-localization/metadata-boundary/faq.mdx index fe3508b7b535ec..9c0fc874b4283e 100644 --- a/src/content/docs/data-localization/metadata-boundary/faq.mdx +++ b/src/content/docs/data-localization/metadata-boundary/faq.mdx @@ -4,6 +4,7 @@ title: FAQs structured_data: true sidebar: order: 3 +description: Commonly asked questions about Cloudflare's Customer Metadata Boundary. --- ## What data is covered by the Customer Metadata Boundary? diff --git a/src/content/docs/data-localization/metadata-boundary/logpush-datasets.mdx b/src/content/docs/data-localization/metadata-boundary/logpush-datasets.mdx index 7b045518e29581..d06fe3eb57e755 100644 --- a/src/content/docs/data-localization/metadata-boundary/logpush-datasets.mdx +++ b/src/content/docs/data-localization/metadata-boundary/logpush-datasets.mdx @@ -12,22 +12,29 @@ Be aware that if you enable CMB for a dataset that does not support your region, | Dataset name | Level | Respects CMB | Available with US CMB region | Available with EU CMB region | | ---------------------- | ------- | ------------ | ---------------------------- | ---------------------------- | -| HTTP requests | Zone | ✅ | ✅ | ✅ | -| Firewall events | Zone | ✅ | ✅ | ✅ | -| DNS logs | Zone | ✅ | ✅ | ✅ | -| NEL reports | Zone | ✘ | ✅ | ✘ | -| Spectrum events | Zone | ✅ | ✅ | ✅ | -| Page Shield | Zone | ✅ | ✅ | ✅ | -| Access Requests | Account | ✅ | ✅ | ✘ | -| Audit Logs | Account | ✘ | ✅ | ✘ | -| CASB Findings | Account | ✘ | ✅ | ✘ | +| HTTP requests | Zone | ✅ | ✅ | ✅ | +| Firewall events | Zone | ✅ | ✅ | ✅ | +| DNS logs | Zone | ✅ | ✅ | ✅ | +| DNS Firewall logs | Account | ✅ | ✅ | ✅ | +| Spectrum events | Zone | ✅ | ✅ | ✅ | +| Magic IDS Detections | Account | ✅ | ✅ | ✅ | +| Workers Trace Events | Account | ✅ | ✅ | ✅ | +| Zero Trust Sessions | Account | ✅ | ✅ | ✅ | +| Gateway DNS | Account | ✅ | ✅ | ✅ | +| Gateway Network | Account | ✅ | ✅ | ✅ | +| Gateway HTTP | Account | ✅ | ✅ | ✅ | +| Page Shield | Zone | ✅ | ✅ | ✅ | +| Sinkhole Events | Account | ✅ | ✅ | ✅ | +| AI Gateway Events | Account | ✅ | ✅ | ✅ | +| DLP Forensic Copies | Account | N/A[^1] | ✘ | ✘ | +| Email Security Alerts | Account | ✅ | ✅ | ✅ | +| Zaraz Events | Zone | ✅ | ✅ | ✅ | +| Browser Isolation User Actions | Account | ✅ | ✅ | ✅ | +| NEL reports | Zone | ✘ | ✅ | ✘ | +| CASB Findings | Account | ✘ | ✅ | ✘ | +| Network Analytics Logs | Account | ✅ | ✅ | ✅ | | Device Posture Results | Account | ✘ | ✅ | ✘ | -| DNS Firewall logs | Account | ✅ | ✅ | ✅ | -| Gateway DNS | Account | ✅ | ✅ | ✅ | -| Gateway HTTP | Account | ✅ | ✅ | ✅ | -| Gateway Network | Account | ✅ | ✅ | ✅ | -| Magic IDS Detections | Account | ✅ | ✅ | ✅ | -| Network Analytics Logs | Account | ✅ | ✅ | ✅ | -| Workers Trace Events | Account | ✅ | ✅ | ✅ | -| Zero Trust Sessions | Account | ✅ | ✅ | ✅ | -| Sinkhole Events | Account | ✅ | ✅ | ✅ | +| Audit Logs | Account | ✘ | ✅ | ✘ | +| Access Requests | Account | ✅ | ✅ | ✘ | + +[^1]: Customer Metadata Boundary does not apply in this case, as these logs are sent directly from the processing location to your configured destination. \ No newline at end of file diff --git a/src/content/docs/ddos-protection/frequently-asked-questions.mdx b/src/content/docs/ddos-protection/frequently-asked-questions.mdx new file mode 100644 index 00000000000000..990e4de0c430e5 --- /dev/null +++ b/src/content/docs/ddos-protection/frequently-asked-questions.mdx @@ -0,0 +1,111 @@ +--- +title: FAQ +pcx_content_type: FAQ +sidebar: + order: 18 + label: FAQ +head: + - tag: title + content: Frequently asked questions for DDoS Protection + +--- + +## What is a DDoS attack event? + +When Cloudflare's DDoS systems detect and mitigate attacks, they drop, rate-limit, or challenge (as applicable) packets, DNS queries, or HTTP requests, based on the type of attack. + +There are three main DDoS mitigation systems: + +1. [DDoS Managed Ruleset](/ddos-protection/managed-rulesets/) + + a. [Network-layer DDoS Managed Ruleset](/ddos-protection/managed-rulesets/network/) + + b. [HTTP DDoS Managed Ruleset](/ddos-protection/managed-rulesets/http/) + +3. [Advanced TCP Protection](/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/) +4. [Advanced DNS Protection](/ddos-protection/advanced-ddos-systems/overview/advanced-dns-protection/) + +The DDoS Managed Ruleset includes many individual rules. Each rule provides the heuristics that instructs the system how to identify attack traffic. When the DDoS Managed Ruleset identifies an attack, it will generate a real-time fingerprint to match against the attack traffic, and install an ephemeral mitigation rule to mitigate the attack. + +The start time of the attack is when the mitigation rule is installed. The attack ends when there is no more traffic matching the rule. This is a single DDoS attack. + +A DDoS attack therefore has a start time, end time, and additional attack metadata such as: + +1. Attack ID +2. Attack vector +3. Mitigating rule +4. Total bytes +5. Total packets +6. Attack target + +This information is used to populate the [Executive Summary](/analytics/network-analytics/understand/main-dashboard/#executive-summary) section in the [Network Analytics](/analytics/network-analytics/) dashboard. + +It can also be retrieved via GraphQL API using the `dosdAttackAnalyticsGroups` node. + +Currently, the concept of a DDoS attack only exists for the Network-layer DDoS Managed Ruleset. There is no such grouping of individual packets, queries, or HTTP requests for the other systems, although we plan to implement it. + +--- + +## How does Cloudflare protect against "low and slow" DDoS attacks? + +A [low and slow DDoS attack](https://www.cloudflare.com/learning/ddos/ddos-low-and-slow-attack/) is most commonly a non-volumetric attack. The attacker will send a low volume of HTTP requests, and do so slowly. This type of attack aims to be less detectable and slowly exhausts resources. + +[Slowloris](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris/) is a type of low and slow attack where the attacker establishes [TCP connections](/fundamentals/reference/tcp-connections/) to the target server, often using HTTP or HTTPS protocols. + +In the case of a Slowloris attack, the attacker sends incomplete HTTP header lines, thus never completing the HTTP request. The server waits for the complete request, holding the connection open. The attacker periodically sends additional HTTP header fields or partial lines to keep the connection alive. This can be achieved by sending partial HTTP headers, or using the `content-length` header to declare a message body size larger than what is actually sent. + +The best practice to defend against low and slow attacks is by using an HTTP reverse proxy, such as Cloudflare's [CDN](/fundamentals/concepts/how-cloudflare-works/) or [WAF](/waf/) service. The reverse proxy acts as a shield. It waits for a full HTTP request before forwarding it to the origin, serving from cache, or applying other actions based on user configuration. If you are using our CDN/WAF services, our L7 reverse proxy will absorb low and slow attacks. It will buffer uploads at the edge by default. The proxy will wait for the full HTTP request before passing it on. The client requests must be completed. + +The request will be served from Cloudflare's [Cache](/cache/) or [Workers](/workers/), if applicable. If not, it will only be sent to the origin — assuming it was fully completed and has passed WAF checks. So the attack does not exist, similar to TCP Slowloris attacks protection. + +Additionally, the reverse proxy will timeout incomplete HTTP requests after a series of [keepalive probes](/fundamentals/reference/tcp-connections/#tcp-connections-and-keepalives). + +There is not a minimum threshold for activation. However, to provide additional security, custom firewall rules check for payload sizes and conducts basic sanity checks to ensure the content looks like what is expected. + +The RUDY (R-U-Dead-Yet?) DDoS attack is another type of denial-of-service (DoS) tool that performs slow-rate attacks on targeted servers. + +Unlike conventional DDoS attacks that overwhelm servers with a high volume of requests in a short period, RUDY focuses on creating a few prolonged requests. It does this by submitting form data at an extremely slow pace to keep the web server tied up and unavailable to legitimate traffic. This approach makes RUDY attacks difficult to detect, because the traffic can appear legitimate and does not flood the server with requests that would typically trigger conventional DDoS protection mechanisms​​​​​​. + +RUDY specifically targets the application layer (Layer 7) of web servers by exploiting the way web forms handle data submission. The attack works by injecting one byte of information into an application `POST` field at a time, then waiting. This process causes application threads to await the completion of the form submission indefinitely, effectively exhausting the server's resources and preventing it from processing legitimate requests​​​​. + +Refer to the [learning center](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/r-u-dead-yet-rudy/) for more information on RUDY attacks. + +--- + +## How does Cloudflare deal with SSL/TLS negotiation attacks or floods? + +SSL/TLS based attacks such as BEAST, Poodle, and CRIME are mitigated by Cloudflare's TLS settings, configuration, and cipher limitations. Because Cloudflare serves as the HTTP reverse proxy, TLS exhaustion style attacks are mitigated by terminating TLS sessions before passing HTTP requests to origin servers. TLS traffic is not proxied to origin servers without completing a proper TLS handshake. Additionally, our automated DDoS detection and mitigation systems leverage cipher suites, packet fields, HTTP request attributes and metadata, origin health, traffic profiling, Machine Learning models, and threat intelligence to detect and mitigate additional SSL-based attacks. + +--- + +## Does Cloudflare use BGP Flowspec for upstream mitigation? + +Yes. Using our anycast network, along with Traffic Manager, Unimog, and Plurimog, we conduct automated traffic engineering to spread the load of traffic (legitimate and attack) to ensure our network is performant, especially during mitigation of large attacks. + +--- + +## Where can I see DDoS trends? + +Refer to [Reports](/ddos-protection/reference/reports/) or [Radar](/radar/) for more information on viewing DDoS trends. + +--- + +## What is the Ping of Death DDoS attacks? + +The Ping of Death (PoD) attack involves sending malformed or oversized packets to another computer or server, which can cause the system to freeze, crash, or reboot. Packets are pieces of data sent over the Internet, and the Ping of Death takes advantage of the fact that the IP protocol requires packets to be a maximum of 65,535 bytes in size. By sending a packet larger than this size, the attacker can exploit vulnerabilities in the target's TCP/IP stack, causing a buffer overflow and leading to unpredictable behavior, including system crashes. This type of attack is less common nowadays, as most modern systems and networking equipment have been patched to handle such anomalies. + +--- + +## What are LOIC and HOIC? + +LOIC is a popular network stress testing and DoS attack application that is used to flood a server with TCP, UDP, or HTTP requests with the intention of disrupting the service. It is known for its simplicity and ability to be used by individuals with minimal hacking experience. LOIC can be directed by the user to attack a small server, which can cause the server to slow down or crash from the overload of requests. It became famous around 2010 for its use by the hacker group Anonymous in attacks against major companies and organizations. + +HOIC is an upgrade from LOIC, designed to overcome some of its limitations, especially in terms of detection and mitigation. It allows users to launch a more powerful DoS attack by enabling attacks on multiple websites at the same time with a higher volume of requests. HOIC also incorporates a feature that makes it more difficult for defense mechanisms to identify and mitigate the attack traffic, partly because it uses a technique that allows the traffic to mimic legitimate HTTP traffic, which is more challenging for traditional network security tools to detect. HOIC supports the use of "booster" scripts that enable it to target various websites simultaneously, significantly increasing its potency as a tool for conducting broad-scale DoS attacks. + +These tools and attacks exploit different aspects of network protocols and behaviors to overwhelm targets with unwanted traffic, leading to denial of service. Due to their potential for abuse, their use is illegal and unethical outside of controlled environments for testing purposes. + +--- + +## Can I exclude a user agent from DDoS protection? + +You can override a user agent using a low sensitivity level or `Log` if you want visibility. diff --git a/src/content/docs/ddos-protection/index.mdx b/src/content/docs/ddos-protection/index.mdx index 72dcd27bc1448d..7ae6d315706dd9 100644 --- a/src/content/docs/ddos-protection/index.mdx +++ b/src/content/docs/ddos-protection/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare DDoS Protection pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare DDoS Protection - + content: Overview --- import { Description, Feature, FeatureTable, GlossaryTooltip, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/ddos-protection/managed-rulesets/adaptive-protection.mdx b/src/content/docs/ddos-protection/managed-rulesets/adaptive-protection.mdx index 085cfe25745e69..b96b084831007b 100644 --- a/src/content/docs/ddos-protection/managed-rulesets/adaptive-protection.mdx +++ b/src/content/docs/ddos-protection/managed-rulesets/adaptive-protection.mdx @@ -20,8 +20,6 @@ Adaptive DDoS Protection provides the following types of protection: Cloudflare Adaptive DDoS Protection is available to Enterprise customers according to the following table: - - | Feature | Profiling dimension | WAF/CDN1 | Magic Transit /
    Spectrum BYOIP2 | | --------------------------------- | ------------------------------------------ | :-----------------: | :--------------------------------------------: | | **HTTP Adaptive DDoS Protection** | | | | @@ -32,8 +30,6 @@ Cloudflare Adaptive DDoS Protection is available to Enterprise customers accordi | For Protocols | IP protocol | — | Yes | | For Protocols | Client IP country and Region for UDP | — | Yes | - - 1 _WAF/CDN customers on the Enterprise plan with the Advanced DDoS Protection subscription._
    2 _Magic Transit and Spectrum BYOIP customers on an Enterprise plan._ @@ -70,10 +66,24 @@ To view traffic flagged by L3/4 Adaptive DDoS Protection rules: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. 2. Go to Account Home > **Analytics & Logs** > **Network Analytics**. -3. Filter by `Ruleset ID equals 3b64149bfa6e4220bbbc2bd6db589552` (the ID of the Network-layer DDoS Attack Protection managed ruleset) and by rule ID. +3. Filter by rule ID. You may also obtain information about flagged traffic through [Logpush](/logs/about/) or the [GraphQL API](/analytics/graphql-api/). +To determine if an adaptive rule fits your traffic in a way that will only mitigate attack traffic and will not cause false positives, review the traffic that is _Logged_ by the adaptive rules. + +:::note +You may not see any traffic matching the adaptive rules. This can be because there was no deviation from your traffic profile, so you may want to increase the time range and look for any _Logged_ traffic. Another reason why you may not see _Logged_ traffic by the adaptive rules is that there was not sufficient traffic volume to generate a traffic profile for your zone. +::: + +If you do see traffic that was _Logged_ by the adaptive rules, use the dashboard to determine if the traffic matches the characteristics of legitimate users or that of attack traffic. As each Internet property is unique, understanding if the traffic is legitimate requires your understanding of how your legitimate traffic looks. For example, the user agent, source country, headers, query string for HTTP requests, and protocols and ports for L3/4 traffic. + +- In cases where you are certain that the rule is only flagging attack traffic, you should consider creating an override and enabling that rule with a [Managed Challenge](/waf/reference/cloudflare-challenges/#managed-challenge-recommended) or `Block` action. +- In cases where you see legitimate traffic being flagged, you should lower the sensitivity level of the rule and observe the flagged traffic. You can continue reducing the sensitivity level until you reach a point where legitimate traffic is not flagged. Then, you should create an override to enable the rule with a mitigation action. +- If the rule is still flagging legitimate traffic you can consider using the expression filters to condition the rules to exclude certain types of traffic. + +The default rule action for `log` with a sensitivity set to `high` will only show packets or requests with suspected attack traffic over internal `high` thresholds in your logs. For instance, if you set the threshold to `medium` or `low`, then only packets over those thresholds will be logged. + ## Configure the rules You can adjust the action and sensitivity of the Adaptive DDoS Protection rules. The default action is _Log_. Use this action to first observe what traffic is flagged before deciding on a mitigation action. diff --git a/src/content/docs/developer-spotlight/tutorials/create-sitemap-from-sanity-cms.mdx b/src/content/docs/developer-spotlight/tutorials/create-sitemap-from-sanity-cms.mdx index 64a764de067251..583d06bfefdbea 100644 --- a/src/content/docs/developer-spotlight/tutorials/create-sitemap-from-sanity-cms.mdx +++ b/src/content/docs/developer-spotlight/tutorials/create-sitemap-from-sanity-cms.mdx @@ -2,7 +2,6 @@ updated: 2024-04-21 pcx_content_type: tutorial difficulty: Beginner -content_type: 📝 Tutorial title: Create a sitemap from Sanity CMS with Workers products: - Workers diff --git a/src/content/docs/developer-spotlight/tutorials/creating-a-recommendation-api.mdx b/src/content/docs/developer-spotlight/tutorials/creating-a-recommendation-api.mdx index 2571d6548dd11e..44de05a4c704bd 100644 --- a/src/content/docs/developer-spotlight/tutorials/creating-a-recommendation-api.mdx +++ b/src/content/docs/developer-spotlight/tutorials/creating-a-recommendation-api.mdx @@ -1,7 +1,6 @@ --- updated: 2024-06-24 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Recommend products on e-commerce sites using Workers AI and Stripe products: diff --git a/src/content/docs/developer-spotlight/tutorials/custom-access-control-for-files.mdx b/src/content/docs/developer-spotlight/tutorials/custom-access-control-for-files.mdx index 06ff14a9b92c01..354c92b7e77cdc 100644 --- a/src/content/docs/developer-spotlight/tutorials/custom-access-control-for-files.mdx +++ b/src/content/docs/developer-spotlight/tutorials/custom-access-control-for-files.mdx @@ -1,7 +1,6 @@ --- updated: 2024-06-17 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Custom access control for files in R2 using D1 and Workers products: @@ -42,7 +41,7 @@ To get started developing your Worker you will use the [`create-cloudflare` CLI] product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -96,8 +95,6 @@ npx wrangler r2 bucket create This works similar to the D1 database creation, where you will need to replace `` with the name you want to use for your bucket. To do this, go to the Wrangler file again and then add the following lines: - - ```toml diff --git a/src/content/docs/developer-spotlight/tutorials/fullstack-authentication-with-next-js-and-cloudflare-d1.mdx b/src/content/docs/developer-spotlight/tutorials/fullstack-authentication-with-next-js-and-cloudflare-d1.mdx index 65196de17a89b3..d0c2fd60356261 100644 --- a/src/content/docs/developer-spotlight/tutorials/fullstack-authentication-with-next-js-and-cloudflare-d1.mdx +++ b/src/content/docs/developer-spotlight/tutorials/fullstack-authentication-with-next-js-and-cloudflare-d1.mdx @@ -1,7 +1,6 @@ --- updated: 2025-01-13 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Setup Fullstack Authentication with Next.js, Auth.js, and Cloudflare D1 products: diff --git a/src/content/docs/developer-spotlight/tutorials/handle-form-submission-with-astro-resend.mdx b/src/content/docs/developer-spotlight/tutorials/handle-form-submission-with-astro-resend.mdx index 4a0d200274839b..cbc82b20a4dde8 100644 --- a/src/content/docs/developer-spotlight/tutorials/handle-form-submission-with-astro-resend.mdx +++ b/src/content/docs/developer-spotlight/tutorials/handle-form-submission-with-astro-resend.mdx @@ -1,14 +1,12 @@ --- updated: 2024-06-17 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Send form submissions using Astro and Resend products: - Workers tags: - Forms - - Resend - Astro languages: - TypeScript diff --git a/src/content/docs/dmarc-management/index.mdx b/src/content/docs/dmarc-management/index.mdx index a73fcc400f7209..7c06dd4de39930 100644 --- a/src/content/docs/dmarc-management/index.mdx +++ b/src/content/docs/dmarc-management/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare DMARC Management pcx_content_type: overview sidebar: order: 1 @@ -7,9 +7,8 @@ sidebar: text: Beta head: - tag: title - content: Cloudflare DMARC Management + content: Overview description: Stop brand impersonation. - --- import { Description, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/dns/cname-flattening/index.mdx b/src/content/docs/dns/cname-flattening/index.mdx index dcdd96e576dce4..024337b483121f 100644 --- a/src/content/docs/dns/cname-flattening/index.mdx +++ b/src/content/docs/dns/cname-flattening/index.mdx @@ -6,16 +6,12 @@ sidebar: label: About --- -import { Render } from "~/components" +import { Render, GlossaryTooltip } from "~/components" -CNAME flattening speeds up CNAME resolution and allows you to use a CNAME record at your root/apex domain (`example.com`). +CNAME flattening speeds up CNAME resolution and allows you to use a CNAME record at your zone apex (`example.com`). :::note - - This functionality is also what allows you to use a [root custom domain](/pages/configuration/custom-domains/) with a Cloudflare Pages site. - - ::: ## How it works diff --git a/src/content/docs/dns/concepts.mdx b/src/content/docs/dns/concepts.mdx index c46363a575e513..cf629bd138f8bb 100644 --- a/src/content/docs/dns/concepts.mdx +++ b/src/content/docs/dns/concepts.mdx @@ -7,12 +7,12 @@ head: - tag: title content: DNS concepts +description: Understand key DNS concepts with Cloudflare's technical documentation. Learn about nameservers, DNS records, DNSSEC, and more. --- import { Details, Example, GlossaryTooltip } from "~/components"; This page defines and articulates key concepts that are relevant to the Cloudflare DNS service and are used in this documentation. For more concepts and broader descriptions, refer to the [Cloudflare Learning Center](https://www.cloudflare.com/learning/dns/what-is-dns/). - ## Domain Also known as domain name, a domain is the string of text that identifies a specific website, such as `google.com` or `facebook.com`. Every time you access a website from your web browser, a DNS query takes place and the DNS service maps the domain to the actual IP address where the website is [hosted](/fundamentals/setup/manage-domains/). @@ -45,7 +45,7 @@ In this context, you can have a primary DNS setup, when you use Cloudflare to ma When you have a primary DNS setup, you can either use only Cloudflare (also known as [Full setup](/dns/zone-setups/full-setup/)), or you can use Cloudflare and another provider, where the other provider is the one to receive [outgoing zone transfers](/dns/zone-setups/zone-transfers/cloudflare-as-primary/) from Cloudflare. -Finally, as Cloudflare also works as a [reverse proxy](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-reverse-proxy), [partial (CNAME) setups](/dns/zone-setups/partial-setup/) can be used when you do not want Cloudflare to be [authoritative](#authoritative-dns) for your domain but you still want to proxy individual subdomains through Cloudflare. +Finally, as Cloudflare also works as a [reverse proxy](/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy), [partial (CNAME) setups](/dns/zone-setups/partial-setup/) can be used when you do not want Cloudflare to be [authoritative](#authoritative-dns) for your domain but you still want to proxy individual subdomains through Cloudflare. ## DNS records diff --git a/src/content/docs/dns/dns-firewall/faq.mdx b/src/content/docs/dns/dns-firewall/faq.mdx index 402610a3d26660..f408cf77c05778 100644 --- a/src/content/docs/dns/dns-firewall/faq.mdx +++ b/src/content/docs/dns/dns-firewall/faq.mdx @@ -1,6 +1,7 @@ --- title: FAQ pcx_content_type: faq +description: Find answers to common questions about Cloudflare's DNS Firewall, including cache behavior, EDNS support, and setting PTR records. sidebar: order: 4 head: diff --git a/src/content/docs/dns/dns-firewall/random-prefix-attacks/about.mdx b/src/content/docs/dns/dns-firewall/random-prefix-attacks/about.mdx index f78a74376771b6..e58f43aaa79594 100644 --- a/src/content/docs/dns/dns-firewall/random-prefix-attacks/about.mdx +++ b/src/content/docs/dns/dns-firewall/random-prefix-attacks/about.mdx @@ -7,6 +7,7 @@ head: - tag: title content: About random prefix attacks - DNS Firewall +description: Learn about random prefix attacks. As part of DNS Firewall, Cloudflare can protect your upstream authoritative nameservers from these attacks. --- import { Render } from "~/components" diff --git a/src/content/docs/dns/get-started.mdx b/src/content/docs/dns/get-started.mdx index 5acb783bb2a723..9ccbca95b9f66f 100644 --- a/src/content/docs/dns/get-started.mdx +++ b/src/content/docs/dns/get-started.mdx @@ -23,7 +23,7 @@ Once the setup is completed: - You [manage DNS records](/dns/manage-dns-records/how-to/create-dns-records/) through the Cloudflare dashboard or API. This is how you control which resources are available on the apex domain (`example.com`) or specific subdomains (`blog.example.com`) of your website, as well as control other configurations. -- Cloudflare [responds to all DNS queries](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-dns-provider) for your hostnames and your DNS records are propagated across the [Cloudflare global network](https://www.cloudflare.com/network/), speeding up your domain. +- Cloudflare [responds to all DNS queries](/fundamentals/concepts/how-cloudflare-works/) for your hostnames and your DNS records are propagated across the [Cloudflare global network](https://www.cloudflare.com/network/), speeding up your domain. ## Resources diff --git a/src/content/docs/dns/internal-dns/analytics.mdx b/src/content/docs/dns/internal-dns/analytics.mdx new file mode 100644 index 00000000000000..a9860e61e5875c --- /dev/null +++ b/src/content/docs/dns/internal-dns/analytics.mdx @@ -0,0 +1,25 @@ +--- +pcx_content_type: how-to +title: Analytics and logs +sidebar: + order: 10 +--- + +Internal DNS leverages [Gateway analytics](/cloudflare-one/insights/analytics/gateway/). Below you can find information about specific fields and different methods you can use to access this data. + +## GraphQL + +For detailed metrics, use the [GraphQL API](/analytics/graphql-api/). Refer to the GraphQL Analytics API documentation for guidance on how to [get started](/analytics/graphql-api/getting-started/). + +The [fields](/analytics/graphql-api/getting-started/querying-basics/) added to cover Internal DNS are the following: + +- `InternalDNSFallbackStrategy`: The fallback strategy applied to the internal DNS response. Empty if no fallback strategy was applied. +- `InternalDNSRCode`: The response code sent back by the internal DNS service. +- `InternalDNSViewID`: The view identifier that was sent to the internal DNS service. +- `InternalDNSZoneID`: The internal zone identifier returned by the internal DNS service. + +## Logs + +Leverage Logpush jobs for [Gateway DNS](/logs/reference/log-fields/account/gateway_dns/#internaldnsfallbackstrategy). For help setting up Logpush, refer to [Get started with Logs](/logs/get-started/). + +You can also set up [Logpush filters](/logs/reference/filters/) to only push logs related to a specific [internal zone](/dns/internal-dns/internal-zones/) or [view](/dns/internal-dns/dns-views/) ID. \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/connectivity.mdx b/src/content/docs/dns/internal-dns/connectivity.mdx new file mode 100644 index 00000000000000..3e62a4515cf8b7 --- /dev/null +++ b/src/content/docs/dns/internal-dns/connectivity.mdx @@ -0,0 +1,18 @@ +--- +title: Connect to Gateway resolver +pcx_content_type: reference +sidebar: + order: 8 + label: Connectivity +--- + +To connect to Cloudflare Gateway resolver - which is [required to reach private resources in Internal DNS](/dns/internal-dns/#architecture-overview) - you can use the following options: + +- DNS endpoints supported with [DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/) + - DNS over UDP/TCP port 53 (IPv4 or IPv6) + - DNS over TLS + - DNS over HTTPS +- [Proxy Auto-Configuration (PAC) files](/cloudflare-one/connections/connect-devices/agentless/pac-files/) +- [WARP device client](/cloudflare-one/connections/connect-devices/warp/) +- [Clientless browser isolation](/cloudflare-one/policies/browser-isolation/setup/clientless-browser-isolation/#filter-dns-queries) +- [Magic WAN](/magic-wan/zero-trust/cloudflare-gateway/) \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/dns-views.mdx b/src/content/docs/dns/internal-dns/dns-views.mdx new file mode 100644 index 00000000000000..669192d0720898 --- /dev/null +++ b/src/content/docs/dns/internal-dns/dns-views.mdx @@ -0,0 +1,37 @@ +--- +pcx_content_type: how-to +title: Manage DNS views +sidebar: + order: 3 + label: Views +--- + +import { Details, Render } from "~/components"; + +Internal DNS views are logical groupings of [internal DNS zones](/dns/internal-dns/internal-zones/). As explained in the [architecture overview](/dns/internal-dns/#architecture-overview), DNS views are referenced by [Gateway resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) to define how a specific query should be resolved. + +Refer to the sections below for details on how to manage your DNS views, or consider the [get started](/dns/internal-dns/#architecture-overview) for a complete workflow. + +## Configuration conditions + +When setting up DNS views, observe the following conditions: + + + +## Create a view + +Use the [Create Internal DNS View](/api/resources/dns/subresources/settings/subresources/views/methods/create/) endpoint. For each view you create, list all the internal zones that should be grouped under that view. + +## Delete a view + +Use the [Delete Internal DNS View](/api/resources/dns/subresources/settings/subresources/views/methods/delete/) endpoint. + +DNS views can be deleted even if they still have internal zones linked to them. The internal DNS zones will continue to exist but will be unlinked once the view is deleted. + +It is also possible to delete a DNS view that is being referenced by a Gateway resolver policy. In this case, queries matching the policy will return SERVFAIL. + +## Other actions + +- [Update a DNS view](/api/resources/dns/subresources/settings/subresources/views/methods/edit/) (`PATCH`) +- [Get view details](/api/resources/dns/subresources/settings/subresources/views/methods/get/) (`GET`) +- [List DNS views](/api/resources/dns/subresources/settings/subresources/views/methods/list/) (`GET`) \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/get-started.mdx b/src/content/docs/dns/internal-dns/get-started.mdx new file mode 100644 index 00000000000000..9113e9ab1e86f4 --- /dev/null +++ b/src/content/docs/dns/internal-dns/get-started.mdx @@ -0,0 +1,94 @@ +--- +title: Get started +pcx_content_type: get-started +sidebar: + order: 2 +--- + +import { TabItem, Tabs, Details, Example, Render } from "~/components"; + +Follow this guide to get started with Internal DNS. + +Although there are some steps that can be achieved on the dashboard, currently the whole process can only be completed via API. + +## Before you begin + + + +- Make sure you have an Enterprise account with access to [Gateway resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) and [Internal DNS](/dns/internal-dns/). +- Consider the different ways in which you can [connect to Gateway resolver](/dns/internal-dns/connectivity/). +- If you are not familiar with how to use Cloudflare API, refer to [Fundamentals](/fundamentals/api/get-started/). +- If you will be using an API token for authentication, make sure you have the following permissions: + +
    + +**Permissions** +- *Account* - *DNS Views* - *Edit* +- *Zone* - *DNS* - *Edit* +- *Account* - *Account Settings* - *Edit* +- *Zone* - *DNS Settings* - *Edit* +- *Zone* - *Zone* - *Edit* + +**Account Resources** +- *Include* - *(Your account)* + +**Zone Resources** +- *Include* - *All zones* + + + + + +## 1. Set up your internal DNS zone + + + +### (Optional) Reference a zone from another zone + +1. Use the [Update DNS settings](/api/resources/dns/subresources/settings/methods/edit/) endpoint to add a reference from an internal zone to another internal zone. In `--data`, specify the `internal_dns` object with the parameter `reference_zone_id`. For details, refer to [reference zones](/dns/internal-dns/internal-zones/#reference-zones). + + + + + +## 2. Link your internal zone to a view + +Since the resolver policy will require a [DNS view](/dns/internal-dns/dns-views/), you must have at least one view to be able to route requests to internal zones. + +1. Use the [Create Internal DNS View](/api/resources/dns/subresources/settings/subresources/views/methods/create/) endpoint. For each view you create, list all the internal zones that should be grouped under that view. + +
    + +
    + +## 3. Configure Gateway policies + +:::note +The Gateway configuration must exist within the same Cloudflare account where the internal zone exists. +::: + +Besides selecting an internal DNS view when setting up your resolver policies, you can also enable the **fallback through public DNS** option. + + + +1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Gateway** > **Resolver policies**. +2. Select **Add a policy** and enter a name and description. +3. Create an expression for the traffic you wish to route. For guidance about selectors, operators, and values, refer to [Gateway](/cloudflare-one/policies/gateway/resolver-policies/#selectors). +4. Select **Use DNS view**. In the dropdown, choose the view that queries matching the expression should be sent to. +5. (Optional) Adjust the option to **fallback through public DNS** according to your use case. +- Off: Gateway DNS resolver returns the response as-is to the client. +- On: In case the response from the internal zone is REFUSED, NXDOMAIN, or a response with a CNAME type, Gateway DNS resolver sends the query to Cloudflare 1.1.1.1 public resolver and tries to resolve the query via public DNS. +6. Select **Create policy** to confirm. + + + +Use the API endpoints under [Zero Trust > Gateway > Rules](/api/resources/zero_trust/subresources/gateway/subresources/rules/) to set up resolver policies. For guidance about selectors, operators, and values, refer to [Gateway](/cloudflare-one/policies/gateway/resolver-policies/#selectors). + +Use the rule settings object to define `resolve_dns_internally`, specifying `view_id` and `fallback` option. The fallback options behave as follows: + +- `none`: Gateway DNS resolver returns the response as-is to the client. +- `public_dns`: In case the response from the internal zone is REFUSED, NXDOMAIN, or a response with a CNAME type, Gateway DNS resolver sends the query to Cloudflare 1.1.1.1 public resolver and tries to resolve the query via public DNS. + + \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/index.mdx b/src/content/docs/dns/internal-dns/index.mdx new file mode 100644 index 00000000000000..14348e33e0b50d --- /dev/null +++ b/src/content/docs/dns/internal-dns/index.mdx @@ -0,0 +1,115 @@ +--- +pcx_content_type: overview +title: Internal DNS (beta) +sidebar: + order: 14 + label: Overview + group: + badge: + text: Beta + label: Internal DNS +head: + - tag: title + content: Internal DNS +--- + +import { Render, Description, Plan, RelatedProduct, DirectoryListing, GlossaryTooltip, Example } from "~/components"; + + +Simplify private network management with Cloudflare DNS for your internal resources. + + + + +Manage DNS records that should only be accessible within your private network. Internal DNS [zones](/dns/internal-dns/internal-zones/) and [views](/dns/internal-dns/dns-views/) pair up with [Gateway resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) so that you can control how a DNS query should be responded to according to the query context, such as its source IP. + + + +## Architecture overview + +You can use different [connectivity options](/dns/internal-dns/connectivity/) to on-ramp your traffic to Cloudflare. Then, Cloudflare Gateway resolver acts as an interface between the DNS client and internal DNS zones. + +Internal DNS zones do not get assigned Cloudflare nameservers and can only be queried via Cloudflare Gateway resolver. + +```mermaid +flowchart LR + accTitle: Internal DNS query overview + accDescr: Diagram comparing internal DNS query with public DNS + A[Client] + subgraph Cloudflare account + subgraph Gateway + B[Default 1.1.1.1 resolver] + X[Resolver policy selecting an internal DNS view] + end + subgraph Authoritative DNS + Y[(Public DNS)] + Z[(Internal DNS)] + end + end + + C[Public resolver] + + B --Query--> Y + X --Query + View ID--> Z + A --Query--> B + A --Query--> X + C --Query--> Y +``` + +Internal DNS zones are grouped into DNS views, which are selected by the resolver policy you define. Views are usually logical groupings relevant to your organization, such as different geographical locations. + +```mermaid +flowchart LR + accTitle: Internal DNS views and zones + accDescr: Diagram exemplifying Internal DNS views and zones relationship + subgraph Internal DNS + subgraph View 111 - London + Y[Zone 600
    example.local] + Z[Zone 601
    local] + end + subgraph View 110 - San Francisco + X[Zone 101
    example.com] + B[Zone 100
    example.local] + S[Zone 102
    com] + end + W[Zone 701
    net] + end +``` + +Internal DNS zones contain the DNS records that should be used to resolve an internal DNS query. Also, if no internal record is found within a matching internal zone, Cloudflare will check if the matching internal zone is [referencing another internal zone](/dns/internal-dns/internal-zones/#reference-zones). + + + +```mermaid +flowchart LR + accTitle: Internal DNS zones and internal records + accDescr: Diagram exemplifying Internal DNS zones and records relationship + subgraph View 111 - London + subgraph Zone 601 - local + S[@ A 192.0.2.10] + T[ghi.example A 192.0.2.15] + end + subgraph Zone 600 - example.local + X[@ A 192.0.2.1] + Y[abc A 192.0.2.6] + Z[def A 192.0.2.9] + end + end +``` +In this example, a query for `ghi.example.local` routed to view ID 111 would go to zone 600, which presents the longest matching zone name (`example.local`). Zone 600 does not contain a record for `ghi` but, if it is referencing zone 601, Cloudflare will then look for the queried record within the reference zone. + + + +## Resources + + + +## Related products + + +Set up policies to inspect DNS, Network, HTTP, and Egress traffic. + + + +Improve security and performance for your entire corporate networking, reducing cost and operation complexity. + \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/internal-zones/index.mdx b/src/content/docs/dns/internal-dns/internal-zones/index.mdx new file mode 100644 index 00000000000000..04b0f1f95bbe18 --- /dev/null +++ b/src/content/docs/dns/internal-dns/internal-zones/index.mdx @@ -0,0 +1,30 @@ +--- +pcx_content_type: concept +title: Internal zones +sidebar: + order: 2 + group: + label: Internal zones +--- + +import { Example, Render } from "~/components"; + +Internal DNS zones are groupings of internal DNS records. While [public DNS records](/dns/manage-dns-records/) contain information about resources that you want to make available to the public Internet, [internal DNS records](#internal-dns-records) allow you to manage resources that should only be available within your private network. + +Refer to [Manage internal zones](/dns/internal-dns/internal-zones/setup/) for a full list of configuration conditions and step-by-step instructions. + +Internal DNS zones do not get assigned Cloudflare nameservers and can only be queried via [Cloudflare Gateway](/cloudflare-one/policies/gateway/resolver-policies/) when linked to a [DNS view](/dns/internal-dns/dns-views/). The Gateway configuration must exist within the same Cloudflare account where the internal zone exists. + +## Reference zones + + + +Refer to [Set up reference zones](/dns/internal-dns/internal-zones/reference-zones/) for step-by-step instructions. + +## Internal DNS records + +Internal zones can contain the same [DNS record types](/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones. + +You can manage internal DNS records in the same way as you would manage public DNS records, with the difference that [proxy status](/dns/proxy-status/) does not apply to internal DNS records. + +Refer to [Manage DNS records](/dns/manage-dns-records/how-to/create-dns-records/) or to the [API documentation](/api/resources/dns/subresources/records/) for further guidance. \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/internal-zones/reference-zones.mdx b/src/content/docs/dns/internal-dns/internal-zones/reference-zones.mdx new file mode 100644 index 00000000000000..f95374c11d3c3b --- /dev/null +++ b/src/content/docs/dns/internal-dns/internal-zones/reference-zones.mdx @@ -0,0 +1,21 @@ +--- +pcx_content_type: how-to +title: Set up reference zones +sidebar: + order: 4 +--- + +import { Example, Render } from "~/components"; + + + +## Steps + +To set up a reference zone, use the [Update DNS settings](/api/resources/dns/subresources/settings/methods/edit/) endpoint. In `--data`, specify the `internal_dns` object with the parameter `reference_zone_id`. + + + + +A third zone (C) could also point to zone B as a reference, but zone A cannot add another zone as a reference while also having zone B configured as its reference zone. + + \ No newline at end of file diff --git a/src/content/docs/dns/internal-dns/internal-zones/setup.mdx b/src/content/docs/dns/internal-dns/internal-zones/setup.mdx new file mode 100644 index 00000000000000..14d35e8716f509 --- /dev/null +++ b/src/content/docs/dns/internal-dns/internal-zones/setup.mdx @@ -0,0 +1,29 @@ +--- +pcx_content_type: how-to +title: Manage internal zones +sidebar: + order: 2 +--- + +import { Example, Render } from "~/components"; + +Refer to the following sections to learn how to manage your internal DNS zones. + +## Configuration conditions + +When setting up internal zones, observe the following conditions: + + + +## Create an internal zone + + + +## Other actions + +The API endpoints to manage internal zones are the same as for managing public zones. The main difference is that the zone type must be set to `internal`. Refer to the API documentation below for details: + +- [Update an internal zone](/api/resources/zones/methods/edit/) (`PATCH`) +- [Get internal zone details](/api/resources/zones/methods/get/) (`GET`) +- [List internal zones](/api/resources/zones/methods/list/) (`GET`) +- [Delete an internal zone](/api/resources/zones/methods/delete/) (`DELETE`) \ No newline at end of file diff --git a/src/content/docs/dns/nameservers/index.mdx b/src/content/docs/dns/nameservers/index.mdx index 6d1adfb7dfb908..453de6d65dff46 100644 --- a/src/content/docs/dns/nameservers/index.mdx +++ b/src/content/docs/dns/nameservers/index.mdx @@ -16,7 +16,7 @@ In the context of Cloudflare DNS, nameservers refer to authoritative nameservers Within Cloudflare, and depending on your plan, you can choose between using Cloudflare-branded nameservers or setting up your own custom nameservers. The names for Cloudflare-branded nameservers are automatically assigned and cannot be changed. -Regardless of the type you choose, for these nameservers to be authoritative for your domain, you need to [update your domain nameservers](/dns/nameservers/update-nameservers/). Updating your nameservers is required to activate your domain on Cloudflare and use most of our [application services](/fundamentals/concepts/how-cloudflare-works/#application-services). +Regardless of the type you choose, for these nameservers to be authoritative for your domain, you need to [update your domain nameservers](/dns/nameservers/update-nameservers/). Updating your nameservers is required to activate your domain on Cloudflare and use most of our [application services](/fundamentals/concepts/how-cloudflare-works/). ### Standard nameservers diff --git a/src/content/docs/dns/nameservers/update-nameservers.mdx b/src/content/docs/dns/nameservers/update-nameservers.mdx index e9d1c3cd1c2350..b4fd43f46e823e 100644 --- a/src/content/docs/dns/nameservers/update-nameservers.mdx +++ b/src/content/docs/dns/nameservers/update-nameservers.mdx @@ -8,7 +8,7 @@ sidebar: import { Render } from "~/components" -To use Cloudflare DNS as an authoritative DNS provider - be it in a [primary (full)](/dns/zone-setups/full-setup/) or [secondary](/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) setup -, your domain nameservers must point to nameservers that you get from your Cloudflare account. Updating your nameservers is required to activate your domain on Cloudflare and use most of our [application services](/fundamentals/concepts/how-cloudflare-works/#application-services). +To use Cloudflare DNS as an authoritative DNS provider - be it in a [primary (full)](/dns/zone-setups/full-setup/) or [secondary](/dns/zone-setups/zone-transfers/cloudflare-as-secondary/) setup -, your domain nameservers must point to nameservers that you get from your Cloudflare account. Updating your nameservers is required to activate your domain on Cloudflare and use most of our [application services](/fundamentals/concepts/how-cloudflare-works/). ## Specific processes diff --git a/src/content/docs/dns/proxy-status/limitations.mdx b/src/content/docs/dns/proxy-status/limitations.mdx index 17b67848b9e687..781d2c6c09d6a2 100644 --- a/src/content/docs/dns/proxy-status/limitations.mdx +++ b/src/content/docs/dns/proxy-status/limitations.mdx @@ -28,7 +28,7 @@ To proxy HTTP/HTTPS traffic on [non-standard ports](/fundamentals/reference/netw -This means that DNS records — even those set to [proxy traffic through Cloudflare](#proxied-records) — will be [DNS-only](/dns/proxy-status/#dns-only-records) until your zone has been activated and any requests to your DNS records will return your origin server's IP address. +This means that DNS records — even those set to [proxy traffic through Cloudflare](#proxy-eligibility) — will be [DNS-only](/dns/proxy-status/#dns-only-records) until your zone has been activated and any requests to your DNS records will return your origin server's IP address. If this warning is still present after 24 hours, refer to [Troubleshooting](/dns/troubleshooting/). diff --git a/src/content/docs/dns/zone-setups/index.mdx b/src/content/docs/dns/zone-setups/index.mdx index d57f9fd1777ab7..42312c4c5185a4 100644 --- a/src/content/docs/dns/zone-setups/index.mdx +++ b/src/content/docs/dns/zone-setups/index.mdx @@ -14,12 +14,16 @@ When using Cloudflare DNS, you have a few options for your DNS zone setup: * [Subdomain setup](/dns/zone-setups/subdomain-setup/): With your apex domain (`example.com`) on a partial or full setup, independently manage the settings for a specific subdomain (`blog.example.com`) within a separate zone and, potentially, a separate account. * [Zone transfers](/dns/zone-setups/zone-transfers/): Use Cloudflare and another DNS provider together across your entire zone to increase availability and fault tolerance. DNS records will be transferred between providers using [AXFR](https://datatracker.ietf.org/doc/html/rfc5936) or [IXFR](https://datatracker.ietf.org/doc/html/rfc1995). -:::note[Note:] - - +:::note If you run your own authoritative nameservers but still want to benefit from Cloudflare's global anycast network, check out [DNS Firewall](/dns/dns-firewall/). +::: +## Zone status +For details on zone status, consider the [Reference page](/dns/zone-setups/reference/domain-status/). + +:::caution[Do not use pending zones in production] +If you have a paid plan, make sure not to use pending zones for production traffic. Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs but there are associated risks, especially if you do not use [zone holds](/fundamentals/setup/account/account-security/zone-holds/). ::: ## Common use cases and availability @@ -48,4 +52,4 @@ If you are on an Enterprise plan, you also have the option to use [zone transfer If you are on an Enterprise plan, you can use [subdomain setup](/dns/zone-setups/subdomain-setup/) to manage the Cloudflare settings for one or more subdomains separately from your domain apex. -
    +
    \ No newline at end of file diff --git a/src/content/docs/dns/zone-setups/partial-setup/dns-resolution.mdx b/src/content/docs/dns/zone-setups/partial-setup/dns-resolution.mdx index 9a8bf3240f1306..603418a082a61b 100644 --- a/src/content/docs/dns/zone-setups/partial-setup/dns-resolution.mdx +++ b/src/content/docs/dns/zone-setups/partial-setup/dns-resolution.mdx @@ -70,15 +70,15 @@ In this case, Cloudflare will always resolve the CNAME target based on the value ```mermaid flowchart TD accTitle: DNS resolution flow with CNAME target in a zone within the same account - A[Request to www.alice.com] --> B[CNAME record for www.alice.com to www.partialzone.com] - B --> C[A record for www.partialzone.com to 192.0.2.4] + A[Request to www\.alice.com] --> B[CNAME record for www\.alice.com to www\.partialzone.com] + B --> C[A record for www\.partialzone.com to 192.0.2.4] C --> D[192.0.2.4] subgraph Cloudflare account subgraph Cloudflare zone 1 B end subgraph Cloudflare zone 2 - E[A record for www.partialzone.com to 203.0.113.1] + E[A record for www\.partialzone.com to 203.0.113.1] end end subgraph Authoritative DNS diff --git a/src/content/docs/dns/zone-setups/reference/domain-status.mdx b/src/content/docs/dns/zone-setups/reference/domain-status.mdx index 48f6fcc54b7fcb..bb3f02646714d1 100644 --- a/src/content/docs/dns/zone-setups/reference/domain-status.mdx +++ b/src/content/docs/dns/zone-setups/reference/domain-status.mdx @@ -51,21 +51,29 @@ If your zone is in **Setup** for over 28 days, it will be automatically [deleted Your zone status is presented as **Pending Nameserver Update** on the Cloudflare dashboard. -Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs, but your zone is still not active and cannot be used to [proxy traffic to Cloudflare](/dns/proxy-status/limitations/#pending-domains). - -If your domain is on the Free plan, it will be deleted automatically if it is not activated within 28 days. Any pending zone with a paid plan (Pro, Business, Enterprise) will remain pending until the plan is removed, or the domain is activated or [removed from Cloudflare](/fundamentals/setup/manage-domains/remove-domain/). - -For Enterprise zones, if you want to adjust settings before zone activation, Logpush for [DNS logs](/logs/reference/log-fields/zone/dns_logs/) and [DNS Zone Transfer](/dns/zone-setups/zone-transfers/) configuration work as expected in pending state. - :::note If you have mistakenly added a zone to your account it will appear as pending. It can be safely [removed](/fundamentals/setup/manage-domains/remove-domain/). ::: +Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs, but your zone is still not active and cannot be used to [proxy traffic to Cloudflare](/dns/proxy-status/limitations/#pending-domains). + ### Causes * [Full setup](/dns/zone-setups/full-setup/): You have either not [changed your authoritative nameservers](/dns/nameservers/update-nameservers/) or your change has not yet been authenticated by Cloudflare. * [Partial (CNAME) setup](/dns/zone-setups/partial-setup/): You have either not added the verification TXT record to your authoritative DNS provider or the record has not yet been authenticated by Cloudflare. +### Expected behavior for different plans + +If your domain is on the Free plan, it will be deleted automatically if it is not activated within 28 days. + +Any pending zone with a paid plan (Pro, Business, Enterprise) will remain pending until the plan is removed, or the domain is activated or [removed from Cloudflare](/fundamentals/setup/manage-domains/remove-domain/). + +:::caution[Do not use pending zones in production] +Make sure not to use pending zones for production traffic. Cloudflare responds to DNS queries for pending zones on the assigned Cloudflare nameserver IPs but there are associated risks, especially if you do not use [zone holds](/fundamentals/setup/account/account-security/zone-holds/). +::: + +For Enterprise zones, if you want to adjust settings before zone activation, Logpush for [DNS logs](/logs/reference/log-fields/zone/dns_logs/) and [DNS Zone Transfer](/dns/zone-setups/zone-transfers/) configuration work as expected in pending state. + ## Active Cloudflare has authenticated your [nameserver changes](/dns/nameservers/update-nameservers/) or [verification TXT record](/dns/zone-setups/partial-setup/setup/#2-verify-ownership-for-your-domain) and you can proxy domain traffic through Cloudflare. For more details refer to [How Cloudflare works](/fundamentals/concepts/how-cloudflare-works/) and [Domain configurations](/fundamentals/setup/manage-domains/connect-your-domain/#domain-configurations). diff --git a/src/content/docs/dns/zone-setups/troubleshooting/cannot-add-domain.mdx b/src/content/docs/dns/zone-setups/troubleshooting/cannot-add-domain.mdx index 94013e9aeaa5d3..0c0bc4f4a17e9e 100644 --- a/src/content/docs/dns/zone-setups/troubleshooting/cannot-add-domain.mdx +++ b/src/content/docs/dns/zone-setups/troubleshooting/cannot-add-domain.mdx @@ -9,7 +9,7 @@ head: If you encounter issues [adding a domain](/fundamentals/setup/manage-domains/add-site/) to Cloudflare, follow these troubleshooting steps. -## 1. Disable DNSSEC +## Disable DNSSEC Cloudflare cannot provide authoritative DNS resolution for a domain — a [full setup domain](/dns/zone-setups/full-setup/) — when **DNSSEC** is enabled at your domain registrar. @@ -23,7 +23,7 @@ If you experience these issues, refer to [Configuring DNSSEC](/dns/dnssec) and [ --- -## 2. Register the domain +## Register the domain If the issue is with your registrar, you may receive the following error messages: @@ -39,7 +39,7 @@ If you receive these error messages, make sure that: --- -## 3. Resolve DNS for apex domain +## Resolve DNS for apex domain Before a domain can be added to Cloudflare, the domain must return `NS` records for valid, working nameservers. `NS` records can be checked via third-party online tools such as [https://www.whatsmydns.net](https://www.whatsmydns.net/) or via a command-line terminal using a dig command: @@ -69,7 +69,7 @@ ns3.cloudflare.com. dns.cloudflare.com. 2029202248 10000 2400 604800 300 --- -## 4. Check if the domain is restricted at Cloudflare +## Check if the domain is restricted at Cloudflare If Cloudflare has temporary or permanent restrictions on a domain, you will receive the following errors: @@ -77,13 +77,35 @@ If Cloudflare has temporary or permanent restrictions on a domain, you will rece - **Message**: `Error with Cloudflare request: [1105] This zone is temporarily restricted and cannot be added to Cloudflare at this time, please contact Cloudflare Support.` - **Cause**: We have seen too many attempts to add a domain to Cloudflare - **Resolution**: Wait 3 hours before attempting to re-add the domain to Cloudflare. Support cannot speed up this process. -- \_**Error 1093 or 1116** +- **Error 1093 or 1116** - **Message**: `This zone cannot be added to Cloudflare at this time, please contact Cloudflare Support. (Code: 1093)` - **Cause**: You may have entered a subdomain (`www.example.com`) instead of the apex domain (also known as "root domain", e.g. `example.com`). - **Resolution**: Verify that you are entering the apex domain. If you are and still experience issues, contact [Cloudflare Support](/support/contacting-cloudflare-support/). -- \_**Error 1097** +- _**Error 1097** - **Message**: `This web property cannot be added to Cloudflare at this time. If you are an Enterprise customer, contact your Customer Success Manager. Otherwise, email abusereply@cloudflare.com with a detailed explanation of your association with this zone. (Code: 1097)` - **Resolution**: Contact [abusereply@cloudflare.com](mailto:abusereply@cloudflare.com) with a detailed explanation of your association with this zone. - **Error: Cannot be found** OR **`` is not a registered domain (code: 1049)** - This can happen if the domain has not been registered yet. Some domains, like `.gov` domains, have special requirements that require the domain be added first. - **Resolution:** Please contact [Cloudflare Support](/support/contacting-cloudflare-support/) if you require assistance adding a `.gov` and/or other domains that require manual registration. + +--- + +## Contact the zone owner in case of zone hold error + +Enterprise customers can use the [zone hold](/fundamentals/setup/account/account-security/zone-holds/) feature to prevent domains to be added in any other account. +If you get the following error when adding your domain, it means that a zone hold is active: + +``` +The zone name provided is subject to a hold which disallows the creation of this zone. +Please contact the owner of the Cloudflare account that manages this domain to have this hold removed. +``` + +In this case you'll need to remove the zone hold if you own the Cloudflare account in which the zone is active, or contact the owner of the Cloudflare account which has the zone active. + +If you are not the owner of the Cloudflare account that has the hold on the zone, using an online WHOIS tool might help you finding the owner of a website. + +See this [external WHOIS tool](https://www.godaddy.com/whois) or this [other external tool](https://www.whois.com/whois/). + +The owner might be your hosting provider, or a SaaS service provider. + +You can also use the [Cloudflare Forgot Email?](https://dash.cloudflare.com/forgot-email) page, and check the documentation related to the [Forgot Email? feature](/fundamentals/setup/account/account-security/login-and-account-issues/#forgot-your-email). diff --git a/src/content/docs/durable-objects/api/sql-storage.mdx b/src/content/docs/durable-objects/api/sql-storage.mdx index c6f8b558b9194f..65a6725cc35b68 100644 --- a/src/content/docs/durable-objects/api/sql-storage.mdx +++ b/src/content/docs/durable-objects/api/sql-storage.mdx @@ -176,11 +176,11 @@ This type can then be passed as the type parameter to a `sql.exec` call: ```ts // The type parameter is passed between the "pointy brackets" before the function argument: -const result = this.ctx.storage.sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", [user_id]).one() +const result = this.ctx.storage.sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", user_id).one() // result will now have a type of "User" // Alternatively, if you are iterating over results using a cursor -let cursor = this.sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", [user_id]) +let cursor = this.sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", user_id) for (let row of cursor) { // Each row object will be of type User } @@ -194,7 +194,7 @@ type UserRow = [ ]; // ... and then pass it as the type argument to the raw() method: -let cursor = sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", [user_id]).raw(); +let cursor = sql.exec("SELECT id, name, email_address, version FROM users WHERE id = ?", user_id).raw(); for (let row of cursor) { // row is of type User diff --git a/src/content/docs/durable-objects/best-practices/websockets.mdx b/src/content/docs/durable-objects/best-practices/websockets.mdx index 7d84e282125789..d9c640931698c9 100644 --- a/src/content/docs/durable-objects/best-practices/websockets.mdx +++ b/src/content/docs/durable-objects/best-practices/websockets.mdx @@ -7,17 +7,179 @@ sidebar: import { Tabs, TabItem, GlossaryTooltip, Type } from "~/components"; +This guide covers how to use Durable Objects as WebSocket servers that can connect thousands of clients (per instance), as well as a WebSocket client to connect to other servers or even Durable Objects. + +There are two sets of WebSockets API + +1. Native Durable Object WebSocket API, which allows your Durable Object to hibernate without disconnecting clients when not actively doing work **(recommended)** +2. Web Standard WebSocket APIs, using the familiar `addEventListener` event pattern. + +### What are WebSockets? + WebSockets are long-lived TCP connections that enable bi-directional, real-time communication between client and server. Both Cloudflare Durable Objects and Workers can act as WebSocket endpoints – either as a client or as a server. Because WebSocket sessions are long-lived, applications commonly use Durable Objects to accept either the client or server connection. While there are other use cases for using Workers exclusively with WebSockets, for example proxying WebSocket messages, WebSockets are most useful when combined with Durable Objects. Because Durable Objects provide a single-point-of-coordination between [Cloudflare Workers](/workers/), a single Durable Object instance can be used in parallel with WebSockets to coordinate between multiple clients, such as participants in a chat room or a multiplayer game. Refer to [Cloudflare Edge Chat Demo](https://github.com/cloudflare/workers-chat-demo) for an example of using Durable Objects with WebSockets. -Both Cloudflare Durable Objects and Workers can use the [Web Standard WebSocket API](/workers/runtime-apis/websockets/) to build applications, but a major differentiator of Cloudflare Durable Objects relative to other platforms is the ability to Hibernate WebSocket connections to save costs. +Both Cloudflare Durable Objects and Workers can use the [Web Standard WebSocket API](/workers/runtime-apis/websockets/) to build applications, but a major differentiator of Cloudflare Durable Objects relative to other platforms is the ability to Hibernate WebSocket connections to save costs. Clients can remain connected when the Durable Object is idle (and not sending messages or running compute tasks), which allows you to push events to clients and minimize the active duration (GB-seconds) associated with long-running Durable Object processes. + +### WebSocket Hibernation API + +In addition to [Workers WebSocket API](/workers/runtime-apis/websockets/), Cloudflare Durable Objects can use the WebSocket Hibernation API which extends the Web Standard WebSocket API to reduce costs. Specifically, [billable Duration (GB-s) charges](/durable-objects/platform/pricing/) are not incurred during periods of inactivity. Note that other events, for example [alarms](/durable-objects/api/alarms/), can prevent a Durable Object from being inactive and therefore prevent this cost saving. + +The WebSocket consists of Cloudflare-specific extensions to the Web Standard WebSocket API. These extensions are either present on the [DurableObjectState](/durable-objects/api/state) interface, or as handler methods on the Durable Object class. + +:::note + +Hibernation is only supported when a Durable Object acts as a WebSocket server. Currently, outgoing WebSockets cannot hibernate. + +::: + +The Worker used in the WebSocket Standard API example does not require any code changes to make use of the WebSocket Hibernation API. The changes to the Durable Object are described in the code sample below. In summary, [`DurableObjectState::acceptWebSocket`](/durable-objects/api/state/#acceptwebsocket) is called to accept the server side of the WebSocket connection, and handler methods are defined on the Durable Object class for relevant event types rather than adding event listeners. + +If an event occurs for a hibernated Durable Object's corresponding handler method, it will return to memory. This will call the Durable Object's constructor, so it is best to minimize work in the constructor when using WebSocket hibernation. + + + +```js +import { DurableObject } from "cloudflare:workers"; + +// Durable Object +export class WebSocketHibernationServer extends DurableObject { + async fetch(request) { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket + // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while + // the connection is open. During periods of inactivity, the Durable Object can be evicted + // from memory, but the WebSocket connection will remain open. If at some later point the + // WebSocket receives a message, the runtime will recreate the Durable Object + // (run the `constructor`) and deliver the message to the appropriate handler. + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } + + async webSocketMessage(ws, message) { + // Upon receiving a message from the client, reply with the same message, + // but will prefix the message with "[Durable Object]: " and return the + // total number of connections. + ws.send( + `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, + ); + } + + async webSocketClose(ws, code, reason, wasClean) { + // If the client closes the connection, the runtime will invoke the webSocketClose() handler. + ws.close(code, "Durable Object is closing WebSocket"); + } +} +``` + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export interface Env { + WEBSOCKET_HIBERNATION_SERVER: DurableObjectNamespace; +} + +// Durable Object +export class WebSocketHibernationServer extends DurableObject { + async fetch(request: Request): Promise { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket + // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while + // the connection is open. During periods of inactivity, the Durable Object can be evicted + // from memory, but the WebSocket connection will remain open. If at some later point the + // WebSocket receives a message, the runtime will recreate the Durable Object + // (run the `constructor`) and deliver the message to the appropriate handler. + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } + + async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + ws.send( + `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, + ); + } + + async webSocketClose( + ws: WebSocket, + code: number, + reason: string, + wasClean: boolean, + ) { + // If the client closes the connection, the runtime will invoke the webSocketClose() handler. + ws.close(code, "Durable Object is closing WebSocket"); + } +} +``` + + + +Similar to the WebSocket Standard API example, to execute this code, configure your Wrangler file to include a Durable Object [binding](/durable-objects/get-started/tutorial/#5-configure-durable-object-bindings) and [migration](/durable-objects/reference/durable-objects-migrations/) based on the namespace and class name chosen previously. + +```toml title="wrangler.toml" +name = "websocket-hibernation-server" + +[[durable_objects.bindings]] +name = "WEBSOCKET_HIBERNATION_SERVER" +class_name = "WebSocketHibernationServer" + +[[migrations]] +tag = "v1" +new_classes = ["WebSocketHibernationServer"] +``` + +A full example can be found in [Build a WebSocket server with WebSocket Hibernation](/durable-objects/examples/websocket-hibernation-server/). + +:::caution[Support for local development] + +Prior to `wrangler@3.13.2` and Miniflare `v3.20231016.0`, WebSockets did not hibernate when using local development environments such as `wrangler dev` or Miniflare. + +If you are using older versions, note that while hibernatable WebSocket events such as [`webSocketMessage()`](/durable-objects/api/base/#websocketmessage) will still be delivered, the Durable Object will never be evicted from memory. + +::: + +## Extended methods + +### `serializeAttachment` + +- serializeAttachment(value ): + + - Keeps a copy of `value` associated with the WebSocket to survive hibernation. The value can be any type supported by the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), which is true of most types. If the value needs to be durable please use [Durable Object Storage](/durable-objects/api/storage-api/). + + - If you modify `value` after calling this method, those changes will not be retained unless you call this method again. The serialized size of `value` is limited to 2,048 bytes, otherwise this method will throw an error. If you need larger values to survive hibernation, use the [Storage API](/durable-objects/api/storage-api/) and pass the corresponding key to this method so it can be retrieved later. + +### `deserializeAttachment` + +- `deserializeAttachment()`: + + - Retrieves the most recent value passed to `serializeAttachment()`, or `null` if none exists. -This guide covers: -1. Building a WebSocket server using Web Standard APIs -2. Using WebSocket Hibernation APIs. -## WebSocket Standard API +### WebSocket Standard API WebSocket connections are established by making an HTTP GET request with the `Upgrade: websocket` header. A Cloudflare Worker is commonly used to validate the request, proxy the request to the Durable Object to accept the server side connection, and return the client side connection in the response. @@ -239,165 +401,9 @@ Code updates will disconnect all WebSockets. If you deploy a new version of a Wo ::: -## WebSocket Hibernation API - -In addition to [Workers WebSocket API](/workers/runtime-apis/websockets/), Cloudflare Durable Objects can use the WebSocket Hibernation API which extends the Web Standard WebSocket API to reduce costs. Specifically, [billable Duration (GB-s) charges](/durable-objects/platform/pricing/) are not incurred during periods of inactivity. Note that other events, for example [alarms](/durable-objects/api/alarms/), can prevent a Durable Object from being inactive and therefore prevent this cost saving. - -The WebSocket consists of Cloudflare-specific extensions to the Web Standard WebSocket API. These extensions are either present on the [DurableObjectState](/durable-objects/api/state) interface, or as handler methods on the Durable Object class. - -:::note - -Hibernation is only supported when a Durable Object acts as a WebSocket server. Currently, outgoing WebSockets cannot hibernate. - -::: - -The Worker used in the WebSocket Standard API example does not require any code changes to make use of the WebSocket Hibernation API. The changes to the Durable Object are described in the code sample below. In summary, [`DurableObjectState::acceptWebSocket`](/durable-objects/api/state/#acceptwebsocket) is called to accept the server side of the WebSocket connection, and handler methods are defined on the Durable Object class for relevant event types rather than adding event listeners. - -If an event occurs for a hibernated Durable Object's corresponding handler method, it will return to memory. This will call the Durable Object's constructor, so it is best to minimize work in the constructor when using WebSocket hibernation. - - - -```js -import { DurableObject } from "cloudflare:workers"; - -// Durable Object -export class WebSocketHibernationServer extends DurableObject { - async fetch(request) { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } - - async webSocketMessage(ws, message) { - // Upon receiving a message from the client, reply with the same message, - // but will prefix the message with "[Durable Object]: " and return the - // total number of connections. - ws.send( - `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, - ); - } - - async webSocketClose(ws, code, reason, wasClean) { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - } -} -``` - - - -```ts -import { DurableObject } from "cloudflare:workers"; - -export interface Env { - WEBSOCKET_HIBERNATION_SERVER: DurableObjectNamespace; -} - -// Durable Object -export class WebSocketHibernationServer extends DurableObject { - async fetch(request: Request): Promise { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } - - async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { - // Upon receiving a message from the client, the server replies with the same message, - // and the total number of connections with the "[Durable Object]: " prefix - ws.send( - `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, - ); - } - - async webSocketClose( - ws: WebSocket, - code: number, - reason: string, - wasClean: boolean, - ) { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - } -} -``` - - - -Similar to the WebSocket Standard API example, to execute this code, configure your Wrangler file to include a Durable Object [binding](/durable-objects/get-started/tutorial/#5-configure-durable-object-bindings) and [migration](/durable-objects/reference/durable-objects-migrations/) based on the namespace and class name chosen previously. - -```toml title="wrangler.toml" -name = "websocket-hibernation-server" - -[[durable_objects.bindings]] -name = "WEBSOCKET_HIBERNATION_SERVER" -class_name = "WebSocketHibernationServer" - -[[migrations]] -tag = "v1" -new_classes = ["WebSocketHibernationServer"] -``` - -A full example can be found in [Build a WebSocket server with WebSocket Hibernation](/durable-objects/examples/websocket-hibernation-server/). - -:::caution[Support for local development] - -Prior to `wrangler@3.13.2` and Miniflare `v3.20231016.0`, WebSockets did not hibernate when using local development environments such as `wrangler dev` or Miniflare. - -If you are using older versions, note that while hibernatable WebSocket events such as [`webSocketMessage()`](/durable-objects/api/base/#websocketmessage) will still be delivered, the Durable Object will never be evicted from memory. - -::: - -## Extended methods - -### `serializeAttachment` - -- serializeAttachment(value ): - - - Keeps a copy of `value` associated with the WebSocket to survive hibernation. The value can be any type supported by the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), which is true of most types. If the value needs to be durable please use [Durable Object Storage](/durable-objects/api/storage-api/). - - - If you modify `value` after calling this method, those changes will not be retained unless you call this method again. The serialized size of `value` is limited to 2,048 bytes, otherwise this method will throw an error. If you need larger values to survive hibernation, use the [Storage API](/durable-objects/api/storage-api/) and pass the corresponding key to this method so it can be retrieved later. - -### `deserializeAttachment` - -- `deserializeAttachment()`: - - - Retrieves the most recent value passed to `serializeAttachment()`, or `null` if none exists. - ## Related resources - [Mozilla Developer Network's (MDN) documentation on the WebSocket class](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) - [Cloudflare's WebSocket template for building applications on Workers using WebSockets](https://github.com/cloudflare/websocket-template) - [Durable Object base class](/durable-objects/api/base/) -- [Durable Object State interface](/durable-objects/api/state/) \ No newline at end of file +- [Durable Object State interface](/durable-objects/api/state/) diff --git a/src/content/docs/durable-objects/examples/alarms-api.mdx b/src/content/docs/durable-objects/examples/alarms-api.mdx index b9f5bf21296d17..9327fb84179f23 100644 --- a/src/content/docs/durable-objects/examples/alarms-api.mdx +++ b/src/content/docs/durable-objects/examples/alarms-api.mdx @@ -1,16 +1,11 @@ --- type: example summary: Use the Durable Objects Alarms API to batch requests to a Durable Object. -tags: - - Durable Objects - - Alarms - - API pcx_content_type: example title: Use the Alarms API sidebar: order: 3 description: Use the Durable Objects Alarms API to batch requests to a Durable Object. - --- import { GlossaryTooltip, WranglerConfig } from "~/components"; @@ -22,57 +17,57 @@ When a request is received and no alarm is set, it sets an alarm for 10 seconds If no new requests are received, no further alarms will be set until the next request arrives. ```js -import { DurableObject } from 'cloudflare:workers'; +import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env) { - let id = env.BATCHER.idFromName("foo"); - return await env.BATCHER.get(id).fetch(request); - }, + async fetch(request, env) { + let id = env.BATCHER.idFromName("foo"); + return await env.BATCHER.get(id).fetch(request); + }, }; const SECONDS = 10; // Durable Object export class Batcher extends DurableObject { - constructor(state, env) { - this.state = state; - this.storage = state.storage; - this.state.blockConcurrencyWhile(async () => { - let vals = await this.storage.list({ reverse: true, limit: 1 }); - this.count = vals.size == 0 ? 0 : parseInt(vals.keys().next().value); - }); - } - - async fetch(request) { - this.count++; - - // If there is no alarm currently set, set one for 10 seconds from now - // Any further POSTs in the next 10 seconds will be part of this batch. - let currentAlarm = await this.storage.getAlarm(); - if (currentAlarm == null) { - this.storage.setAlarm(Date.now() + (1000 * SECONDS)); - } - - // Add the request to the batch. - await this.storage.put(this.count, await request.text()); - return new Response(JSON.stringify({ queued: this.count }), { - headers: { - "content-type": "application/json;charset=UTF-8", - }, - }); - } - - async alarm() { - let vals = await this.storage.list(); - await fetch("http://example.com/some-upstream-service", { - method: "POST", - body: Array.from(vals.values()), - }); - await this.storage.deleteAll(); - this.count = 0; - } + constructor(state, env) { + this.state = state; + this.storage = state.storage; + this.state.blockConcurrencyWhile(async () => { + let vals = await this.storage.list({ reverse: true, limit: 1 }); + this.count = vals.size == 0 ? 0 : parseInt(vals.keys().next().value); + }); + } + + async fetch(request) { + this.count++; + + // If there is no alarm currently set, set one for 10 seconds from now + // Any further POSTs in the next 10 seconds will be part of this batch. + let currentAlarm = await this.storage.getAlarm(); + if (currentAlarm == null) { + this.storage.setAlarm(Date.now() + 1000 * SECONDS); + } + + // Add the request to the batch. + await this.storage.put(this.count, await request.text()); + return new Response(JSON.stringify({ queued: this.count }), { + headers: { + "content-type": "application/json;charset=UTF-8", + }, + }); + } + + async alarm() { + let vals = await this.storage.list(); + await fetch("http://example.com/some-upstream-service", { + method: "POST", + body: Array.from(vals.values()), + }); + await this.storage.deleteAll(); + this.count = 0; + } } ``` diff --git a/src/content/docs/durable-objects/examples/build-a-counter.mdx b/src/content/docs/durable-objects/examples/build-a-counter.mdx index f8be0b9c308651..ec840c752b2577 100644 --- a/src/content/docs/durable-objects/examples/build-a-counter.mdx +++ b/src/content/docs/durable-objects/examples/build-a-counter.mdx @@ -1,17 +1,14 @@ --- type: example summary: Build a counter using Durable Objects and Workers with RPC methods. -tags: - - Durable Objects pcx_content_type: example title: Build a counter sidebar: order: 3 description: Build a counter using Durable Objects and Workers with RPC methods. - --- -import { TabItem, Tabs, WranglerConfig } from "~/components" +import { TabItem, Tabs, WranglerConfig } from "~/components"; This example shows how to build a counter using Durable Objects and Workers with [RPC methods](/workers/runtime-apis/rpc) that can print, increment, and decrement a `name` provided by the URL query string parameter, for example, `?name=A`. @@ -22,71 +19,70 @@ import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env) { - let url = new URL(request.url); - let name = url.searchParams.get("name"); - if (!name) { - return new Response( - "Select a Durable Object to contact by using" + - " the `name` URL query string parameter, for example, ?name=A" - ); - } - - // Every unique ID refers to an individual instance of the Counter class that - // has its own state. `idFromName()` always returns the same ID when given the - // same string as input (and called on the same class), but never the same - // ID for two different strings (or for different classes). - let id = env.COUNTERS.idFromName(name); - - // Construct the stub for the Durable Object using the ID. - // A stub is a client Object used to send messages to the Durable Object. - let stub = env.COUNTERS.get(id); - - // Send a request to the Durable Object using RPC methods, then await its response. - let count = null; - switch (url.pathname) { - case "/increment": - count = await stub.increment(); - break; - case "/decrement": - count = await stub.decrement(); - break; - case "/": - // Serves the current value. - count = await stub.getCounterValue(); - break; - default: - return new Response("Not found", { status: 404 }); - } - - return new Response(`Durable Object '${name}' count: ${count}`); - } + async fetch(request, env) { + let url = new URL(request.url); + let name = url.searchParams.get("name"); + if (!name) { + return new Response( + "Select a Durable Object to contact by using" + + " the `name` URL query string parameter, for example, ?name=A", + ); + } + + // Every unique ID refers to an individual instance of the Counter class that + // has its own state. `idFromName()` always returns the same ID when given the + // same string as input (and called on the same class), but never the same + // ID for two different strings (or for different classes). + let id = env.COUNTERS.idFromName(name); + + // Construct the stub for the Durable Object using the ID. + // A stub is a client Object used to send messages to the Durable Object. + let stub = env.COUNTERS.get(id); + + // Send a request to the Durable Object using RPC methods, then await its response. + let count = null; + switch (url.pathname) { + case "/increment": + count = await stub.increment(); + break; + case "/decrement": + count = await stub.decrement(); + break; + case "/": + // Serves the current value. + count = await stub.getCounterValue(); + break; + default: + return new Response("Not found", { status: 404 }); + } + + return new Response(`Durable Object '${name}' count: ${count}`); + }, }; // Durable Object export class Counter extends DurableObject { - - async getCounterValue() { - let value = (await this.ctx.storage.get("value")) || 0; - return value; - } - - async increment(amount = 1) { - let value = (await this.ctx.storage.get("value")) || 0; - value += amount; - // You do not have to worry about a concurrent request having modified the value in storage. - // "input gates" will automatically protect against unwanted concurrency. - // Read-modify-write is safe. - await this.ctx.storage.put("value", value); - return value; - } - - async decrement(amount = 1) { - let value = (await this.ctx.storage.get("value")) || 0; - value -= amount; - await this.ctx.storage.put("value", value); - return value; - } + async getCounterValue() { + let value = (await this.ctx.storage.get("value")) || 0; + return value; + } + + async increment(amount = 1) { + let value = (await this.ctx.storage.get("value")) || 0; + value += amount; + // You do not have to worry about a concurrent request having modified the value in storage. + // "input gates" will automatically protect against unwanted concurrency. + // Read-modify-write is safe. + await this.ctx.storage.put("value", value); + return value; + } + + async decrement(amount = 1) { + let value = (await this.ctx.storage.get("value")) || 0; + value -= amount; + await this.ctx.storage.put("value", value); + return value; + } } ``` @@ -96,75 +92,74 @@ export class Counter extends DurableObject { import { DurableObject } from "cloudflare:workers"; export interface Env { - COUNTERS: DurableObjectNamespace; + COUNTERS: DurableObjectNamespace; } // Worker export default { - async fetch(request, env) { - let url = new URL(request.url); - let name = url.searchParams.get("name"); - if (!name) { - return new Response( - "Select a Durable Object to contact by using" + - " the `name` URL query string parameter, for example, ?name=A" - ); - } - - // Every unique ID refers to an individual instance of the Counter class that - // has its own state. `idFromName()` always returns the same ID when given the - // same string as input (and called on the same class), but never the same - // ID for two different strings (or for different classes). - let id = env.COUNTERS.idFromName(name); - - // Construct the stub for the Durable Object using the ID. - // A stub is a client Object used to send messages to the Durable Object. - let stub = env.COUNTERS.get(id); - - let count = null; - switch (url.pathname) { - case "/increment": - count = await stub.increment(); - break; - case "/decrement": - count = await stub.decrement(); - break; - case "/": - // Serves the current value. - count = await stub.getCounterValue(); - break; - default: - return new Response("Not found", { status: 404 }); - } - - return new Response(`Durable Object '${name}' count: ${count}`); - } + async fetch(request, env) { + let url = new URL(request.url); + let name = url.searchParams.get("name"); + if (!name) { + return new Response( + "Select a Durable Object to contact by using" + + " the `name` URL query string parameter, for example, ?name=A", + ); + } + + // Every unique ID refers to an individual instance of the Counter class that + // has its own state. `idFromName()` always returns the same ID when given the + // same string as input (and called on the same class), but never the same + // ID for two different strings (or for different classes). + let id = env.COUNTERS.idFromName(name); + + // Construct the stub for the Durable Object using the ID. + // A stub is a client Object used to send messages to the Durable Object. + let stub = env.COUNTERS.get(id); + + let count = null; + switch (url.pathname) { + case "/increment": + count = await stub.increment(); + break; + case "/decrement": + count = await stub.decrement(); + break; + case "/": + // Serves the current value. + count = await stub.getCounterValue(); + break; + default: + return new Response("Not found", { status: 404 }); + } + + return new Response(`Durable Object '${name}' count: ${count}`); + }, } satisfies ExportedHandler; // Durable Object export class Counter extends DurableObject { - - async getCounterValue() { - let value = (await this.ctx.storage.get("value")) || 0; - return value; - } - - async increment(amount = 1) { - let value: number = (await this.ctx.storage.get("value")) || 0; - value += amount; - // You do not have to worry about a concurrent request having modified the value in storage. - // "input gates" will automatically protect against unwanted concurrency. - // Read-modify-write is safe. - await this.ctx.storage.put("value", value); - return value; - } - - async decrement(amount = 1) { - let value: number = (await this.ctx.storage.get("value")) || 0; - value -= amount; - await this.ctx.storage.put("value", value); - return value; - } + async getCounterValue() { + let value = (await this.ctx.storage.get("value")) || 0; + return value; + } + + async increment(amount = 1) { + let value: number = (await this.ctx.storage.get("value")) || 0; + value += amount; + // You do not have to worry about a concurrent request having modified the value in storage. + // "input gates" will automatically protect against unwanted concurrency. + // Read-modify-write is safe. + await this.ctx.storage.put("value", value); + return value; + } + + async decrement(amount = 1) { + let value: number = (await this.ctx.storage.get("value")) || 0; + value -= amount; + await this.ctx.storage.put("value", value); + return value; + } } ``` @@ -190,5 +185,5 @@ new_classes = ["Counter"] ### Related resources -* [Workers RPC](/workers/runtime-apis/rpc/) -* [Durable Objects: Easy, Fast, Correct — Choose three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/). +- [Workers RPC](/workers/runtime-apis/rpc/) +- [Durable Objects: Easy, Fast, Correct — Choose three](https://blog.cloudflare.com/durable-objects-easy-fast-correct-choose-three/). diff --git a/src/content/docs/durable-objects/examples/build-a-rate-limiter.mdx b/src/content/docs/durable-objects/examples/build-a-rate-limiter.mdx index 3cd21b778894ec..7e0f3273ad1227 100644 --- a/src/content/docs/durable-objects/examples/build-a-rate-limiter.mdx +++ b/src/content/docs/durable-objects/examples/build-a-rate-limiter.mdx @@ -1,17 +1,14 @@ --- type: example summary: Build a rate limiter using Durable Objects and Workers. -tags: - - Durable Objects pcx_content_type: example title: Build a rate limiter sidebar: order: 2 description: Build a rate limiter using Durable Objects and Workers. - --- -import { TabItem, Tabs, GlossaryTooltip, WranglerConfig } from "~/components" +import { TabItem, Tabs, GlossaryTooltip, WranglerConfig } from "~/components"; This example shows how to build a rate limiter using Durable Objects and Workers that can be used to protect upstream resources, including third-party APIs that your application relies on and/or services that may be costly for you to invoke. @@ -21,9 +18,9 @@ The Worker creates a `RateLimiter` Durable Object on a per IP basis to protect u It might seem simpler to implement a global rate limiter, `const id = env.RATE_LIMITER.idFromName("global");`, which can provide better guarantees on the request rate to the upstream resource. However: -* This would require all requests globally to make a sub-request to a single Durable Object. -* Implementing a global rate limiter would add additional latency for requests not colocated with the Durable Object, and global throughput would be capped to the throughput of a single Durable Object. -* A single Durable Object that all requests rely on is typically considered an anti-pattern. Durable Objects work best when they are scoped to a user, room, service and/or the specific subset of your application that requires global co-ordination. +- This would require all requests globally to make a sub-request to a single Durable Object. +- Implementing a global rate limiter would add additional latency for requests not colocated with the Durable Object, and global throughput would be capped to the throughput of a single Durable Object. +- A single Durable Object that all requests rely on is typically considered an anti-pattern. Durable Objects work best when they are scoped to a user, room, service and/or the specific subset of your application that requires global co-ordination. :::note @@ -31,12 +28,12 @@ If you do not need unique or custom rate-limiting capabilities, refer to [Rate l ::: -The Durable Object uses a token bucket algorithm to implement rate limiting. The naive idea is that each request requires a token to complete, and the tokens are replenished according to the reciprocal of the desired number of requests per second. As an example, a 1000 requests per second rate limit will have a token replenished every millisecond (as specified by milliseconds\_per\_request) up to a given capacity limit. +The Durable Object uses a token bucket algorithm to implement rate limiting. The naive idea is that each request requires a token to complete, and the tokens are replenished according to the reciprocal of the desired number of requests per second. As an example, a 1000 requests per second rate limit will have a token replenished every millisecond (as specified by milliseconds_per_request) up to a given capacity limit. This example uses Durable Object's [Alarms API](/durable-objects/api/alarms) to schedule the Durable Object to be woken up at a time in the future. -* When the alarm's scheduled time comes, the `alarm()` handler method is called, and in this case, the alarm will add a token to the "Bucket". -* The implementation is made more efficient by adding tokens in bulk (as specified by milliseconds\_for\_updates) and preventing the alarm handler from being invoked every millisecond. More frequent invocations of Durable Objects will lead to higher invocation and duration charges. +- When the alarm's scheduled time comes, the `alarm()` handler method is called, and in this case, the alarm will add a token to the "Bucket". +- The implementation is made more efficient by adding tokens in bulk (as specified by milliseconds_for_updates) and preventing the alarm handler from being invoked every millisecond. More frequent invocations of Durable Objects will lead to higher invocation and duration charges. The first implementation of a rate limiter is below: @@ -48,70 +45,76 @@ import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env, _ctx) { - // Determine the IP address of the client - const ip = request.headers.get("CF-Connecting-IP"); - if (ip === null) { - return new Response("Could not determine client IP", { status: 400 }); - } - - // Obtain an identifier for a Durable Object based on the client's IP address - const id = env.RATE_LIMITER.idFromName(ip); - - try { - const stub = env.RATE_LIMITER.get(id); - const milliseconds_to_next_request = await stub.getMillisecondsToNextRequest(); - if (milliseconds_to_next_request > 0) { - // Alternatively one could sleep for the necessary length of time - return new Response("Rate limit exceeded", { status: 429 }); - } - } catch (error) { - return new Response("Could not connect to rate limiter", { status: 502 }); - } - - // TODO: Implement me - return new Response("Call some upstream resource...") - } + async fetch(request, env, _ctx) { + // Determine the IP address of the client + const ip = request.headers.get("CF-Connecting-IP"); + if (ip === null) { + return new Response("Could not determine client IP", { status: 400 }); + } + + // Obtain an identifier for a Durable Object based on the client's IP address + const id = env.RATE_LIMITER.idFromName(ip); + + try { + const stub = env.RATE_LIMITER.get(id); + const milliseconds_to_next_request = + await stub.getMillisecondsToNextRequest(); + if (milliseconds_to_next_request > 0) { + // Alternatively one could sleep for the necessary length of time + return new Response("Rate limit exceeded", { status: 429 }); + } + } catch (error) { + return new Response("Could not connect to rate limiter", { status: 502 }); + } + + // TODO: Implement me + return new Response("Call some upstream resource..."); + }, }; // Durable Object export class RateLimiter extends DurableObject { - static milliseconds_per_request = 1; - static milliseconds_for_updates = 5000; - static capacity = 10000; - - constructor(ctx, env) { - super(ctx, env); - this.tokens = RateLimiter.capacity; - } - - async getMillisecondsToNextRequest() { - this.checkAndSetAlarm() - - let milliseconds_to_next_request = RateLimiter.milliseconds_per_request; - if (this.tokens > 0) { - this.tokens -= 1; - milliseconds_to_next_request = 0; - } - - return milliseconds_to_next_request; - } - - async checkAndSetAlarm() { - let currentAlarm = await this.ctx.storage.getAlarm(); - if (currentAlarm == null) { - this.ctx.storage.setAlarm(Date.now() + - RateLimiter.milliseconds_for_updates * RateLimiter.milliseconds_per_request); - } - } - - async alarm() { - if (this.tokens < RateLimiter.capacity) { - this.tokens = Math.min(RateLimiter.capacity, - this.tokens + RateLimiter.milliseconds_for_updates); - this.checkAndSetAlarm() - } - } + static milliseconds_per_request = 1; + static milliseconds_for_updates = 5000; + static capacity = 10000; + + constructor(ctx, env) { + super(ctx, env); + this.tokens = RateLimiter.capacity; + } + + async getMillisecondsToNextRequest() { + this.checkAndSetAlarm(); + + let milliseconds_to_next_request = RateLimiter.milliseconds_per_request; + if (this.tokens > 0) { + this.tokens -= 1; + milliseconds_to_next_request = 0; + } + + return milliseconds_to_next_request; + } + + async checkAndSetAlarm() { + let currentAlarm = await this.ctx.storage.getAlarm(); + if (currentAlarm == null) { + this.ctx.storage.setAlarm( + Date.now() + + RateLimiter.milliseconds_for_updates * + RateLimiter.milliseconds_per_request, + ); + } + } + + async alarm() { + if (this.tokens < RateLimiter.capacity) { + this.tokens = Math.min( + RateLimiter.capacity, + this.tokens + RateLimiter.milliseconds_for_updates, + ); + this.checkAndSetAlarm(); + } + } } ``` @@ -122,77 +125,83 @@ export class RateLimiter extends DurableObject { import { DurableObject } from "cloudflare:workers"; export interface Env { - RATE_LIMITER: DurableObjectNamespace; + RATE_LIMITER: DurableObjectNamespace; } // Worker export default { - async fetch(request, env, _ctx): Promise { - // Determine the IP address of the client - const ip = request.headers.get("CF-Connecting-IP"); - if (ip === null) { - return new Response("Could not determine client IP", { status: 400 }); - } - - // Obtain an identifier for a Durable Object based on the client's IP address - const id = env.RATE_LIMITER.idFromName(ip); - - try { - const stub = env.RATE_LIMITER.get(id); - const milliseconds_to_next_request = await stub.getMillisecondsToNextRequest(); - if (milliseconds_to_next_request > 0) { - // Alternatively one could sleep for the necessary length of time - return new Response("Rate limit exceeded", { status: 429 }); - } - } catch (error) { - return new Response("Could not connect to rate limiter", { status: 502 }); - } - - // TODO: Implement me - return new Response("Call some upstream resource...") - } + async fetch(request, env, _ctx): Promise { + // Determine the IP address of the client + const ip = request.headers.get("CF-Connecting-IP"); + if (ip === null) { + return new Response("Could not determine client IP", { status: 400 }); + } + + // Obtain an identifier for a Durable Object based on the client's IP address + const id = env.RATE_LIMITER.idFromName(ip); + + try { + const stub = env.RATE_LIMITER.get(id); + const milliseconds_to_next_request = + await stub.getMillisecondsToNextRequest(); + if (milliseconds_to_next_request > 0) { + // Alternatively one could sleep for the necessary length of time + return new Response("Rate limit exceeded", { status: 429 }); + } + } catch (error) { + return new Response("Could not connect to rate limiter", { status: 502 }); + } + + // TODO: Implement me + return new Response("Call some upstream resource..."); + }, } satisfies ExportedHandler; // Durable Object export class RateLimiter extends DurableObject { - static readonly milliseconds_per_request = 1; - static readonly milliseconds_for_updates = 5000; - static readonly capacity = 10000; - - tokens: number; - - constructor(ctx: DurableObjectState, env: Env) { - super(ctx, env); - this.tokens = RateLimiter.capacity; - } - - async getMillisecondsToNextRequest(): Promise { - this.checkAndSetAlarm() - - let milliseconds_to_next_request = RateLimiter.milliseconds_per_request; - if (this.tokens > 0) { - this.tokens -= 1; - milliseconds_to_next_request = 0; - } - - return milliseconds_to_next_request; - } - - private async checkAndSetAlarm() { - let currentAlarm = await this.ctx.storage.getAlarm(); - if (currentAlarm == null) { - this.ctx.storage.setAlarm(Date.now() + - RateLimiter.milliseconds_for_updates * RateLimiter.milliseconds_per_request); - } - } - - async alarm() { - if (this.tokens < RateLimiter.capacity) { - this.tokens = Math.min(RateLimiter.capacity, - this.tokens + RateLimiter.milliseconds_for_updates); - this.checkAndSetAlarm() - } - } + static readonly milliseconds_per_request = 1; + static readonly milliseconds_for_updates = 5000; + static readonly capacity = 10000; + + tokens: number; + + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + this.tokens = RateLimiter.capacity; + } + + async getMillisecondsToNextRequest(): Promise { + this.checkAndSetAlarm(); + + let milliseconds_to_next_request = RateLimiter.milliseconds_per_request; + if (this.tokens > 0) { + this.tokens -= 1; + milliseconds_to_next_request = 0; + } + + return milliseconds_to_next_request; + } + + private async checkAndSetAlarm() { + let currentAlarm = await this.ctx.storage.getAlarm(); + if (currentAlarm == null) { + this.ctx.storage.setAlarm( + Date.now() + + RateLimiter.milliseconds_for_updates * + RateLimiter.milliseconds_per_request, + ); + } + } + + async alarm() { + if (this.tokens < RateLimiter.capacity) { + this.tokens = Math.min( + RateLimiter.capacity, + this.tokens + RateLimiter.milliseconds_for_updates, + ); + this.checkAndSetAlarm(); + } + } } ``` @@ -209,24 +218,26 @@ import { DurableObject } from "cloudflare:workers"; // Durable Object export class RateLimiter extends DurableObject { - static milliseconds_per_request = 1; - static milliseconds_for_grace_period = 5000; - - constructor(ctx, env) { - super(ctx, env); - this.nextAllowedTime = 0; - } - - async getMillisecondsToNextRequest() { - const now = Date.now(); - - this.nextAllowedTime = Math.max(now, this.nextAllowedTime); - this.nextAllowedTime += RateLimiter.milliseconds_per_request; - - const value = Math.max(0, - this.nextAllowedTime - now - RateLimiter.milliseconds_for_grace_period); - return value; - } + static milliseconds_per_request = 1; + static milliseconds_for_grace_period = 5000; + + constructor(ctx, env) { + super(ctx, env); + this.nextAllowedTime = 0; + } + + async getMillisecondsToNextRequest() { + const now = Date.now(); + + this.nextAllowedTime = Math.max(now, this.nextAllowedTime); + this.nextAllowedTime += RateLimiter.milliseconds_per_request; + + const value = Math.max( + 0, + this.nextAllowedTime - now - RateLimiter.milliseconds_for_grace_period, + ); + return value; + } } ``` @@ -238,26 +249,28 @@ import { DurableObject } from "cloudflare:workers"; // Durable Object export class RateLimiter extends DurableObject { - static milliseconds_per_request = 1; - static milliseconds_for_grace_period = 5000; + static milliseconds_per_request = 1; + static milliseconds_for_grace_period = 5000; - nextAllowedTime: number; + nextAllowedTime: number; - constructor(ctx: DurableObjectState, env: Env) { - super(ctx, env); - this.nextAllowedTime = 0; - } + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + this.nextAllowedTime = 0; + } - async getMillisecondsToNextRequest(): Promise { - const now = Date.now(); + async getMillisecondsToNextRequest(): Promise { + const now = Date.now(); - this.nextAllowedTime = Math.max(now, this.nextAllowedTime); - this.nextAllowedTime += RateLimiter.milliseconds_per_request; + this.nextAllowedTime = Math.max(now, this.nextAllowedTime); + this.nextAllowedTime += RateLimiter.milliseconds_per_request; - const value = Math.max(0, - this.nextAllowedTime - now - RateLimiter.milliseconds_for_grace_period); - return value; - } + const value = Math.max( + 0, + this.nextAllowedTime - now - RateLimiter.milliseconds_for_grace_period, + ); + return value; + } } ``` @@ -284,6 +297,6 @@ new_classes = ["RateLimiter"] ### Related resources -* Learn more about Durable Object's [Alarms API](/durable-objects/api/alarms) and how to configure alarms. -* [Understand how to troubleshoot](/durable-objects/observability/troubleshooting/) common errors related with Durable Objects. -* Review how [Durable Objects are priced](/durable-objects/platform/pricing/), including pricing examples. +- Learn more about Durable Object's [Alarms API](/durable-objects/api/alarms) and how to configure alarms. +- [Understand how to troubleshoot](/durable-objects/observability/troubleshooting/) common errors related with Durable Objects. +- Review how [Durable Objects are priced](/durable-objects/platform/pricing/), including pricing examples. diff --git a/src/content/docs/durable-objects/examples/durable-object-in-memory-state.mdx b/src/content/docs/durable-objects/examples/durable-object-in-memory-state.mdx index 0f6230e6bec26a..79f15fb8f4bfd6 100644 --- a/src/content/docs/durable-objects/examples/durable-object-in-memory-state.mdx +++ b/src/content/docs/durable-objects/examples/durable-object-in-memory-state.mdx @@ -2,15 +2,12 @@ type: example summary: Create a Durable Object that stores the last location it was accessed from in-memory. -tags: - - Durable Objects pcx_content_type: example title: Durable Object in-memory state sidebar: order: 3 description: Create a Durable Object that stores the last location it was accessed from in-memory. - --- import { WranglerConfig } from "~/components"; @@ -18,55 +15,55 @@ import { WranglerConfig } from "~/components"; This example shows you how Durable Objects are stateful, meaning in-memory state can be retained between requests. After a brief period of inactivity, the Durable Object will be evicted, and all in-memory state will be lost. The next request will reconstruct the object, but instead of showing the city of the previous request, it will display a message indicating that the object has been reinitialized. If you need your applications state to survive eviction, write the state to storage by using the [Storage API](/durable-objects/api/storage-api/), or by storing your data elsewhere. ```js -import { DurableObject } from 'cloudflare:workers'; +import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env) { - return await handleRequest(request, env); - } -} + async fetch(request, env) { + return await handleRequest(request, env); + }, +}; async function handleRequest(request, env) { - let id = env.LOCATION.idFromName("A"); - let obj = env.LOCATION.get(id); - // Forward the request to the remote Durable Object. - let resp = await obj.fetch(request); - // Return the response to the client. - return new Response(await resp.text()); + let id = env.LOCATION.idFromName("A"); + let obj = env.LOCATION.get(id); + // Forward the request to the remote Durable Object. + let resp = await obj.fetch(request); + // Return the response to the client. + return new Response(await resp.text()); } // Durable Object export class Location extends DurableObject { - constructor(state, env) { - this.state = state; - // Upon construction, you do not have a location to provide. - // This value will be updated as people access the Durable Object. - // When the Durable Object is evicted from memory, this will be reset. - this.location = null - } - - // Handle HTTP requests from clients. - async fetch(request) { - let response = null - - if (this.location == null) { - response = new String(` + constructor(state, env) { + this.state = state; + // Upon construction, you do not have a location to provide. + // This value will be updated as people access the Durable Object. + // When the Durable Object is evicted from memory, this will be reset. + this.location = null; + } + + // Handle HTTP requests from clients. + async fetch(request) { + let response = null; + + if (this.location == null) { + response = new String(` This is the first request, you called the constructor, so this.location was null. You will set this.location to be your city: (${request.cf.city}). Try reloading the page.`); - } else { - response = new String(` + } else { + response = new String(` The Durable Object was already loaded and running because it recently handled a request. Previous Location: ${this.location} New Location: ${request.cf.city}`); - } + } - // You set the new location to be the new city. - this.location = request.cf.city; - console.log(response); - return new Response(response); - } + // You set the new location to be the new city. + this.location = request.cf.city; + console.log(response); + return new Response(response); + } } ``` diff --git a/src/content/docs/durable-objects/examples/durable-object-ttl.mdx b/src/content/docs/durable-objects/examples/durable-object-ttl.mdx index 8495b826fc1a92..14e02bf77056d7 100644 --- a/src/content/docs/durable-objects/examples/durable-object-ttl.mdx +++ b/src/content/docs/durable-objects/examples/durable-object-ttl.mdx @@ -1,10 +1,6 @@ --- type: example summary: Implement a Time To Live (TTL) for Durable Object instances. -tags: - - Durable Objects - - Alarms - - API pcx_content_type: example title: Durable Object Time To Live sidebar: diff --git a/src/content/docs/durable-objects/examples/testing-with-durable-objects.mdx b/src/content/docs/durable-objects/examples/testing-with-durable-objects.mdx index 37a1c7e5a0470d..ca56d80dae991c 100644 --- a/src/content/docs/durable-objects/examples/testing-with-durable-objects.mdx +++ b/src/content/docs/durable-objects/examples/testing-with-durable-objects.mdx @@ -1,136 +1,150 @@ --- type: example summary: Write tests for Durable Objects. -tags: - - Durable Objects pcx_content_type: example title: Testing with Durable Objects sidebar: order: 3 description: Write tests for Durable Objects. - --- ```ts -import { unstable_dev } from "wrangler" -import type { UnstableDevWorker } from "wrangler" -import { describe, expect, it, beforeAll, afterAll } from "vitest" +import { unstable_dev } from "wrangler"; +import type { UnstableDevWorker } from "wrangler"; +import { describe, expect, it, beforeAll, afterAll } from "vitest"; describe("Worker", () => { - let worker: UnstableDevWorker - - beforeAll(async () => { - worker = await unstable_dev("src/index.ts", { - experimental: { disableExperimentalWarning: true }, - }); - }); - - afterAll(async () => { - await worker.stop() - }) - - it("should deny request for short paths", async () => { - const cases = { - failures: ["/", "/foo", "/foo/", "/%2F"], - } - for (const path of cases.failures) { - const resp = await worker.fetch(`http://example.com${path}`) - if (resp) { - const text = await resp.text() - expect(text).toMatchInlineSnapshot('"path must be at least 5 characters"') - } - } - }) - - describe("durable object", () => { - it("Should send text from a POST to a matching GET", async () => { - const path = "/stuff1" - const url = `http://example.com${path}` - - // The get request should wait for the post request to complete - const getResponsePromise = worker.fetch(url) - - // The post request to the same path should receive a response that the text was consumed - const postResponse = await worker.fetch(url, { method: "POST", body: "Hello World 12345" }) - expect(postResponse.status).toBe(200) - const postText = await postResponse.text() - expect(postText).toBe("The text was consumed!") - - // The get request should now receive the text - const getResponse = await getResponsePromise - expect(getResponse.status).toBe(200) - const text = await getResponse.text() - expect(text).toBe("Hello World 12345") - }) - - it("Shouldn't send text from a POST to a different GET", async () => { - const path1 = "/stuff1" - const path2 = "/stuff2" - const url = (p: string) => `http://example.com${p}` - - // The get request should wait for the post request to complete - const getResponsePromise1 = worker.fetch(url(path1)) - const getResponsePromise2 = worker.fetch(url(path2)) - - // The post request to the same path should receive a response that the text was consumed - const postResponse1 = await worker.fetch(url(path1), { method: "POST", body: "Hello World 12345" }) - expect(postResponse1.status).toBe(200) - const postText1 = await postResponse1.text() - expect(postText1).toBe("The text was consumed!") - - const postResponse2 = await worker.fetch(url(path2), { method: "POST", body: "Hello World 789" }) - expect(postResponse2.status).toBe(200) - const postText2 = await postResponse2.text() - expect(postText2).toBe("The text was consumed!") - - // The get request should now receive the text - const getResponse1 = await getResponsePromise1 - expect(getResponse1.status).toBe(200) - const text1 = await getResponse1.text() - expect(text1).toBe("Hello World 12345") - - const getResponse2 = await getResponsePromise2 - expect(getResponse2.status).toBe(200) - const text2 = await getResponse2.text() - expect(text2).toBe("Hello World 789") - }) - - it("Should not send the same POST twice", async () => { - const path = "/stuff1" - const url = (p: string) => `http://example.com${p}` - - // The get request should wait for the post request to complete - const getResponsePromise1 = worker.fetch(url(path)) - - // The post request to the same path should receive a response that the text was consumed - const postResponse1 = await worker.fetch(url(path), { method: "POST", body: "Hello World 12345" }) - expect(postResponse1.status).toBe(200) - const postText1 = await postResponse1.text() - expect(postText1).toBe("The text was consumed!") - - // The get request should now receive the text - const getResponse1 = await getResponsePromise1 - expect(getResponse1.status).toBe(200) - const text1 = await getResponse1.text() - expect(text1).toBe("Hello World 12345") - - // The next get request should wait for the next post request to complete - const getResponsePromise2 = worker.fetch(url(path)) - - // Send a new POST with different text - const postResponse2 = await worker.fetch(url(path), { method: "POST", body: "Hello World 789" }) - expect(postResponse2.status).toBe(200) - const postText2 = await postResponse2.text() - expect(postText2).toBe("The text was consumed!") - - // The get request should receive the new text, not the old text - const getResponse2 = await getResponsePromise2 - expect(getResponse2.status).toBe(200) - const text2 = await getResponse2.text() - expect(text2).toBe("Hello World 789") - }) - }) -}) + let worker: UnstableDevWorker; + + beforeAll(async () => { + worker = await unstable_dev("src/index.ts", { + experimental: { disableExperimentalWarning: true }, + }); + }); + + afterAll(async () => { + await worker.stop(); + }); + + it("should deny request for short paths", async () => { + const cases = { + failures: ["/", "/foo", "/foo/", "/%2F"], + }; + for (const path of cases.failures) { + const resp = await worker.fetch(`http://example.com${path}`); + if (resp) { + const text = await resp.text(); + expect(text).toMatchInlineSnapshot( + '"path must be at least 5 characters"', + ); + } + } + }); + + describe("durable object", () => { + it("Should send text from a POST to a matching GET", async () => { + const path = "/stuff1"; + const url = `http://example.com${path}`; + + // The get request should wait for the post request to complete + const getResponsePromise = worker.fetch(url); + + // The post request to the same path should receive a response that the text was consumed + const postResponse = await worker.fetch(url, { + method: "POST", + body: "Hello World 12345", + }); + expect(postResponse.status).toBe(200); + const postText = await postResponse.text(); + expect(postText).toBe("The text was consumed!"); + + // The get request should now receive the text + const getResponse = await getResponsePromise; + expect(getResponse.status).toBe(200); + const text = await getResponse.text(); + expect(text).toBe("Hello World 12345"); + }); + + it("Shouldn't send text from a POST to a different GET", async () => { + const path1 = "/stuff1"; + const path2 = "/stuff2"; + const url = (p: string) => `http://example.com${p}`; + + // The get request should wait for the post request to complete + const getResponsePromise1 = worker.fetch(url(path1)); + const getResponsePromise2 = worker.fetch(url(path2)); + + // The post request to the same path should receive a response that the text was consumed + const postResponse1 = await worker.fetch(url(path1), { + method: "POST", + body: "Hello World 12345", + }); + expect(postResponse1.status).toBe(200); + const postText1 = await postResponse1.text(); + expect(postText1).toBe("The text was consumed!"); + + const postResponse2 = await worker.fetch(url(path2), { + method: "POST", + body: "Hello World 789", + }); + expect(postResponse2.status).toBe(200); + const postText2 = await postResponse2.text(); + expect(postText2).toBe("The text was consumed!"); + + // The get request should now receive the text + const getResponse1 = await getResponsePromise1; + expect(getResponse1.status).toBe(200); + const text1 = await getResponse1.text(); + expect(text1).toBe("Hello World 12345"); + + const getResponse2 = await getResponsePromise2; + expect(getResponse2.status).toBe(200); + const text2 = await getResponse2.text(); + expect(text2).toBe("Hello World 789"); + }); + + it("Should not send the same POST twice", async () => { + const path = "/stuff1"; + const url = (p: string) => `http://example.com${p}`; + + // The get request should wait for the post request to complete + const getResponsePromise1 = worker.fetch(url(path)); + + // The post request to the same path should receive a response that the text was consumed + const postResponse1 = await worker.fetch(url(path), { + method: "POST", + body: "Hello World 12345", + }); + expect(postResponse1.status).toBe(200); + const postText1 = await postResponse1.text(); + expect(postText1).toBe("The text was consumed!"); + + // The get request should now receive the text + const getResponse1 = await getResponsePromise1; + expect(getResponse1.status).toBe(200); + const text1 = await getResponse1.text(); + expect(text1).toBe("Hello World 12345"); + + // The next get request should wait for the next post request to complete + const getResponsePromise2 = worker.fetch(url(path)); + + // Send a new POST with different text + const postResponse2 = await worker.fetch(url(path), { + method: "POST", + body: "Hello World 789", + }); + expect(postResponse2.status).toBe(200); + const postText2 = await postResponse2.text(); + expect(postText2).toBe("The text was consumed!"); + + // The get request should receive the new text, not the old text + const getResponse2 = await getResponsePromise2; + expect(getResponse2.status).toBe(200); + const text2 = await getResponse2.text(); + expect(text2).toBe("Hello World 789"); + }); + }); +}); ``` Find the [full code for this example on GitHub](https://github.com/jahands/do-demo). diff --git a/src/content/docs/durable-objects/examples/websocket-hibernation-server.mdx b/src/content/docs/durable-objects/examples/websocket-hibernation-server.mdx index 927ce9c5d46c62..08886312712501 100644 --- a/src/content/docs/durable-objects/examples/websocket-hibernation-server.mdx +++ b/src/content/docs/durable-objects/examples/websocket-hibernation-server.mdx @@ -3,26 +3,23 @@ type: example summary: Build a WebSocket server using WebSocket Hibernation on Durable Objects and Workers. tags: - - Durable Objects + - WebSockets pcx_content_type: example title: Build a WebSocket server with WebSocket Hibernation sidebar: order: 3 description: Build a WebSocket server using WebSocket Hibernation on Durable Objects and Workers. - --- -import { TabItem, Tabs, WranglerConfig } from "~/components" +import { TabItem, Tabs, WranglerConfig } from "~/components"; This example is similar to the [Build a WebSocket server](/durable-objects/examples/websocket-server/) example, but uses the WebSocket Hibernation API. The WebSocket Hibernation API should be preferred for WebSocket server applications built on Durable Objects, since it significantly decreases duration charge, and provides additional features that pair well with WebSocket applications. For more information, refer to [Use Durable Objects with WebSockets](/durable-objects/best-practices/websockets/). :::note - WebSocket Hibernation is unavailable for outgoing WebSocket use cases. Hibernation is only supported when the Durable Object acts as a server. For use cases where outgoing WebSockets are required, refer to [Write a WebSocket client](/workers/examples/websockets/#write-a-websocket-client). - ::: @@ -32,71 +29,73 @@ import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env, ctx) { - if (request.url.endsWith("/websocket")) { - // Expect to receive a WebSocket Upgrade request. - // If there is one, accept the request and return a WebSocket Response. - const upgradeHeader = request.headers.get('Upgrade'); - if (!upgradeHeader || upgradeHeader !== 'websocket') { - return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); - } - - // This example will refer to the same Durable Object, - // since the name "foo" is hardcoded. - let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo"); - let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id); - - return stub.fetch(request); - } - - return new Response(null, { - status: 400, - statusText: 'Bad Request', - headers: { - 'Content-Type': 'text/plain', - }, - }); - } + async fetch(request, env, ctx) { + if (request.url.endsWith("/websocket")) { + // Expect to receive a WebSocket Upgrade request. + // If there is one, accept the request and return a WebSocket Response. + const upgradeHeader = request.headers.get("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response("Durable Object expected Upgrade: websocket", { + status: 426, + }); + } + + // This example will refer to the same Durable Object, + // since the name "foo" is hardcoded. + let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo"); + let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id); + + return stub.fetch(request); + } + + return new Response(null, { + status: 400, + statusText: "Bad Request", + headers: { + "Content-Type": "text/plain", + }, + }); + }, }; // Durable Object export class WebSocketHibernationServer extends DurableObject { - - async fetch(request) { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } - - async webSocketMessage(ws, message) { - // Upon receiving a message from the client, reply with the same message, - // but will prefix the message with "[Durable Object]: " and return the - // total number of connections. - ws.send(`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`); - } - - async webSocketClose(ws, code, reason, wasClean) { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - } + async fetch(request) { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket + // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while + // the connection is open. During periods of inactivity, the Durable Object can be evicted + // from memory, but the WebSocket connection will remain open. If at some later point the + // WebSocket receives a message, the runtime will recreate the Durable Object + // (run the `constructor`) and deliver the message to the appropriate handler. + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } + + async webSocketMessage(ws, message) { + // Upon receiving a message from the client, reply with the same message, + // but will prefix the message with "[Durable Object]: " and return the + // total number of connections. + ws.send( + `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, + ); + } + + async webSocketClose(ws, code, reason, wasClean) { + // If the client closes the connection, the runtime will invoke the webSocketClose() handler. + ws.close(code, "Durable Object is closing WebSocket"); + } } - ``` @@ -105,73 +104,85 @@ export class WebSocketHibernationServer extends DurableObject { import { DurableObject } from "cloudflare:workers"; export interface Env { - WEBSOCKET_HIBERNATION_SERVER: DurableObjectNamespace; + WEBSOCKET_HIBERNATION_SERVER: DurableObjectNamespace; } // Worker export default { - async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { - if (request.url.endsWith("/websocket")) { - // Expect to receive a WebSocket Upgrade request. - // If there is one, accept the request and return a WebSocket Response. - const upgradeHeader = request.headers.get('Upgrade'); - if (!upgradeHeader || upgradeHeader !== 'websocket') { - return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); - } - - // This example will refer to the same Durable Object, - // since the name "foo" is hardcoded. - let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo"); - let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id); - - return stub.fetch(request); - } - - return new Response(null, { - status: 400, - statusText: 'Bad Request', - headers: { - 'Content-Type': 'text/plain', - }, - }); - } + async fetch( + request: Request, + env: Env, + ctx: ExecutionContext, + ): Promise { + if (request.url.endsWith("/websocket")) { + // Expect to receive a WebSocket Upgrade request. + // If there is one, accept the request and return a WebSocket Response. + const upgradeHeader = request.headers.get("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response("Durable Object expected Upgrade: websocket", { + status: 426, + }); + } + + // This example will refer to the same Durable Object, + // since the name "foo" is hardcoded. + let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo"); + let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id); + + return stub.fetch(request); + } + + return new Response(null, { + status: 400, + statusText: "Bad Request", + headers: { + "Content-Type": "text/plain", + }, + }); + }, }; // Durable Object export class WebSocketHibernationServer extends DurableObject { - - async fetch(request: Request): Promise { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } - - async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { - // Upon receiving a message from the client, the server replies with the same message, - // and the total number of connections with the "[Durable Object]: " prefix - ws.send(`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`); - } - - async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - } + async fetch(request: Request): Promise { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket + // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while + // the connection is open. During periods of inactivity, the Durable Object can be evicted + // from memory, but the WebSocket connection will remain open. If at some later point the + // WebSocket receives a message, the runtime will recreate the Durable Object + // (run the `constructor`) and deliver the message to the appropriate handler. + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } + + async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + ws.send( + `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, + ); + } + + async webSocketClose( + ws: WebSocket, + code: number, + reason: string, + wasClean: boolean, + ) { + // If the client closes the connection, the runtime will invoke the webSocketClose() handler. + ws.close(code, "Durable Object is closing WebSocket"); + } } ``` @@ -197,4 +208,4 @@ new_classes = ["WebSocketHibernationServer"] ### Related resources -* [Durable Objects: Edge Chat Demo with Hibernation](https://github.com/cloudflare/workers-chat-demo/). +- [Durable Objects: Edge Chat Demo with Hibernation](https://github.com/cloudflare/workers-chat-demo/). diff --git a/src/content/docs/durable-objects/examples/websocket-server.mdx b/src/content/docs/durable-objects/examples/websocket-server.mdx index 80047bbe15e170..71766b05988c3d 100644 --- a/src/content/docs/durable-objects/examples/websocket-server.mdx +++ b/src/content/docs/durable-objects/examples/websocket-server.mdx @@ -2,25 +2,22 @@ type: example summary: Build a WebSocket server using Durable Objects and Workers. tags: - - Durable Objects + - WebSockets pcx_content_type: example title: Build a WebSocket server sidebar: order: 3 description: Build a WebSocket server using Durable Objects and Workers. - --- -import { TabItem, Tabs, GlossaryTooltip, WranglerConfig } from "~/components" +import { TabItem, Tabs, GlossaryTooltip, WranglerConfig } from "~/components"; This example shows how to build a WebSocket server using Durable Objects and Workers. The example exposes an endpoint to create a new WebSocket connection. This WebSocket connection echos any message while including the total number of WebSocket connections currently established. For more information, refer to [Use Durable Objects with WebSockets](/durable-objects/best-practices/websockets/). :::caution - WebSocket connections pin your Durable Object to memory, and so duration charges will be incurred so long as the WebSocket is connected (regardless of activity). To avoid duration charges during periods of inactivity, use the [WebSocket Hibernation API](/durable-objects/examples/websocket-hibernation-server/), which only charges for duration when JavaScript is actively executing. - ::: @@ -30,75 +27,79 @@ import { DurableObject } from "cloudflare:workers"; // Worker export default { - async fetch(request, env, ctx) { - if (request.url.endsWith("/websocket")) { - // Expect to receive a WebSocket Upgrade request. - // If there is one, accept the request and return a WebSocket Response. - const upgradeHeader = request.headers.get('Upgrade'); - if (!upgradeHeader || upgradeHeader !== 'websocket') { - return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); - } - - // This example will refer to the same Durable Object, - // since the name "foo" is hardcoded. - let id = env.WEBSOCKET_SERVER.idFromName("foo"); - let stub = env.WEBSOCKET_SERVER.get(id); - - return stub.fetch(request); - } - - return new Response(null, { - status: 400, - statusText: 'Bad Request', - headers: { - 'Content-Type': 'text/plain', - }, - }); - } + async fetch(request, env, ctx) { + if (request.url.endsWith("/websocket")) { + // Expect to receive a WebSocket Upgrade request. + // If there is one, accept the request and return a WebSocket Response. + const upgradeHeader = request.headers.get("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response("Durable Object expected Upgrade: websocket", { + status: 426, + }); + } + + // This example will refer to the same Durable Object, + // since the name "foo" is hardcoded. + let id = env.WEBSOCKET_SERVER.idFromName("foo"); + let stub = env.WEBSOCKET_SERVER.get(id); + + return stub.fetch(request); + } + + return new Response(null, { + status: 400, + statusText: "Bad Request", + headers: { + "Content-Type": "text/plain", + }, + }); + }, }; // Durable Object export class WebSocketServer extends DurableObject { - currentlyConnectedWebSockets; - - constructor(ctx, env) { - // This is reset whenever the constructor runs because - // regular WebSockets do not survive Durable Object resets. - // - // WebSockets accepted via the Hibernation API can survive - // a certain type of eviction, but we will not cover that here. - super(ctx, env); - this.currentlyConnectedWebSockets = 0; - } - - async fetch(request) { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `accept()` tells the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - server.accept(); - this.currentlyConnectedWebSockets += 1; - - // Upon receiving a message from the client, the server replies with the same message, - // and the total number of connections with the "[Durable Object]: " prefix - server.addEventListener('message', (event) => { - server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`); - }); - - // If the client closes the connection, the runtime will close the connection too. - server.addEventListener('close', (cls) => { - this.currentlyConnectedWebSockets -= 1; - server.close(cls.code, "Durable Object is closing WebSocket"); - }); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } + currentlyConnectedWebSockets; + + constructor(ctx, env) { + // This is reset whenever the constructor runs because + // regular WebSockets do not survive Durable Object resets. + // + // WebSockets accepted via the Hibernation API can survive + // a certain type of eviction, but we will not cover that here. + super(ctx, env); + this.currentlyConnectedWebSockets = 0; + } + + async fetch(request) { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `accept()` tells the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + server.accept(); + this.currentlyConnectedWebSockets += 1; + + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + server.addEventListener("message", (event) => { + server.send( + `[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`, + ); + }); + + // If the client closes the connection, the runtime will close the connection too. + server.addEventListener("close", (cls) => { + this.currentlyConnectedWebSockets -= 1; + server.close(cls.code, "Durable Object is closing WebSocket"); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } } ``` @@ -108,80 +109,84 @@ export class WebSocketServer extends DurableObject { import { DurableObject } from "cloudflare:workers"; export interface Env { - WEBSOCKET_SERVER: DurableObjectNamespace; + WEBSOCKET_SERVER: DurableObjectNamespace; } // Worker export default { - async fetch(request, env, ctx): Promise { - if (request.url.endsWith("/websocket")) { - // Expect to receive a WebSocket Upgrade request. - // If there is one, accept the request and return a WebSocket Response. - const upgradeHeader = request.headers.get('Upgrade'); - if (!upgradeHeader || upgradeHeader !== 'websocket') { - return new Response('Durable Object expected Upgrade: websocket', { status: 426 }); - } - - // This example will refer to the same Durable Object, - // since the name "foo" is hardcoded. - let id = env.WEBSOCKET_SERVER.idFromName("foo"); - let stub = env.WEBSOCKET_SERVER.get(id); - - return stub.fetch(request); - } - - return new Response(null, { - status: 400, - statusText: 'Bad Request', - headers: { - 'Content-Type': 'text/plain', - }, - }); - } + async fetch(request, env, ctx): Promise { + if (request.url.endsWith("/websocket")) { + // Expect to receive a WebSocket Upgrade request. + // If there is one, accept the request and return a WebSocket Response. + const upgradeHeader = request.headers.get("Upgrade"); + if (!upgradeHeader || upgradeHeader !== "websocket") { + return new Response("Durable Object expected Upgrade: websocket", { + status: 426, + }); + } + + // This example will refer to the same Durable Object, + // since the name "foo" is hardcoded. + let id = env.WEBSOCKET_SERVER.idFromName("foo"); + let stub = env.WEBSOCKET_SERVER.get(id); + + return stub.fetch(request); + } + + return new Response(null, { + status: 400, + statusText: "Bad Request", + headers: { + "Content-Type": "text/plain", + }, + }); + }, } satisfies ExportedHandler; // Durable Object export class WebSocketServer extends DurableObject { - currentlyConnectedWebSockets: number; - - constructor(ctx: DurableObjectState, env: Env) { - // This is reset whenever the constructor runs because - // regular WebSockets do not survive Durable Object resets. - // - // WebSockets accepted via the Hibernation API can survive - // a certain type of eviction, but we will not cover that here. - super(ctx, env); - this.currentlyConnectedWebSockets = 0; - } - - async fetch(request: Request): Promise { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Calling `accept()` tells the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - server.accept(); - this.currentlyConnectedWebSockets += 1; - - // Upon receiving a message from the client, the server replies with the same message, - // and the total number of connections with the "[Durable Object]: " prefix - server.addEventListener('message', (event: MessageEvent) => { - server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`); - }); - - // If the client closes the connection, the runtime will close the connection too. - server.addEventListener('close', (cls: CloseEvent) => { - this.currentlyConnectedWebSockets -= 1; - server.close(cls.code, "Durable Object is closing WebSocket"); - }); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } + currentlyConnectedWebSockets: number; + + constructor(ctx: DurableObjectState, env: Env) { + // This is reset whenever the constructor runs because + // regular WebSockets do not survive Durable Object resets. + // + // WebSockets accepted via the Hibernation API can survive + // a certain type of eviction, but we will not cover that here. + super(ctx, env); + this.currentlyConnectedWebSockets = 0; + } + + async fetch(request: Request): Promise { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Calling `accept()` tells the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + server.accept(); + this.currentlyConnectedWebSockets += 1; + + // Upon receiving a message from the client, the server replies with the same message, + // and the total number of connections with the "[Durable Object]: " prefix + server.addEventListener("message", (event: MessageEvent) => { + server.send( + `[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`, + ); + }); + + // If the client closes the connection, the runtime will close the connection too. + server.addEventListener("close", (cls: CloseEvent) => { + this.currentlyConnectedWebSockets -= 1; + server.close(cls.code, "Durable Object is closing WebSocket"); + }); + + return new Response(null, { + status: 101, + webSocket: client, + }); + } } ``` @@ -207,4 +212,4 @@ new_classes = ["WebSocketServer"] ### Related resources -* [Durable Objects: Edge Chat Demo](https://github.com/cloudflare/workers-chat-demo). +- [Durable Objects: Edge Chat Demo](https://github.com/cloudflare/workers-chat-demo). diff --git a/src/content/docs/durable-objects/get-started/tutorial-with-sql-api.mdx b/src/content/docs/durable-objects/get-started/tutorial-with-sql-api.mdx index d458fcbafcf88b..206d2fc09c3e38 100644 --- a/src/content/docs/durable-objects/get-started/tutorial-with-sql-api.mdx +++ b/src/content/docs/durable-objects/get-started/tutorial-with-sql-api.mdx @@ -53,7 +53,7 @@ Running `create cloudflare@latest` will install [Wrangler](/workers/wrangler/ins product="workers" params={{ category: "hello-world", - type: "Hello World Worker Using Durable Objects", + type: "Worker + Durable Objects", lang: "TypeScript", }} /> @@ -229,8 +229,6 @@ Migrations are performed through the `[[migrations]]` configurations key in your The Durable Object migration to create a new Durable Object class with SQLite storage backend will look like the following in your Worker's Wrangler file: - - ```toml diff --git a/src/content/docs/durable-objects/get-started/tutorial.mdx b/src/content/docs/durable-objects/get-started/tutorial.mdx index 8e6dc725af81c5..6b24023470cd82 100644 --- a/src/content/docs/durable-objects/get-started/tutorial.mdx +++ b/src/content/docs/durable-objects/get-started/tutorial.mdx @@ -46,7 +46,7 @@ Running `create cloudflare@latest` will install [Wrangler](/workers/wrangler/ins product="workers" params={{ category: "hello-world", - type: "Hello World Worker using Durable Objects", + type: "Worker + Durable Objects", lang: "JavaScript / TypeScript", }} /> @@ -205,8 +205,6 @@ Migrations are performed through the `[[migrations]]` configurations key in your The Durable Object migration to create a new Durable Object class will look like the following in your Worker's Wrangler file: - - ```toml @@ -229,8 +227,6 @@ A Durable Object class can only have a single storage type, which cannot be chan To configure SQL storage and API, replace `new_classes` with `new_sqlite_classes` in your Worker's Wrangler file: - - ```toml diff --git a/src/content/docs/durable-objects/get-started/video-series/app-frontend.mdx b/src/content/docs/durable-objects/get-started/video-series/app-frontend.mdx deleted file mode 100644 index 4c700eab62ac02..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/app-frontend.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -pcx_content_type: video -title: Building the App Frontend and UI -sidebar: - order: 6 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -Now, we're moving to the frontend. In this video, we'll set up the frontend starter code (the starter code is located in the Veet GitHub repository), connect to Durable Objects using a call room ID, and display a local video preview. - -Useful links: - -- [GitHub code](https://github.com/megaconfidence/veet) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/deploy-app.mdx b/src/content/docs/durable-objects/get-started/video-series/deploy-app.mdx deleted file mode 100644 index d527e88abbb8e0..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/deploy-app.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -pcx_content_type: video -title: Deploy your Video Call app -sidebar: - order: 8 -prev: true -tableOfContents: false -next: - link: /durable-objects/examples/ - label: View more examples ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -We're almost done with the project, and in this video, we'll add the finishing touches. Learn how to handle call disconnections, wire up essential media controls like muting/unmuting and video toggling, and integrate a TURN server to ensure reliable connections even behind firewalls. By the end of this video, your app will be fully functional and ready for deployment. - -Useful links: - -- [GitHub code](https://github.com/megaconfidence/veet) -- [TURN service](/calls/turn/) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/durable-objects.mdx b/src/content/docs/durable-objects/get-started/video-series/durable-objects.mdx deleted file mode 100644 index 36d3e79181a23e..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/durable-objects.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -pcx_content_type: video -title: What are Durable Objects? -sidebar: - order: 3 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -In this video, we will show how Durable Objects work and start building a video call app together. - -Useful links: - -- [Sign up](https://dash.cloudflare.com/sign-up) for a Cloudflare account - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/index.mdx b/src/content/docs/durable-objects/get-started/video-series/index.mdx deleted file mode 100644 index 02e39e4204066d..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/index.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -pcx_content_type: navigation -title: Video series -sidebar: - order: 3 -next: true ---- - -import { DirectoryListing, Stream } from "~/components"; - -Building stateful apps on a serverless architecture has been difficult until Cloudflare's Durable Objects - a powerful API that enables you to easily build stateful serverless apps on Workers. In this series of videos, we will show how Durable Objects work and start building a video call app together. - -To get started, [create an account](https://dash.cloudflare.com/sign-up) on Cloudflare today for free. - - diff --git a/src/content/docs/durable-objects/get-started/video-series/intro.mdx b/src/content/docs/durable-objects/get-started/video-series/intro.mdx deleted file mode 100644 index 2f45db5a629d54..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/intro.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -pcx_content_type: navigation -title: Introduction -sidebar: - order: 2 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -In this episode, we will present an overview of the final project, discuss its underlying architecture, and access resources to set up the project locally. - -Useful links: - -- [GitHub code](https://github.com/megaconfidence/veet) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/make-answer-webrtc-calls.mdx b/src/content/docs/durable-objects/get-started/video-series/make-answer-webrtc-calls.mdx deleted file mode 100644 index f407403f6a935b..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/make-answer-webrtc-calls.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -pcx_content_type: video -title: Make and Answer WebRTC calls -sidebar: - order: 7 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -In this video, we'll build on the frontend we set up earlier by adding functionality for making and answering WebRTC video calls. You'll learn how to create peer-to-peer connections, handle ICE candidates, and seamlessly send and receive video streams between users. - -Useful links: - -- [GitHub code](https://github.com/megaconfidence/veet) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/real-time-messaging.mdx b/src/content/docs/durable-objects/get-started/video-series/real-time-messaging.mdx deleted file mode 100644 index b6d32518281136..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/real-time-messaging.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -pcx_content_type: video -title: Real-time messaging with WebSockets -sidebar: - order: 5 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -Now, we'll take it a step further by enabling our server to receive and broadcast messages. In this video, you'll learn how to route and broadcast incoming messages from WebSocket connections and implement error handling such as closed WebSocket connections. By the end, you will have completed the backend for our video call app. - -Useful links: - -- [GitHub code](https://github.com/megaconfidence/veet) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/get-started/video-series/serverless-websocket.mdx b/src/content/docs/durable-objects/get-started/video-series/serverless-websocket.mdx deleted file mode 100644 index 0d3f5d2cebae51..00000000000000 --- a/src/content/docs/durable-objects/get-started/video-series/serverless-websocket.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -pcx_content_type: video -title: Create a Serverless Websocket 'Backend' -sidebar: - order: 4 -prev: true -next: true -tableOfContents: false ---- - -import { Details, DirectoryListing, Stream } from "~/components"; - - - -In this video, we'll create a WebSocket backend using serverless technology, making the process simpler than ever before. You'll learn how to create your first Durable Object, set up a WebSocket server to coordinate connections, and keep track of connected clients. - -Useful links: - -- [CLI command](/pages/get-started/c3/) for creating new Workers and Pages projects -- [Hopscotch.io](https://hoppscotch.io/) for local WebSocket testing -- [GitHub code](https://github.com/megaconfidence/veet) - -
    - - - -
    diff --git a/src/content/docs/durable-objects/index.mdx b/src/content/docs/durable-objects/index.mdx index 15be50ea880416..610045a6194cf6 100644 --- a/src/content/docs/durable-objects/index.mdx +++ b/src/content/docs/durable-objects/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare Durable Objects order: 0 type: overview pcx_content_type: overview @@ -7,8 +7,7 @@ sidebar: order: 1 head: - tag: title - content: Cloudflare Durable Objects - + content: Overview --- import { Render, CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, LinkButton } from "~/components" diff --git a/src/content/docs/durable-objects/platform/index.mdx b/src/content/docs/durable-objects/platform/index.mdx index 7c3c97f7b5320e..1720605aee0206 100644 --- a/src/content/docs/durable-objects/platform/index.mdx +++ b/src/content/docs/durable-objects/platform/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Platform sidebar: - order: 11 + order: 12 group: hideIndex: true --- diff --git a/src/content/docs/durable-objects/platform/limits.mdx b/src/content/docs/durable-objects/platform/limits.mdx index 4a40aa2456332d..fc2d97f263eee7 100644 --- a/src/content/docs/durable-objects/platform/limits.mdx +++ b/src/content/docs/durable-objects/platform/limits.mdx @@ -44,7 +44,9 @@ For Durable Object classes with [SQLite storage backend](/durable-objects/best-p -## How much work can a single Durable Object do? +## Frequently Asked Questions + +### How much work can a single Durable Object do? Durable Objects can scale horizontally across many Durable Objects. Each individual Object is inherently single-threaded. @@ -54,7 +56,7 @@ Durable Objects can scale horizontally across many Durable Objects. Each individ A Durable Object that receives too many requests will, after attempting to queue them, return an [overloaded](/durable-objects/observability/troubleshooting/#durable-object-is-overloaded) error to the caller. -## How many Durable Objects can I create? +### How many Durable Objects can I create? Durable Objects are designed such that the number of individual objects in the system do not need to be limited, and can scale horizontally. diff --git a/src/content/docs/durable-objects/platform/pricing.mdx b/src/content/docs/durable-objects/platform/pricing.mdx index f13817b57511fa..c298448da7e4c1 100644 --- a/src/content/docs/durable-objects/platform/pricing.mdx +++ b/src/content/docs/durable-objects/platform/pricing.mdx @@ -118,3 +118,15 @@ In this scenario, the estimated monthly cost would be calculated as: ## Storage API billing + +## Frequently Asked Questions + +### Does an empty table / SQLite database contribute to my storage? + +Yes, although minimal. Empty tables can consume at least a few kilobytes, based on the number of columns (table width) in the table. An empty SQLite database consumes approximately 12 KB of storage. + +### Does metadata stored in Durable Objects count towards my storage? + +All writes to a SQLite-backed Durable Object stores nominal amounts of metadata in internal tables in the Durable Object, which counts towards your billable storage. + +The metadata remains in the Durable Object until you call [`deleteAll()`](/durable-objects/api/storage-api/#deleteall). \ No newline at end of file diff --git a/src/content/docs/durable-objects/reference/index.mdx b/src/content/docs/durable-objects/reference/index.mdx index 9dafbc86d4897b..adcefc0bc39146 100644 --- a/src/content/docs/durable-objects/reference/index.mdx +++ b/src/content/docs/durable-objects/reference/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: navigation title: Reference sidebar: - order: 12 + order: 13 group: hideIndex: true --- diff --git a/src/content/docs/durable-objects/changelog.mdx b/src/content/docs/durable-objects/release-notes.mdx similarity index 93% rename from src/content/docs/durable-objects/changelog.mdx rename to src/content/docs/durable-objects/release-notes.mdx index 313393199a27e6..f757617cd792de 100644 --- a/src/content/docs/durable-objects/changelog.mdx +++ b/src/content/docs/durable-objects/release-notes.mdx @@ -1,10 +1,10 @@ --- pcx_content_type: changelog -title: Changelog +title: Release notes release_notes_file_name: - durable-objects sidebar: - order: 15 + order: 20 --- import { ProductReleaseNotes } from "~/components"; diff --git a/src/content/docs/durable-objects/tutorials/build-a-seat-booking-app/index.mdx b/src/content/docs/durable-objects/tutorials/build-a-seat-booking-app/index.mdx index 7c14d279427bc1..ac115b0a9e16de 100644 --- a/src/content/docs/durable-objects/tutorials/build-a-seat-booking-app/index.mdx +++ b/src/content/docs/durable-objects/tutorials/build-a-seat-booking-app/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-09-24 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a seat booking app with SQLite in Durable Objects products: @@ -63,7 +62,7 @@ Create a new Worker project to create and deploy your app. product="workers" params={{ category: "hello-world", - type: "Hello World Worker Using Durable Objects", + type: "Worker + Durable Objects", lang: "TypeScript", }} /> diff --git a/src/content/docs/durable-objects/video-tutorials.mdx b/src/content/docs/durable-objects/video-tutorials.mdx new file mode 100644 index 00000000000000..58f47d42a908b5 --- /dev/null +++ b/src/content/docs/durable-objects/video-tutorials.mdx @@ -0,0 +1,18 @@ +--- +pcx_content_type: navigation +title: Videos +sidebar: + order: 11 +--- + +import { CardGrid, LinkCard } from "~/components"; + + + + + + diff --git a/src/content/docs/email-routing/email-workers/reply-email-workers.mdx b/src/content/docs/email-routing/email-workers/reply-email-workers.mdx index a35ec6378b2d4e..5e2cb2173a8fd9 100644 --- a/src/content/docs/email-routing/email-workers/reply-email-workers.mdx +++ b/src/content/docs/email-routing/email-workers/reply-email-workers.mdx @@ -40,12 +40,12 @@ export default { } ``` -To mitigate security risks and abuse, replying to incoming emails has a few requirements: +To mitigate security risks and abuse, replying to incoming emails has a few requirements and limits: * The incoming email has to have valid [DMARC](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/). * The email can only be replied to once in the same `EmailMessage` event. -* The `In-Reply-To` header of the reply message must be set to the `Message-ID` of the incoming message. * The recipient in the reply must match the incoming sender. * The outgoing sender domain must match the same domain that received the email. +* Every time an email passes through Email Routing or another MTA, an entry is added to the `References` list. We stop accepting replies to emails with more than 100 `References` entries to prevent abuse or accidental loops. -If these and other internal conditions are not met, then `reply()` will fail with an exception, otherwise you can freely compose your reply message and send it back to the original sender. +If these and other internal conditions are not met, `reply()` will fail with an exception. Otherwise, you can freely compose your reply message, send it back to the original sender, and receive subsequent replies multiple times. \ No newline at end of file diff --git a/src/content/docs/email-routing/index.mdx b/src/content/docs/email-routing/index.mdx index baf8dad35048fc..62fd387e595337 100644 --- a/src/content/docs/email-routing/index.mdx +++ b/src/content/docs/email-routing/index.mdx @@ -1,19 +1,18 @@ --- -title: Overview +title: Cloudflare Email Routing pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Email Routing - + content: Overview --- import { Description, Feature, Plan, RelatedProduct, Render } from "~/components" -Create custom email addresses for your domain and route incoming emails to your preferred mailbox. +Create custom email addresses for your domain and route incoming emails to your preferred mailbox. @@ -27,15 +26,15 @@ It is available to all Cloudflare customers [using Cloudflare as an authoritativ ## Features -Leverage the power of Cloudflare Workers to implement any logic you need to process your emails. Create rules as complex or simple as you need. +Leverage the power of Cloudflare Workers to implement any logic you need to process your emails. Create rules as complex or simple as you need. -With Email Routing you can have many custom email addresses to use for specific situations. +With Email Routing you can have many custom email addresses to use for specific situations. -Email Routing includes metrics to help you check on your email traffic history. +Email Routing includes metrics to help you check on your email traffic history. *** @@ -43,9 +42,9 @@ Email Routing includes metrics to help you check on your email traffic history. ## Related products -Cloudflare Area 1 Email Security is a cloud-native service that stops phishing attacks, the biggest cybersecurity threat, across all threat vectors - email, web, and network - either at the edge or in the cloud. +Cloudflare Area 1 Email Security is a cloud-native service that stops phishing attacks, the biggest cybersecurity threat, across all threat vectors - email, web, and network - either at the edge or in the cloud. -Email Routing is available to customers using Cloudflare as an authoritative nameserver. +Email Routing is available to customers using Cloudflare as an authoritative nameserver. diff --git a/src/content/docs/email-routing/postmaster.mdx b/src/content/docs/email-routing/postmaster.mdx index 39149664484a58..5602e436cee8f8 100644 --- a/src/content/docs/email-routing/postmaster.mdx +++ b/src/content/docs/email-routing/postmaster.mdx @@ -28,17 +28,22 @@ The best way to contact us is using our [community forum](https://community.clou Through this standard, the sender publishes its public key to a domain's DNS once, and then signs the body of each message before it leaves the server. The recipient server reads the message, gets the domain public key from the domain's DNS, and validates the signature to ensure the message was not altered in transit. -Email Routing signs email on behalf of `email.cloudflare.net`. If the sender did not sign the email, the receiver will likely use Cloudflare's signature for authentication. +Email Routing adds two new signatures to the emails in transit, one on behalf of the Cloudflare domain used for sender rewriting `email.cloudflare.net`, and another one on behalf of the customer's recipient domain. Below is the DKIM key for `email.cloudflare.net`: ```sh -dig TXT 2022._domainkey.email.cloudflare.net +short +dig TXT cf2024-1._domainkey.email.cloudflare.net +short ``` ```sh output +"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiweykoi+o48IOGuP7GR3X0MOExCUDY/BCRHoWBnh3rChl7WhdyCxW3jgq1daEjPPqoi7sJvdg5hEQVsgVRQP4DcnQDVjGMbASQtrY4WmB1VebF+RPJB2ECPsEDTpeiI5ZyUAwJaVX7r6bznU67g7LvFq35yIo4sdlmtZGV+i0H4cpYH9+3JJ78k" "m4KXwaf9xUJCWF6nxeD+qG6Fyruw1Qlbds2r85U9dkNDVAS3gioCvELryh1TxKGiVTkg4wqHTyHfWsp7KD3WQHYJn0RyfJJu6YEmL77zonn7p2SRMvTMP3ZEXibnC9gz3nnhR6wcYL8Q7zXypKTMD58bTixDSJwIDAQAB" +``` + +You can find the DKIM key for the customer's `example.com` domain by querying the following: -"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnraPy1d8e6+lzeE1HIoUvYWoAOUSREkNHcwxA/ueVM8f6FKXvPu/9gVpgkn8iUyaCfk2z1MW+OVLuFeH64YRMa39mkaQalgke2tZ05SnjRUtYEHYvfrqPuMT+Ouk+GecpgvrtMq5gMXm6ZfeUhQkdWxmMQJGf4fdW5I0piUQJMhK/Qc1dNRSskk" "TiUtXKnsEdjTN2xcnHhyj985S0xOEAxm9Uj1rykPqVvKpqEdjUkujbXOwR0KmHTvPyFpBjCCfxAVqOwwo9zBYuvk/nh0qlDgLIpy0SimrYhNFCq2XBxIj4tdUzIl7qZ5Ck6zLCQ+rjzJ4sm/zA+Ov9kDkbcmyrwIDAQAB" +```sh +dig TXT cf2024-1._domainkey.example.com +short ``` ### DMARC enforcing @@ -88,14 +93,34 @@ example.com. 300 IN TXT "v=spf1 include:_spf.mx.cloudflare.net ~all" [The MX (mail exchange) records](https://www.cloudflare.com/learning/dns/dns-records/dns-mx-record/) tell the Internet where the inbound servers receiving email messages for the zone are. In this case, anyone who wants to send an email to `example.com` can use the `amir.mx.cloudflare.net`, `linda.mx.cloudflare.net`, or `isaac.mx.cloudflare.net` SMTP servers. +### Outbound prefixes + +Email Routing sends its traffic using both IPv4 and IPv6 prefixes, when supported by the upstream SMTP server. + +If you are a postmaster and are having trouble receiving Email Routing's emails, allow the following outbound IP addresses in your server configuration: + +**IPv4** + +`104.30.0.0/19` + +**IPv6** + +`2405:8100:c000::/38` + +_Ranges last updated: December 13th, 2023_ + ### Outbound hostnames -In addition to the outbound prefixes, Email Routing will use the domain `email.cloudflare.net` for the `HELO/EHLO` command. +In addition to the outbound prefixes, Email Routing will use the following outbound domains for the `HELO/EHLO` command: + +- `cloudflare-email.net` +- `cloudflare-email.org` +- `cloudflare-email.com` PTR records (reverse DNS) ensure that each hostname has an corresponding IP. For example: ```sh -dig a0-7.email.cloudflare.net +short +dig a-h.cloudflare-email.net +short ``` ```sh output @@ -107,25 +132,9 @@ dig -x 104.30.0.7 +short ``` ```sh output -a0-7.email.cloudflare.net. +a-h.cloudflare-email.net. ``` -### Outbound prefixes - -Email Routing sends its traffic using both IPv4 and IPv6 prefixes, when supported by the upstream SMTP server. - -If you are a postmaster and are having trouble receiving Email Routing's emails, allow the following outbound IP addresses in your server configuration: - -**IPv4** - -`104.30.0.0/20` - -**IPv6** - -`2405:8100:c000::/38` - -_Ranges last updated: December 13th, 2023_ - ### Sender rewriting Email Routing rewrites the SMTP envelope sender (`MAIL FROM`) to the forwarding domain to avoid issues with [SPF](#spf-record). Email Routing uses the [Sender Rewriting Scheme](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme) to achieve this. @@ -136,14 +145,27 @@ This has no effect to the end user's experience, though. The message headers wil In most cases, Email Routing forwards the upstream SMTP errors back to the sender client in-session. -### Spam and abusive traffic +### Realtime Block Lists -Handling spam and abusive traffic is essential to any email provider. Email Routing filters emails based on advanced anti-spam criteria, [powered by Email Security (formerly Area 1)](/email-security/). When Email Routing detects and blocks a spam email, you will receive a message with details explaining what happened. For example: +Email Routing uses an internal Domain Name System Blocklists (DNSBL) service to check if the sender's IP is present in one or more Realtime Block Lists (RBL) lists. When the system detects an abusive IP, it blocks the email and returns an SMTP error: ```txt -554 found on one or more DNSBLs (abusixip). Refer to https://developers.cloudflare.com/email-routing/postmaster/#spam-and-abusive-traffic/ +554 found on one or more RBLs (abusixip). Refer to https://developers.cloudflare.com/email-routing/postmaster/#spam-and-abusive-traffic/ +``` +We update our RBLs regularly. You can use combined block list lookup services like [MxToolbox](https://mxtoolbox.com/blacklists.aspx) to check if your IP matches other RBLs. IP reputation blocks are usually temporary, but if you feel your IP should be removed immediately, please contact the RBL's maintainer mentioned in the SMTP error directly. + +### Anti-spam + +In addition to DNSBL, Email Routing uses advanced heuristic and statistical analysis of the email's headers and text to calculate a spam score. We inject the score in the custom `X-Cf-Spamh-Score` header: + +``` +X-Cf-Spamh-Score: 2 ``` +This header is visible in the forwarded email. The higher the score, 5 being the maximum, the more likely the email is spam. Currently, this system is experimental and passive; we do not act on it and suggest that upstream servers and email clients don't act on it either. + +We will update this page with more information as we fine-tune the system. + ### SPF record A SPF DNS record is an anti-spoofing mechanism that is used to specify which IP addresses and domains are allowed to send emails on behalf of your zone. @@ -204,4 +226,4 @@ Email Routing does not support sending or replying from your Cloudflare domain. ### Signs such "`+`" and "`.`" are treated as normal characters for custom addresses -Email Routing does not have advanced routing options. Characters such as `+` or `.`, which perform special actions in email providers like Gmail and Outlook, are currently treated as normal characters on custom addresses. More flexible routing options are in our roadmap. +Email Routing does not have advanced routing options. Characters such as `+` or `.`, which perform special actions in email providers like Gmail and Outlook, are currently treated as normal characters on custom addresses. More flexible routing options are in our roadmap. \ No newline at end of file diff --git a/src/content/docs/email-security/index.mdx b/src/content/docs/email-security/index.mdx index 2aeb9f525241b6..dca369cc293b45 100644 --- a/src/content/docs/email-security/index.mdx +++ b/src/content/docs/email-security/index.mdx @@ -18,7 +18,7 @@ Stop phishing attacks with Em :::caution[Area 1 has been renamed] - +Area 1 is now **Email Security (formerly Area 1)**. Customers who purchased the new Email Security can access the documentation by going to Cloudflare Zero Trust > [Email Security](/cloudflare-one/email-security/). ::: diff --git a/src/content/docs/fundamentals/api/how-to/create-via-api.mdx b/src/content/docs/fundamentals/api/how-to/create-via-api.mdx index b3ea27fb775a72..81c63fa9b8f130 100644 --- a/src/content/docs/fundamentals/api/how-to/create-via-api.mdx +++ b/src/content/docs/fundamentals/api/how-to/create-via-api.mdx @@ -1,6 +1,7 @@ --- title: Create tokens via API pcx_content_type: how-to +description: Learn how to create API tokens via Cloudflare's API. Follow steps to define access policies, set restrictions, and generate tokens securely. sidebar: order: 3 @@ -24,7 +25,7 @@ Cloudflare also recommends limiting the use of the token via client IP address f ## Creating API tokens with the API -You can create a user owned token or account owned token to use with the API. Refer to the [user owned token](/api/resources/user/subresources/tokens/methods/create/) or the [account owned token](/api/resources/accounts/subresources/tokens/methods/create/) API schema docs for more information. +You can create a user owned token or account owned token to use with the API. Refer to the [user owned token](/api/resources/user/subresources/tokens/methods/create/) or the [account owned token](/api/resources/accounts/subresources/tokens/methods/create/) API schema docs for more information. To create a token: @@ -75,7 +76,7 @@ API token policies support three resource types: `User`, `Account`, and `Zone`. :::note -Fetch each object's ID by calling the appropriate `GET ` API. Refer to [User](/api/resources/user/methods/get/), [Account](/api/resources/accounts/methods/list/), and [Zone](/api/resources/zones/methods/list/) documentation for more details. +Fetch each object's ID by calling the appropriate `GET ` API. Refer to [User](/api/resources/user/methods/get/), [Account](/api/resources/accounts/methods/list/), and [Zone](/api/resources/zones/methods/list/) documentation for more details. ::: ##### Account diff --git a/src/content/docs/fundamentals/api/how-to/make-api-calls.mdx b/src/content/docs/fundamentals/api/how-to/make-api-calls.mdx index ed530bf960c4f7..837e261cfc0a25 100644 --- a/src/content/docs/fundamentals/api/how-to/make-api-calls.mdx +++ b/src/content/docs/fundamentals/api/how-to/make-api-calls.mdx @@ -1,5 +1,6 @@ --- title: Make API calls +description: Learn how to make API calls using Cloudflare's API with step-by-step instructions for Windows, including using curl and PowerShell, and handling JSON. pcx_content_type: how-to sidebar: order: 2 diff --git a/src/content/docs/fundamentals/api/reference/permissions.mdx b/src/content/docs/fundamentals/api/reference/permissions.mdx index a47dffbcf81798..cbd21f41507e78 100644 --- a/src/content/docs/fundamentals/api/reference/permissions.mdx +++ b/src/content/docs/fundamentals/api/reference/permissions.mdx @@ -39,14 +39,20 @@ The applicable scope of account permissions is `com.cloudflare.api.account`. @@ -57,10 +63,16 @@ The applicable scope of zone permissions is `com.cloudflare.api.account.zone`. - + - + diff --git a/src/content/docs/fundamentals/api/troubleshooting.mdx b/src/content/docs/fundamentals/api/troubleshooting.mdx index 1a64847c9b1dac..cf71271be903c4 100644 --- a/src/content/docs/fundamentals/api/troubleshooting.mdx +++ b/src/content/docs/fundamentals/api/troubleshooting.mdx @@ -5,7 +5,7 @@ sidebar: order: 5 head: - tag: title - content: Troubleshooting | Cloudflare API + content: Troubleshooting | Cloudflare API --- ## The token is not verified diff --git a/src/content/docs/fundamentals/concepts/how-cloudflare-works.mdx b/src/content/docs/fundamentals/concepts/how-cloudflare-works.mdx index 65f4f568ecc5d0..3301426e46be50 100644 --- a/src/content/docs/fundamentals/concepts/how-cloudflare-works.mdx +++ b/src/content/docs/fundamentals/concepts/how-cloudflare-works.mdx @@ -27,7 +27,7 @@ When you onboard your website or application to Cloudflare, Cloudflare becomes t Cloudflare only becomes the primary authoritative DNS provider when you use the default, full DNS setup. For alternative options, refer to [DNS setups](/dns/zone-setups/). ::: -If your [domain's status](/dns/zone-setups/reference/domain-status/) is active and the queried DNS record is set to `proxied`, Cloudflare responds with an [anycast IP address](/fundamentals/concepts/cloudflare-ip-addresses/), instead of the origin IP address defined in your DNS table. +If your [domain's status](/dns/zone-setups/reference/domain-status/) is active and the queried DNS record is set to `proxied`, Cloudflare responds with an [anycast IP address](/fundamentals/concepts/cloudflare-ip-addresses/), instead of the origin IP address defined in your DNS table. Your domain status is active when your [nameservers are updated](/dns/nameservers/update-nameservers/) to point to Cloudflare and have been authenticated. The [proxy status](/dns/proxy-status/) defines how Cloudflare treats queries for specific DNS records. The [anycast IP address](/fundamentals/concepts/cloudflare-ip-addresses/) is used to distribute traffic amongst Cloudflare's network, which protects your website or app from [DDoS](https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/) and other attacks, while optimizing site speed. @@ -37,7 +37,7 @@ A reverse proxy is a network of servers that sits in front of web servers and ei ![The flow of a request from a server through Cloudflare to the origin server when Cloudflare is a reverse proxy.](~/assets/images/fundamentals/reverse-proxy.png) -When Cloudflare receives a DNS query for your domain, the response is determined by the configuration [set in your DNS table](/dns/manage-dns-records/how-to/create-dns-records/), including the [type of the record](/dns/manage-dns-records/reference/dns-record-types/), the record's [proxy eligibility](/dns/proxy-status/limitations/#proxy-eligibility), and its [proxy status](/dns/proxy-status/#proxy-eligibility). +When Cloudflare receives a DNS query for your domain, the response is determined by the configuration [set in your DNS table](/dns/manage-dns-records/how-to/create-dns-records/), including the [type of the record](/dns/manage-dns-records/reference/dns-record-types/), the record's [proxy eligibility](/dns/proxy-status/limitations/#proxy-eligibility), and its [proxy status](/dns/proxy-status/#proxied-records). When DNS records in your DNS table have a `proxied` status, the record's HTTP/HTTPS traffic will route through Cloudflare on its way between the client and the origin server. If the domain's status is active, all HTTP/HTTPS requests for proxied DNS records route through Cloudflare. diff --git a/src/content/docs/fundamentals/index.mdx b/src/content/docs/fundamentals/index.mdx index e47ab4e661f826..3ac127864c59d0 100644 --- a/src/content/docs/fundamentals/index.mdx +++ b/src/content/docs/fundamentals/index.mdx @@ -1,14 +1,16 @@ --- -title: Overview +title: Cloudflare Fundamentals pcx_content_type: overview sidebar: order: 1 - +head: + - tag: title + content: Overview --- -import { Render } from "~/components" +import { Render } from "~/components"; -Cloudflare helps connect and protect millions of customers globally. Everyone from individuals to the world's largest enterprises use our unified platform of networking, security, and developer services to succeed everywhere in the world. + Before you get started, we recommend reviewing [Concepts](/fundamentals/concepts/) to learn about key concepts related to using different Cloudflare products. diff --git a/src/content/docs/fundamentals/reference/connection-limits.mdx b/src/content/docs/fundamentals/reference/connection-limits.mdx index 65135605f8ecd0..d07460fa0f6744 100644 --- a/src/content/docs/fundamentals/reference/connection-limits.mdx +++ b/src/content/docs/fundamentals/reference/connection-limits.mdx @@ -6,7 +6,7 @@ title: Connection limits import { GlossaryTooltip } from "~/components" -When HTTP/HTTPS traffic is [proxied through Cloudflare](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-reverse-proxy), there are often two established [TCP connections](/fundamentals/reference/tcp-connections/): the first is between the requesting client to Cloudflare and the second is between Cloudflare and the origin server. Each connection has their own set of TCP and HTTP limits, which are documented below. +When HTTP/HTTPS traffic is [proxied through Cloudflare](/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy), there are often two established [TCP connections](/fundamentals/reference/tcp-connections/): the first is between the requesting client to Cloudflare and the second is between Cloudflare and the origin server. Each connection has their own set of TCP and HTTP limits, which are documented below. ## Between client and Cloudflare @@ -19,7 +19,7 @@ When HTTP/HTTPS traffic is [proxied through Cloudflare](/fundamentals/concepts/h :::note -If you are using [Cloudflare tunnels](/cloudflare-one/connections/connect-networks/), refer to [Origin configuration](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/) to view or modify your connection settings. +If you are using [Cloudflare tunnels](/cloudflare-one/connections/connect-networks/), refer to [Origin configuration](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/) to view or modify your connection settings. ::: | Type | Limit (seconds) | HTTP status code at limit | [Configurable](/fundamentals/reference/connection-limits/#configurable-limits) | diff --git a/src/content/docs/fundamentals/reference/policies-compliances/cloudflare-cookies.mdx b/src/content/docs/fundamentals/reference/policies-compliances/cloudflare-cookies.mdx index a13788f072c618..1f98319f8973c3 100644 --- a/src/content/docs/fundamentals/reference/policies-compliances/cloudflare-cookies.mdx +++ b/src/content/docs/fundamentals/reference/policies-compliances/cloudflare-cookies.mdx @@ -46,7 +46,7 @@ Bot Management is available to Enterprise customers as an add-on service. Contac ### cf_clearance cookie for Cloudflare bot products -The `cf_clearance` cookie is required for [JavaScript detections](/bots/reference/javascript-detections/). JavaScript detections are stored in the `cf_clearance` cookie. +The `cf_clearance` cookie is required for [JavaScript detections](/bots/reference/javascript-detections/). JavaScript detections are stored in the `cf_clearance` cookie. ### cf\_ob\_info and cf\_use\_ob cookie for Cloudflare Always Online diff --git a/src/content/docs/fundamentals/reference/policies-compliances/compliance-docs.mdx b/src/content/docs/fundamentals/reference/policies-compliances/compliance-docs.mdx index ad7eee8aa691dd..d61b7843c810ad 100644 --- a/src/content/docs/fundamentals/reference/policies-compliances/compliance-docs.mdx +++ b/src/content/docs/fundamentals/reference/policies-compliances/compliance-docs.mdx @@ -15,7 +15,7 @@ To access compliance documentation: :::note -For confidentiality purposes, only **Super Administrators** for an account can access compliance documentation. +For confidentiality purposes, only **Super Administrators** for an account can access compliance documentation. ::: ## Tax documentation diff --git a/src/content/docs/fundamentals/reference/report-abuse/abuse-report-obligations.mdx b/src/content/docs/fundamentals/reference/report-abuse/abuse-report-obligations.mdx index 3460114e27838b..e38def1dab841e 100644 --- a/src/content/docs/fundamentals/reference/report-abuse/abuse-report-obligations.mdx +++ b/src/content/docs/fundamentals/reference/report-abuse/abuse-report-obligations.mdx @@ -16,6 +16,6 @@ Our Trust & Safety team sends abuse reports to the domain owner or the abuse poi To assist with timely resolution and avoid potential service interruptions: -* Confirm that the administrator email address associated with your account is actively managed and monitored for potential abuse report notifications. +* Confirm that the [abuse contact email address](/fundamentals/setup/account/account-security/abuse-contact/) associated with your account is actively managed and monitored for potential abuse report notifications. * Consider using a mailing list email address that goes to multiple people or teams within your organization instead of the email address for an individual person. * Respond to any abuse report notification within 24 hours. In your response, include any information that you believe will be relevant to Cloudflare in its assessment of the abuse report. Failure to respond in a timely manner or to address the concerns in the abuse report may result in the removal or blocking of reported content, websites, or apps and suspension or termination of Cloudflare services for the associated account. diff --git a/src/content/docs/fundamentals/reference/sdk-ecosystem-support-policy.mdx b/src/content/docs/fundamentals/reference/sdk-ecosystem-support-policy.mdx index d603106555bb5c..d4359d8e0f5d02 100644 --- a/src/content/docs/fundamentals/reference/sdk-ecosystem-support-policy.mdx +++ b/src/content/docs/fundamentals/reference/sdk-ecosystem-support-policy.mdx @@ -14,7 +14,7 @@ We provide three primary stages of development: early access, active support, an :::note -These lifecycle stages may be referred to in different terms across Cloudflare products, but the underlying principles are the same. +These lifecycle stages may be referred to in different terms across Cloudflare products, but the underlying principles are the same. ::: ### Early access @@ -47,7 +47,7 @@ The SDK ecosystem follows semantic versioning, which defines versions as follows As Cloudflare has recently swapped to [automatically generating our libraries using OpenAPI](https://blog.cloudflare.com/lessons-from-building-an-automated-sdk-pipeline), we have relaxed the strict versioning requirements on the libraries (Terraform is not changing). Minor releases *may* contain breaking changes in the forms of method, structure, or type renames as the service owners stabilize their schemas and iterate on usability improvements. -If this is not suitable for your use case, pin to a known good version or use the previous major version of the library. +If this is not suitable for your use case, pin to a known good version or use the previous major version of the library. ::: Depending on your needs, you should ensure your application's package manager versioning is configured correctly. At a minimum, restrict installation to the current major version of the library or tool you are using to prevent any major version upgrades occurring automatically. diff --git a/src/content/docs/fundamentals/reference/under-attack-mode.mdx b/src/content/docs/fundamentals/reference/under-attack-mode.mdx index df35ff624991b1..acf75f2c931d57 100644 --- a/src/content/docs/fundamentals/reference/under-attack-mode.mdx +++ b/src/content/docs/fundamentals/reference/under-attack-mode.mdx @@ -2,31 +2,29 @@ pcx_content_type: reference source: https://support.cloudflare.com/hc/en-us/articles/200170076-Understanding-Cloudflare-Under-Attack-mode-advanced-DDOS-protection- title: Under Attack mode - --- import { Example } from "~/components" -Cloudflare's **I'm Under Attack Mode** performs additional security checks to help mitigate layer 7 DDoS attacks. Validated users access your website and suspicious traffic is blocked. It is designed to be used as one of the last resorts when a zone is under attack (and will temporarily pause access to your site and impact your site analytics). +Cloudflare's Under Attack mode performs additional security checks to help mitigate layer 7 DDoS attacks. Validated users access your website and suspicious traffic is blocked. It is designed to be used as one of the last resorts when a zone is under attack (and will temporarily pause access to your site and impact your site analytics). When enabled, visitors receive an interstitial page. -## Enable Under Attack mode +## Turn on Under Attack mode -**I'm Under Attack Mode** is disabled by default for your zone. +Under Attack mode is turned off by default for your zone. ### Globally -To put your entire zone in **I'm Under Attack Mode**: +To put your entire zone in Under Attack mode: -1. Log into the [Cloudflare dashboard](https://dash.cloudflare.com). +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com). 2. Select your account and zone. -3. Go to **Security** > **Settings**. -4. For **Security Level**, choose **I'm Under Attack!**. +3. In the zone overview page, turn on **Under Attack Mode** in the **Quick Actions** sidebar. ### Selectively -To enable **I'm Under Attack Mode** for specific pages or sections of your site, use a [Configuration Rule](/rules/configuration-rules/) to adjust the **Security Level**. +To enable Under Attack mode for specific pages or sections of your site, use a [configuration rule](/rules/configuration-rules/) to adjust the **Security Level**. @@ -48,11 +46,11 @@ If you are using the Expression Editor, enter the following expression:
    To turn it on for specific ASNs (hosts/ISPs that own IP addresses), countries, or IP ranges, use [IP Access Rules](/waf/tools/ip-access-rules/). -*** +--- ## Preview Under Attack mode -To preview what **I'm Under Attack** mode looks like for your visitors: +To preview what Under Attack mode looks like for your visitors: 1. Log into the [Cloudflare dashboard](https://dash.cloudflare.com). 2. Select your account. @@ -60,9 +58,9 @@ To preview what **I'm Under Attack** mode looks like for your visitors: 4. Go to **Custom Pages**. 5. For **Managed Challenge / I'm Under Attack Mode™**, select **Custom Pages** > **View default**. -The "Checking your browser before accessing..." challenge determines whether to block or allow a visitor within five seconds. After passing the challenge, the visitor does not observe another challenge until the duration configured in [**Challenge Passage**](/waf/tools/challenge-passage/). +The `Checking your browser before accessing...` challenge determines whether to block or allow a visitor within five seconds. After passing the challenge, the visitor does not observe another challenge until the duration configured in [Challenge Passage](/waf/tools/challenge-passage/). -*** +--- ## Potential issues diff --git a/src/content/docs/fundamentals/security/under-ddos-attack.mdx b/src/content/docs/fundamentals/security/under-ddos-attack.mdx index 0dace06ff65251..efb7a486d0cf64 100644 --- a/src/content/docs/fundamentals/security/under-ddos-attack.mdx +++ b/src/content/docs/fundamentals/security/under-ddos-attack.mdx @@ -20,5 +20,5 @@ Common signs that you are under DDoS attack include: :::note -If you are currently under DDoS attack, refer to our guide on [responding to a DDoS attack](/ddos-protection/best-practices/respond-to-ddos-attacks/). +If you are currently under DDoS attack, refer to our guide on [responding to a DDoS attack](/ddos-protection/best-practices/respond-to-ddos-attacks/). ::: diff --git a/src/content/docs/fundamentals/setup/account/account-security/2fa.mdx b/src/content/docs/fundamentals/setup/account/account-security/2fa.mdx index 9ecd2bb1f4e06d..6464c93fd50df7 100644 --- a/src/content/docs/fundamentals/setup/account/account-security/2fa.mdx +++ b/src/content/docs/fundamentals/setup/account/account-security/2fa.mdx @@ -22,7 +22,7 @@ import { Render } from "~/components" :::caution -Security keys only work with browsers that support the WebAuthn protocol. +Security keys only work with browsers that support the WebAuthn protocol. ::: A security key provides phishing-resistant multifactor authentication to your Cloudflare account using a built-in authenticator (Apple Touch ID, Android fingerprint, or Windows Hello) or an external hardware key (like [YubiKey](https://www.yubico.com/works-with-yubikey/catalog/cloudflare/)) that connects to your computer through USB-A, USB-C, NFC, or Bluetooth. @@ -71,7 +71,7 @@ Ensure that your hardware security key is configured and plugged in. On a Window :::note -You can regenerate your backup codes at any time using the Cloudflare dashboard. +You can regenerate your backup codes at any time using the Cloudflare dashboard. ::: 7. Select **Next** on the backup code page to complete the recovery code setup. @@ -82,7 +82,7 @@ You may need to reconfigure your mobile application authentication if you join a :::note -Reconfiguring TOTP mobile application authentication does not turn off 2FA. +Reconfiguring TOTP mobile application authentication does not turn off 2FA. ::: To reconfigure, follow [Steps 1-7](/fundamentals/setup/account/account-security/2fa/#configure-totp-mobile-application-authentication-for-two-factor-cloudflare-login) as detailed above. @@ -95,7 +95,7 @@ Each backup code is one-time use only, but you can always request a new set of b :::note -Regenerating your backup codes will invalidate your previous codes. +Regenerating your backup codes will invalidate your previous codes. ::: 1. Log in to the Cloudflare dashboard. @@ -111,7 +111,7 @@ To disable 2FA for your Cloudflare account, you must delete all security keys an :::note -If you are not the Super Administrator of an organization with **2FA Enforcement** enabled, you may not have permission to disable 2FA. +If you are not the Super Administrator of an organization with **2FA Enforcement** enabled, you may not have permission to disable 2FA. ::: 1. Log in to the Cloudflare dashboard @@ -151,7 +151,7 @@ When setting up 2FA, you should have saved your backup codes in a secure locatio :::note -Once you use a backup code, it becomes invalid. +Once you use a backup code, it becomes invalid. ::: ## Recover your account @@ -171,7 +171,7 @@ If you do not have access to your 2FA account or backup codes and cannot current * Your browser may be set to clear cookies on exit or after browser or OS upgrades. This interferes with the device verification process. * You may be using anti-malware or other software that automatically clears your browser cookies and makes your device unregognizable by Cloudflare's Dashboard. -If you are still unable to verify your device, [contact Support](/support/contacting-cloudflare-support/). +If you are still unable to verify your device, follow the instructions shown in the recovery workflow. *** diff --git a/src/content/docs/fundamentals/setup/account/account-security/login-and-account-issues.mdx b/src/content/docs/fundamentals/setup/account/account-security/login-and-account-issues.mdx index 67bbe66ad4c231..1ff1f889299773 100644 --- a/src/content/docs/fundamentals/setup/account/account-security/login-and-account-issues.mdx +++ b/src/content/docs/fundamentals/setup/account/account-security/login-and-account-issues.mdx @@ -20,7 +20,7 @@ If you forget the email address associated with your application: :::note -This process does not affect your account or share your email address with anyone. +This process does not affect your account or share your email address with anyone. ::: If you still cannot access the email address associated with your Cloudflare account, you may need to [move your domain to another account](/fundamentals/setup/manage-domains/move-domain/). @@ -45,7 +45,7 @@ Cloudflare recommends strong passwords. Minimum requirements are: * Password must be at least 8 characters. * Password must contain a digit. -* Password must contain a special character. +* Password must contain a special character. ::: *** @@ -80,7 +80,7 @@ You have several sign-in options for the [Cloudflare dashboard](https://dash.clo :::note -If you login to your Cloudflare user account with Single Sign-On (SSO), you will not be able to sign in with Apple. +If you login to your Cloudflare user account with Single Sign-On (SSO), you will not be able to sign in with Apple. ::: *** diff --git a/src/content/docs/fundamentals/setup/account/account-security/multi-factor-email-authentication.mdx b/src/content/docs/fundamentals/setup/account/account-security/multi-factor-email-authentication.mdx index d9f579aa69ddef..d866fb38bc0299 100644 --- a/src/content/docs/fundamentals/setup/account/account-security/multi-factor-email-authentication.mdx +++ b/src/content/docs/fundamentals/setup/account/account-security/multi-factor-email-authentication.mdx @@ -1,7 +1,7 @@ --- title: Multi-Factor Email Authentication pcx_content_type: troubleshooting - +description: Cloudflare's Multi-Factor Email Authentication prevents unauthorized access by sending one-time codes to your email. --- ## Overview @@ -18,7 +18,7 @@ Cloudflare challenges the login by sending a one-time code that expires in 30 mi :::note -Email MFA can only be disabled by enabling [two-factor authentication](/fundamentals/setup/account/account-security/2fa/). +Email MFA can only be disabled by enabling [two-factor authentication](/fundamentals/setup/account/account-security/2fa/). ::: *** diff --git a/src/content/docs/fundamentals/setup/account/account-security/scim-setup.mdx b/src/content/docs/fundamentals/setup/account/account-security/scim-setup.mdx index 28220942f7d723..7d1e3992360ece 100644 --- a/src/content/docs/fundamentals/setup/account/account-security/scim-setup.mdx +++ b/src/content/docs/fundamentals/setup/account/account-security/scim-setup.mdx @@ -5,7 +5,7 @@ updated: 2024-12-04 --- -Cloudflare supports bulk provisioning of users into the Cloudflare dashboard by using the System for Cross-domain Identity Management (SCIM) protocol. This allows you to connect your external identity provider (IdP) to Cloudflare and quickly onboard and manage users and their permissions. Cloudflare supports SCIM onboarding with Okta and Microsoft Entra. +Cloudflare supports bulk provisioning of users into the Cloudflare dashboard by using the System for Cross-domain Identity Management (SCIM) protocol. This allows you to connect your external identity provider (IdP) to Cloudflare and quickly onboard and manage users and their permissions. Cloudflare supports SCIM onboarding with Okta and Microsoft Entra. :::note Cloudflare Zero Trust also supports SCIM for onboarding users to Cloudflare Access. [Learn more](/cloudflare-one/identity/users/scim/) @@ -14,7 +14,7 @@ Cloudflare Zero Trust also supports SCIM for onboarding users to Cloudflare Acce ## Limitations - If a user is the only Super Administrator on an Enterprise account, they will not be deprovisioned. -- Cloudflare currently only supports [Account-scoped Roles](/fundamentals/setup/manage-members/roles/#account-scoped-roles) and does not support Domain-scoped Roles provisioning via SCIM. +- Cloudflare currently only supports [Account-scoped Roles](/fundamentals/setup/manage-members/roles/#account-scoped-roles) and does not support Domain-scoped Roles provisioning via SCIM. - Cloudflare does not allow custom user groups. ## Prerequisites @@ -31,7 +31,7 @@ Accounts provisioned with SCIM need to verify their email addresses. --- ## Gather the required data -To start, you will need to collect a couple of pieces of data from Cloudflare and set these aside for later use. +To start, you will need to collect a couple of pieces of data from Cloudflare and set these aside for later use. ### Get your Account ID @@ -91,26 +91,26 @@ To start, you will need to collect a couple of pieces of data from Cloudflare an 1. In **Provisioning to App**, select **Edit**. 2. Enable **Create Users** and **Deactivate Users**. Select **Save**. 3. In the integration page, go to **Assignments** > **Assign** > **Assign to Groups**. -4. Choose the group(s) that you want to provision to Cloudflare. +4. Choose the group(s) that you want to provision to Cloudflare. 5. Select **Done**. This will provision all of the users in the group(s) affected to your Cloudflare account with "minimal account access." -### Configure user permissions +### Configure user permissions There are two options for managing user permissions: -* Manage your user permissions on a per-user basis in the Cloudflare dashboard, API, or using Terraform. -* Map your IdP groups to a Cloudflare built-in [Role](/fundamentals/setup/manage-members/roles/). Groups may only be linked to one role. +* Manage your user permissions on a per-user basis in the Cloudflare dashboard, API, or using Terraform. +* Map your IdP groups to a Cloudflare built-in [Role](/fundamentals/setup/manage-members/roles/). Groups may only be linked to one role. 1. Go to your SCIM application in the App Integration Catalog, then select **Provisioning**. 2. Under **To App*, select **Edit**. 3. Enable **Create Users** and **Deactivate Users**. Select **Save**. 4. Go to **Push Groups**. 5. Select **+ Push Groups**, then **Find groups by name**. -6. Enter the name of the group(s) that you want to sync to Cloudflare. +6. Enter the name of the group(s) that you want to sync to Cloudflare. 7. Choose **Link Group**. -8. Cloudflare provisioned user groups are named in the pattern `CF- - `. Choose the appropriate group that maps to your target role. +8. Cloudflare provisioned user groups are named in the pattern `CF- - `. Choose the appropriate group that maps to your target role. 9. Disable **Rename groups**. Select **Save**. 10. Within the **Push Groups** tab, select **Push Groups**. 11. Add the groups you created. @@ -153,5 +153,17 @@ Refer to the list of [Roles](/fundamentals/setup/manage-members/roles/) for more 7. Select **Start provisioning** to view the new users and groups populated on the Cloudflare dashboard. :::note -To successfully provision with Microsoft Entra ID, the `user principal name` and `email` fields must match. These values are case-sensitive. +To successfully provision with Microsoft Entra ID, the `user principal name` and `email` fields must match. These values are case-sensitive. ::: + +## Expected behaviors + +Expectations for user lifecycle management with SCIM: + +| Expected Cloudflare dash behavior | Identity provider action | +| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| User is added to account as member | Assign the user to a SCIM application. They will be assigned the Minimal Account Access role so that their dash experience is not broken. | +| User is removed from account as member | Unassign the user from the SCIM application. | +| Add role to user | Add the user to a group in the IdP which is pushed via SCIM. They must also be assigned to the SCIM application and exist as an account member. | +| Remove role from user | Remove the user from the corresponding group in the IdP. | +| Retain user in account but with no permissions | Remove the user from all role groups but leave them assigned to the SCIM application. They will be an account member with only the role Minimal Account Access. | \ No newline at end of file diff --git a/src/content/docs/fundamentals/setup/account/login.mdx b/src/content/docs/fundamentals/setup/account/login.mdx index 2dd429029f83a3..fb8d4e50ac2354 100644 --- a/src/content/docs/fundamentals/setup/account/login.mdx +++ b/src/content/docs/fundamentals/setup/account/login.mdx @@ -25,11 +25,16 @@ Enter your email address (available if your admin has [enabled SSO](/cloudflare- :::note -If you log into your Cloudflare user account with Single Sign-On (SSO), you will not be able to sign in with Apple. +If you log into your Cloudflare user account with Single Sign-On (SSO), you will not be able to sign in with Apple or Google. ::: +:::warning + +For the below sign-in options, initially your user profile will not have a password associated. Some dashboard operations will require a dashboard password is set - to do this, visit [Forgot Password](https://dash.cloudflare.com/forgot-password) and set one. +::: + ### Sign in with Apple * *Same Cloudflare account email as Apple ID*: You can either sign in with your email and password or sign in with Apple. diff --git a/src/content/docs/fundamentals/setup/manage-domains/add-site.mdx b/src/content/docs/fundamentals/setup/manage-domains/add-site.mdx index 2197256411cad3..74cdd53192d2ea 100644 --- a/src/content/docs/fundamentals/setup/manage-domains/add-site.mdx +++ b/src/content/docs/fundamentals/setup/manage-domains/add-site.mdx @@ -6,9 +6,9 @@ pcx_content_type: tutorial import { Render } from "~/components" -Follow these steps to onboard your website or application to Cloudflare. Once your domain is [active](/dns/zone-setups/reference/domain-status/#active), your web traffic will [proxy through Cloudflare](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-reverse-proxy), which speeds up and protects websites and services on your domain. +Follow these steps to onboard your website or application to Cloudflare. Once your domain is [active](/dns/zone-setups/reference/domain-status/#active), your web traffic will [proxy through Cloudflare](/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-reverse-proxy), which speeds up and protects websites and services on your domain. -Cloudflare will become the primary [DNS provider](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-dns-provider) for your domain, meaning your [DNS records](/dns/concepts/#dns-records) are managed at Cloudflare, and we authoritatively answer all DNS queries. +Cloudflare will become the primary [DNS provider](/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-dns-provider) for your domain, meaning your [DNS records](/dns/concepts/#dns-records) are managed at Cloudflare, and we authoritatively answer all DNS queries. :::note @@ -38,6 +38,6 @@ If you do not already own a domain and plan to use Cloudflare for your [authorit To prevent insecure connections and visitor browser errors, [make sure you have SSL/TLS protection](/ssl/get-started/). -Many Cloudflare services will automatically protect and speed up your web traffic once your nameservers are updated. +Many Cloudflare services will automatically protect and speed up your web traffic once your nameservers are updated. -To get more out of Cloudflare, refer to the [Security](/fundamentals/security/) and [Performance](/fundamentals/performance/) tasks. +To get more out of Cloudflare, refer to the [Security](/fundamentals/security/) and [Performance](/fundamentals/performance/) tasks. diff --git a/src/content/docs/fundamentals/setup/manage-domains/connect-your-domain.mdx b/src/content/docs/fundamentals/setup/manage-domains/connect-your-domain.mdx index a503c58c014f8e..ad63a14100a9d5 100644 --- a/src/content/docs/fundamentals/setup/manage-domains/connect-your-domain.mdx +++ b/src/content/docs/fundamentals/setup/manage-domains/connect-your-domain.mdx @@ -47,7 +47,7 @@ The activation process involves different steps if you are using a [secondary DN Registrars take up to 24 hours to process nameserver changes (quicker in most cases). You will receive an email when your domain becomes active. While your domain is pending, your `HTTP/HTTPS` traffic is not proxied through Cloudflare, but Cloudflare will respond to DNS queries on your assigned nameservers. -By activating your domain on a full setup, your traffic will immediately start using [Cloudflare's DNS services](/fundamentals/concepts/how-cloudflare-works/#how-cloudflare-works-as-a-dns-provider), so it is important to review how to [avoid downtime](/fundamentals/setup/manage-domains/connect-your-domain/#avoiding-downtime) and what [proxying traffic](/fundamentals/concepts/how-cloudflare-works/) means. +By activating your domain on a full setup, your traffic will immediately start using [Cloudflare's DNS services](/fundamentals/concepts/how-cloudflare-works/#cloudflare-as-a-dns-provider), so it is important to review how to [avoid downtime](/fundamentals/setup/manage-domains/connect-your-domain/#avoiding-downtime) and what [proxying traffic](/fundamentals/concepts/how-cloudflare-works/) means. ## Avoiding downtime diff --git a/src/content/docs/fundamentals/setup/manage-domains/move-domain.mdx b/src/content/docs/fundamentals/setup/manage-domains/move-domain.mdx index ef2fb9a5bfc36e..fb541550dffd7d 100644 --- a/src/content/docs/fundamentals/setup/manage-domains/move-domain.mdx +++ b/src/content/docs/fundamentals/setup/manage-domains/move-domain.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: reference title: Move a domain between Cloudflare accounts +description: Learn how to transfer a domain between Cloudflare accounts, including requirements, DNS settings, and SSL/TLS certificate management for seamless migration. --- diff --git a/src/content/docs/fundamentals/setup/manage-domains/remove-domain.mdx b/src/content/docs/fundamentals/setup/manage-domains/remove-domain.mdx index 5dd7fb90427269..7ae1ef1dd2d032 100644 --- a/src/content/docs/fundamentals/setup/manage-domains/remove-domain.mdx +++ b/src/content/docs/fundamentals/setup/manage-domains/remove-domain.mdx @@ -17,6 +17,13 @@ If you have an Enterprise plan, you need to [change the zone plan](/fundamentals If you need to re-add the domain in a different account, make sure the current settings have been saved. For example, you may [Import and export DNS records](/dns/manage-dns-records/how-to/import-and-export/). +:::note +If you have just added a domain and haven't configured its plan yet, the domain is in the `Initializing (Setup)` status and cannot be deleted. +At this step you'll need to select a plan for this domain: the status will then change to `Pending` and you can then delete the domain. +Please also note that domains in the `Initializing (Setup)` or `Pending` statuses will [automatically be deleted after 28 days](/dns/zone-setups/reference/domain-status/#initializing-setup) if they do not activate. +::: + + ### Actions outside of Cloudflare * When you remove a domain from Cloudflare, it also prevents your domain from using Cloudflare for DNS resolution. To avoid DNS errors, update your nameservers at your domain registrar to use nameservers not owned by Cloudflare. @@ -50,7 +57,7 @@ If you need to re-add the domain in a different account, make sure the current s ![Remove site from Cloudflare is an option under Advanced Actions](~/assets/images/fundamentals/get-started/remove-domain.png) :::note - If you are using an Enterprise domain, [change your domain plan](/fundamentals/subscriptions-and-billing/change-plan/#change-plan-type) to **Free**, which will give you access to **Remove Site from Cloudflare**.

    If this does not work, contact your Customer Success Manager. + If you are using an Enterprise domain, [change your domain plan](/fundamentals/subscriptions-and-billing/change-plan/#change-plan-type) to **Free**, which will give you access to **Remove Site from Cloudflare**.

    If this does not work, contact your Customer Success Manager. ::: 3. Select **Confirm**. diff --git a/src/content/docs/fundamentals/setup/manage-members/roles.mdx b/src/content/docs/fundamentals/setup/manage-members/roles.mdx index 83768dc0b79738..ae3b5d3eb4d9ad 100644 --- a/src/content/docs/fundamentals/setup/manage-members/roles.mdx +++ b/src/content/docs/fundamentals/setup/manage-members/roles.mdx @@ -14,63 +14,67 @@ Whenever you [add a new member](/fundamentals/setup/manage-members/manage/) to y Account-scoped roles apply across an entire Cloudflare account, and through all domains in that account. -| Role | Description | -| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Administrator | Can access the full account and edit subscriptions. Cannot manage memberships nor billing profile. | -| Super Administrator | Can edit any Cloudflare setting, make purchases, update billing, and manage memberships. Super Administrators can revoke the access of other Super Administrators. | -| Administrator Read Only | Can access the full account in read-only mode. | -| Analytics | Can read Analytics. | -| API Gateway | Grants full access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | -| API Gateway Read | Grants read access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | -| Audit Logs Viewer | Can view [Audit Logs](/fundamentals/setup/account/account-security/review-audit-logs/). | -| Bot Management (Account-wide) | Can edit [Bot Management](/bots/plans/bm-subscription/) (including [Super Bot Fight Mode](/bots/get-started/pro/)) configurations for all domains in account. | -| Billing | Can edit the account’s [billing profile](/fundamentals/subscriptions-and-billing/create-billing-profile/) and subscriptions | -| Cloudflare Access | Can edit [Cloudflare Access](/cloudflare-one/policies/access/) and [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/). | -| Cache Purge | Can purge the edge cache and allows the reading of zone settings. | -| Cloudflare DEX | Can edit [Cloudflare DEX](/cloudflare-one/insights/dex/). | -| Cloudflare Gateway | Can edit [Cloudflare Gateway](/cloudflare-one/policies/gateway/) and read [Access](/cloudflare-one/identity/). | -| Cloudflare Images | Can access [Cloudflare Images](/images/) data. | -| Cloudflare R2 Admin | Can edit Cloudflare [R2](/r2/) buckets, objects, and associated configurations. | -| Cloudflare R2 Read | Can read Cloudflare [R2](/r2/) buckets, objects, and associated configurations. | -| Cloudflare Stream | Can edit [Cloudflare Stream](/stream/) media. | -| Cloudflare Workers Admin | Can edit Cloudflare [Workers](/workers/), [Pages](/pages/), [Durable Objects](/durable-objects/), [KV](/kv/) and [R2](/r2/). Also provides read access to Zones, [Zone Analytics](/analytics/account-and-zone-analytics/zone-analytics/) and [Page Rules](/rules/). | -| Cloudflare Zero Trust | Can edit [Cloudflare for Zero Trust](/cloudflare-one/). Grants administrator access to all Zero Trust products including Access, Gateway, WARP, Tunnel, Browser Isolation, CASB, DLP, DEX, and Email Security. | -| Cloudflare Zero Trust PII | Can access [Cloudflare for Zero Trust](/cloudflare-one/) PII. | -| Cloudflare Zero Trust Read Only | Can access [Cloudflare for Zero Trust](/cloudflare-one/) read only mode. | -| Cloudflare Zero Trust Reporting | Can access [Cloudflare for Zero Trust](/cloudflare-one/) reporting data. | -| DNS | Can edit [DNS records](/dns/manage-dns-records/). | +| Role | Description | +| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Administrator | Can access the full account and edit subscriptions. Cannot manage memberships nor billing profile. | +| Super Administrator | Can edit any Cloudflare setting, make purchases, update billing, and manage memberships. Super Administrators can revoke the access of other Super Administrators. | +| Administrator Read Only | Can access the full account in read-only mode. | +| Analytics | Can read Analytics. | +| API Gateway | Grants full access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | +| API Gateway Read | Grants read access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | +| Audit Logs Viewer | Can view [Audit Logs](/fundamentals/setup/account/account-security/review-audit-logs/). | +| Bot Management (Account-wide) | Can edit [Bot Management](/bots/plans/bm-subscription/) (including [Super Bot Fight Mode](/bots/get-started/pro/)) configurations for all domains in account. | +| Billing | Can edit the account's [billing profile](/fundamentals/subscriptions-and-billing/create-billing-profile/) and subscriptions | +| Cloudflare Access | Can edit [Cloudflare Access](/cloudflare-one/policies/access/) and [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/). | +| Cache Purge | Can purge the edge cache and allows the reading of zone settings. | +| Cloudflare DEX | Can edit [Cloudflare DEX](/cloudflare-one/insights/dex/). | +| Cloudflare Gateway | Can edit [Cloudflare Gateway](/cloudflare-one/policies/gateway/) and read [Access](/cloudflare-one/identity/). | +| Cloudflare Images | Can access [Cloudflare Images](/images/) data. | +| Cloudflare R2 Admin | Can edit Cloudflare [R2](/r2/) buckets, objects, and associated configurations. | +| Cloudflare R2 Read | Can read Cloudflare [R2](/r2/) buckets, objects, and associated configurations. | +| Cloudflare Stream | Can edit [Cloudflare Stream](/stream/) media. | +| Cloudflare Workers Admin | Can edit Cloudflare [Workers](/workers/), [Pages](/pages/), [Durable Objects](/durable-objects/), [KV](/kv/) and [R2](/r2/). Also provides read access to Zones, [Zone Analytics](/analytics/account-and-zone-analytics/zone-analytics/) and [Page Rules](/rules/). | +| Cloudflare Zero Trust | Can edit [Cloudflare Zero Trust](/cloudflare-one/). Grants administrator access to all Zero Trust products including Access, Gateway, WARP, Tunnel, Browser Isolation, CASB, DLP, DEX, and Email Security. | +| Cloudflare Zero Trust DNS Locations Write | Can view [Gateway DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/#secure-dns-locations) and create and edit [secure DNS locations](/cloudflare-one/connections/connect-devices/agentless/dns/locations/#secure-dns-locations). | +| Cloudflare Zero Trust PII | Can access [Cloudflare Zero Trust](/cloudflare-one/) PII. | +| Cloudflare Zero Trust Read Only | Can access [Cloudflare Zero Trust](/cloudflare-one/) read only mode. | +| Cloudflare Zero Trust Reporting | Can access [Cloudflare Zero Trust](/cloudflare-one/) reporting data. | +| DNS | Can edit [DNS records](/dns/manage-dns-records/). | | Email Configuration Admin | Grants write access to all of Email Security, [CASB](/cloudflare-one/applications/casb/), [DLP](/cloudflare-one/policies/data-loss-prevention/), [Gateway](/cloudflare-one/policies/gateway/), and [Tunnels](/cloudflare-one/connections/connect-networks/), except Mail Preview, Raw Email, on-demand reports, actions on emails, and Submissions, Submission Transparency (Requires Cloudflare Zero Trust PII). | | Email Integration Admin | Grants write access to Email Security account integration only, [CASB](/cloudflare-one/applications/casb/), [DLP](/cloudflare-one/policies/data-loss-prevention/), [Gateway](/cloudflare-one/policies/gateway/), and [Tunnels](/cloudflare-one/connections/connect-networks/). | | Email Security Analyst | Grants write access to all of Email Security, except Settings which is read only (Requires Cloudflare Zero Trust PII). | | Email Security Read Only | Grants read access to all of Email Security, but cannot see Raw Email, take action on emails, or make Submissions (Requires Cloudflare Zero Trust PII). | | Email Security Reporting | Grants read access to Email Security Home, PhishGuard, and Submission Transparency. | -| Firewall | Can edit [WAF](/waf/), [IP Access rules](/waf/tools/ip-access-rules/), [Zone Lockdown](/waf/tools/zone-lockdown/) settings, and [Cache Rules](/cache/how-to/cache-rules/). | -| Load Balancer | Can edit [Load Balancers](/load-balancing/), Pools, Origins, and Health Checks. | -| Log Share | Can edit [Log Share](/logs/) configuration. | -| Log Share Reader | Can read Enterprise [Log Share](/logs/). | -| Magic Network Monitoring | Can view and edit [MNM configuration](/magic-network-monitoring/). | -| Magic Network Monitoring Admin | Can view, edit, create, and delete [MNM configuration](/magic-network-monitoring/). | -| Magic Network Monitoring Read-Only | Can view [MNM configuration](/magic-network-monitoring/). | -| Network Services Write (Magic) | Grants write access to network configurations for Magic services. Magic Tunnel health checks require the Analytics role for non-admin users. | -| Network Services Read (Magic) | Grants read access to network configurations for Magic services. Magic Tunnel health checks require the Analytics role for non-admin users. | -| Minimal Account Access | Can view account, and nothing else. | -| Page Shield | Grants write access to [Page Shield](/page-shield/) across the whole account. | -| Page Shield Read | Grants read access to [Page Shield](/page-shield/) across the whole account. | -| Hyperdrive Read | Grants read access to [Hyperdrive](/hyperdrive/) database configuration. | -| Hyperdrive Admin | Grants write access to [Hyperdrive](/hyperdrive/) database configuration. | -| SSL/TLS, Caching, Performance, Page Rules, and Customization | Can edit most Cloudflare settings except for [DNS](/dns/) and [Firewall](/waf/). | -| Trust and Safety | Can access trust and safety related services. | -| Turnstile | Grants full access to [Turnstile](/turnstile/). | -| Turnstile Read | Grants read access to [Turnstile](/turnstile/). | -| Vectorize Admin | Can edit [Vectorize](/vectorize/) configurations. | -| Vectorize Read only | Can read [Vectorize](/vectorize/) configurations. | -| Waiting Room Admin | Can edit [Waiting Room](/waiting-room/) configuration. | -| Waiting Room Read | Can read [Waiting Room](/waiting-room/) configuration. | -| Zaraz Admin | Can edit and publish [Zaraz](/zaraz/) configuration. | -| Zaraz Edit | Can edit [Zaraz](/zaraz/) configuration. | -| Zaraz Read | Can read [Zaraz](/zaraz/) configuration. | -| Zone Versioning (Account-Wide) | Can view and edit [Zone Versioning](/version-management/) for all domains in account. | -| Zone Versioning Read (Account-Wide) | Can view [Zone Versioning](/version-management/) for all domains in account. | +| Firewall | Can edit [WAF](/waf/), [IP Access rules](/waf/tools/ip-access-rules/), [Zone Lockdown](/waf/tools/zone-lockdown/) settings, and [Cache Rules](/cache/how-to/cache-rules/). | +| Load Balancer | Can edit [Load Balancers](/load-balancing/), Pools, Origins, and Health Checks. | +| Log Share | Can edit [Log Share](/logs/) configuration. | +| Log Share Reader | Can read Enterprise [Log Share](/logs/). | +| Magic Network Monitoring | Can view and edit [MNM configuration](/magic-network-monitoring/). | +| Magic Network Monitoring Admin | Can view, edit, create, and delete [MNM configuration](/magic-network-monitoring/). | +| Magic Network Monitoring Read-Only | Can view [MNM configuration](/magic-network-monitoring/). | +| Network Services Write (Magic) | Grants write access to network configurations for Magic services. Magic Tunnel health checks require the Analytics role for non-admin users. | +| Network Services Read (Magic) | Grants read access to network configurations for Magic services. Magic Tunnel health checks require the Analytics role for non-admin users. | +| Minimal Account Access | Can view account, and nothing else. | +| Page Shield | Grants write access to [Page Shield](/page-shield/) across the whole account. | +| Page Shield Read | Grants read access to [Page Shield](/page-shield/) across the whole account. | +| Hyperdrive Read | Grants read access to [Hyperdrive](/hyperdrive/) database configuration. | +| Hyperdrive Admin | Grants write access to [Hyperdrive](/hyperdrive/) database configuration. | +| SSL/TLS, Caching, Performance, Page Rules, and Customization | Can edit most Cloudflare settings except for [DNS](/dns/) and [Firewall](/waf/). | +| Security Center Brand Protection | Can access the Brand Protection feature on the API and Cloudflare dashboard. Brand Protection role also gives you access to the Investigate platform. | +| Security Center Cloudforce One Admin | Grants write access to [Cloudforce One](/security-center/cloudforce-one/). | +| Security Center Cloudforce One Read | Grants read access to [Cloudforce One](/security-center/cloudforce-one/), and cannot create and/or edit RFIs or PIRs. | +| Trust and Safety | Can access trust and safety related services. | +| Turnstile | Grants full access to [Turnstile](/turnstile/). | +| Turnstile Read | Grants read access to [Turnstile](/turnstile/). | +| Vectorize Admin | Can edit [Vectorize](/vectorize/) configurations. | +| Vectorize Read only | Can read [Vectorize](/vectorize/) configurations. | +| Waiting Room Admin | Can edit [Waiting Room](/waiting-room/) configuration. | +| Waiting Room Read | Can read [Waiting Room](/waiting-room/) configuration. | +| Zaraz Admin | Can edit and publish [Zaraz](/zaraz/) configuration. | +| Zaraz Edit | Can edit [Zaraz](/zaraz/) configuration. | +| Zaraz Read | Can read [Zaraz](/zaraz/) configuration. | +| Zone Versioning (Account-Wide) | Can view and edit [Zone Versioning](/version-management/) for all domains in account. | +| Zone Versioning Read (Account-Wide) | Can view [Zone Versioning](/version-management/) for all domains in account. | ## Domain-scoped roles @@ -79,7 +83,7 @@ Domain-scoped roles apply for a given domain within an account. | Role | Description | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bot Management | Can edit [Bot Management](/bots/plans/bm-subscription/) (including [Super Bot Fight Mode](/bots/get-started/pro/)) configurations. | -| Cache Domain Purge | Grants access to [purge the edge cache](/cache/how-to/purge-cache/) for a specific domain and allows the reading of zone settings. | +| Cache Domain Purge | Grants access to [purge the edge cache](/cache/how-to/purge-cache/) for a specific domain and allows the reading of zone settings. | | Domain Administrator | Grants full access to domains in an account, and read-only access to account-wide [Firewall](/waf/account/managed-rulesets/deploy-dashboard/), [Access](/cloudflare-one/policies/access/), and [Worker](/workers/) resources. | | Domain Administrator Read Only | Grants read-only access to domains in an account, as well as account-wide [Firewall](/waf/account/managed-rulesets/deploy-dashboard/), [Access](/cloudflare-one/policies/access/), and [Worker](/workers/) resources. | | Domain API Gateway | Grants full access to API Gateway (including [API Shield](/api-shield/)). | diff --git a/src/content/docs/fundamentals/setup/troubleshooting.mdx b/src/content/docs/fundamentals/setup/troubleshooting.mdx index e9ff1b7f7534d5..bbfb6f3094a550 100644 --- a/src/content/docs/fundamentals/setup/troubleshooting.mdx +++ b/src/content/docs/fundamentals/setup/troubleshooting.mdx @@ -55,5 +55,5 @@ Ideally, because Cloudflare is a reverse proxy, your hosting provider observes a :::note -If an attacker is directly targeting your origin web server, refer to [Respond to DDoS attacks](/ddos-protection/best-practices/respond-to-ddos-attacks/). +If an attacker is directly targeting your origin web server, refer to [Respond to DDoS attacks](/ddos-protection/best-practices/respond-to-ddos-attacks/). ::: diff --git a/src/content/docs/fundamentals/subscriptions-and-billing/troubleshooting-failed-payments.mdx b/src/content/docs/fundamentals/subscriptions-and-billing/troubleshooting-failed-payments.mdx index 67aeaf3ac71652..647c09bdec1b29 100644 --- a/src/content/docs/fundamentals/subscriptions-and-billing/troubleshooting-failed-payments.mdx +++ b/src/content/docs/fundamentals/subscriptions-and-billing/troubleshooting-failed-payments.mdx @@ -12,7 +12,7 @@ If payment for a recurring charge for a Cloudflare plan, add-on, or subscription :::caution -The five-day grace period for failed payments on recurring Cloudflare charges includes weekends and holidays. +The five-day grace period for failed payments on recurring Cloudflare charges includes weekends and holidays. ::: After confirming your payment method information, Cloudflare suggests [manually updating your plan type](/fundamentals/subscriptions-and-billing/change-plan/) and subscriptions using the Cloudflare dashboard. @@ -61,7 +61,7 @@ The billing information that Cloudflare has on file is inaccurate or incomplete. :::note -Gift cards and pre-payment cards may not be accepted for payment as they are not associated with a billing address. +Gift cards and pre-payment cards may not be accepted for payment as they are not associated with a billing address. ::: To ensure all billing information is current and accurate, refer to [Updating your Cloudflare billing information](/fundamentals/subscriptions-and-billing/update-billing-info/). diff --git a/src/content/docs/fundamentals/trace-request/how-to.mdx b/src/content/docs/fundamentals/trace-request/how-to.mdx index 0e200fa91bb185..910fc778a79e00 100644 --- a/src/content/docs/fundamentals/trace-request/how-to.mdx +++ b/src/content/docs/fundamentals/trace-request/how-to.mdx @@ -9,10 +9,9 @@ head: - tag: title content: How to - Cloudflare Trace (beta) description: Learn how to use Cloudflare Trace in the dashboard and with the API. - --- -import { GlossaryTooltip } from "~/components" +import { GlossaryTooltip } from "~/components"; ## Use Trace in the dashboard @@ -27,18 +26,18 @@ import { GlossaryTooltip } from "~/components" 2. Enter a URL to trace. The URL must include a hostname that belongs to your account. -3. Select an HTTP method. If you select *POST*, *PUT*, or *PATCH*, you should enter a value in **Request body**. +3. Select an HTTP method. If you select _POST_, _PUT_, or _PATCH_, you should enter a value in **Request body**. 4. (Optional) Define any custom request properties to simulate the conditions of a specific HTTP/S request. You can customize the following request properties: - * **Protocol** (HTTP protocol version) - * **Request headers** - * **Cookies** - * **Geolocation** (request source [country](/ruleset-engine/rules-language/fields/reference/ip.src.country/), [region](/ruleset-engine/rules-language/fields/reference/ip.src.region/), and [city](/ruleset-engine/rules-language/fields/reference/ip.src.city/)) - * [**Bot score**](/bots/concepts/bot-score/) - * **Threat score** - * **Request body** (for `POST`, `PUT`, and `PATCH` requests) - * **Skip challenge** (skips a Cloudflare-issued [challenge](/waf/reference/cloudflare-challenges/), if any, allowing the trace to continue) + - **Protocol** (HTTP protocol version) + - **Request headers** + - **Cookies** + - **Geolocation** (request source [country](/ruleset-engine/rules-language/fields/reference/ip.src.country/), [region](/ruleset-engine/rules-language/fields/reference/ip.src.region/), and [city](/ruleset-engine/rules-language/fields/reference/ip.src.city/)) + - [**Bot score**](/bots/concepts/bot-score/) + - **Threat score** + - **Request body** (for `POST`, `PUT`, and `PATCH` requests) + - **Skip challenge** (skips a Cloudflare-issued [challenge](/waf/reference/cloudflare-challenges/), if any, allowing the trace to continue) 5. Select **Send trace**. @@ -48,7 +47,7 @@ The **Trace results** page shows all evaluated and executed configurations from 1. Analyze the different [steps](#steps-in-trace-results) with evaluated and executed configurations for the current trace. Trace results include matches for all active rules and configurations, whether configured at the account level or for a specific domain or subdomain. - To show all configurations, including the ones that did not match the request, select *All configurations* in the **Results shown** dropdown. + To show all configurations, including the ones that did not match the request, select _All configurations_ in the **Results shown** dropdown. 2. (Optional) Update your Cloudflare configuration (at the account or at the domain/subdomain level) and create a new trace to check the impact of your changes. @@ -63,10 +62,10 @@ To run a trace later with the same configuration: Use the [Request Trace](/api/resources/request_tracers/subresources/traces/methods/create/) operation to perform a trace using the Cloudflare API. -*** +--- ## Steps in trace results -* Execution of one or more rules of Cloudflare products built on the [Ruleset Engine](/ruleset-engine/). Refer to the Ruleset Engine's [Phases list](/ruleset-engine/reference/phases-list/) for a list of such products. -* [Page Rules](/rules/page-rules/): Execution of one or more rules. -* [Workers](/workers/): Execution of one or more scripts. +- Execution of one or more rules of Cloudflare products built on the [Ruleset Engine](/ruleset-engine/). Refer to the Ruleset Engine's [Phases list](/ruleset-engine/reference/phases-list/) for a list of such products. +- [Page Rules](/rules/page-rules/): Execution of one or more rules. +- [Workers](/workers/): Execution of one or more scripts. diff --git a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx index 1f780c84acd078..2f730c55fd2729 100644 --- a/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx +++ b/src/content/docs/hyperdrive/configuration/connect-to-private-database.mdx @@ -55,7 +55,7 @@ Your tunnel must be configured to use a public hostname so that Hyperdrive can r 3. Select **Save tunnel**. :::note -If you are setting up the tunnel through the CLI instead ([locally-managed tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/)), you will have to complete these steps manually. Follow the Cloudflare Zero Trust documentation to [add a public hostname to your tunnel](/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns/) and [configure the public hostname to route to the address of your database](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/). +If you are setting up the tunnel through the CLI instead ([locally-managed tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/)), you will have to complete these steps manually. Follow the Cloudflare Zero Trust documentation to [add a public hostname to your tunnel](/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns/) and [configure the public hostname to route to the address of your database](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/). ::: ## 2. Create and configure Hyperdrive to connect to the Cloudflare Tunnel diff --git a/src/content/docs/hyperdrive/configuration/firewall-and-networking-configuration.mdx b/src/content/docs/hyperdrive/configuration/firewall-and-networking-configuration.mdx new file mode 100644 index 00000000000000..f1c38e864ba8ef --- /dev/null +++ b/src/content/docs/hyperdrive/configuration/firewall-and-networking-configuration.mdx @@ -0,0 +1,16 @@ +--- +pcx_content_type: concept +title: Firewall and networking configuration +sidebar: + order: 7 +--- + +import { TabItem, Tabs, Render, WranglerConfig } from "~/components"; + +Hyperdrive uses the [Cloudflare IP address ranges](https://www.cloudflare.com/ips/) to connect to your database. If you decide to restrict the IP addresses that can access your database with firewall rules, the IP address ranges listed in this reference need to be allow-listed in your database's firewall and networking configurations. + +You can connect to your database from Hyperdrive using any of the 3 following networking configurations: + +1. Configure your database to allow inbound connectivity from the public Internet (all IP address ranges). +2. Configure your database to allow inbound connectivity from the public Internet, with only the IP address ranges used by Hyperdrive allow-listed in an IP access control list (ACL). +3. Configure your database to allow inbound connectivity from a private network, and run a Cloudflare Tunnel instance in your private network to enable Hyperdrive to connect from the Cloudflare network to your private network. Refer to [documentation on connecting to a private database using Tunnel](/hyperdrive/configuration/connect-to-private-database/). diff --git a/src/content/docs/hyperdrive/configuration/how-hyperdrive-works.mdx b/src/content/docs/hyperdrive/configuration/how-hyperdrive-works.mdx index d91908dc79a129..8c070574f4f27c 100644 --- a/src/content/docs/hyperdrive/configuration/how-hyperdrive-works.mdx +++ b/src/content/docs/hyperdrive/configuration/how-hyperdrive-works.mdx @@ -3,7 +3,6 @@ pcx_content_type: concept title: How Hyperdrive works sidebar: order: 2 - --- Connecting to traditional centralized databases from Cloudflare's global network which consists of over [300 data center locations](https://www.cloudflare.com/network/) presents a few challenges as queries can originate from any of these locations. @@ -16,9 +15,17 @@ Hyperdrive solves these challenges by managing the number of global connections ![Hyperdrive connection](~/assets/images/hyperdrive/configuration/hyperdrive-comparison.svg) +## Edge connection setup + +When a database driver connects to a database from a Cloudflare Worker (illustrated above on the right half of the diagram in **Direct (without Hyperdrive)**) it will first go through the connection setup. This may require multiple round trips to the database in order to verify and establish a secure connection. This can incur additional network latency due to the distance between your Cloudflare Worker and your database. + +**With Hyperdrive** (on the left half of the above diagram), this connection setup occurs between your Cloudflare Worker and Hyperdrive on the edge, as close to your Worker as possible. This incurs significantly less latency, since the connection setup is completed within the same location. + ## Connection Pooling -Hyperdrive creates a global pool of connections to your database that can be reused as your application executes queries against your database. +Hyperdrive creates a pool of connections to your database that can be reused as your application executes queries against your database. + +The pool of database connections is placed in one or more regions closest to your origin database. This minimizes the latency incurred by roundtrips between your Cloudflare Workers and database to establish new connections. This also ensures that as little network latency is incurred for uncached queries. When a query hits Hyperdrive, the request is routed to the nearest connection pool. @@ -28,15 +35,14 @@ If the connection pool does not have pre-existing connections, it will establish :::note -Hyperdrive automatically manages the connection pool properties for you, including limiting the total number of connections to your origin database. Refer to [Limits](/hyperdrive/platform/limits/) to learn more. +Hyperdrive automatically manages the connection pool properties for you, including limiting the total number of connections to your origin database. Refer to [Limits](/hyperdrive/platform/limits/) to learn more. ::: ## Pooling mode The Hyperdrive connection pooler operates in transaction mode, where the client that executes the query communicates through a single connection for the duration of a transaction. When that transaction has completed, the connection is returned to the pool. - -Hyperdrive supports [`SET` statements](https://www.postgresql.org/docs/current/sql-set.html) for the duration of a transaction or a query. For instance, if you manually create a transaction with `BEGIN`/`COMMIT`, `SET` statements within the transaction will take effect. Moreover, a query that includes a `SET` command (`SET X; SELECT foo FROM bar;`) will also apply the `SET` command. When a connection is returned to the pool, the connection is `RESET` such that the `SET` commands will not take effect on subsequent queries. +Hyperdrive supports [`SET` statements](https://www.postgresql.org/docs/current/sql-set.html) for the duration of a transaction or a query. For instance, if you manually create a transaction with `BEGIN`/`COMMIT`, `SET` statements within the transaction will take effect. Moreover, a query that includes a `SET` command (`SET X; SELECT foo FROM bar;`) will also apply the `SET` command. When a connection is returned to the pool, the connection is `RESET` such that the `SET` commands will not take effect on subsequent queries. This implies that a single Worker invocation may obtain multiple connections to perform its database operations and may need to `SET` any configurations for every query or transaction. It is not recommended to wrap multiple database operations with a single transaction to maintain the `SET` state. Doing so will affect the performance and scaling of Hyperdrive as the connection cannot be reused by other Worker isolates for the duration of the transaction. @@ -46,11 +52,11 @@ Hyperdrive supports named prepared statements as implemented in the `postgres.js Hyperdrive does not support the following PostgreSQL features: -* SQL-level management of prepared statements, such as using `PREPARE`, `DISCARD`, `DEALLOCATE`, or `EXECUTE`. -* Advisory locks ([PostgreSQL documentation](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)). -* `LISTEN` and `NOTIFY`. -* `PREPARE` and `DEALLOCATE`. -* Any modification to per-session state not explicitly documented as supported elsewhere. +- SQL-level management of prepared statements, such as using `PREPARE`, `DISCARD`, `DEALLOCATE`, or `EXECUTE`. +- Advisory locks ([PostgreSQL documentation](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)). +- `LISTEN` and `NOTIFY`. +- `PREPARE` and `DEALLOCATE`. +- Any modification to per-session state not explicitly documented as supported elsewhere. In cases where you need to issue these unsupported statements from your application, the Hyperdrive team recommends setting up a second, direct client without Hyperdrive. @@ -66,4 +72,4 @@ Caching reduces the burden on your origin database and accelerates the response ## Related resources -* [Query caching](/hyperdrive/configuration/query-caching/) +- [Query caching](/hyperdrive/configuration/query-caching/) diff --git a/src/content/docs/hyperdrive/get-started.mdx b/src/content/docs/hyperdrive/get-started.mdx index d16b4eda708978..3e22c93f6d320f 100644 --- a/src/content/docs/hyperdrive/get-started.mdx +++ b/src/content/docs/hyperdrive/get-started.mdx @@ -1,5 +1,5 @@ --- -title: Get started +title: Getting started pcx_content_type: get-started sidebar: order: 2 @@ -64,7 +64,7 @@ Create a new project named `hyperdrive-tutorial` by running: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -129,18 +129,14 @@ If successful, the command will output your new Hyperdrive configuration: ```json { - "id": "", - "name": "YOUR_CONFIG_NAME", - "origin": { - "host": "YOUR_DATABASE_HOST", - "port": 5432, - "database": "DATABASE", - "user": "DATABASE_USER" - }, - "caching": { - "disabled": false - } + "hyperdrive": [ + { + "binding": "HYPERDRIVE", + "id": "" + } + ] } + ``` Copy the `id` field: you will use this in the next step to make Hyperdrive accessible from your Worker script. @@ -151,6 +147,7 @@ Hyperdrive will attempt to connect to your database with the provided credential ::: + ## 4. Bind your Worker to Hyperdrive @@ -257,4 +254,4 @@ By finishing this tutorial, you have created a Hyperdrive configuration, a Worke - How to [configure query caching](/hyperdrive/configuration/query-caching/). - [Troubleshooting common issues](/hyperdrive/observability/troubleshooting/) when connecting a database to Hyperdrive. -If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the [Cloudflare Developers community on Discord](https://discord.cloudflare.com). \ No newline at end of file +If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the [Cloudflare Developers community on Discord](https://discord.cloudflare.com). diff --git a/src/content/docs/hyperdrive/index.mdx b/src/content/docs/hyperdrive/index.mdx index 9589f6ce29b814..7b3e4b4759c6b7 100644 --- a/src/content/docs/hyperdrive/index.mdx +++ b/src/content/docs/hyperdrive/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Hyperdrive order: 0 type: overview pcx_content_type: overview @@ -7,27 +7,96 @@ sidebar: order: 1 head: - tag: title - content: Hyperdrive - + content: Overview --- -import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" +import { + CardGrid, + Description, + Feature, + LinkTitleCard, + Plan, + RelatedProduct, + Tabs, + TabItem, + LinkButton +} from "~/components"; - Turn your existing regional database into a globally distributed database. - -Hyperdrive is a service that accelerates queries you make to existing databases, making it faster to access your data from across the globe, irrespective of your users' location. Hyperdrive supports any Postgres database, including those hosted on AWS, Google Cloud and Neon, as well as Postgres-compatible databases like CockroachDB and Timescale, with MySQL coming soon. +Hyperdrive is a service that accelerates queries you make to existing databases, making it faster to access your data from across the globe from [Cloudflare Workers](/workers/), irrespective of your users' location. + +Hyperdrive supports any Postgres database, including those hosted on AWS, Google Cloud and Neon, as well as Postgres-compatible databases like CockroachDB and Timescale, with MySQL coming soon. You do not need to write new code or replace your favorite tools: Hyperdrive works with your existing code and tools you use. + +Use Hyperdrive's connection string from your Cloudflare Workers application with your existing Postgres drivers and object-relational mapping (ORM) libraries: + + + + + +```ts +import postgres from 'postgres'; + +export default { + async fetch(request, env, ctx): Promise { + // Hyperdrive provides a unique generated connection string to connect to + // your database via Hyperdrive that can be used with your existing tools + const sql = postgres(env.HYPERDRIVE.connectionString); + + try { + // Sample SQL query + const results = await sql`SELECT * FROM pg_tables`; + + // Close the client after the response is returned + ctx.waitUntil(sql.end()); + + return Response.json(results); + } catch (e) { + return Response.json({ error: e instanceof Error ? e.message : e }, { status: 500 }); + } + }, +} satisfies ExportedHandler<{ HYPERDRIVE: Hyperdrive }>; +``` + + + +```json + { + "$schema": "node_modules/wrangler/config-schema.json", + "name": "WORKER-NAME", + "main": "src/index.ts", + "compatibility_date": "2025-02-04", + "compatibility_flags": [ + "nodejs_compat" + ], + "observability": { + "enabled": true + }, + "hyperdrive": [ + { + "binding": "HYPERDRIVE", + "id": "", + "localConnectionString": "" + } + ] + } +``` + + + + +Get started + + + -Use your existing Postgres drivers and object-relational mapping (ORM) libraries of your choice without any changes. Hyperdrive gives you a connection string that looks just like any other. You do not need to write new code or replace your favorite tools: Hyperdrive works with the ones you already use. - -*** +--- ## Features @@ -35,24 +104,21 @@ Use your existing Postgres drivers and object-relational mapping (ORM) libraries Connect Hyperdrive to your existing database and deploy a [Worker](/workers/) that queries it. - Hyperdrive allows you to connect to any PostgreSQL or PostgreSQL-compatible database. - Use Hyperdrive to cache the most popular queries executed against your database. - -*** +--- ## Related products @@ -60,40 +126,62 @@ Use Hyperdrive to cache the most popular queries executed against your database. Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale. - Deploy dynamic front-end applications in record time. - -*** +--- ## More resources - -Learn about Hyperdrive's pricing. + + Learn about Hyperdrive's pricing. - -Learn about Hyperdrive limits. + + Learn about Hyperdrive limits. - -Learn more about the storage and database options you can build on with Workers. + + Learn more about the storage and database options you can build on with + Workers. - -Connect with the Workers community on Discord to ask questions, show what you are building, and discuss the platform with other developers. + + Connect with the Workers community on Discord to ask questions, show what you + are building, and discuss the platform with other developers. - -Follow @CloudflareDev on Twitter to learn about product announcements, and what is new in Cloudflare Developer Platform. + + Follow @CloudflareDev on Twitter to learn about product announcements, and + what is new in Cloudflare Developer Platform. +```` diff --git a/src/content/docs/hyperdrive/observability/metrics.mdx b/src/content/docs/hyperdrive/observability/metrics.mdx index 92932e2e259939..3fafc960f42213 100644 --- a/src/content/docs/hyperdrive/observability/metrics.mdx +++ b/src/content/docs/hyperdrive/observability/metrics.mdx @@ -18,8 +18,8 @@ Hyperdrive currently exports the below metrics as part of the `hyperdriveQueries | Cache Status | `cacheStatus` | Whether the query was cached or not. Can be one of `disabled`, `hit`, `miss`, `uncacheable`, `multiplestatements`, `notaquery`, `oversizedquery`, `oversizedresult`, `parseerror`, `transaction`, and `volatile`. | | Query Bytes | `queryBytes` | The size of your queries, in bytes. | | Result Bytes | `resultBytes` | The size of your query *results*, in bytes. | -| Connection Latency | `connectionLatency` | The time (in milliseconds) required to establish new connections from Hyperdrive to your database. | -| Query Latency | `queryLatency` | The time (in milliseconds) required to query (and receive results) from your database. | +| Connection Latency | `connectionLatency` | The time (in milliseconds) required to establish new connections from Hyperdrive to your database, as measured from your Hyperdrive connection pool(s). | +| Query Latency | `queryLatency` | The time (in milliseconds) required to query (and receive results) from your database, as measured from your Hyperdrive connection pool(s). | | Event Status | `eventStatus` | Whether a query responded successfully (`complete`) or failed (`error`). | Metrics can be queried (and are retained) for the past 31 days. diff --git a/src/content/docs/hyperdrive/platform/changelog.mdx b/src/content/docs/hyperdrive/platform/release-notes.mdx similarity index 95% rename from src/content/docs/hyperdrive/platform/changelog.mdx rename to src/content/docs/hyperdrive/platform/release-notes.mdx index 53f05d758a199d..40255079dbc31e 100644 --- a/src/content/docs/hyperdrive/platform/changelog.mdx +++ b/src/content/docs/hyperdrive/platform/release-notes.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: changelog -title: Changelog +title: Release notes release_notes_file_name: - hyperdrive sidebar: diff --git a/src/content/docs/hyperdrive/reference/faq.mdx b/src/content/docs/hyperdrive/reference/faq.mdx index 0b1eebed4f510f..2c72bf23f66acc 100644 --- a/src/content/docs/hyperdrive/reference/faq.mdx +++ b/src/content/docs/hyperdrive/reference/faq.mdx @@ -3,11 +3,18 @@ pcx_content_type: concept title: FAQ sidebar: order: 10 - --- Below you will find answers to our most commonly asked questions regarding Hyperdrive. +## Connectivity + +### Does Hyperdrive use specific IP addresses to connect to my database? + +Hyperdrive connects to your database using [Cloudflare's IP address ranges](https://www.cloudflare.com/ips/). These are shared by all Hyperdrive configurations and other Cloudflare products. + +You can use this to configure restrictions in your database firewall to restrict the IP addresses that can access your database. + ## Pricing ### Does Hyperdrive charge for data transfer / egress? @@ -27,4 +34,3 @@ Hyperdrive itself does not charge for compute (CPU) or processing (wall clock) t ### Are there any limits to Hyperdrive? Refer to the published [limits](/hyperdrive/platform/limits/) documentation. - diff --git a/src/content/docs/hyperdrive/tutorials/serverless-timeseries-api-with-timescale/index.mdx b/src/content/docs/hyperdrive/tutorials/serverless-timeseries-api-with-timescale/index.mdx index bd3d0c12ffc8ee..dfbb5b7b1e0dfb 100644 --- a/src/content/docs/hyperdrive/tutorials/serverless-timeseries-api-with-timescale/index.mdx +++ b/src/content/docs/hyperdrive/tutorials/serverless-timeseries-api-with-timescale/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-10-30 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Create a serverless, globally distributed time-series API with Timescale products: @@ -42,7 +41,7 @@ Run the following command to create a Worker project from the command line: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/images/get-started.mdx b/src/content/docs/images/get-started.mdx index a6b1a714393ba5..0866704240c391 100644 --- a/src/content/docs/images/get-started.mdx +++ b/src/content/docs/images/get-started.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: get-started -title: Get started +title: Getting started sidebar: order: 2 diff --git a/src/content/docs/images/index.mdx b/src/content/docs/images/index.mdx index a199fafffe78d8..3b9da0dd4f894a 100644 --- a/src/content/docs/images/index.mdx +++ b/src/content/docs/images/index.mdx @@ -1,20 +1,19 @@ --- -title: Overview +title: Cloudflare Images pcx_content_type: overview description: Streamline your image infrastructure with Cloudflare Images. Store, transform, and deliver images efficiently using Cloudflare's global network. sidebar: order: 1 head: - tag: title - content: Cloudflare Images - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan } from "~/components" -Store, transform, optimize, and deliver images at scale +Store, transform, optimize, and deliver images at scale @@ -30,7 +29,7 @@ Cloudflare Images is available on both [Free and Paid plans](/images/pricing/). :::note[Image Resizing is now available as transformations] -All Image Resizing features are available as transformations with Images. Each unique transformation is billed only once per 30 days. +All Image Resizing features are available as transformations with Images. Each unique transformation is billed only once per 30 days. If you are using a legacy plan with Image Resizing, visit the [dashboard](https://dash.cloudflare.com/) to switch to an Imagesplan. @@ -48,15 +47,15 @@ Use Cloudflare’s edge network to store your images. -Accept uploads directly and securely from your users by generating a one-time token. +Accept uploads directly and securely from your users by generating a one-time token. -Add up to 100 variants to specify how images should be resized for various use cases. +Add up to 100 variants to specify how images should be resized for various use cases. -Control access to your images by using signed URL tokens. +Control access to your images by using signed URL tokens. *** @@ -67,7 +66,7 @@ Control access to your images by using signed URL tokens. -Engage with other users and the Images team on Cloudflare support forum. +Engage with other users and the Images team on Cloudflare support forum. diff --git a/src/content/docs/images/transform-images/bindings.mdx b/src/content/docs/images/transform-images/bindings.mdx index d205dd9dda0926..85a8d8ef55469f 100644 --- a/src/content/docs/images/transform-images/bindings.mdx +++ b/src/content/docs/images/transform-images/bindings.mdx @@ -60,6 +60,7 @@ const response = ( await env.IMAGES.input(stream) .transform({ rotate: 90 }) .transform({ width: 128 }) + .transform({ blur: 20 }) .output({ format: "image/avif" }) ).response(); diff --git a/src/content/docs/images/transform-images/index.mdx b/src/content/docs/images/transform-images/index.mdx index b1d8ae4258d9c7..3044260656695c 100644 --- a/src/content/docs/images/transform-images/index.mdx +++ b/src/content/docs/images/transform-images/index.mdx @@ -10,7 +10,7 @@ import { Render } from "~/components" Transformations let you optimize and manipulate images stored outside of the Cloudflare Images product. Transformed images are served from one of your zones on Cloudflare. -To transform an image, you must [enable transformations for your zone](/images/get-started/#enable-transformations). +To transform an image, you must [enable transformations for your zone](/images/get-started/#enable-transformations-on-your-zone). You can transform an image by using a [specially-formatted URL](/images/transform-images/transform-via-url/) or [through Workers](/images/transform-images/transform-via-workers/). diff --git a/src/content/docs/images/transform-images/sources.mdx b/src/content/docs/images/transform-images/sources.mdx index 3e40721c19f631..1341dfe11c3b6e 100644 --- a/src/content/docs/images/transform-images/sources.mdx +++ b/src/content/docs/images/transform-images/sources.mdx @@ -19,7 +19,7 @@ If you use a Worker to optimize remote images via a `fetch()` subrequest, then t In the Cloudflare dashboard, go to **Images** > **Transformations** and select the zone where you want to serve transformations. -To get started, you must have [transformations enabled on your zone](/images/get-started/#enable-transformations). +To get started, you must have [transformations enabled on your zone](/images/get-started/#enable-transformations-on-your-zone). In **Sources**, you can configure the origins for transformations on your zone. diff --git a/src/content/docs/images/transform-images/transform-via-url.mdx b/src/content/docs/images/transform-images/transform-via-url.mdx index ccd4c66077f06f..8ef91e65aba46b 100644 --- a/src/content/docs/images/transform-images/transform-via-url.mdx +++ b/src/content/docs/images/transform-images/transform-via-url.mdx @@ -79,6 +79,10 @@ You must specify at least one option. Options are comma-separated (spaces are no +### `flip` + + + ### `format` @@ -119,6 +123,10 @@ You must specify at least one option. Options are comma-separated (spaces are no +### `slow-connection-quality` + + + ### `trim` @@ -161,4 +169,4 @@ If Custom Cache Keys are used for the origin image, the origin image might not b Resized images follow the same caching rules as the original image they were resized from, except the minimum cache time is one hour. If you need images to be updated more frequently, add `must-revalidate` to the `Cache-Control` header. Resizing supports cache revalidation, so we recommend serving images with the `Etag` header. Refer to the [Cache docs for more information](/cache/concepts/cache-control/#revalidation). -Cloudflare Images does not support purging resized variants individually. URLs starting with `/cdn-cgi/` cannot be purged. However, purging of the original image's URL will also purge all of its resized variants. +Cloudflare Images does not support purging resized variants individually. URLs starting with `/cdn-cgi/` cannot be purged. However, purging of the original image's URL will also purge all of its resized variants. \ No newline at end of file diff --git a/src/content/docs/images/transform-images/transform-via-workers.mdx b/src/content/docs/images/transform-images/transform-via-workers.mdx index e3ef0deebdabf1..8565589468cdc4 100644 --- a/src/content/docs/images/transform-images/transform-via-workers.mdx +++ b/src/content/docs/images/transform-images/transform-via-workers.mdx @@ -66,6 +66,10 @@ The `fetch()` function accepts parameters in the second argument inside the `{cf +### `flip` + + + ### `format` diff --git a/src/content/docs/images/upload-images/index.mdx b/src/content/docs/images/upload-images/index.mdx index b37ecbf907928e..1bc0e9a46d6aae 100644 --- a/src/content/docs/images/upload-images/index.mdx +++ b/src/content/docs/images/upload-images/index.mdx @@ -13,7 +13,7 @@ Cloudflare Images allows developers to upload images using different methods, fo You can upload the following image formats to Cloudflare Images: * PNG -* GIF +* GIF (including animations) * JPEG * WebP (Cloudflare Images also supports uploading animated WebP files) * SVG diff --git a/src/content/docs/key-transparency/index.mdx b/src/content/docs/key-transparency/index.mdx index c60e75a28e0772..f8da1da131decd 100644 --- a/src/content/docs/key-transparency/index.mdx +++ b/src/content/docs/key-transparency/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Key Transparency Auditor pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Key Transparency Auditor - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, RelatedProduct } from "~/components" diff --git a/src/content/docs/kv/concepts/how-kv-works.mdx b/src/content/docs/kv/concepts/how-kv-works.mdx index 6b2611b8f76f40..82f93aaec6cb9e 100644 --- a/src/content/docs/kv/concepts/how-kv-works.mdx +++ b/src/content/docs/kv/concepts/how-kv-works.mdx @@ -7,13 +7,12 @@ sidebar: KV is a global, low-latency, key-value data store. It stores data in a small number of centralized data centers, then caches that data in Cloudflare's data centers after access. -KV supports exceptionally high read volumes with low latency, making it possible to build highly dynamic APIs. - -While reads are periodically revalidated in the background, requests which are not in cache and need to hit the centralized back end can experience high latencies. +KV supports exceptionally high read volumes with low latency, making it possible to build dynamic APIs that scale thanks to KV's built-in caching and global distribution. +Requests which are not in cache and need to access the central stores can experience higher latencies. ## Write data to KV and read data from KV -When you write to KV, your data is written to central data stores. Your data is not sent automatically to every location’s cache. +When you write to KV, your data is written to central data stores. Your data is not sent automatically to every location's cache. ![Your data is written to central data stores when you write to KV.](~/assets/images/kv/kv-write.svg) @@ -26,7 +25,7 @@ A hot read means that the data is cached on Cloudflare's edge network using the ![Initial reads will miss the cache and go to the nearest central data store first.](~/assets/images/kv/kv-slow-read.svg) -Frequent reads from the same location return the cached value without reading from anywhere else, resulting in the fastest response times. KV operates diligently to keep the latest value in the cache by refreshing from upper tiers and the central data stores in the background. +Frequent reads from the same location return the cached value without reading from anywhere else, resulting in the fastest response times. KV operates diligently to update the cached values by refreshing from upper tier caches and central data stores before cache expires in the background. Refreshing from upper tiers and the central data stores in the background is done carefully so that assets that are being accessed continue to be kept served from the cache without any stalls. @@ -44,8 +43,6 @@ Changes are usually immediately visible in the Cloudflare global network locatio Negative lookups indicating that the key does not exist are also cached, so the same delay exists noticing a value is created as when a value is changed. -KV does not perform like an in-memory datastore, such as [Redis](https://redis.io). Accessing KV values, even when locally cached, has significantly more latency than reading a value from memory within a Worker script. - ## Consistency KV achieves high performance by being eventually-consistent. At the Cloudflare global network location at which changes are made, these changes are usually immediately visible. However, this is not guaranteed and therefore it is not advised to rely on this behaviour. In other global network locations changes may take up to 60 seconds or more to be visible as their cached versions of the data time-out. @@ -60,6 +57,22 @@ If you need stronger consistency guarantees, consider using [Durable Objects](/d An approach to achieve write-after-write consistency is to send all of your writes for a given KV key through a corresponding instance of a Durable Object, and then read that value from KV in other Workers. This is useful if you need more control over writes, but are satisfied with KV's read characteristics described above. +## Guidance + +Workers KV is an eventually-consistent edge key-value store. That makes it ideal for **read-heavy**, highly cacheable workloads such as: + +- Serving static assets +- Storing application configuration +- Storing user preferences +- Implementing allow-lists/deny-lists +- Caching + +In these scenarios, Workers are invoked in a data center closest to the user and Workers KV data will be cached in that region for subsequent requests to minimize latency. + +If you have a **write-heavy** [Redis](https://redis.io)-type workload where you are updating the same key tens or hundreds of times per second, KV will not be an ideal fit. +If you can revisit how your application writes to single key-value pairs and spread your writes across several discrete keys, Workers KV can suit your needs. +Alternatively, [Durable Objects](/durable-objects/) provides a key-value API with higher writes per key rate limits. + ## Security Refer to [Data security documentation](/kv/reference/data-security/) to understand how Workers KV secures data. diff --git a/src/content/docs/kv/examples/workers-kv-to-serve-assets.mdx b/src/content/docs/kv/examples/workers-kv-to-serve-assets.mdx index 997d7030f63d8f..4d65807da018fa 100644 --- a/src/content/docs/kv/examples/workers-kv-to-serve-assets.mdx +++ b/src/content/docs/kv/examples/workers-kv-to-serve-assets.mdx @@ -1,8 +1,6 @@ --- type: example summary: Store and retrieve static assets with Workers KV -tags: - - KV pcx_content_type: configuration title: Store and retrieve static assets with Workers KV sidebar: @@ -35,7 +33,7 @@ To get started, create a Worker application using the [`create-cloudflare` CLI]( product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/kv/get-started.mdx b/src/content/docs/kv/get-started.mdx index 4fed2fe922e065..cb74ecab2e7e04 100644 --- a/src/content/docs/kv/get-started.mdx +++ b/src/content/docs/kv/get-started.mdx @@ -1,5 +1,5 @@ --- -title: Get started +title: Getting started pcx_content_type: get-started sidebar: order: 2 @@ -43,7 +43,7 @@ Create a new Worker to read and write to your KV namespace. product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -147,10 +147,6 @@ To create a KV namespace via Wrangler: 4. Select **Add**. -:::note - -::: - ## 3. Bind your Worker to your KV namespace diff --git a/src/content/docs/kv/index.mdx b/src/content/docs/kv/index.mdx index 0b173cb65b9491..6ee4bfae4187a5 100644 --- a/src/content/docs/kv/index.mdx +++ b/src/content/docs/kv/index.mdx @@ -12,6 +12,9 @@ import { LinkTitleCard, Plan, RelatedProduct, + Tabs, + TabItem, + LinkButton, } from "~/components"; @@ -24,6 +27,128 @@ Create a global, low-latency, key-value data storage. Workers KV is a data storage that allows you to store and retrieve data globally. With Workers KV, you can build dynamic and performant APIs and websites that support high read volumes with low latency. +For example, you can use Workers KV for: + +- Caching API responses. +- Storing user configurations / preferences. +- Storing user authentication details. + +Access your Workers KV namespace from Cloudflare Workers using [Workers Bindings](/workers/runtime-apis/bindings/) or from your external application using the REST API: + + + + + +```ts +export default { + async fetch(request, env, ctx): Promise { + // write a key-value pair + await env.KV_BINDING.put('KEY', 'VALUE'); + + // read a key-value pair + const value = await env.KV_BINDING.get('KEY'); + + // list all key-value pairs + const allKeys = await env.KV_BINDING.list(); + + // delete a key-value pair + await env.KV_BINDING.delete('KEY'); + + // return a Workers response + return new Response( + JSON.stringify({ + value: value, + allKeys: allKeys, + }), + ); + }, + +} satisfies ExportedHandler<{ KV_BINDING: KVNamespace }>; + + ``` + + + +```json +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "WORKER-NAME", + "main": "src/index.ts", + "compatibility_date": "2025-02-04", + "observability": { + "enabled": true + }, + + "kv_namespaces": [ + { + "binding": "KV_BINDING", + "id": "" + } + ] +} +``` + + + + +See the full [Workers KV binding API reference](/kv/api/read-key-value-pairs/). + + + + + + + ``` + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/values/$KEY_NAME \ + -X PUT \ + -H 'Content-Type: multipart/form-data' \ + -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ + -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \ + -d '{ + "value": "Some Value" + }' + + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/values/$KEY_NAME \ + -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ + -H "X-Auth-Key: $CLOUDFLARE_API_KEY" + ``` + + + ```ts + const client = new Cloudflare({ + apiEmail: process.env['CLOUDFLARE_EMAIL'], // This is the default and can be omitted + apiKey: process.env['CLOUDFLARE_API_KEY'], // This is the default and can be omitted + }); + + const value = await client.kv.namespaces.values.update('', 'KEY', { + account_id: '', + value: 'VALUE', + }); + + const value = await client.kv.namespaces.values.get('', 'KEY', { + account_id: '', + }); + + const value = await client.kv.namespaces.values.delete('', 'KEY', { + account_id: '', + }); + + // Automatically fetches more pages as needed. + for await (const namespace of client.kv.namespaces.list({ account_id: '' })) { + console.log(namespace.id); + } + + ``` + + + +See the full Workers KV [REST API and SDK reference](/api/resources/kv/subresources/namespaces/methods/list/) for details on using REST API from external applications, with pre-generated SDK's for external TypeScript, Python, or Go applications. + + + + +Get started + --- ## Features diff --git a/src/content/docs/kv/platform/limits.mdx b/src/content/docs/kv/platform/limits.mdx index 085a4c2e5f302d..5aa87c1d7fc18f 100644 --- a/src/content/docs/kv/platform/limits.mdx +++ b/src/content/docs/kv/platform/limits.mdx @@ -10,22 +10,22 @@ sidebar: import { Render } from "~/components" -| Feature | Free | Paid | -| ---------------------------- | --------------------- | ------------ | -| Reads | 100,000 reads per day | Unlimited | -| Writes to different keys | 1,000 writes per day | Unlimited | -| Writes to same key | 1 per second | 1 per second | -| Operations/worker invocation | 1000 | 1000 | -| Namespaces | 1000 | 1000 | -| Storage/account | 1 GB | Unlimited | -| Storage/namespace | 1 GB | Unlimited | -| Keys/namespace | Unlimited | Unlimited | -| Key size | 512 bytes | 512 bytes | -| Key metadata | 1024 bytes | 1024 bytes | -| Value size | 25 MiB | 25 MiB | +| Feature | Free | Paid | +| --------------------------------- | --------------------- | ------------ | +| Reads | 100,000 reads per day | Unlimited | +| Writes to different keys | 1,000 writes per day | Unlimited | +| Writes to same key | 1 per second | 1 per second | +| Operations/Worker invocation [^1] | 1000 | 1000 | +| Namespaces | 1000 | 1000 | +| Storage/account | 1 GB | Unlimited | +| Storage/namespace | 1 GB | Unlimited | +| Keys/namespace | Unlimited | Unlimited | +| Key size | 512 bytes | 512 bytes | +| Key metadata | 1024 bytes | 1024 bytes | +| Value size | 25 MiB | 25 MiB | | Minimum [`cacheTtl`](/kv/api/read-key-value-pairs/#cachettl-parameter) | 60 seconds | 60 seconds | - +[^1]: Within a single invocation, a Worker can make up to 1,000 operations to external services (for example, 500 Workers KV reads and 500 R2 reads). diff --git a/src/content/docs/kv/platform/changelog.mdx b/src/content/docs/kv/platform/release-notes.mdx similarity index 95% rename from src/content/docs/kv/platform/changelog.mdx rename to src/content/docs/kv/platform/release-notes.mdx index c2124f97cca477..2614079dd56998 100644 --- a/src/content/docs/kv/platform/changelog.mdx +++ b/src/content/docs/kv/platform/release-notes.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: changelog -title: Changelog +title: Release notes sidebar: order: 8 release_notes_file_name: diff --git a/src/content/docs/learning-paths/application-security/default-traffic-security/security-level.mdx b/src/content/docs/learning-paths/application-security/default-traffic-security/security-level.mdx deleted file mode 100644 index 3e994141c32ece..00000000000000 --- a/src/content/docs/learning-paths/application-security/default-traffic-security/security-level.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Security level -pcx_content_type: learning-unit -sidebar: - order: 2 ---- - -import { Render } from "~/components"; - - - - - - diff --git a/src/content/docs/learning-paths/china-network-overview/series/china-express-overview-2.mdx b/src/content/docs/learning-paths/china-network-overview/series/china-express-overview-2.mdx new file mode 100644 index 00000000000000..8587d4ae67753b --- /dev/null +++ b/src/content/docs/learning-paths/china-network-overview/series/china-express-overview-2.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: How to accelerate dynamic traffic outside of mainland China +sidebar: + order: 2 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, Jess Liu discusses Cloudflare's CDN Global Acceleration (formerly China Express), including solutions for high latency on dynamic content, accelerating API calls, accessing Cloudflare One services like WARP and Magic WAN from within mainland China, and securely connecting private enterprise networks. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/china-network-overview/series/china-network-main-features-1.mdx b/src/content/docs/learning-paths/china-network-overview/series/china-network-main-features-1.mdx new file mode 100644 index 00000000000000..a1dc52da703e4f --- /dev/null +++ b/src/content/docs/learning-paths/china-network-overview/series/china-network-main-features-1.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: How to speed up your web traffic inside mainland China +sidebar: + order: 1 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, Jess Liu walks us through the main features of Cloudflare's China Network. They cover how the China Network works, including integrated caching, in-country China name servers, and compliance with ICP regulations. They also briefly discuss Cloudflare’s CDN Global Acceleration (formerly China Express), an option for accelerating dynamic content that cannot be cached. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/china-network-overview/series/index.mdx b/src/content/docs/learning-paths/china-network-overview/series/index.mdx new file mode 100644 index 00000000000000..0df7484bd14d08 --- /dev/null +++ b/src/content/docs/learning-paths/china-network-overview/series/index.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Overview +sidebar: + order: 4 + group: + hideIndex: true +tableOfContents: false +--- diff --git a/src/content/docs/learning-paths/durable-objects-course/series/build-the-app-frontend-5.mdx b/src/content/docs/learning-paths/durable-objects-course/series/build-the-app-frontend-5.mdx new file mode 100644 index 00000000000000..80c8d37055277c --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/build-the-app-frontend-5.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Build the app frontend and UI +sidebar: + order: 5 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, we set up the frontend starter code (the starter code is located in the Veet GitHub repository), connect to Durable Objects using a call room ID, and display a local video preview. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/deploy-your-video-call-app-7.mdx b/src/content/docs/learning-paths/durable-objects-course/series/deploy-your-video-call-app-7.mdx new file mode 100644 index 00000000000000..89f5ae60ac0498 --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/deploy-your-video-call-app-7.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Deploy your video call app +sidebar: + order: 7 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + We are almost done with the project, and in this final episode, we add the finishing touches, such as learning how to handle call disconnections, wiring up essential media controls like muting/unmuting and video toggling, and integrating a TURN server to ensure reliable connections even behind firewalls. By the end of this video, your app will be fully functional and ready for deployment. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/index.mdx b/src/content/docs/learning-paths/durable-objects-course/series/index.mdx new file mode 100644 index 00000000000000..0df7484bd14d08 --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/index.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Overview +sidebar: + order: 4 + group: + hideIndex: true +tableOfContents: false +--- diff --git a/src/content/docs/learning-paths/durable-objects-course/series/introduction-to-series-1.mdx b/src/content/docs/learning-paths/durable-objects-course/series/introduction-to-series-1.mdx new file mode 100644 index 00000000000000..f9c7b7c9d84794 --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/introduction-to-series-1.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Introduction to the series +sidebar: + order: 1 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this episode, we present an overview of the series, discuss its underlying architecture, and access resources to set up the project locally. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/make-answer-webrtc-calls-6.mdx b/src/content/docs/learning-paths/durable-objects-course/series/make-answer-webrtc-calls-6.mdx new file mode 100644 index 00000000000000..53cbdf44d7046f --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/make-answer-webrtc-calls-6.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Make and answer WebRTC calls +sidebar: + order: 6 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, we build on the frontend we set up earlier by adding functionality for making and answering WebRTC video calls. You will learn how to create peer-to-peer connections, handle ICE candidates, and seamlessly send and receive video streams between users. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/real-time-messaging-with-websockets-4.mdx b/src/content/docs/learning-paths/durable-objects-course/series/real-time-messaging-with-websockets-4.mdx new file mode 100644 index 00000000000000..a26ccbb5bb1644 --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/real-time-messaging-with-websockets-4.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Real-time messaging with WebSockets +sidebar: + order: 4 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + Now, we'll take it a step further by enabling our server to receive and broadcast messages. In this video, you'll learn how to route and broadcast incoming messages from WebSocket connections and implement error handling such as closed WebSocket connections. By the end, you will have completed the backend for our video call app. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/serverless-websocket-backend-3.mdx b/src/content/docs/learning-paths/durable-objects-course/series/serverless-websocket-backend-3.mdx new file mode 100644 index 00000000000000..258713f281a4f7 --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/serverless-websocket-backend-3.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: Create a serverless websocket 'backend' +sidebar: + order: 3 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, we'll create a WebSocket backend using serverless technology, making the process simpler than ever before. You'll learn how to create your first Durable Object, set up a WebSocket server to coordinate connections, and keep track of connected clients. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/durable-objects-course/series/what-are-durable-objects-2.mdx b/src/content/docs/learning-paths/durable-objects-course/series/what-are-durable-objects-2.mdx new file mode 100644 index 00000000000000..2d6e88748693db --- /dev/null +++ b/src/content/docs/learning-paths/durable-objects-course/series/what-are-durable-objects-2.mdx @@ -0,0 +1,32 @@ +--- +pcx_content_type: navigation +title: What are Durable Objects? +sidebar: + order: 2 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, we show how Durable Objects work and start building a video call app together. + + + + + + + + + + + + + diff --git a/src/content/docs/learning-paths/prevent-ddos-attacks/advanced/customize-security.mdx b/src/content/docs/learning-paths/prevent-ddos-attacks/advanced/customize-security.mdx index 47b533d4c3239e..c18962af1e5498 100644 --- a/src/content/docs/learning-paths/prevent-ddos-attacks/advanced/customize-security.mdx +++ b/src/content/docs/learning-paths/prevent-ddos-attacks/advanced/customize-security.mdx @@ -3,17 +3,15 @@ title: Customize Cloudflare security pcx_content_type: learning-unit sidebar: order: 3 - --- Another way of reducing origin traffic is customizing the Cloudflare WAF and other security features. The fewer malicious requests that reach your application, the fewer that could reach (and overwhelm) your origin. To reduce incoming malicious requests, you could: -* Create [WAF custom rules](/waf/custom-rules/) for protection based on specific aspects of incoming requests. -* Adjust DDoS rules to handle [false negatives and false positives](/ddos-protection/managed-rulesets/adjust-rules/). -* Build [rate limiting rules](/waf/rate-limiting-rules/) to protect against specific patterns of requests. -* Enable [bot protection](/bots/get-started/) or set up [Bot Management for Enterprise](/bots/get-started/bm-subscription/) to protect against automated abuse. -* Explore [network-layer DDoS attack protection](/ddos-protection/managed-rulesets/network/). -* Configure your zone's [Security Level](/waf/tools/security-level/) globally or selectively (depending on your needs). -* Review the rest of Cloudflare's [security options](/learning-paths/application-security/account-security/). +- Create [WAF custom rules](/waf/custom-rules/) for protection based on specific aspects of incoming requests. +- Adjust DDoS rules to handle [false negatives and false positives](/ddos-protection/managed-rulesets/adjust-rules/). +- Build [rate limiting rules](/waf/rate-limiting-rules/) to protect against specific patterns of requests. +- Enable [bot protection](/bots/get-started/) or set up [Bot Management for Enterprise](/bots/get-started/bm-subscription/) to protect against automated abuse. +- Explore [network-layer DDoS attack protection](/ddos-protection/managed-rulesets/network/). +- Review the rest of Cloudflare's [security options](/learning-paths/application-security/account-security/). diff --git a/src/content/docs/learning-paths/replace-vpn/build-policies/create-policy.mdx b/src/content/docs/learning-paths/replace-vpn/build-policies/create-policy.mdx index 5536cea49ff6f5..f07eaecfcd88ed 100644 --- a/src/content/docs/learning-paths/replace-vpn/build-policies/create-policy.mdx +++ b/src/content/docs/learning-paths/replace-vpn/build-policies/create-policy.mdx @@ -38,9 +38,8 @@ To create a new policy, open [Zero Trust](https://one.dash.cloudflare.com/) and ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Company Wiki DNS policy", @@ -101,9 +100,8 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Company Wiki network policy", @@ -159,9 +157,8 @@ We recommend adding a catch-all policy to the bottom of your network policy list ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Catch-all block policy", diff --git a/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx b/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx index e86da3b29f1bba..bac9206fcc7e33 100644 --- a/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx +++ b/src/content/docs/learning-paths/replace-vpn/connect-private-network/cloudflared.mdx @@ -26,7 +26,7 @@ All internal applications and services in this IP range are now connected to Clo If the tunnel is disconnected: -* Ensure that your on-premise or cloud firewall allows egress traffic on the [required ports](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). +* Ensure that your on-premise or cloud firewall allows egress traffic on the [required ports](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). * Ensure that the `cloudflared` host machine can connect to your internal applications and services. Verify that the host has the proper security group memberships and that no firewalls will block traffic between the host and the target services. @@ -35,7 +35,7 @@ If the tunnel is disconnected: ## Best practices * Segregate production and staging traffic among different Cloudflare tunnels. -* Add a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) to another host machine for an additional point of availability. +* Add a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) to another host machine for an additional point of availability. * Distribute access to critical services (for example, private DNS, Active Directory, and other critical systems) across different tunnels for blast-radius reduction in the event of a server-side outage. * [Enable notifications](/cloudflare-one/connections/connect-networks/monitor-tunnels/notifications/) in the Cloudflare dashboard to monitor tunnel health. * [Monitor performance metrics](/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics/) to identify potential bottlenecks. diff --git a/src/content/docs/learning-paths/replace-vpn/connect-private-network/tunnel-capacity.mdx b/src/content/docs/learning-paths/replace-vpn/connect-private-network/tunnel-capacity.mdx index 72e0c61600a5f6..bc51ddeee4a5be 100644 --- a/src/content/docs/learning-paths/replace-vpn/connect-private-network/tunnel-capacity.mdx +++ b/src/content/docs/learning-paths/replace-vpn/connect-private-network/tunnel-capacity.mdx @@ -17,7 +17,7 @@ To determine how many `cloudflared` host servers you need: 1. Start with our baseline recommendations: -2. After you have completed this learning path and have users actively engaging with the network, [calculate](/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/#calculate-your-tunnel-capacity) your actual tunnel usage. +2. After you have completed this learning path and have users actively engaging with the network, [calculate](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/#calculate-your-tunnel-capacity) your actual tunnel usage. 3. Decide how much headroom you want to include and [resize the tunnel](#scale-the-tunnel) if needed. @@ -61,7 +61,7 @@ tunnel-3 <--> C ### When to add replicas -Adding additional [replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/#cloudflared-replicas) of an existing Cloudflare Tunnel (two is the baseline recommendation) should only be done to support additional traffic to the IP routes in the tunnel. Replicas should always be added in the same physical location as one another so that they can operate in a pooled mode. If you are considering adding a replica in a different geographic location, reevaluate the network proxy design for your Cloudflare Tunnel and refer to [When to add tunnels](#when-to-add-tunnels). +Adding additional [replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/#cloudflared-replicas) of an existing Cloudflare Tunnel (two is the baseline recommendation) should only be done to support additional traffic to the IP routes in the tunnel. Replicas should always be added in the same physical location as one another so that they can operate in a pooled mode. If you are considering adding a replica in a different geographic location, reevaluate the network proxy design for your Cloudflare Tunnel and refer to [When to add tunnels](#when-to-add-tunnels). ### When to add tunnels diff --git a/src/content/docs/learning-paths/replace-vpn/get-started/prerequisites.mdx b/src/content/docs/learning-paths/replace-vpn/get-started/prerequisites.mdx index 3be949b7580108..f9488158b254ef 100644 --- a/src/content/docs/learning-paths/replace-vpn/get-started/prerequisites.mdx +++ b/src/content/docs/learning-paths/replace-vpn/get-started/prerequisites.mdx @@ -10,5 +10,5 @@ To make the most of this learning path, make sure that you have the following: * A device that can run [WARP](/cloudflare-one/connections/connect-devices/warp/download-warp/), Cloudflare's endpoint agent. * A private network with applications or services that are available locally or via a VPN. -* A [host server](/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/#recommendations) on the private network that can run the lightweight Cloudflare Tunnel daemon process. +* A [host server](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/#recommendations) on the private network that can run the lightweight Cloudflare Tunnel daemon process. * (Optional) A [Linux host server](/cloudflare-one/connections/connect-devices/warp/download-warp/#linux) on the private network that can run the Cloudflare WARP Connector. This is only needed for server-initiated traffic flows such as Microsoft SCCM, Active Directory (AD) updates, and DevOps workflows that require server-initiated connections. diff --git a/src/content/docs/learning-paths/sase-overview-course/series/connect-secure-from-any-network-to-anywhere-4.mdx b/src/content/docs/learning-paths/sase-overview-course/series/connect-secure-from-any-network-to-anywhere-4.mdx new file mode 100644 index 00000000000000..05a52659a9ac5f --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/connect-secure-from-any-network-to-anywhere-4.mdx @@ -0,0 +1,48 @@ +--- +pcx_content_type: navigation +title: Connect and secure from any network to anywhere +sidebar: + order: 5 +prev: true +next: true +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + Build your new corporate network with Cloudflare, connecting any network into our modern SASE platform and secure applications, users, devices and your company data. In this video you will learn all the different methods of connecting networks to Cloudflare and what services can be used to improve security and performance. + + + + + **Related content** + + If you want to dive into detail about using Cloudflare to modernize your corporate network, refer to the following pages: + + - [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) + - [Magic Transit Reference Architecture](/reference-architecture/architectures/magic-transit/) + - [Protect data center networks](/reference-architecture/diagrams/network/protect-data-center-networks/) + - [Protect hybrid cloud networks](/reference-architecture/diagrams/network/protect-hybrid-cloud-networks-with-cloudflare-magic-transit/) + + + + + + + + diff --git a/src/content/docs/learning-paths/sase-overview-course/series/evolution-corporate-networks-1.mdx b/src/content/docs/learning-paths/sase-overview-course/series/evolution-corporate-networks-1.mdx new file mode 100644 index 00000000000000..52dfe8418cd533 --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/evolution-corporate-networks-1.mdx @@ -0,0 +1,48 @@ +--- +pcx_content_type: navigation +title: The evolution of corporate networks +sidebar: + order: 2 +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video, we discuss Cloudflare One, our Secure Access Service Edge (SASE) platform and how it has been designed to revolutionize the corporate network and enable companies with their Zero Trust strategy. Legacy network design is struggling to address today's challenges of security, performance and monitoring needs. Many IT teams are trying to evolve their corporate network with point solutions and finding the lack of integration and performance an issue. + + + + + **Related content** + + If you want to dive into detail about modernizing your corporate network with Cloudflare, refer to the following pages: + + - [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) + - [Network-focused migration from VPN concentrators to Zero Trust Network Access](/reference-architecture/design-guides/network-vpn-migration/) + - [Using a Zero Trust framework to secure SaaS applications](/reference-architecture/design-guides/zero-trust-for-saas/) + - [Building Zero Trust architecture into your startup](/reference-architecture/design-guides/zero-trust-for-startups/) + + + + + + + + diff --git a/src/content/docs/learning-paths/sase-overview-course/series/index.mdx b/src/content/docs/learning-paths/sase-overview-course/series/index.mdx new file mode 100644 index 00000000000000..0df7484bd14d08 --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/index.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Overview +sidebar: + order: 4 + group: + hideIndex: true +tableOfContents: false +--- diff --git a/src/content/docs/learning-paths/sase-overview-course/series/protect-users-from-internet-risks-5.mdx b/src/content/docs/learning-paths/sase-overview-course/series/protect-users-from-internet-risks-5.mdx new file mode 100644 index 00000000000000..f4b6244e0e0336 --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/protect-users-from-internet-risks-5.mdx @@ -0,0 +1,49 @@ +--- +pcx_content_type: navigation +title: Protect your users from Internet risks +sidebar: + order: 6 +prev: true +next: false +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + The Internet has become part of your corporate network, however browsing the web comes with hidden risks including malware, phishing attacks, and malicious websites. In this video, we will explore how Cloudflare's Secure Web Gateway (SWG) helps keep users safe by filtering and inspecting Internet traffic in real time. Whether you are protecting a remote workforce or securing an entire organization, Cloudflare ensures that users can access the web securely — without sacrificing speed or productivity. + + + + + **Related content** + + If you want to dive into detail about modernizing your corporate network with Cloudflare, refer to the following pages: + + - [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) + - [Network-focused migration from VPN concentrators to Zero Trust Network Access](/reference-architecture/design-guides/network-vpn-migration/) + - [Using a Zero Trust framework to secure SaaS applications](/reference-architecture/design-guides/zero-trust-for-saas/) + - [Building Zero Trust architecture into your startup](/reference-architecture/design-guides/zero-trust-for-startups/) + + + + + + + + diff --git a/src/content/docs/learning-paths/sase-overview-course/series/secure-remote-access-to-critical-infrastructure-3.mdx b/src/content/docs/learning-paths/sase-overview-course/series/secure-remote-access-to-critical-infrastructure-3.mdx new file mode 100644 index 00000000000000..b3d6e6c6dde009 --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/secure-remote-access-to-critical-infrastructure-3.mdx @@ -0,0 +1,49 @@ +--- +pcx_content_type: navigation +title: Secure remote access to your critical infrastructure +sidebar: + order: 4 +prev: true +next: true +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + In this video learn how Cloudflare's SASE platform can provide highly secure access to your critical infrastructure by leveraging a modern ZTNA service to implement Zero Trust principles. Applications, databases and their servers are running in a variety of locations from on-premises data centers to cloud hyperscalers, making the need to secure administrative access more important than ever. + + + + + **Related content** + + If you want to dive into detail about using Cloudflare to access critical infrastructure, refer to the following pages: + + - [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) + - [SSH with Access for Infrastructure](/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/) + - [Using a Zero Trust framework to secure SaaS applications](/reference-architecture/design-guides/zero-trust-for-saas/) + - [Building Zero Trust architecture into your startup](/reference-architecture/design-guides/zero-trust-for-startups/) + + + + + + + + diff --git a/src/content/docs/learning-paths/sase-overview-course/series/stop-hosting-own-vpn-service-2.mdx b/src/content/docs/learning-paths/sase-overview-course/series/stop-hosting-own-vpn-service-2.mdx new file mode 100644 index 00000000000000..01fdf03daf0272 --- /dev/null +++ b/src/content/docs/learning-paths/sase-overview-course/series/stop-hosting-own-vpn-service-2.mdx @@ -0,0 +1,49 @@ +--- +pcx_content_type: navigation +title: Stop hosting your own VPN service +sidebar: + order: 3 +prev: true +next: true +tableOfContents: false +--- + +import { Render, Tabs, TabItem, Stream, Card } from "~/components"; + + + + + Cloudflare's SASE platform can replace your traditional, expensive VPN appliances which deliver poor performance for users and create more security risks than solve them. Cloudflare's Zero Trust Network Access (ZTNA) service is a more secure, highly scalable cloud solution. In this video we look at how easily you can deploy Cloudflare to secure access to internal resources. + + + + + **Related content** + + If you want to dive into detail about using Cloudflare to replace your existing VPN solution, refer to the following pages: + + - [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) + - [Network-focused migration from VPN concentrators to Zero Trust Network Access](/reference-architecture/design-guides/network-vpn-migration/) + - [Access to private apps without having to deploy client agents](/reference-architecture/diagrams/sase/sase-clientless-access-private-dns/) + - [Zero Trust and Virtual Desktop Infrastructure](/reference-architecture/diagrams/sase/zero-trust-and-virtual-desktop-infrastructure/) + + + + + + + + \ No newline at end of file diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-list.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-list.mdx index eee0f7f65f00e6..cc9b9f9e557d62 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-list.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-list.mdx @@ -28,7 +28,7 @@ The following DNS policy will allow access to all approved corporate domains inc ```sh -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer " \ --data '{ diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-policy.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-policy.mdx index 06e523498c2336..b5d707de538362 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-policy.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-dns-policies/create-policy.mdx @@ -37,7 +37,7 @@ For more information, refer to [DNS policies](/cloudflare-one/policies/gateway/d To create a new DNS policy using cURL: ```sh -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer " \ --data '{ diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-egress-policies/deploy-egress-ips.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-egress-policies/deploy-egress-ips.mdx index 441c47039cdc0e..fe83882fc826b2 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-egress-policies/deploy-egress-ips.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-egress-policies/deploy-egress-ips.mdx @@ -42,7 +42,7 @@ We recommend building baseline egress policies that can cover a majority of your ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Authorization: Bearer " \ --header "Content-Type: application/json" \ --data '{ diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/browser-isolation.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/browser-isolation.mdx index b4e692ad62235b..0c97a3f510fa19 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/browser-isolation.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/browser-isolation.mdx @@ -48,9 +48,8 @@ You can control potential risk and shape user behavior without applying heavy-ha ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "isolate", @@ -117,9 +116,8 @@ In this context, if some traffic is unknown to your organization, Cloudflare wil ```bash title="Allow known applications and websites" -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "isolate", @@ -142,9 +140,8 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ``` ```bash title="Block security risks" -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "isolate", @@ -167,9 +164,8 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ``` ```bash title="Isolate all other traffic" -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "isolate", diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/data-loss-prevention.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/data-loss-prevention.mdx index 8f6925cc85dfd6..26a123ce42441e 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/data-loss-prevention.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/data-loss-prevention.mdx @@ -46,9 +46,8 @@ To help this better match the needs of your organization, you can also build a c ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "block", @@ -98,9 +97,8 @@ For example, you can use a custom expression to detect when your users share pro ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "action": "block", @@ -158,7 +156,7 @@ Many organizations want to detect and log financial information egressing from u ```bash title="Block financial information shared with AI" -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Authorization: Bearer " \ --header "Content-Type: application/json" \ --data '{ diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/recommended-http-policies.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/recommended-http-policies.mdx index f65a3a28c83984..bc4e38ab406492 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/recommended-http-policies.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/recommended-http-policies.mdx @@ -5,7 +5,7 @@ sidebar: order: 5 --- -import { Render } from "~/components"; +import { Render, Tabs, TabItem } from "~/components"; We recommend you add the following HTTP policies to build an Internet and SaaS app security strategy for your organization. @@ -13,36 +13,202 @@ We recommend you add the following HTTP policies to build an Internet and SaaS a Bypass HTTP inspection for applications that use embedded certificates. This will help avoid any certificate pinning errors that may arise from an initial rollout. + + + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "All-HTTP-Application-InspectBypass", + "description": "Bypass HTTP inspection for applications that use embedded certificates", + "precedence": 0, + "enabled": true, + "action": "block", + "filters": [ + "http" + ], + "traffic": "any(app.type.ids[*] in {16})" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "all_http_application_inspect_bypass" { + account_id = var.cloudflare_account_id + name = "All-HTTP-Application-InspectBypass" + description = "Bypass HTTP inspection for applications that use embedded certificates" + precedence = 0 + enabled = true + action = "block" + filters = ["http"] + traffic = "any(app.type.ids[*] in {16})" +} +``` + + + + ## Android-HTTP-Application-InspectionBypass Bypass HTTPS inspection for Android applications (such as Google Drive) that use certificate pinning, which is incompatible with Gateway inspection. + + | Selector | Operator | Value | Logic | Action | | ---------------------------- | -------- | --------------------------------- | ----- | -------------- | | Application | in | _Google Drive_ | And | Do Not Inspect | | Passed Device Posture Checks | in | _OS Version Android (OS version)_ | | | + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "Android-HTTP-Application-InspectionBypass", + "description": "Bypass HTTPS inspection for Android applications with certificate pinning", + "precedence": 10, + "enabled": true, + "action": "off", + "filters": [ + "http" + ], + "traffic": "any(app.ids[*] in {554})", + "device_posture": "any(device_posture.checks.passed[*] in {\"\"})" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "android_http_application_inspection_bypass" { + account_id = var.cloudflare_account_id + name = "Android-HTTP-Application-InspectionBypass" + description = "Bypass HTTPS inspection for Android applications with certificate pinning" + precedence = 10 + enabled = true + action = "off" + filters = ["http"] + traffic = "any(app.ids[*] in {554})" + device_posture = "any(device_posture.checks.passed[*] in {\"${"$"}{cloudflare_zero_trust_list.android_version_posture_check.id}\"})" +} +``` + + + + ## All-HTTP-Domain-Inspection-Bypass Bypass HTTP inspection for a custom list of domains identified as incompatible with TLS inspection. + + | Selector | Operator | Value | Logic | Action | | -------- | -------- | ------------------------ | ----- | -------------- | | Domain | in list | _DomainInspectionBypass_ | Or | Do Not Inspect | | Domain | in list | _Known Domains_ | | | + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "All-HTTP-Domain-Inspection-Bypass", + "description": "Bypass HTTP inspection for a custom list of domains identified as incompatible with TLS inspection", + "precedence": 20, + "enabled": true, + "action": "off", + "filters": [ + "http" + ], + "traffic": "any(http.conn.domains[*] in $) or any(http.conn.domains[*] in $)" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "android_http_application_inspection_bypass" { + account_id = var.cloudflare_account_id + name = "All-HTTP-Domain-Inspection-Bypass" + description = "Bypass HTTP inspection for a custom list of domains identified as incompatible with TLS inspection" + precedence = 20 + enabled = true + action = "off" + filters = ["http"] + traffic = "any(http.conn.domains[*] in ${"$"}{cloudflare_zero_trust_list.domain_inspection_bypass_list.id}) or any(http.conn.domains[*] in ${"$"}{cloudflare_zero_trust_list.known_domains_list.id})" +} +``` + + + + ## All-HTTP-SecurityRisks-Blocklist -| Selector | Operator | Value | Action | -| -------------- | -------- | -------------------- | ------ | -| Security Risks | in | _All security risks_ | Block | + + +| Selector | Operator | Value | Action | +| ------------------- | -------- | -------------------- | ------ | +| Security Categories | in | _All security risks_ | Block | + + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "All-HTTP-SecurityRisks-Blocklist", + "description": "Block security categories based on Cloudflare's threat intelligence", + "precedence": 30, + "enabled": true, + "action": "block", + "filters": [ + "http" + ], + "traffic": "any(http.request.uri.security_category[*] in {68 178 80 83 176 175 117 131 134 151 153})" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "all_http_security_risks_blocklist" { + account_id = var.cloudflare_account_id + name = "All-HTTP-SecurityRisks-Blocklist" + description = "Block security categories based on Cloudflare's threat intelligence" + precedence = 30 + enabled = true + action = "block" + filters = ["http"] + traffic = "any(http.request.uri.security_category[*] in {68 178 80 83 176 175 117 131 134 151 153})" +} +``` + + + ## All-HTTP-ContentCategories-Blocklist @@ -58,7 +224,12 @@ Bypass HTTP inspection for a custom list of domains identified as incompatible w ## All-HTTP-DomainHost-Blocklist - + + + | Selector | Operator | Value | Logic | Action | | -------- | ------------- | ------------------ | ----- | ------ | @@ -66,6 +237,45 @@ Bypass HTTP inspection for a custom list of domains identified as incompatible w | Host | in list | _Host Blocklist_ | Or | | | Host | matches regex | `.*example\.com` | | | + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "All-HTTP-DomainHost-Blocklist", + "description": "Block specific domains or hosts that are malicious or pose a threat to your organization", + "precedence": 50, + "enabled": true, + "action": "block", + "filters": [ + "http" + ], + "traffic": "any(http.request.domains[*] in $) or http.request.host in $ or http.request.host matches \".*example\\.com\"" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "all_http_domainhost_blocklist" { + account_id = var.cloudflare_account_id + name = "All-HTTP-DomainHost-Blocklist" + description = "Block specific domains or hosts that are malicious or pose a threat to your organization" + precedence = 50 + enabled = true + action = "block" + filters = ["http"] + traffic = "any(http.request.domains[*] in ${"$"}{cloudflare_zero_trust_list.domain_blocklist.id}) or http.request.host in ${"$"}{cloudflare_zero_trust_list.host_blocklist.id} or http.request.host matches \".*example\\.com\"" +} +``` + + + + ## All-HTTP-Application-Blocklist @@ -81,24 +291,149 @@ Isolate traffic for privileged users who regularly access critical systems or ex Security teams often need to perform threat analysis or malware testing that could trigger malware detection. Likewise, privileged users could be the target of attackers trying to gain access to critical systems. + + | Selector | Operator | Value | Action | | ---------------- | -------- | ------------------ | ------- | | User Group Names | in | _Privileged Users_ | Isolate | + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "PrivilegedUsers-HTTP-Any-Isolate", + "description": "Isolate traffic for privileged users who regularly access critical or testing systems", + "precedence": 70, + "enabled": true, + "action": "isolate", + "filters": [ + "http" + ], + "identity": "any(identity.groups.name[*] in {\"Privileged Users\"})" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "privileged_users_http_any_isolate" { + account_id = var.cloudflare_account_id + name = "PrivilegedUsers-HTTP-Any-Isolate" + description = "Isolate traffic for privileged users who regularly access critical or testing systems" + precedence = 70 + enabled = true + action = "isolate" + filters = ["http"] + identity = "any(identity.groups.name[*] in {\"Privileged Users\"})" +} +``` + + + + ## Quarantined-Users-HTTP-Restricted-Access + + | Selector | Operator | Value | Logic | Action | | ---------------- | ----------- | ------------------------------- | ----- | ------ | | Destination IP | not in list | _Quarantined-Users-IPAllowlist_ | And | Block | | User Group Names | in | _Quarantined Users_ | | | + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "Quarantined-Users-HTTP-Restricted-Access", + "description": "Restrict access for users included in an identity provider (IdP) user group for risky users", + "precedence": 80, + "enabled": true, + "action": "block", + "filters": [ + "http" + ], + "traffic": "not(any(http.conn.dst_ip[*] in $))", + "identity": "any(identity.groups.name[*] in {\"Quarantined Users\"})" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "quarantined_users_http_restricted_access" { + account_id = var.cloudflare_account_id + name = "Quarantined-Users-HTTP-Restricted-Access" + description = "Restrict access for users included in an identity provider (IdP) user group for risky users" + precedence = 80 + enabled = true + action = "block" + filters = ["http"] + traffic = "not(any(http.conn.dst_ip[*] in ${"$"}{cloudflare_zero_trust_list.quarantined_users_ip_allowlist.id}))" + identity = "any(identity.groups.name[*] in {\"Quarantined Users\"})" +} +``` + + + + ## All-HTTP-Domain-Isolate Isolate high risk domains or create a custom list of known risky domains to avoid data exfiltration or malware infection. Ideally, your incident response teams can update the blocklist with an [API automation](/security-center/intel-apis/) to provide real-time threat protection. -| Selector | Operator | Value | Logic | Action | -| ------------------ | -------- | ---------------------------------- | ----- | ------- | -| Content Categories | in | _New Domain_, _Newly Seen Domains_ | Or | Isolate | -| Domain | in list | _Domain Isolation_ | | | + + +| Selector | Operator | Value | Logic | Action | +| ------------------ | -------- | ----------------------------------- | ----- | ------- | +| Content Categories | in | _New Domains_, _Newly Seen Domains_ | Or | Isolate | +| Domain | in list | _Domain Isolation_ | | | + + + + +```bash +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ +--header "Content-Type: application/json" \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--data '{ + "name": "All-HTTP-Domain-Isolate", + "description": "Isolate high risk domains or create a custom list of known risky domains to avoid data exfiltration or malware infection", + "precedence": 90, + "enabled": true, + "action": "isolate", + "filters": [ + "http" + ], + "traffic": "any(http.request.uri.content_category[*] in {169 177}) or any(http.request.domains[*] in $)" +}' +``` + + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "all_http_domain_isolate" { + account_id = var.cloudflare_account_id + name = "All-HTTP-Domain-Isolate" + description = "Isolate high risk domains or create a custom list of known risky domains to avoid data exfiltration or malware infection" + precedence = 90 + enabled = true + action = "isolate" + filters = ["http"] + traffic = "any(http.request.uri.content_category[*] in {169 177}) or any(http.request.domains[*] in ${"$"}{cloudflare_zero_trust_list.domain_isolate_list.id})" +} +``` + + + diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/tls-inspection.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/tls-inspection.mdx index b793700bb0ec3e..94fe8e71434ba5 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/tls-inspection.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-http-policies/tls-inspection.mdx @@ -77,7 +77,7 @@ For example, if users are issued a corporate-managed iPhone with limited permiss 1. Create a list of device serial numbers that you do not want to inspect. ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/lists \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/lists \ --header "X-Auth-Email: " \ --header "X-Auth-Key: " \ --header "Content-Type: application/json" \ @@ -96,7 +96,7 @@ For example, if users are issued a corporate-managed iPhone with limited permiss 2. Create a Do Not Inspect policy that checks the device against the list of serial numbers. ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "X-Auth-Email: " \ --header "X-Auth-Key: " \ --header "Content-Type: application/json" \ @@ -141,9 +141,8 @@ If you filter your network-connected devices with Magic WAN tunnels, the WARP Co ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Do not inspect corporate devices", diff --git a/src/content/docs/learning-paths/secure-internet-traffic/build-network-policies/recommended-network-policies.mdx b/src/content/docs/learning-paths/secure-internet-traffic/build-network-policies/recommended-network-policies.mdx index 919b20b0895310..26c0583ee4141e 100644 --- a/src/content/docs/learning-paths/secure-internet-traffic/build-network-policies/recommended-network-policies.mdx +++ b/src/content/docs/learning-paths/secure-internet-traffic/build-network-policies/recommended-network-policies.mdx @@ -97,7 +97,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "Posture-Fail-NET-Restricted-Access", "description": "Restrict access for devices where baseline posture checks have not passed", - "precedence": 0, + "precedence": 10, "enabled": true, "action": "block", "filters": [ @@ -117,7 +117,7 @@ resource "cloudflare_zero_trust_gateway_policy" "posture_fail_net_restricted_acc account_id = var.cloudflare_account_id name = "Posture-Fail-NET-Restricted-Access" description = "Restrict access for devices where baseline posture checks have not passed" - precedence = 0 + precedence = 10 enabled = true action = "block" filters = ["l4"] @@ -155,7 +155,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "FinanceUsers-NET-HTTPS-FinanceServers", "description": "Allow HTTPS access for user groups", - "precedence": 0, + "precedence": 20, "enabled": true, "action": "allow", "filters": [ @@ -175,7 +175,7 @@ resource "cloudflare_zero_trust_gateway_policy" "finance_users_net_https_finance account_id = var.cloudflare_account_id name = "FinanceUsers-NET-HTTPS-FinanceServers" description = "Allow HTTPS access for user groups" - precedence = 0 + precedence = 20 enabled = true action = "allow" filters = ["l4"] @@ -214,7 +214,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "All-NET-Internet-Blocklist", "description": "Block traffic to malicious or risky destination IPs, SNIs, and SNI domains", - "precedence": 0, + "precedence": 30, "enabled": true, "action": "block", "filters": [ @@ -233,7 +233,7 @@ resource "cloudflare_zero_trust_gateway_policy" "finance_users_net_https_finance account_id = var.cloudflare_account_id name = "All-NET-Internet-Blocklist" description = "Block traffic to malicious or risky destination IPs, SNIs, and SNI domains" - precedence = 0 + precedence = 30 enabled = true action = "block" filters = ["l4"] @@ -276,7 +276,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "All-NET-SSH-Internet-Allowlist", "description": "Allow SSH traffic to specific endpoints on the Internet for specific users", - "precedence": 0, + "precedence": 40, "enabled": true, "action": "allow", "filters": [ @@ -296,7 +296,7 @@ resource "cloudflare_zero_trust_gateway_policy" "all_net_ssh_internet_allowlist" account_id = var.cloudflare_account_id name = "All-NET-SSH-Internet-Allowlist" description = "Allow SSH traffic to specific endpoints on the Internet for specific users" - precedence = 0 + precedence = 40 enabled = true action = "allow" filters = ["l4"] @@ -332,7 +332,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "All-NET-NO-HTTP-HTTPS-Internet-Deny", "description": "Block all non-web traffic towards the Internet", - "precedence": 0, + "precedence": 50, "enabled": true, "action": "block", "filters": [ @@ -351,7 +351,7 @@ resource "cloudflare_zero_trust_gateway_policy" "all_net_no_http_https_internet_ account_id = var.cloudflare_account_id name = "All-NET-NO-HTTP-HTTPS-Internet-Deny" description = "Block all non-web traffic towards the Internet" - precedence = 0 + precedence = 50 enabled = true action = "block" filters = ["l4"] @@ -385,7 +385,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "All-NET-InternalNetwork-ImplicitDeny", "description": "Implicitly deny all of your internal IP ranges included in a list", - "precedence": 0, + "precedence": 60, "enabled": true, "action": "block", "filters": [ @@ -404,7 +404,7 @@ resource "cloudflare_zero_trust_gateway_policy" "all_net_internalnetwork_implici account_id = var.cloudflare_account_id name = "All-NET-InternalNetwork-ImplicitDeny" description = "Implicitly deny all of your internal IP ranges included in a list" - precedence = 0 + precedence = 60 enabled = true action = "block" filters = ["l4"] diff --git a/src/content/docs/learning-paths/secure-o365-email/configure-email-security/active-directory-sync.mdx b/src/content/docs/learning-paths/secure-o365-email/configure-email-security/active-directory-sync.mdx index 7c383f02876775..c3324c86957941 100644 --- a/src/content/docs/learning-paths/secure-o365-email/configure-email-security/active-directory-sync.mdx +++ b/src/content/docs/learning-paths/secure-o365-email/configure-email-security/active-directory-sync.mdx @@ -33,6 +33,6 @@ To add multiple groups to the registry at once: In addition, Email Security allows you to: -- [Remove groups from the registry](/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory/#remove-groups-from-registry). -- [Filter the impersonation registry](/cloudflare-one/email-security/directories/manage-ms-directories/manage-groups-directory/#filter-impersonation-registry). -- [Manage users in your directory](/cloudflare-one/email-security/directories/manage-ms-directories/manage-users-directory/). \ No newline at end of file +- [Remove groups from the registry](/cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory/#remove-groups-from-registry). +- [Filter the impersonation registry](/cloudflare-one/email-security/directories/manage-integrated-directories/manage-groups-directory/#filter-impersonation-registry). +- [Manage users in your directory](/cloudflare-one/email-security/directories/manage-integrated-directories/manage-users-directory/). \ No newline at end of file diff --git a/src/content/docs/learning-paths/secure-o365-email/configure-email-security/report-phish.mdx b/src/content/docs/learning-paths/secure-o365-email/configure-email-security/report-phish.mdx index 5aab22d54db13a..b9c254825300b6 100644 --- a/src/content/docs/learning-paths/secure-o365-email/configure-email-security/report-phish.mdx +++ b/src/content/docs/learning-paths/secure-o365-email/configure-email-security/report-phish.mdx @@ -13,7 +13,7 @@ To set up PhishNet O365: 1. Log in to the Microsoft admin panel. Go to **Microsoft 365 admin center** > **Settings** > **Integrated Apps**. 2. Select **Upload custom apps**. -3. Choose **Provide link to manifest file** and paste the the following URL: +3. Choose **Provide link to manifest file** and paste the following URL: ```txt https://phishnet-o365.area1cloudflare-webapps.workers.dev?clientId=ODcxNDA0MjMyNDM3NTA4NjQwNDk1Mzc3MDIxNzE0OTcxNTg0Njk5NDEyOTE2NDU5ODQyNjU5NzYzNjYyNDQ3NjEwMzIxODEyMDk1NQ diff --git a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/index.mdx b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/index.mdx index a24125458fb285..a5baade788048f 100644 --- a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/index.mdx +++ b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/index.mdx @@ -18,7 +18,7 @@ The dashboard will display the following metrics: - [Disposition evaluation](/cloudflare-one/email-security/reference/dispositions-and-attributes/) - Detection details - [Impersonations](/cloudflare-one/email-security/detection-settings/impersonation-registry/) -- [Phish submissions](/cloudflare-one/insights/email-monitoring/phish-submissions/) +- [Phish submissions](/cloudflare-one/email-security/phish-submissions/) - [Auto-move events](/cloudflare-one/email-security/auto-moves/) - [Detection settings metrics](/cloudflare-one/email-security/detection-settings/) diff --git a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/monitor-detections.mdx b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/monitor-detections.mdx index 02f20d62726c26..0da7248705d2a8 100644 --- a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/monitor-detections.mdx +++ b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/monitor-detections.mdx @@ -28,7 +28,7 @@ There are three ways for searching emails: - Regular screen: A regular screen allows you to investigate your inbox by inserting a term to screen across all criteria. - Advanced screen: The advanced screen criteria gives you the option to narrow message results based on specific criteria. The advanced screen has several options (such as keywords, subject keywords, sender domain, and more) to scan your inbox. -Additional information on search can be found on the [Screen criteria](/email-security/reporting/search/) documentation. +Additional information on search can be found on the [Screen criteria](/cloudflare-one/email-security/email-monitoring/search-email/#screen-criteria) documentation. ### Export messages diff --git a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/phish-submissions.mdx b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/phish-submissions.mdx index ec8486f5f492fc..0167504dc67223 100644 --- a/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/phish-submissions.mdx +++ b/src/content/docs/learning-paths/secure-o365-email/monitor-your-inbox/phish-submissions.mdx @@ -7,10 +7,10 @@ sidebar: While Email Security offers industry leading detection efficacy due to Cloudflare's Threat Intelligence, Preemptive Threat Hunting (actor and campaign infrastructure hunting with 8B, plus campaign threat signals assessed every day) and ML-Based Detection Models (Trust Graphs Computer Vision, Sentiment/Thread/Structural Analysis, Industry/Natural Language Understanding Modeling) false negatives and false positive can occur. -There are two different ways to [submit a phish](/cloudflare-one/insights/email-monitoring/phish-submissions/) sample: +There are two different ways to [submit a phish](/cloudflare-one/email-security/phish-submissions/) sample: - User submission: - - Submitted directly by the end user, and used with phish submission buttons. To learn more about user-submitted phish, refer to [PhishNet for Microsoft O365](/cloudflare-one/insights/email-monitoring/phish-submissions/#phishnet-o365). + - Submitted directly by the end user, and used with phish submission buttons. To learn more about user-submitted phish, refer to [PhishNet for Microsoft O365](/cloudflare-one/email-security/phish-submissions/#phishnet-o365). - User submissions can create another challenge for your organization. While it is important for end users to be vigilant and report what they believe may be a phishing email, they are often wrong. About 90% of the time, when an end user reports a missed phishing email, they are mistaken. This puts an extra burden on busy security teams as they sift through end user reports. The PhishGuard team at Cloudflare can solve this problem for your organization by reviewing end user submissions for you. - Admin submission: - To be used when IT administrators or security teams submit to Email Security. Submit original phish samples as an attachment in EML format to the appropriate team submission address. diff --git a/src/content/docs/learning-paths/workers/devplat/intro-to-devplat.mdx b/src/content/docs/learning-paths/workers/devplat/intro-to-devplat.mdx index 21851db9085b75..fdf3977eb83b9e 100644 --- a/src/content/docs/learning-paths/workers/devplat/intro-to-devplat.mdx +++ b/src/content/docs/learning-paths/workers/devplat/intro-to-devplat.mdx @@ -10,7 +10,7 @@ import { Render, Stream } from "~/components" The [Cloudflare Developer Platform](https://www.cloudflare.com/developer-platform/products/) offers various services to empower developers to build full-stack applications, including: [compute](https://www.cloudflare.com/developer-platform/products/#compute), [storage](https://www.cloudflare.com/developer-platform/products/#storage), [web development, image optimization, video streaming](https://www.cloudflare.com/developer-platform/products/#webdev) and [AI](https://ai.cloudflare.com/). - + It is important to note that the developer platform product offering is growing with new releases and features updates. To review a list of product documentation related to Cloudflare Developer Platform: diff --git a/src/content/docs/learning-paths/workers/get-started/first-worker.mdx b/src/content/docs/learning-paths/workers/get-started/first-worker.mdx index b7ce7227218c56..21abbacc9f5ee2 100644 --- a/src/content/docs/learning-paths/workers/get-started/first-worker.mdx +++ b/src/content/docs/learning-paths/workers/get-started/first-worker.mdx @@ -38,7 +38,7 @@ This will prompt you to install the [`create-cloudflare`](https://www.npmjs.com/ product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/learning-paths/zero-trust-web-access/access-application/create-access-app.mdx b/src/content/docs/learning-paths/zero-trust-web-access/access-application/create-access-app.mdx index 9584d8f4e84973..cb00cfbae1c502 100644 --- a/src/content/docs/learning-paths/zero-trust-web-access/access-application/create-access-app.mdx +++ b/src/content/docs/learning-paths/zero-trust-web-access/access-application/create-access-app.mdx @@ -14,6 +14,6 @@ Each application can have multiple policies with different constraints depending ## Add your application to Access - + When users go to the application, they will be prompted to login with your identity provider. diff --git a/src/content/docs/learning-paths/zero-trust-web-access/advanced-workflows/isolate-application.mdx b/src/content/docs/learning-paths/zero-trust-web-access/advanced-workflows/isolate-application.mdx index 7d34d4c8345509..c2e871a42912de 100644 --- a/src/content/docs/learning-paths/zero-trust-web-access/advanced-workflows/isolate-application.mdx +++ b/src/content/docs/learning-paths/zero-trust-web-access/advanced-workflows/isolate-application.mdx @@ -67,9 +67,8 @@ with HTTP policies applied"] ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_uuid}/policies \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_UUID/policies \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "decision": "allow", @@ -114,9 +113,8 @@ To create a list of serial numbers, refer to [Create Zero Trust list](/api/resou ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_uuid}/policies \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_UUID/policies \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "decision": "allow", @@ -164,9 +162,8 @@ Prevents users on unmanaged devices from downloading any files from your private ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Disable file downloads in isolated browser", @@ -250,9 +247,8 @@ Block users on unmanaged devices from downloading files that contain credit card ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Block credit card numbers", diff --git a/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/best-practices.mdx b/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/best-practices.mdx index 2fe20bc7ee282a..7360867fa01f7b 100644 --- a/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/best-practices.mdx +++ b/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/best-practices.mdx @@ -10,7 +10,7 @@ We recommend following these best practices when you deploy Cloudflare Tunnel fo ## Deploy another instance of cloudflared -For an additional point of availability, add a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) to another host machine in your network. +For an additional point of availability, add a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) to another host machine in your network. ## Standardize public hostnames @@ -22,11 +22,11 @@ To make your applications easier to manage, standardize the public hostnames tha ## Disable TLS verification -If your public hostname route serves an `HTTPS` application, we recommend enabling [**No TLS Verify**](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#notlsverify) to reduce connectivity issues caused by mismatched certificates. **No TLS Verify** disables TLS verification between `cloudflared` and the origin service, meaning that `cloudflared` will accept any certificate that the origin service provides. This setting has no impact on traffic between the user's browser and the `cloudflared` host, which will always be encrypted. +If your public hostname route serves an `HTTPS` application, we recommend enabling [**No TLS Verify**](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#notlsverify) to reduce connectivity issues caused by mismatched certificates. **No TLS Verify** disables TLS verification between `cloudflared` and the origin service, meaning that `cloudflared` will accept any certificate that the origin service provides. This setting has no impact on traffic between the user's browser and the `cloudflared` host, which will always be encrypted. ## (Optional) Add `Host` header to accommodate local traffic management tools -If your target application sits behind a load balancer or similar, you may need to set [**HTTP Host Header**](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#httphostheader) to the service hostname. Load balancers in between the origin service and `cloudflared` can be difficult to troubleshoot, and you can typically resolve the issue by adding a request header to match the way that the load balancer typically identifies traffic. +If your target application sits behind a load balancer or similar, you may need to set [**HTTP Host Header**](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#httphostheader) to the service hostname. Load balancers in between the origin service and `cloudflared` can be difficult to troubleshoot, and you can typically resolve the issue by adding a request header to match the way that the load balancer typically identifies traffic. ## Enable tunnel notifications diff --git a/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel.mdx b/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel.mdx index 23084f2659864a..bc4ac1cf78388d 100644 --- a/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel.mdx +++ b/src/content/docs/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel.mdx @@ -30,7 +30,7 @@ All users on the Internet can now connect to this application via its public hos If the tunnel is disconnected: -* Ensure that your on-premise or cloud firewall allows egress traffic on the [required ports](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). +* Ensure that your on-premise or cloud firewall allows egress traffic on the [required ports](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/#required-for-tunnel-operation). * Ensure that the `cloudflared` host machine can connect to your internal applications and services. Verify that the host has the proper security group memberships and that no firewalls will block traffic between the host and the target services. diff --git a/src/content/docs/learning-paths/zero-trust-web-access/terraform/publish-apps-with-terraform.mdx b/src/content/docs/learning-paths/zero-trust-web-access/terraform/publish-apps-with-terraform.mdx index 74296f42f08e09..41f15505f0a41f 100644 --- a/src/content/docs/learning-paths/zero-trust-web-access/terraform/publish-apps-with-terraform.mdx +++ b/src/content/docs/learning-paths/zero-trust-web-access/terraform/publish-apps-with-terraform.mdx @@ -3,20 +3,19 @@ title: Publish applications with Terraform pcx_content_type: overview sidebar: order: 1 - --- -import { Details, Render } from "~/components" +import { Details, Render } from "~/components"; This guide covers how to use the [Cloudflare Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs) to quickly publish and secure a private application. In the following example, we will add a new public hostname route to an existing Cloudflare Tunnel, configure how `cloudflared` proxies traffic to the application, and secure the application with Cloudflare Access. ## Prerequisites -* [Add your domain to Cloudflare](/learning-paths/zero-trust-web-access/initial-setup/add-site/) -* [Configure an IdP integration](/learning-paths/zero-trust-web-access/initial-setup/configure-idp/) -* [Create a Cloudflare Tunnel](/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel/#create-a-tunnel) via the Zero Trust dashboard -* Install the [Terraform client](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) -* [Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) (refer to the [minimum required permissions](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/terraform/#3-create-a-cloudflare-api-token)) +- [Add your domain to Cloudflare](/learning-paths/zero-trust-web-access/initial-setup/add-site/) +- [Configure an IdP integration](/learning-paths/zero-trust-web-access/initial-setup/configure-idp/) +- [Create a Cloudflare Tunnel](/learning-paths/zero-trust-web-access/connect-private-applications/create-tunnel/#create-a-tunnel) via the Zero Trust dashboard +- Install the [Terraform client](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) +- [Create an API token](/fundamentals/api/get-started/create-token/) (refer to the [minimum required permissions](/cloudflare-one/connections/connect-networks/deployment-guides/terraform/#3-create-a-cloudflare-api-token)) ## 1. Create a Terraform configuration directory @@ -76,11 +75,11 @@ Add the following resources to your Terraform configuration. ### Add public hostname route to Cloudflare Tunnel -Using the [`cloudflare_tunnel_config`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/tunnel_config) resource, create an ingress rule that maps your application to a public DNS record. This example makes `localhost:8080` available on `app.mycompany.com`, sets the [Connect Timeout](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#connecttimeout), and enables [Access JWT validation](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#access). +Using the [`cloudflare_tunnel_config`](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/tunnel_config) resource, create an ingress rule that maps your application to a public DNS record. This example makes `localhost:8080` available on `app.mycompany.com`, sets the [Connect Timeout](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#connecttimeout), and enables [Access JWT validation](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#access). ```txt resource "cloudflare_tunnel_config" "example_config" { - account_id = var.account_id + account_id = var.cloudflare_account_id tunnel_id = var.tunnel_id config { diff --git a/src/content/docs/load-balancing/pools/cloudflare-pages-origin.mdx b/src/content/docs/load-balancing/pools/cloudflare-pages-origin.mdx index 2b8b7fb4b4e009..5f1ab959bb9bc5 100644 --- a/src/content/docs/load-balancing/pools/cloudflare-pages-origin.mdx +++ b/src/content/docs/load-balancing/pools/cloudflare-pages-origin.mdx @@ -3,7 +3,6 @@ pcx_content_type: tutorial title: Use Pages as an origin for Load Balancing updated: 2024-07-03 difficulty: Beginner -content_type: 📝 Tutorial products: - Pages sidebar: @@ -209,7 +208,7 @@ Now that you have set up your load balancer and verified everything is working c 1. Confirm that your production hostname has the correct [priority order](/load-balancing/load-balancers/dns-records/#priority-order) of DNS records and is covered by an [SSL/TLS certificate](/load-balancing/load-balancers/dns-records/#ssltls-coverage). - If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [Origin rule](/rules/origin-rules/features/#dns-record) or [Page rule](/rules/page-rules/how-to/override-url-or-ip-address/). + If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [Origin rule](/rules/origin-rules/features/#dns-record). 2. Configure your load balancer to receive production traffic by editing the **Hostname** of your existing load balancer. diff --git a/src/content/docs/load-balancing/private-network/tunnels-setup.mdx b/src/content/docs/load-balancing/private-network/tunnels-setup.mdx index 76a4c067998bd1..559a30ed32cd32 100644 --- a/src/content/docs/load-balancing/private-network/tunnels-setup.mdx +++ b/src/content/docs/load-balancing/private-network/tunnels-setup.mdx @@ -13,9 +13,8 @@ Consider the following steps to learn how to configure Private Network Load Bala The specific configuration steps can vary depending on your infrastructure and services you are looking to connect. If you are not familiar with Cloudflare Tunnel, the pages linked on each step provide more guidance. -1. [Create a tunnel](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#1-create-a-tunnel). -2. [Deploy the tunnel](/cloudflare-one/connections/connect-networks/deploy-tunnels/) to connect to your data center. -3. Create a [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) and assign it to the tunnel you configured in the previous steps. +1. [Create a tunnel](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#1-create-a-tunnel) to connect your data center to Cloudflare. +2. Create a [virtual network](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) and assign it to the tunnel you configured in the previous steps. diff --git a/src/content/docs/load-balancing/reference/limitations.mdx b/src/content/docs/load-balancing/reference/limitations.mdx index 8bc475a18f6c10..2e0cb34c546cd1 100644 --- a/src/content/docs/load-balancing/reference/limitations.mdx +++ b/src/content/docs/load-balancing/reference/limitations.mdx @@ -9,7 +9,7 @@ sidebar: Name | Non-Enterprise | Enterprise | --- | --- | --- | Load balancers | 20 | custom | - Monitor intervals | 60s (min), 3600s (max) | 10s (min), 3600s (max) | + Monitor intervals | 15s (min), 3600s (max) | 10s (min), 3600s (max) | Monitors | 1.5x the number of pools | 1.5x the number of pools | Endpoints | 20 | custom | Pools | 20 | custom | diff --git a/src/content/docs/load-balancing/understand-basics/health-details.mdx b/src/content/docs/load-balancing/understand-basics/health-details.mdx index 1eabaea9e3a693..6ed50dc6054ec3 100644 --- a/src/content/docs/load-balancing/understand-basics/health-details.mdx +++ b/src/content/docs/load-balancing/understand-basics/health-details.mdx @@ -47,6 +47,7 @@ For greater accuracy and consistency when changing endpoint health status, you c When an [individual endpoint becomes unhealthy](#how-an-endpoint-becomes-unhealthy), that may affect the health status of any associated pools (visible in the dashboard): * **Healthy**: All endpoints are healthy. +* **Degraded**: At least one endpoint is unhealthy, but the pool is still considered healthy and could be receiving traffic. * **Critical**: The pool has fallen below the number of available endpoints specified in its **Health Threshold** and will not receive traffic from your load balancer (unless other pools are also unhealthy and this pool is marked as the [**Fallback Pool**](#fallback-pools)). * **Health unknown**: There are either no monitors attached to pool endpoints or the monitors have not yet determined endpoint health. * **No health**: Reserved for your load balancer's [**Fallback Pool**](#fallback-pools). diff --git a/src/content/docs/load-balancing/understand-basics/traffic-steering/origin-level-steering/hash-origin-steering.mdx b/src/content/docs/load-balancing/understand-basics/traffic-steering/origin-level-steering/hash-origin-steering.mdx index ac89e0ba0dc418..6876771de24428 100644 --- a/src/content/docs/load-balancing/understand-basics/traffic-steering/origin-level-steering/hash-origin-steering.mdx +++ b/src/content/docs/load-balancing/understand-basics/traffic-steering/origin-level-steering/hash-origin-steering.mdx @@ -10,3 +10,16 @@ head: --- **Hash steering** guides Cloudflare to send requests to endpoints based on a combination of [endpoint weights](/load-balancing/understand-basics/traffic-steering/origin-level-steering/#weights) and previous requests from that IP address. Ensures requests from the same IP address will hit the same endpoint, but actual traffic distribution may differ from endpoint weights. + +## Limitation when using Workers + +Hash Steering relies on the `x-forwarded-for` header to determine the originating IP address of a request. However, when a [Cloudflare Worker](/workers/) is used in front of a load balancer, this can affect how Hash Steering functions. + +When a request originates from a browser, it lacks an `x-forwarded-for` header, but if a Worker proxies the request to a load balancer, the header is populated with the Worker's IP instead of the original client IP. Since the Worker's IP — often a Cloudflare public IP — can change between requests, Hash Steering may direct the same client's requests to different endpoints, leading to inconsistent traffic routing. + +### Workaround + +To ensure Hash Steering works correctly when using a Worker in front of a Load Balancer, manually set the `x-forwarded-for` header in the Worker to the client's original IP address. By manually setting `x-forwarded-for` to `CF-Connecting-IP`, Hash Steering will function as expected, ensuring traffic consistency for end users. + + + diff --git a/src/content/docs/logs/R2-log-retrieval.mdx b/src/content/docs/logs/R2-log-retrieval.mdx index 0fec688e096c17..3e2406916fa655 100644 --- a/src/content/docs/logs/R2-log-retrieval.mdx +++ b/src/content/docs/logs/R2-log-retrieval.mdx @@ -12,7 +12,7 @@ Logs Engine gives you the ability to store your logs in R2 and query them direct :::note -Logs Engine is going to be replaced by Log Explorer. For further details, consult the [Log Explorer](/logs/log-explorer/) documentation and to request access, complete the [sign-up form](https://cloudflare.com/lp/log-explorer/). +Logs Engine is going to be replaced by Log Explorer. For further details, consult the [Log Explorer](/logs/log-explorer/) documentation and to request access, complete the [sign-up form](https://cloudflare.com/lp/log-explorer/). ::: ## Store logs in R2 @@ -81,7 +81,7 @@ Stream logs stored in R2 that match the provided query parameters, using the end ```bash curl --globoff "https://api.cloudflare.com/client/v4/accounts/{account_id}/logs/retrieve?start=2022-06-01T16:00:00Z&end=2022-06-01T16:05:00Z&bucket=cloudflare-logs&prefix=http_requests/example.com/{DATE}" \ --header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +--header "X-Auth-Key: " \ --header "R2-Access-Key-Id: R2_ACCESS_KEY_ID" \ --header "R2-Secret-Access-Key: R2_SECRET_ACCESS_KEY" ``` diff --git a/src/content/docs/logs/get-started/alerts-and-analytics.mdx b/src/content/docs/logs/get-started/alerts-and-analytics.mdx index 921cb4e69306bc..93bb42acac78c6 100644 --- a/src/content/docs/logs/get-started/alerts-and-analytics.mdx +++ b/src/content/docs/logs/get-started/alerts-and-analytics.mdx @@ -46,7 +46,7 @@ query datetime_gt:"2022-08-15T00:00:00Z", destinationType:"s3", status_neq:200 - }, + }, limit:10) { count, @@ -60,3 +60,7 @@ query } } ``` + +:::note +If you get a `1105` status code error when checking your Logpush job health, it indicates a DNS resolution issue. This means Cloudflare is unable to resolve the target hostname for the Logpush job. To resolve this, check with your DNS service provider and confirm the hostname can be publicly resolved. +::: diff --git a/src/content/docs/logs/get-started/enable-destinations/datadog.mdx b/src/content/docs/logs/get-started/enable-destinations/datadog.mdx index 11e3e84baa6fff..6921d27c6e294f 100644 --- a/src/content/docs/logs/get-started/enable-destinations/datadog.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/datadog.mdx @@ -183,10 +183,10 @@ Response: :::note[Note] -The Datadog destination is exclusive to new jobs and might not be backward compatible with older jobs. Create new jobs if you expect to send your logs directly to Datadog instead of modifying already existing ones. If you try to modify an existing job for another destination to push logs to Datadog, you may observe errors. +The Datadog destination is exclusive to new jobs and might not be backward compatible with older jobs. Create new jobs if you expect to send your logs directly to Datadog instead of modifying already existing ones. If you try to modify an existing job for another destination to push logs to Datadog, you may observe errors. ::: :::note[Note] -To analyze and visualize Cloudflare metrics using the Cloudflare Integration tile for Datadog, follow the steps in the [Datadog Analytics integration page](/analytics/analytics-integrations/datadog/). +To analyze and visualize Cloudflare metrics using the Cloudflare Integration tile for Datadog, follow the steps in the [Datadog Analytics integration page](/analytics/analytics-integrations/datadog/). ::: diff --git a/src/content/docs/logs/get-started/enable-destinations/google-cloud-storage.mdx b/src/content/docs/logs/get-started/enable-destinations/google-cloud-storage.mdx index 2bac0eb864dbc3..2702162a00424d 100644 --- a/src/content/docs/logs/get-started/enable-destinations/google-cloud-storage.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/google-cloud-storage.mdx @@ -57,5 +57,5 @@ To enable Logpush to GCS: :::note[Note] -To analyze your Cloudflare Logs data using the Google Cloud Platform (GCP), follow the steps in the [Google Cloud Analytics integration page](/analytics/analytics-integrations/google-cloud/). +To analyze your Cloudflare Logs data using the Google Cloud Platform (GCP), follow the steps in the [Google Cloud Analytics integration page](/analytics/analytics-integrations/google-cloud/). ::: diff --git a/src/content/docs/logs/get-started/enable-destinations/http.mdx b/src/content/docs/logs/get-started/enable-destinations/http.mdx index a6dac762a267d5..cc7adabedb2cf0 100644 --- a/src/content/docs/logs/get-started/enable-destinations/http.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/http.mdx @@ -13,7 +13,7 @@ Cloudflare Logpush now supports the ability to send logs to configurable HTTP en Note that when using Logpush to HTTP endpoints, Cloudflare customers are expected to perform their own authentication of the pushed logs. For example, customers may specify a secret token in the URL or an HTTP header of the Logpush destination. :::note[Endpoint requirements] -Cloudflare expects that the endpoint is available over HTTPS, using a trusted certificate. The endpoint must accept `POST` requests. +Cloudflare expects that the endpoint is available over HTTPS, using a trusted certificate. The endpoint must accept `POST` requests. ::: ## Manage via the Cloudflare dashboard @@ -62,7 +62,7 @@ The supported parameters are as follows: :::note[Note] -The `ownership_challenge` parameter is not required to create a Logpush job to an HTTP endpoint. You need to make sure that the file upload to validate the destination accepts a gzipped `test.txt.gz` with content as `{"content":"tests"}` compressed, otherwise it will return an error, like `error validating destination: error writing object: error uploading`. +The `ownership_challenge` parameter is not required to create a Logpush job to an HTTP endpoint. You need to make sure that the file upload to validate the destination accepts a gzipped `test.txt.gz` with content as `{"content":"tests"}` compressed, otherwise it will return an error, like `error validating destination: error writing object: error uploading`. ::: diff --git a/src/content/docs/logs/get-started/enable-destinations/ibm-cloud-logs.mdx b/src/content/docs/logs/get-started/enable-destinations/ibm-cloud-logs.mdx index c113591a9b0738..99a2b53bb1c66f 100644 --- a/src/content/docs/logs/get-started/enable-destinations/ibm-cloud-logs.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/ibm-cloud-logs.mdx @@ -9,7 +9,7 @@ head: --- -Cloudflare Logpush supports pushing logs directly to IBM Cloud Logs via API. The dashboard functionality will later be added. +Cloudflare Logpush supports pushing logs directly to IBM Cloud Logs via API. The dashboard functionality will later be added. ## Manage via API @@ -25,7 +25,7 @@ Ensure Log Share permissions are enabled, before attempting to read or configure ### 1. Create a job To create a job, make a `POST` request to the Logpush jobs endpoint with the following fields: - + - **name** (optional) - Use your domain name as the job name. - **output_options** (optional) - This parameter is used to define the desired output format and structure. Below are the configurable fields: - output_type diff --git a/src/content/docs/logs/get-started/enable-destinations/new-relic.mdx b/src/content/docs/logs/get-started/enable-destinations/new-relic.mdx index 55234d5fd068f4..caae29ebadcff1 100644 --- a/src/content/docs/logs/get-started/enable-destinations/new-relic.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/new-relic.mdx @@ -63,7 +63,7 @@ To create a job, make a `POST` request to the Logpush jobs endpoint with the fol :::note[Note] - To query Cloudflare logs, New Relic requires fields to be sent as a Unix Timestamp. + To query Cloudflare logs, New Relic requires fields to be sent as a UNIX timestamp. ::: @@ -176,6 +176,6 @@ Response: :::note[Note] -To analyze and visualize Cloudflare metrics using the Cloudflare Network Logs quickstart, follow the steps in the [New Relic Analytics integration page](/analytics/analytics-integrations/new-relic/). +To analyze and visualize Cloudflare metrics using the Cloudflare Network Logs quickstart, follow the steps in the [New Relic Analytics integration page](/analytics/analytics-integrations/new-relic/). ::: diff --git a/src/content/docs/logs/get-started/enable-destinations/r2.mdx b/src/content/docs/logs/get-started/enable-destinations/r2.mdx index c7330065287cfd..a1b4995c69508d 100644 --- a/src/content/docs/logs/get-started/enable-destinations/r2.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/r2.mdx @@ -8,13 +8,37 @@ sidebar: import { Render } from "~/components" -Cloudflare Logpush supports pushing logs directly to R2 via the Cloudflare dashboard or via API. +Cloudflare Logpush supports pushing logs directly to R2. You can do so via the automatic setup (Cloudflare creates an R2 bucket for you), or you can create your own R2 bucket with the custom setup. The automatic setup is ideal for quickly setting up a bucket or for testing purposes. Instead, use the custom setup if you need full control over the configuration. For more information about R2, refer to the [Cloudflare R2](/r2/) documentation. +## Automatic setup + +If you want to use the automatic setup for your logpush job: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login). + +2. Select the Enterprise account or domain (also known as zone) you want to use with Logpush. Depending on your choice, you have access to [account-scoped datasets](/logs/reference/log-fields/account/) and [zone-scoped datasets](/logs/reference/log-fields/zone/), respectively. + +3. Go to **Analytics & Logs** > **Logpush**. + +4. Select **Create a Logpush job**. + +5. Select **R2 Object Storage - automatic** as destination. + +6. Next, select the dataset and the storage region you want to use. + +7. To finalize, select **Create Logpush job**. + +Your setup should now be complete. If you require full control over the configuration, consider using the custom setup instead. + +## Custom setup + +Cloudflare Logpush supports pushing logs directly to R2 via the Cloudflare dashboard or via API. + Before getting started: -* Create an R2 bucket and set up R2 API tokens. +- Create an R2 bucket and set up R2 API tokens. 1. Go to the R2 UI > **Create bucket**. @@ -26,11 +50,11 @@ Before getting started: 5. Copy the Secret Access Key and Access Key ID. You will need these when setting up your Logpush job. -* Ensure that you have the following permissions: +- Ensure that you have the following permissions: - * R2 write, Logshare Edit. + - R2 write, Logshare Edit. -## Manage via the Cloudflare dashboard +### Manage via the Cloudflare dashboard @@ -58,7 +82,7 @@ When you are done entering the destination details, select **Continue**. 10. Select **Submit** once you are done configuring your logpush job. -## Manage via API +### Manage via API To create a job, make a `POST` request to the Logpush jobs endpoint with the following fields: @@ -67,7 +91,7 @@ To create a job, make a `POST` request to the Logpush jobs endpoint with the fol :::note[Note] -We recommend adding the `{DATE}` parameter in the `destination_conf` to separate your logs into daily subfolders. +We recommend adding the `{DATE}` parameter in the `destination_conf` to separate your logs into daily subfolders. ::: ```bash @@ -95,3 +119,33 @@ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/logpush/jobs \ "enabled": true }' ``` + +## Download logs from R2 + +Once your logs are stored in R2, you can download them using various methods: + +### Dashboard + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/). + +2. Navigate to R2 and select your bucket. + +3. From your bucket's page, locate the desired log file. + +4. Select on the **...** icon next to the file to download it. + +![Log files list](~/assets/images/logs/logs-r2.png) + +### AWS CLI + +Cloudflare R2 is S3-compatible, so you can use the AWS CLI to interact with it. + - Configure the AWS CLI with your R2 credentials. + - Use the `aws s3 cp` command to download the log file: + +```bash +aws s3 cp s3:///` +``` + +Replace ``, ``, and `` with your specific details. + +Downloaded files are gzipped so they must be decompressed before you can open them in a text editor. diff --git a/src/content/docs/logs/get-started/enable-destinations/s3-compatible-endpoints.mdx b/src/content/docs/logs/get-started/enable-destinations/s3-compatible-endpoints.mdx index 194e64c95c8f8f..b95db315660192 100644 --- a/src/content/docs/logs/get-started/enable-destinations/s3-compatible-endpoints.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/s3-compatible-endpoints.mdx @@ -107,7 +107,7 @@ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/logpush/jobs \ "output_options": { "field_names": ["ClientIP", "ClientIP", "ClientRequestHost", "ClientRequestMethod", "ClientRequestURI","EdgeEndTimestamp", "EdgeResponseBytes", "EdgeResponseStatus", "EdgeStartTimestamp", "RayID"], "timestamp_format": "rfc3339" - }, + }, "dataset": "http_requests" }' ``` diff --git a/src/content/docs/logs/get-started/enable-destinations/sumo-logic.mdx b/src/content/docs/logs/get-started/enable-destinations/sumo-logic.mdx index dfdaebfa0f9d5e..fcd43306cd86e8 100644 --- a/src/content/docs/logs/get-started/enable-destinations/sumo-logic.mdx +++ b/src/content/docs/logs/get-started/enable-destinations/sumo-logic.mdx @@ -56,5 +56,5 @@ To enable Logpush to Sumo Logic: * Sumo Logic may impose throttling and caps on your log ingestion to prevent your account from using **On-Demand Capacity**. Refer to [manage ingestion](https://help.sumologic.com/docs/manage/ingestion-volume/log-ingestion/). -* To analyze and visualize Cloudflare Logs using the Cloudflare App for Sumo Logic, follow the steps in the Sumo Logic integration documentation to [install the Cloudflare App](https://help.sumologic.com/docs/integrations/saas-cloud/cloudflare/#installing-the-cloudflare-app) and [view the Cloudflare dashboards](https://help.sumologic.com/docs/integrations/saas-cloud/cloudflare/#viewing-the-cloudflare-dashboards). +* To analyze and visualize Cloudflare Logs using the Cloudflare App for Sumo Logic, follow the steps in the Sumo Logic integration documentation to [install the Cloudflare App](https://help.sumologic.com/docs/integrations/saas-cloud/cloudflare/#installing-the-cloudflare-app) and [view the Cloudflare dashboards](https://help.sumologic.com/docs/integrations/saas-cloud/cloudflare/#viewing-the-cloudflare-dashboards). ::: diff --git a/src/content/docs/logs/index.mdx b/src/content/docs/logs/index.mdx index effccb934276d3..9581832a93ae07 100644 --- a/src/content/docs/logs/index.mdx +++ b/src/content/docs/logs/index.mdx @@ -13,7 +13,7 @@ import { CardGrid, Description, Feature, LinkTitleCard, RelatedProduct } from "~ -Detailed logs that contain metadata generated by our products. +Detailed logs that contain metadata generated by our products. These logs are helpful for debugging, identifying configuration adjustments, and creating analytics, especially when combined with logs from other sources, such as your application server. For information about the types of data Cloudflare collects, refer to [Cloudflare's Types of analytics](/analytics/types-of-analytics/). @@ -48,11 +48,11 @@ Use Logs Engine to store your logs in R2 and query them directly. ## Related products -Summarize the history of changes made within your Cloudflare account. +Summarize the history of changes made within your Cloudflare account. -Provides privacy-first analytics without changing your DNS or using Cloudflare's proxy. +Provides privacy-first analytics without changing your DNS or using Cloudflare's proxy. *** diff --git a/src/content/docs/logs/log-explorer.mdx b/src/content/docs/logs/log-explorer.mdx index 079132830e3cdd..eb880f4b7c4ef4 100644 --- a/src/content/docs/logs/log-explorer.mdx +++ b/src/content/docs/logs/log-explorer.mdx @@ -7,7 +7,7 @@ sidebar: text: Beta --- -import { TabItem, Tabs } from "~/components"; +import { TabItem, Tabs, Render } from "~/components"; Log Explorer enables you to store and explore your Cloudflare logs directly within the Cloudflare Dashboard or API. Giving you visibility into your logs without the need to forward them to third parties. Logs are stored on Cloudflare's global network using the R2 object storage platform and can be queried via the Dashboard or SQL API. @@ -26,13 +26,7 @@ Log Explorer is available at the account and zone level. At the zone level, data At the account level, the datasets available are: -- [Access requests](/logs/reference/log-fields/account/access_requests/) (`FROM access_requests`) -- [CASB Findings](/logs/reference/log-fields/account/casb_findings/) (`FROM casb_findings`) -- [Device posture results](/logs/reference/log-fields/account/device_posture_results/) (`FROM device_posture_results`) -- [Gateway DNS](/logs/reference/log-fields/account/gateway_dns/) (`FROM gateway_dns`) -- [Gateway HTTP](/logs/reference/log-fields/account/gateway_http/) (`FROM gateway_http`) -- [Gateway Network](/logs/reference/log-fields/account/gateway_network/) (`FROM gateway_network`) -- [Zero Trust Network Session Logs](/logs/reference/log-fields/account/zero_trust_network_sessions/) (`FROM zero_trust_network_sessions`) + ## Authentication @@ -45,7 +39,7 @@ Note that these permissions exist at the account and zone level and you need the Authentication with the API can be done via an authentication header or API token. Append your API call with either of the following additional parameters. -- **Authentication header** +- **Authentication header** - `X-Auth-Email` - the Cloudflare account email address associated with the domain - `X-Auth-Key` - the Cloudflare API key @@ -54,11 +48,9 @@ Authentication with the API can be done via an authentication header or API toke - `Authorization: Bearer ` To create an appropriately scoped API token, refer to [Create API token](/fundamentals/api/get-started/create-token/) documentation. Copy and paste the token into the authorization parameter for your API call. - - ## Enable Log Explorer -In order for Log Explorer to begin storing logs, you need to enable the desired datasets. You can do this via the dashboard or the API. +In order for Log Explorer to begin storing logs, you need to enable the desired datasets. You can do this via the dashboard or the API. @@ -150,18 +142,18 @@ Which returns the following HTTP request details: ```json { - "result": [ - { - "clientrequestscheme": "https", - "clientrequesthost": "example.com", - "clientrequestmethod": "GET", - "clientrequestuseragent": "curl/7.88.1", - "edgeresponsestatus": 200 - } - ], - "success": true, - "errors": [], - "messages": [] + "result": [ + { + "clientrequestscheme": "https", + "clientrequesthost": "example.com", + "clientrequestmethod": "GET", + "clientrequestuseragent": "curl/7.88.1", + "edgeresponsestatus": 200 + } + ], + "success": true, + "errors": [], + "messages": [] } ``` @@ -177,23 +169,23 @@ Which returns the following request details: ```json { - "result": [ - { - "createdat": "2025-01-14T18:17:55Z", - "appdomain": "example.com", - "appuuid": "a66b4ab0-ccdf-4d60-a6d0-54a59a827d92", - "action": "login", - "allowed": true, - "country": "us", - "rayid": "90fbb07c0b316957", - "email": "user@example.com", - "ipaddress": "1.2.3.4", - "useruid": "52859e81-711e-4de0-8b31-283336060e79" - } - ], - "success": true, - "errors": [], - "messages": [] + "result": [ + { + "createdat": "2025-01-14T18:17:55Z", + "appdomain": "example.com", + "appuuid": "a66b4ab0-ccdf-4d60-a6d0-54a59a827d92", + "action": "login", + "allowed": true, + "country": "us", + "rayid": "90fbb07c0b316957", + "email": "user@example.com", + "ipaddress": "1.2.3.4", + "useruid": "52859e81-711e-4de0-8b31-283336060e79" + } + ], + "success": true, + "errors": [], + "messages": [] } ``` diff --git a/src/content/docs/logs/logpull/index.mdx b/src/content/docs/logs/logpull/index.mdx index 5fa7139055b1d0..a617ffbe0eef19 100644 --- a/src/content/docs/logs/logpull/index.mdx +++ b/src/content/docs/logs/logpull/index.mdx @@ -25,3 +25,7 @@ Review the following content to learn more about Logpull. ## Availability + +### Limitation + +Logpull is unavailable when the Customer Metadata Boundary (CMB) is set outside the US region. Specifically, it does not work when CMB is restricted to the EU-only setting. For more details, refer to the [Cloudflare Data Localization](/data-localization/) documentation. diff --git a/src/content/docs/logs/reference/log-fields/account/biso_user_actions.md b/src/content/docs/logs/reference/log-fields/account/biso_user_actions.md new file mode 100644 index 00000000000000..7823baa873b8c5 --- /dev/null +++ b/src/content/docs/logs/reference/log-fields/account/biso_user_actions.md @@ -0,0 +1,46 @@ +--- +# Code generator. DO NOT EDIT. + +title: Browser Isolation User Actions +pcx_content_type: configuration +sidebar: + order: 21 +--- + +The descriptions below detail the fields available for `biso_user_actions`. + +## AccountID + +Type: `string` + +The Cloudflare account ID. + +## Decision + +Type: `string` + +The decision applied ('allow' or 'block'). + +## DomainName + +Type: `string` + +The domain name in the URL. + +## Timestamp + +Type: `int or string` + +The date and time. + +## Type + +Type: `string` + +The user action type ('copy', 'paste', 'download', etc.). + +## UserID + +Type: `string` + +The user ID. diff --git a/src/content/docs/logs/reference/log-fields/account/dns_firewall_logs.md b/src/content/docs/logs/reference/log-fields/account/dns_firewall_logs.md index 23fec511275337..76a2f2db3c7151 100644 --- a/src/content/docs/logs/reference/log-fields/account/dns_firewall_logs.md +++ b/src/content/docs/logs/reference/log-fields/account/dns_firewall_logs.md @@ -25,7 +25,7 @@ The ID of the cluster which handled this request. Type: `string` -IATA airport code of data center that received the request. +IATA airport code of the data center that received the request. ## EDNSSubnet diff --git a/src/content/docs/logs/reference/log-fields/account/gateway_dns.md b/src/content/docs/logs/reference/log-fields/account/gateway_dns.md index 0375ea60a18237..3af52013693509 100644 --- a/src/content/docs/logs/reference/log-fields/account/gateway_dns.md +++ b/src/content/docs/logs/reference/log-fields/account/gateway_dns.md @@ -61,13 +61,13 @@ Resolved intermediate cname domains in reverse (for example, ['com.example.alias Type: `string` -The name of the colo that received the DNS query (for example, 'SJC', 'MIA', 'IAD'). +The name of the data center that received the DNS query (for example, 'SJC', 'MIA', 'IAD'). ## ColoID Type: `int` -The ID of the colo that received the DNS query (for example, 46, 72, 397). +The ID of the data center that received the DNS query (for example, 46, 72, 397). ## CustomResolveDurationMs diff --git a/src/content/docs/logs/reference/log-fields/account/network_analytics_logs.md b/src/content/docs/logs/reference/log-fields/account/network_analytics_logs.md index 19d1ef6b7d6c51..27916b19c4e76d 100644 --- a/src/content/docs/logs/reference/log-fields/account/network_analytics_logs.md +++ b/src/content/docs/logs/reference/log-fields/account/network_analytics_logs.md @@ -31,31 +31,31 @@ Descriptive name of the type of attack that this packet was a part of, if any. O Type: `string` -The city where the Cloudflare datacenter that received the packet is located. +The city where the Cloudflare data center that received the packet is located. ## ColoCode Type: `string` -The Cloudflare datacenter that received the packet (nearest IATA airport code). +The Cloudflare data center that received the packet (nearest IATA airport code). ## ColoCountry Type: `string` -The country where the Cloudflare datacenter that received the packet is located (ISO 3166-1 alpha-2). +The country where the Cloudflare data center that received the packet is located (ISO 3166-1 alpha-2). ## ColoGeoHash Type: `string` -The latitude and longitude where the colo that received the packet is located (Geohash encoding). +The latitude and longitude where the Cloudflare data center that received the packet is located (Geohash encoding). ## ColoName Type: `string` -The unique site identifier of the Cloudflare datacenter that received the packet (for example, 'ams01', 'sjc01', 'lhr01'). +The unique site identifier of the Cloudflare data center that received the packet (for example, 'ams01', 'sjc01', 'lhr01'). ## Datetime diff --git a/src/content/docs/logs/reference/log-fields/account/workers_trace_events.md b/src/content/docs/logs/reference/log-fields/account/workers_trace_events.md index b7a9cf32c03c8a..347c53e522ff31 100644 --- a/src/content/docs/logs/reference/log-fields/account/workers_trace_events.md +++ b/src/content/docs/logs/reference/log-fields/account/workers_trace_events.md @@ -55,7 +55,7 @@ List of console messages emitted during the invocation. Type: `string` -The outcome of the worker script invocation.
    Possible values are ok \| exception. +The outcome of the Worker script invocation.
    Possible values are ok \| exception. ## ScriptName diff --git a/src/content/docs/logs/reference/log-fields/account/zero_trust_network_sessions.md b/src/content/docs/logs/reference/log-fields/account/zero_trust_network_sessions.md index 0045a9c3470755..47f6aa4dda395a 100644 --- a/src/content/docs/logs/reference/log-fields/account/zero_trust_network_sessions.md +++ b/src/content/docs/logs/reference/log-fields/account/zero_trust_network_sessions.md @@ -91,7 +91,7 @@ Name of the client device which initiated the network session, if applicable, (f Type: `string` -The name of the Cloudflare colo from which traffic egressed to the origin. +The name of the Cloudflare data center from which traffic egressed to the origin. ## EgressIP @@ -127,7 +127,7 @@ Email address associated with the user identity which initiated the network sess Type: `string` -The name of the Cloudflare colo to which traffic ingressed. +The name of the Cloudflare data center to which traffic ingressed. ## Offramp diff --git a/src/content/docs/logs/reference/log-fields/zone/dns_logs.md b/src/content/docs/logs/reference/log-fields/zone/dns_logs.md index 9c06af1b8c03e1..f21b39be05e265 100644 --- a/src/content/docs/logs/reference/log-fields/zone/dns_logs.md +++ b/src/content/docs/logs/reference/log-fields/zone/dns_logs.md @@ -13,7 +13,7 @@ The descriptions below detail the fields available for `dns_logs`. Type: `string` -IATA airport code of data center that received the request. +IATA airport code of the data center that received the request. ## EDNSSubnet diff --git a/src/content/docs/logs/reference/log-fields/zone/firewall_events.md b/src/content/docs/logs/reference/log-fields/zone/firewall_events.md index e8b369840b48ea..2650de523e8064 100644 --- a/src/content/docs/logs/reference/log-fields/zone/firewall_events.md +++ b/src/content/docs/logs/reference/log-fields/zone/firewall_events.md @@ -145,7 +145,7 @@ The description of the rule triggered by this request. Type: `string` -The airport code of the Cloudflare datacenter that served this request. +The airport code of the Cloudflare data center that served this request. ## EdgeResponseStatus diff --git a/src/content/docs/logs/reference/log-fields/zone/http_requests.md b/src/content/docs/logs/reference/log-fields/zone/http_requests.md index f7b624e7a2dc4c..e4dc90c323ad42 100644 --- a/src/content/docs/logs/reference/log-fields/zone/http_requests.md +++ b/src/content/docs/logs/reference/log-fields/zone/http_requests.md @@ -253,19 +253,19 @@ String key-value pairs for Cookies. This field is populated based on [Logpush Cu Type: `bool` -True if the request looped through multiple zones on the Cloudflare edge. This is considered an orange to orange (o2o) request. +True if the request looped through multiple zones on the Cloudflare edge. This is considered an orange to orange (O2O) request. ## EdgeColoCode Type: `string` -IATA airport code of data center that received the request. +IATA airport code of the data center that received the request. ## EdgeColoID Type: `int` -Cloudflare edge colo id. +Cloudflare edge data center ID. ## EdgeEndTimestamp @@ -511,13 +511,13 @@ Array of security products that matched the request. The same product can appear Type: `int` -The Cloudflare datacenter used to connect to the origin server if Argo Smart Routing is used. +The Cloudflare data center used to connect to the origin server if Argo Smart Routing is used. ## UpperTierColoID Type: `int` -The "upper tier" datacenter that was checked for a cached copy if Tiered Cache is used. +The "upper tier" data center that was checked for a cached copy if Tiered Cache is used. ## WAFAttackScore @@ -559,31 +559,31 @@ WAF score for an XSS attack. Type: `int` -Amount of time in microseconds spent executing a worker, if any. +Amount of time in microseconds spent executing a Worker, if any. ## WorkerScriptName Type: `string` -The worker script name that made the request. +The Worker script name that made the request. ## WorkerStatus Type: `string` -Status returned from worker daemon. +Status returned from Worker daemon. ## WorkerSubrequest Type: `bool` -Whether or not this request was a worker subrequest. +Whether or not this request was a Worker subrequest. ## WorkerSubrequestCount Type: `int` -Number of subrequests issued by a worker when handling this request. +Number of subrequests issued by a Worker when handling this request. ## WorkerWallTimeUs @@ -595,4 +595,4 @@ The elapsed time in microseconds between the start of a Worker invocation, and w Type: `string` -The human-readable name of the zone (e.g. 'cloudflare.com'). +The human-readable name of the zone (for example, 'cloudflare.com'). diff --git a/src/content/docs/logs/reference/log-fields/zone/page_shield_events.md b/src/content/docs/logs/reference/log-fields/zone/page_shield_events.md index 79a70e52895d9c..7659c1454a3b10 100644 --- a/src/content/docs/logs/reference/log-fields/zone/page_shield_events.md +++ b/src/content/docs/logs/reference/log-fields/zone/page_shield_events.md @@ -43,7 +43,7 @@ The ID of the policy which was violated. Type: `string` -The resource type of the violated directive. Possible values are 'script', 'connection' or 'other' for unmonitored resource types +The resource type of the violated directive. Possible values are 'script', 'connection', or 'other' for unmonitored resource types. ## Timestamp @@ -61,7 +61,7 @@ The resource URL. Type: `bool` -Whether the resource URL contains the CDN-CGI path. +Whether the resource URL contains the '/cdn-cgi/' path. ## URLHost diff --git a/src/content/docs/logs/reference/log-fields/zone/spectrum_events.md b/src/content/docs/logs/reference/log-fields/zone/spectrum_events.md index 74f1c2a53306cc..bc218707b160bf 100644 --- a/src/content/docs/logs/reference/log-fields/zone/spectrum_events.md +++ b/src/content/docs/logs/reference/log-fields/zone/spectrum_events.md @@ -43,7 +43,7 @@ Client IP address. Type: `string` -Whether the connection matched any IP Firewall rules. UNKNOWN = No match or Firewall not enabled for spectrum; UNKNOWN \| ALLOW \| BLOCK_ERROR \| BLOCK_IP \| BLOCK_COUNTRY \| BLOCK_ASN \| WHITELIST_IP \| WHITELIST_COUNTRY \| WHITELIST_ASN. +Whether the connection matched any IP Firewall rules. UNKNOWN = No match or Firewall not enabled for Spectrum; UNKNOWN \| ALLOW \| BLOCK_ERROR \| BLOCK_IP \| BLOCK_COUNTRY \| BLOCK_ASN \| WHITELIST_IP \| WHITELIST_COUNTRY \| WHITELIST_ASN. ## ClientPort @@ -91,7 +91,7 @@ Indicates state of TLS session from the client to Spectrum; UNKNOWN \| Type: `string` -IATA airport code of data center that received the request. +IATA airport code of the data center that received the request. ## ConnectTimestamp diff --git a/src/content/docs/magic-cloud-networking/get-started.mdx b/src/content/docs/magic-cloud-networking/get-started.mdx index 5da27cdadddf82..7760a7f51b4d4f 100644 --- a/src/content/docs/magic-cloud-networking/get-started.mdx +++ b/src/content/docs/magic-cloud-networking/get-started.mdx @@ -6,15 +6,23 @@ sidebar: --- -To get started with Magic Cloud Networking (beta) you need to give Cloudflare permission to interact with cloud providers on your behalf. You might have multiple provider accounts for the same cloud provider - for example, you might want Cloudflare to manage virtual private clouds (VPCs) belonging to two different AWS accounts. +To get started with Magic Cloud Networking (beta) you need to give Cloudflare permission to interact with cloud providers on your behalf. You might have multiple provider accounts for the same cloud provider — for example, you might want Cloudflare to manage virtual private clouds (VPCs) belonging to two different AWS accounts. -Once Cloudflare has the credentials required to access your cloud environments, Magic Cloud Networking will automatically begin discovering your cloud resources - like routing tables and virtual private networks. Discovered resources appear in your [Cloud resource catalog](/magic-cloud-networking/manage-resources/#cloud-resource-catalog). +Once Cloudflare has the credentials required to access your cloud environments, Magic Cloud Networking will automatically begin discovering your cloud resources — like routing tables and virtual private networks. Discovered resources appear in your [Cloud resource catalog](/magic-cloud-networking/manage-resources/#cloud-resource-catalog). -## 1. Set up cloud credentials +## Set up Amazon AWS -Before you can connect Magic Cloud Networking to your cloud provider, you first need to create credentials with the correct permissions in your cloud provider. +### 1. Create integration -### Amazon AWS +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account. +2. Select **Manage Account** > **Cloud integrations**. +3. Go to **Integrations** and select **Connect integration**. +4. Select **AWS integration**. +5. Give a descriptive name to your integration. Optionally, you can also add a description for it. +6. Select **Create integration**. +7. Select **Authorize access** to start the process of connecting your Cloudflare account to Amazon AWS. + +### 2. Create IAM policy 1. Create a [custom access policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html) in your AWS account, and take note of the name you entered. Then, paste the following [JSON code](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html) in the JSON tab: @@ -46,46 +54,91 @@ Before you can connect Magic Cloud Networking to your cloud provider, you first } ``` -2. Follow the [instructions on AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html) to create an IAM user up until step 4 - do not check the **Provide users access to the AWS Management Console** option. +### 3. Authorize access to your AWS account + +1. Create a [custom access policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html) in your AWS account, and take note of the name you entered. +2. Create an [AWS role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-custom.html) with the following settings: + - **Trusted entity type**: Select **Custom trust policy**, and paste the custom trust policy returned by the Cloudflare dashboard. + - **Permissions**: Add the IAM policy created in step 1, along with these AWS-managed policies: + - `NetworkAdministrator` + - `AmazonEC2ReadOnlyAccess` + - `AmazonVPCReadOnlyAccess` + - `IAMReadOnlyAccess` + - **ARN**: Copy the ARN for your newly created user. + + :::note + The trust policy may take several minutes to propagate to all regions. It usually takes less than four minutes, but can sometimes take longer. You may have to retry the **Authorize** button while the propagation takes effect. + ::: -3. **In Give users permissions to manage their own security credentials** (step 7 of the AWS instructions) select **Attach policies directly**, and add the following policies: - - `AmazonEC2ReadOnlyAccess` - - `IAMReadOnlyAccess` - - `NetworkAdministrator` - - `` (from step 1). +3. Select **I authorize Cloudflare to access my AWS account.** +4. Select **Authorize**. -4. [Add an Access Key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) to the new user. Take note of the access key as you cannot retrieve this information later. Cloudflare will ask for this value when you make an AWS Cloud Integration. +The first discovery of resources may not succeed in all regions, while the IAM policy is propagating. If you do not see all resources after creating your cloud integration, please try re-discovering. -### Microsoft Azure +## Set up Microsoft Azure -1. [Register an application](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#register-an-application) and skip the optional **Redirect URL** step. -2. [Add a client secret](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#add-a-client-secret) to the app registration. Take note of the secret value as you cannot retrieve this information later. Cloudflare will ask for this value when you make an Azure Cloud Integration. -3. [Add a role assignment](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal). The purpose of this step is to give the app that you registered in step 1 permission to access your Azure Subscription. - 1. In step 3 of the linked document, select the **Contributor** role from the **Privileged administrator roles** tab. - 2. In step 4 of the linked document, search for the app registration from step 1 when selecting members. +### 1. Create integration -### Google Cloud Platform +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account. +2. Select **Manage Account** > **Cloud integrations**. +3. Go to **Integrations** and select **Connect integration**. +4. Select **Azure integration**. +5. Give a descriptive name to your integration. Optionally, you can also add a description for it. +6. Select **Create integration**. +7. Select **Authorize access** to start the process of connecting your Cloudflare account to Microsoft Azure. + +### 2. Authorize access to your Azure account + +1. Select **Create service principal**. You will be redirected to Microsoft's login page. +2. Enter your Azure credentials. If your account does not have administrator privileges, you may need to pass this link to an account that has administrator privileges. +3. The next screen lists Cloudflare required permissions to access your account. Select **Accept**. +4. [Add a role assignment](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal). The purpose of this step is to give the app that you registered in step 1 permission to access your Azure Subscription. + - In step 3 of the linked document, select the **Contributor** role from the **Privileged administrator roles** tab. + - In step 4 of the linked document, search for `mcn-provider-integrations-bot-prod` when selecting members. +5. In **Provide account information**, enter the **Tenant ID** and **Subscription ID** you copied from step 4. +6. In **Verify account ownership**, [add the tags displayed in the Cloudflare dashboard](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources-portal). + + :::note + The tags may take several minutes to propagate and become readable to Cloudflare. It usually takes less than four minutes, but can sometimes take longer. You may have to retry the **Authorize** button while the propagation takes effect. + ::: + +7. Select **I authorize Cloudflare to access my AWS account.** If your account does not have administrator privileges, you may need to pass this link to an account that has administrator privileges. +8. Select **Authorize**. -1. Enable the [Compute Engine API](https://cloud.google.com/apis/docs/getting-started#enabling_apis). -2. [Create](https://cloud.google.com/iam/docs/service-accounts-create) a service account. -3. Grant the new service account the **Compute Network Admin** role. -4. [Create](https://cloud.google.com/iam/docs/keys-create-delete) a service account key. Use the JSON key type. +The first discovery of resources may not succeed in all regions, while the IAM policy is propagating. If you do not see all resources after creating your cloud integration, please try re-discovering. -## 2. Set up Cloud Integrations +## Set up Google Cloud + +### 1. Create integration 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account. 2. Select **Manage Account** > **Cloud integrations**. -3. Go to **Cloud integrations** and select **Add**. -4. Select your cloud provider to start the cloud integration wizard. -5. Enter a descriptive name, and optionally a description, for your cloud integration. -6. Select **Continue**. -7. Enter the credentials that you have created in [Set up cloud credentials](#1-set-up-cloud-credentials). These allow Magic Cloud Networking to access the resources in your cloud provider. +3. Go to **Integrations** and select **Connect integration**. +4. Select **Google integration**. +5. Give a descriptive name to your integration. Optionally, you can also add a description for it. +6. Select **Create integration**. +7. Select **Authorize access** to start the process of connecting your Cloudflare account to Google Cloud. + +### 2. Authorize access to your Google account + +1. Create a new [GCP service account](https://cloud.google.com/iam/docs/service-accounts-create) in your **Google account** > **GCP Console** > **IAM & Admin** > **Service Accounts**. +2. Grant the new service account these roles: + - `Compute Network Admin` + - `Compute Viewer` +3. Grant the **Service Account Token Creator** role to our bot account to allow it to impersonate this service account. Learn how to grant a specific role [in Google's documentation](https://cloud.google.com/iam/docs/manage-access-service-accounts#grant-single-role): + - `mcn-integrations-bot-prod@mcn-gcp-01.iam.gserviceaccount.com` +4. In the **service account email field**, enter the email account that you used to create the GCP service account. +5. In the **Project ID field**, enter the [project ID](https://support.google.com/googleapi/answer/7014113?hl=en) associated with your project. +6. [Add the label](https://cloud.google.com/resource-manager/docs/creating-managing-labels#create-labels) displayed on the dash to your project. +7. Select **I authorize Cloudflare to access my GCP account.** If your account does not have administrator privileges, you may need to pass this link to an account that has administrator privileges. 8. Select **Authorize**. You have successfully connected your cloud provider to Magic Cloud Networking. Cloud resources found by Magic Cloud Networking are available in the [Cloud resource catalog](/magic-cloud-networking/manage-resources/#cloud-resource-catalog). +The first discovery of resources may not succeed in all regions, while the IAM policy is propagating. If you do not see all resources after creating your cloud integration, please try re-discovering. + ## Next steps - [Set up Magic WAN](/magic-cloud-networking/cloud-on-ramps/) as an on-ramp to your cloud. - [Manage resources](/magic-cloud-networking/manage-resources/) found by Magic Cloud Networking. -- [Edit](/magic-cloud-networking/manage-resources/#edit-cloud-integrations) cloud integrations. +- [Edit](/magic-cloud-networking/manage-resources/#edit-cloud-integrations) cloud integrations. \ No newline at end of file diff --git a/src/content/docs/magic-firewall/about/list-types.mdx b/src/content/docs/magic-firewall/about/list-types.mdx index 1d0ebc4c14d1dc..f7064119edfdd3 100644 --- a/src/content/docs/magic-firewall/about/list-types.mdx +++ b/src/content/docs/magic-firewall/about/list-types.mdx @@ -11,7 +11,7 @@ The threat intelligence feed categories are described in [Managed IP Lists](/waf ## IP lists -Use [IP lists](/waf/tools/lists/custom-lists/#lists-with-ip-addresses-ip-lists) to group services in networks, like web servers, or for lists of known bad IP addresses to make managing good network endpoints easier. IP lists are helpful for users with very expansive firewall rules with many IP lists. You can add up to 100,000 IPs per list that can used in rules. Refer to [Use an IP list](/magic-firewall/how-to/add-rules/#use-an-ip-list) to check an example of how to use an IP list. +Use [IP lists](/waf/tools/lists/custom-lists/#lists-with-ip-addresses-ip-lists) to group services in networks, like web servers, or for lists of known bad IP addresses to make managing good network endpoints easier. IP lists are helpful for users with very expansive firewall rules with many IP lists. By default, you can add up to 10,000 IPs across all lists. Refer to [Use an IP list](/magic-firewall/how-to/add-rules/#use-an-ip-list) to check an example of how to use an IP list. ## Geo-blocking diff --git a/src/content/docs/magic-firewall/how-to/add-rules.mdx b/src/content/docs/magic-firewall/how-to/add-rules.mdx index ec106198e36947..ac18043a9e58d8 100644 --- a/src/content/docs/magic-firewall/how-to/add-rules.mdx +++ b/src/content/docs/magic-firewall/how-to/add-rules.mdx @@ -15,7 +15,7 @@ By default, you can create a maximum of 200 rules. We recommend you create lists 1. Log in to your [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. 2. Select **Magic Firewall**. 3. In the **Custom rules** tab, select **Add a Rule**. -4. Fill out the information for your new rule. +4. Fill out the information for your new rule. You can use a managed [IP list](https://www.cloudflare.com/en-gb/ips/) when populating the **Value**. 5. When you are done, select **Add new rule**. ## Create a disabled rule diff --git a/src/content/docs/magic-firewall/index.mdx b/src/content/docs/magic-firewall/index.mdx index deffddfc44a934..74c2c46fc18812 100644 --- a/src/content/docs/magic-firewall/index.mdx +++ b/src/content/docs/magic-firewall/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Magic Firewall pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Magic Firewall - + content: Overview --- import { Description, Feature, GlossaryTooltip, Plan, RelatedProduct } from "~/components" @@ -28,7 +27,7 @@ Magic Firewall is available with the purchase of [Magic Transit](/magic-transit/ ## Features -Actively monitor for a wide range of known threat signatures in your traffic. +Actively monitor for a wide range of known threat signatures in your traffic. *** @@ -36,9 +35,9 @@ Actively monitor for a wide range of known threat signatures in your traffic. ## Related products -Secure your network from incoming Internet traffic, and improve performance at Cloudflare scale. +Secure your network from incoming Internet traffic, and improve performance at Cloudflare scale. -Improve security and performance for your entire corporate networking, reducing cost and operation complexity. +Improve security and performance for your entire corporate networking, reducing cost and operation complexity. diff --git a/src/content/docs/magic-firewall/packet-captures/collect-pcaps.mdx b/src/content/docs/magic-firewall/packet-captures/collect-pcaps.mdx index 29a9be27f0c1b5..8306e36a567c2f 100644 --- a/src/content/docs/magic-firewall/packet-captures/collect-pcaps.mdx +++ b/src/content/docs/magic-firewall/packet-captures/collect-pcaps.mdx @@ -93,7 +93,7 @@ While the collection is in progress, the response returns the `status` field as "packet_limit": 10000, "byte_limit": 100000000, "colo": "ORD", - "destination_conf": "gs://test-magic-pcaps" + "destination_conf": "gs://" // Ensure you use a bucket that you created and registered in the Cloudflare dashboard }, "success": true, "errors": [], diff --git a/src/content/docs/magic-firewall/packet-captures/pcaps-bucket-setup.mdx b/src/content/docs/magic-firewall/packet-captures/pcaps-bucket-setup.mdx index 0ff1dbfe6dcf02..85e21e2b2ce956 100644 --- a/src/content/docs/magic-firewall/packet-captures/pcaps-bucket-setup.mdx +++ b/src/content/docs/magic-firewall/packet-captures/pcaps-bucket-setup.mdx @@ -72,7 +72,7 @@ The response has a `"filename"` parameter which contains the content of the `own "status": "pending", "submitted": "2022-04-22T18:54:13.397413Z", "validated": "", - "destination_conf": "gs://bucket-test", + "destination_conf": "gs://bucket-test", // Ensure you use a bucket that you created and registered in the Cloudflare dashboard. "filename": "ownership-challenge-1234.txt" }, "success": true, @@ -101,7 +101,7 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/pcaps/ownership/ "status": "success", "submitted": "2022-04-22T18:54:13.397413Z", "validated": "2022-04-27T14:54:46.440548Z", - "destination_conf": "gs://bucket-test", + "destination_conf": "gs://", // Ensure you use a bucket that you created and registered in the Cloudflare dashboard "filename": "ownership-challenge-1234.txt" }, "success": true, diff --git a/src/content/docs/magic-firewall/tutorials/graphql-analytics.mdx b/src/content/docs/magic-firewall/tutorials/graphql-analytics.mdx index bab9e53047001f..35dea13ad7c0d0 100644 --- a/src/content/docs/magic-firewall/tutorials/graphql-analytics.mdx +++ b/src/content/docs/magic-firewall/tutorials/graphql-analytics.mdx @@ -1,7 +1,6 @@ --- title: GraphQL Analytics pcx_content_type: tutorial -content_type: 📝 Tutorial languages: - GraphQL sidebar: diff --git a/src/content/docs/magic-network-monitoring/faq.mdx b/src/content/docs/magic-network-monitoring/faq.mdx index 73ddb88066dc0d..0516907dd0f7e9 100644 --- a/src/content/docs/magic-network-monitoring/faq.mdx +++ b/src/content/docs/magic-network-monitoring/faq.mdx @@ -6,6 +6,14 @@ sidebar: order: 11 --- +Below you will find answers to our most commonly asked questions. If you cannot find the answer you are looking for, refer to the [community page](https://community.cloudflare.com/) to explore more resources. + +## I am getting an "Invalid account settings request body: account name format contains illegal characters or is not supported" error when trying to create a rule. + +This probably means that your account name has unsupported characters. Make sure your account name does not have characters like, for example, `&`, `<`, `>`, `"`, `'`, ``` ` ```. + +Refer to [Account name](/fundamentals/setup/account/customize-account/account-name/) to learn how to change your account name. + ## Can I send NetFlow/sFlow data to Cloudflare in a secure, encrypted way? Yes. Both enterprise and free customers can send encrypted network flow data to Cloudflare. diff --git a/src/content/docs/magic-network-monitoring/index.mdx b/src/content/docs/magic-network-monitoring/index.mdx index ac682fdcebd219..ec10ad12688d40 100644 --- a/src/content/docs/magic-network-monitoring/index.mdx +++ b/src/content/docs/magic-network-monitoring/index.mdx @@ -1,11 +1,11 @@ --- -title: Overview +title: Cloudflare Magic Network Monitoring pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Magic Network Monitoring + content: Overview --- import { diff --git a/src/content/docs/magic-network-monitoring/rules/index.mdx b/src/content/docs/magic-network-monitoring/rules/index.mdx index a2ea229e813fb5..991fcabaad5aaa 100644 --- a/src/content/docs/magic-network-monitoring/rules/index.mdx +++ b/src/content/docs/magic-network-monitoring/rules/index.mdx @@ -2,12 +2,24 @@ title: Rules pcx_content_type: how-to sidebar: + label: Manage rules order: 4 --- Magic Network Monitoring rules will allow you to monitor the traffic volume destined for IP addresses or IP prefixes on your network. You can also receive alerts if the volume of traffic arriving at specific destinations exceeds a defined threshold. +:::caution[Invalid account settings error when trying to create a rule] +If you get the following error when trying to create a rule: + +`Invalid account settings request body: account name format contains illegal characters or is not supported` + +Make sure the name for your Cloudflare account does not contain unsupported characters, like, for example, `&`, `<`, `>`, `"`, `'`, ``` ` ```. + +Refer to [Account name](/fundamentals/setup/account/customize-account/account-name/) to learn how to change your account name. +::: + + ## Create rules Refer to [Recommended rule configuration](/magic-network-monitoring/rules/recommended-rule-configuration/) for more details on the settings we recommend to create appropriate Magic Network Monitoring rules. diff --git a/src/content/docs/magic-network-monitoring/tutorials/encrypt-network-flow-data.mdx b/src/content/docs/magic-network-monitoring/tutorials/encrypt-network-flow-data.mdx index 1c6d4d22aacac8..c89e6eadbb880d 100644 --- a/src/content/docs/magic-network-monitoring/tutorials/encrypt-network-flow-data.mdx +++ b/src/content/docs/magic-network-monitoring/tutorials/encrypt-network-flow-data.mdx @@ -9,6 +9,8 @@ head: content: Magic Network Monitoring encrypt network flow data --- +import { APIRequest } from "~/components" + Customers can encrypt the network flow data sent from their router to Cloudflare by [routing](https://www.cloudflare.com/learning/network-layer/what-is-routing/) their network flow traffic through a device running the WARP client. Then, encrypted network flow traffic can be forwarded from the WARP enabled device to Cloudflare's network flow endpoints. To learn more about the WARP client, and to install the WARP client on Linux, macOS, or Windows, you can visit the [WARP client documentation](/cloudflare-one/connections/connect-devices/warp/). @@ -28,22 +30,19 @@ The `warp_devices` array at the account level is a list of WARP devices through For example: -```bash -curl --request PATCH \ -"https://api.cloudflare.com/client/v4/accounts/{account_id}/mnm/config" \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "warp_devices": [ +", + "name": "", + "router_ip": "YOUR_ROUTER_IP" } ] -}' -``` + }} +/> ## 2. Route Magic Network Monitoring traffic through WARP diff --git a/src/content/docs/magic-transit/how-to/advertise-prefixes.mdx b/src/content/docs/magic-transit/how-to/advertise-prefixes.mdx index c6ccf3ad1a4907..624bb7869d8f6a 100644 --- a/src/content/docs/magic-transit/how-to/advertise-prefixes.mdx +++ b/src/content/docs/magic-transit/how-to/advertise-prefixes.mdx @@ -30,7 +30,7 @@ List all prefixes and the [autonomous systems (ASNs)](https://www.cloudflare.com ## Cloudflare ASN vs. your own ASN -When customers supply their own ASN, Cloudflare prepends the main Cloudflare ASN (AS13335) to the BGP `AS_PATH`. For example, if the customer ASN is AS64496, anyone directly peering with Cloudflare sees the path as `13335 64496`. +As a part of your onboarding process, you need to decide the ASN Cloudflare will use to announce your prefixes. If you supply your own ASN, Cloudflare prepends the main Cloudflare ASN (AS13335) to the BGP `AS_PATH`. For example, if your ASN is `AS64496`, anyone directly peering with Cloudflare sees the path as `13335 64496`. If you do not have an ASN or do not want to bring your ASN to Cloudflare, you can use the Cloudflare Customer ASN (AS13335). @@ -69,14 +69,12 @@ You can only delete a prefix with an **Unapproved** status. To delete prefixes w 1. From the **IP Prefixes** tab, locate the prefix you want to modify and select **Delete**. 2. Confirm your choice from the modal by selecting **Delete**. -## Border Gateway Protocol (BGP) control for advertisements +## Border Gateway Protocol (BGP) control for advertisements (optional) -Use BGP to control the advertisement status of your prefix - advertised or withdrawn - from Cloudflare's global network for on-demand deployment scenarios. BGP Control works by establishing BGP sessions to Cloudflare's globally distributed Route Reflectors, which will initiate propagation of your prefix advertisement across Cloudflare's global network. +Optionally, you can use BGP to control the advertisement status of your prefix — advertised or withdrawn — from Cloudflare's global network for on-demand deployment scenarios. BGP Control works by establishing BGP sessions to Cloudflare's globally distributed Route Reflectors, which will initiate propagation of your prefix advertisement across Cloudflare's global network. Prefixes can be advertised from Cloudflare's network in a supported on-demand method such as BGP Control, or dynamically via the UI, API, or [Magic Network Monitoring](/magic-transit/magic-network-monitoring/). During the onboarding of your on-demand prefixes, please specify whether you want BGP-controlled advertisement or dynamic advertisement (via dashboard/API/Magic Network Monitoring). -![BGP diagram for Magic Transit](~/assets/images/magic-transit/bgp-diagram.png) - To begin using BGP control, contact your account team with the following information: - BGP endpoint IP addresses @@ -91,7 +89,7 @@ When you withdraw a prefix using BGP, you must ensure the prefix is withdrawn ac ### BGP peering -If you use Direct CNI as a way to on-ramp your network traffic to Magic Transit, refer to [BGP peering](/magic-transit/how-to/bgp-peering/) to learn how to configure BGP peering. +If you use Direct CNI as a way to on-ramp your network traffic to Magic Transit, refer to [BGP peering](/magic-transit/how-to/bgp-peering/) to learn how to use BGP to handle traffic routing between Cloudflare and your network. Note that this is a different option to using BGP as a means to control the advertisement status of your prefix. ### Regional settings diff --git a/src/content/docs/magic-transit/how-to/configure-magic-tunnel-alerts.mdx b/src/content/docs/magic-transit/how-to/configure-magic-tunnel-alerts.mdx index 5060997166440c..9ac342cc699dd4 100644 --- a/src/content/docs/magic-transit/how-to/configure-magic-tunnel-alerts.mdx +++ b/src/content/docs/magic-transit/how-to/configure-magic-tunnel-alerts.mdx @@ -5,7 +5,7 @@ head: [] description: Use the API to set up and configure Magic Tunnel health alerts --- -import { Render, Tabs, TabItem } from "~/components"; +import { APIRequest, Render, Tabs, TabItem } from "~/components"; ' \ ---header 'Content-Type: application/json' \ ---data '{ - "alert_type": "magic_tunnel_health_check_event", - "description": "", - "enabled": true, - "filters": { - "slo": [ - "99.9" - ] - }, - "mechanisms": { - "email": [ - { - "id": "EMAIL_ADDRESS" - } - ], - "name": "" -}' -``` +", + "enabled": true, + "filters": { + "slo": [ + "99.9" + ] + }, + "mechanisms": { + "email": [ + { + "id": "EMAIL_ADDRESS" + } + ]}, + "name": "" + + }} +/> ```json output { diff --git a/src/content/docs/magic-transit/how-to/configure-static-routes.mdx b/src/content/docs/magic-transit/how-to/configure-static-routes.mdx index 318e091fb2f395..71e6d6ddc6df81 100644 --- a/src/content/docs/magic-transit/how-to/configure-static-routes.mdx +++ b/src/content/docs/magic-transit/how-to/configure-static-routes.mdx @@ -20,9 +20,7 @@ import { Render } from "~/components" BGPpath: "/magic-transit/how-to/bgp-peering/", anycastURL: "/magic-transit/reference/tunnels/", trafficSteering: "/magic-transit/reference/traffic-steering/", - magicWANecmp: " ", createPath: "Magic Transit > Configuration", - tunnelEndpoints: "/magic-transit/how-to/configure-tunnels/", - ipRanges: " " + tunnelEndpoints: "/magic-transit/how-to/configure-tunnels/" }} /> diff --git a/src/content/docs/magic-transit/how-to/configure-tunnels.mdx b/src/content/docs/magic-transit/how-to/configure-tunnels.mdx index 4eeb25352adce9..207ecc83464205 100644 --- a/src/content/docs/magic-transit/how-to/configure-tunnels.mdx +++ b/src/content/docs/magic-transit/how-to/configure-tunnels.mdx @@ -58,8 +58,9 @@ import { GlossaryTooltip, Render } from "~/components"; healthCheck: "/magic-transit/how-to/tunnel-health-checks/", productPathProbe: "/magic-transit/reference/tunnel-health-checks/", antiReplayPagePath: "/magic-transit/reference/anti-replay-protection/", - BiVsUniHealthCheck: "unidirectional", + biVsUniHealthCheck: "unidirectional", tunnelHealthDash: "/magic-transit/how-to/check-tunnel-health-dashboard/", + biVsUniHealthCheckDefaults: "For Magic Transit this option defaults to unidirectional" }} /> diff --git a/src/content/docs/magic-transit/index.mdx b/src/content/docs/magic-transit/index.mdx index 7ed8a46a187851..37ad20baa6372b 100644 --- a/src/content/docs/magic-transit/index.mdx +++ b/src/content/docs/magic-transit/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Magic Transit pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Magic Transit - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/magic-wan/configuration/common-settings/configure-magic-tunnel-alerts.mdx b/src/content/docs/magic-wan/configuration/common-settings/configure-magic-tunnel-alerts.mdx index ad4a460287dfee..18225a334e292b 100644 --- a/src/content/docs/magic-wan/configuration/common-settings/configure-magic-tunnel-alerts.mdx +++ b/src/content/docs/magic-wan/configuration/common-settings/configure-magic-tunnel-alerts.mdx @@ -5,7 +5,7 @@ head: [] description: Use the API to set up and configure Magic Tunnel health alerts --- -import { Render, Tabs, TabItem } from "~/components"; +import { APIRequest, Render, Tabs, TabItem } from "~/components"; ' \ ---header 'Content-Type: application/json' \ ---data '{ - "alert_type": "magic_wan_tunnel_health", - "description": "", - "enabled": true, - "filters": { - "slo": [ - "99.9" - ] - }, - "mechanisms": { - "email": [ - { - "id": "EMAIL_ADDRESS" - } - ], - "name": "" -}' -``` +", + "enabled": true, + "filters": { + "slo": [ + "99.9" + ] + }, + "mechanisms": { + "email": [ + { + "id": "EMAIL_ADDRESS" + } + ]}, + "name": "" + }} +/> ```json output { diff --git a/src/content/docs/magic-wan/configuration/connector/configure-hardware-connector/index.mdx b/src/content/docs/magic-wan/configuration/connector/configure-hardware-connector/index.mdx index d42c7aa88c5f12..223631f024d49a 100644 --- a/src/content/docs/magic-wan/configuration/connector/configure-hardware-connector/index.mdx +++ b/src/content/docs/magic-wan/configuration/connector/configure-hardware-connector/index.mdx @@ -11,7 +11,6 @@ import { Render } from "~/components"; If you need a throughput higher than 1 Gbps, you can use one of the SFP+ ports. Refer to [SFP+ port information](/magic-wan/configuration/connector/configure-hardware-connector/sfp-port-information/) for more information on the hardware supported.", lan: "refers to the physical Magic WAN Connector Ethernet port that you are using for your LAN. The ports are labeled `GE1`, `GE2`, `GE3`, `GE4`, `GE5`, and `GE6`. Choose a number corresponding to the port that you are using in Connector.
    If you need a throughput higher than 1 Gbps, you can use one of the SFP+ ports. Refer to [SFP+ port information](/magic-wan/configuration/connector/configure-hardware-connector/sfp-port-information/) for more information on the hardware supported.", noConnectorShows: "You need to have bought a Connector already for it to show up here. Refer to [Prerequisites](#prerequisites) if no Connector shows up in this list.", diff --git a/src/content/docs/magic-wan/configuration/connector/configure-virtual-connector.mdx b/src/content/docs/magic-wan/configuration/connector/configure-virtual-connector.mdx index 1da57d3d018bb4..85f563182fddd4 100644 --- a/src/content/docs/magic-wan/configuration/connector/configure-virtual-connector.mdx +++ b/src/content/docs/magic-wan/configuration/connector/configure-virtual-connector.mdx @@ -10,7 +10,6 @@ import { Render } from "~/components"; - -```mermaid -flowchart LR -accTitle: In this example, the applications go directly to the Internet, skipping Cloudflare's security. filtering - a(Magic WAN Connector) --> b(Cloudflare) -->|Filtered traffic|c(Internet) - - a-- Breakout traffic ---d(Application1) & e(Application2) --> c - - classDef orange fill:#f48120,color: black - class a,b orange -``` - -_In the graph above, Applications 1 and 2 are configured to bypass Cloudflare's security filtering, and go straight to the Internet_ - -:::note[A note on security] -We recommend [routing](https://www.cloudflare.com/learning/network-layer/what-is-routing/) all traffic through our global network for comprehensive security filtering and access controls. However, there may be specific cases where you want a subset of traffic to bypass Cloudflare's security filtering and route it directly to the Internet. You can scope this breakout traffic to specific applications from the Cloudflare dashboard. - -Refer to [Traffic steering](/magic-wan/reference/traffic-steering/) to learn how Cloudflare routes traffic. -::: - -## Add an application - -You need to configure Breakout traffic for each of your existing sites, as it is a per-site configuration. - - - - -6. Select one or more applications that should bypass Cloudflare filtering from the list. You can also use the search box. -7. Select **Add applications**. - -The traffic for that application will now go directly to the Internet and bypass Cloudflare's filtering. - - - - - -1. Send a [`GET` request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with an account. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/apps \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": [ - { - "managed_app_id": "", - "name": "", - "type": "", - "hostnames": ["", ""] - } - ], - "success": true, - "errors": [], - "messages": [] - } - ``` - - Take note of the `"managed_app_id"` value for any application you want to configure. - -2. Send a [`POST` request](/api/resources/magic_transit/subresources/sites/subresources/app_configuration/methods/create/) to add new apps the breakout traffic policy. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " \ - --header "Content-Type: application/json" \ - --data '{ - "managed_app_id": "", - "breakout": true - }' - ``` - - ```json output - { - "result": { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - }, - "success": true, - "errors": [], - "messages": [] - } - ``` - - - -## Delete an application - - - - - - - - - -1. Send a [`GET` request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with a site. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": [ - { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - } - ], - "success": true, - "errors": [], - "messages": [] - } - ``` - -Take note of the `"id"` value for the application that want to delete. - -2. Send a [`DELETE` request](/api/resources/magic_transit/subresources/apps/methods/delete/) to delete an application from the breakout traffic policy. - - ```bash - curl --request DELETE \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs/{id} \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - }, - "success": true, - "errors": [], - "messages": [] - } - ``` - - - -## WARP traffic - - +import { Render } from "~/components"; + + \ No newline at end of file diff --git a/src/content/docs/magic-wan/configuration/connector/network-options/application-based-policies/prioritized-traffic.mdx b/src/content/docs/magic-wan/configuration/connector/network-options/application-based-policies/prioritized-traffic.mdx index aa6abfad3e9b69..82911f38bc5f86 100644 --- a/src/content/docs/magic-wan/configuration/connector/network-options/application-based-policies/prioritized-traffic.mdx +++ b/src/content/docs/magic-wan/configuration/connector/network-options/application-based-policies/prioritized-traffic.mdx @@ -6,155 +6,11 @@ description: Prioritized traffic allows you to define which applications are processed first by Magic WAN Connector. --- -import { Render, TabItem, Tabs } from "~/components"; - -Prioritized traffic allows you to define which applications Magic WAN Connector should process first. Applications not in the list will be queued behind prioritized traffic. - -Similarly to breakout traffic, prioritized traffic also works via DNS requests inspection. - -:::caution -Prioritized traffic will not work for applications that use DNS-over-HTTPS. -::: - -## Add an application - -You need to configure Prioritized traffic for each of your existing sites, as it is a per-site configuration. - - - - - -6. Select one or more applications that should take precedence over other traffic. You can also use the search box. -7. Select **Add applications**. - -The traffic for the applications you chose are now processed first by Connector. - - - - - -1. Send a [`GET` request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with an account. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/apps \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": [ - { - "managed_app_id": "", - "name": "", - "type": "", - "hostnames": ["", ""] - } - ], - "success": true, - "errors": [], - "messages": [] - } - ``` - - Take note of the `"managed_app_id"` value for any application you want to configure. - -2. Send a [`POST` request](/api/resources/magic_transit/subresources/sites/subresources/app_configuration/methods/create/) to add new apps the priority traffic policy. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " \ - --header "Content-Type: application/json" \ - --data '{ - "managed_app_id": "", - "priority": 1 - }' - ``` - - ```json output - { - "result": { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - }, - "success": true, - "errors": [], - "messages": [] - } - ``` - - - -## Delete an application - - - - - - - -1. Send a [`GET` request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with a site. - - Example: - - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": [ - { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - } - ], - "success": true, - "errors": [], - "messages": [] - } - ``` - - Take note of the `"id"` value for the application that want to delete. - -2. Send a `DELETE` request [using the API](/api/resources/magic_transit/subresources/apps/methods/delete/) to delete an application from the breakout traffic policy. - - ```bash - curl --request DELETE \ - https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/app_configs/{id} \ - --header "X-Auth-Email: " \ - --header "X-Auth-Key: " - ``` - - ```json output - { - "result": { - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "site_id": "023e105f4ecef8ad9ca31a8372d0c353", - "managed_app_id": "", - "breakout": true - }, - "success": true, - "errors": [], - "messages": [] - } - ``` - - +import { Render } from "~/components"; + + \ No newline at end of file diff --git a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-relay.mdx b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-relay.mdx index 4632e386167d17..05e745edc7af94 100644 --- a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-relay.mdx +++ b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-relay.mdx @@ -3,7 +3,7 @@ pcx_content_type: how-to title: DHCP relay --- -import { Render, TabItem, Tabs } from "~/components"; +import { APIRequest, Render, TabItem, Tabs } from "~/components"; DHCP Relay provides a way for DHCP clients to communicate with DHCP servers that are not available on the same local subnet/broadcast domain. When you enable DHCP Relay, Magic WAN Connector forwards DHCP discover messages to a predefined DHCP server, and routes the responses back to the original device that sent the discover message. @@ -48,14 +48,11 @@ Create a [`PUT` request](/api/resources/magic_transit/subresources/sites/subreso Example: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/lans/{lan_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "lan": { +
    diff --git a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-server.mdx b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-server.mdx index fd0da78a43083c..0747b8a2577c5b 100644 --- a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-server.mdx +++ b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-server.mdx @@ -3,7 +3,7 @@ pcx_content_type: how-to title: DHCP server --- -import { Render, TabItem, Tabs } from "~/components"; +import { APIRequest, Render, TabItem, Tabs } from "~/components"; When you use a static IP address, Magic WAN Connector can also act as a DHCP server in your network. To enable this feature: @@ -37,14 +37,11 @@ Create a [`PUT` request](/api/resources/magic_transit/subresources/sites/subreso Example: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/lans/{lan_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "lan": { +", @@ -53,7 +50,7 @@ https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id} } } } -}' -``` + }} +/>
    diff --git a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-static-address-reservation.mdx b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-static-address-reservation.mdx index b120153936624c..f6a7856db2bf50 100644 --- a/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-static-address-reservation.mdx +++ b/src/content/docs/magic-wan/configuration/connector/network-options/dhcp/dhcp-static-address-reservation.mdx @@ -3,7 +3,7 @@ pcx_content_type: how-to title: DHCP static address reservation --- -import { Render, TabItem, Tabs } from "~/components"; +import { APIRequest, Render, TabItem, Tabs } from "~/components"; If you configure your Connector to be a DHCP server, you can also assign IP addresses to specific devices on your network. To reserve IP addresses: @@ -23,14 +23,11 @@ Create a [`PUT` request](/api/resources/magic_transit/subresources/sites/subreso Example: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/lans/{lan_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "lan": { +
    diff --git a/src/content/docs/magic-wan/configuration/connector/network-options/network-segmentation.mdx b/src/content/docs/magic-wan/configuration/connector/network-options/network-segmentation.mdx index 9932a6f71ec9c1..698f761daa8146 100644 --- a/src/content/docs/magic-wan/configuration/connector/network-options/network-segmentation.mdx +++ b/src/content/docs/magic-wan/configuration/connector/network-options/network-segmentation.mdx @@ -4,7 +4,7 @@ title: Network segmentation description: Define policies to define if traffic should flow between your LANs without leaving your local premises, or if traffic should be forwarded to Cloudflare for additional security configurations. --- -import { Render, TabItem, Tabs } from "~/components"; +import { APIRequest, Render, TabItem, Tabs } from "~/components"; You can define policies in your Connector to either allow traffic to flow between your LANs without it leaving your local premises or to forward it via the Cloudflare network where you can add additional security features. The default behavior is to drop all LAN-to-LAN traffic. These policies can be created for specific subnets, and link two LANs. @@ -69,17 +69,14 @@ The new policy will ensure that traffic between the specified LANs flows locally -Create a `POST` request [using the API](/api/operations/magic-site-acls-create-acl) to create a network policy. +Create a `POST` request [using the API](/api/resources/magic_transit/subresources/sites/subresources/acls/methods/create/) to create a network policy. Example: -```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/acls \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "acl": { +", "forward_locally": true, "lan_1": { @@ -106,38 +103,60 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{sit "protocols": [ "tcp" ] - } -}' -``` + }} +/> ```json output { - "errors": [], - "messages": [], - "result": { - "acls": [ - { - "description": "", - "forward_locally": true, - "id": "023e105f4ecef8ad9ca31a8372d0c353", - "lan_1": { - "lan_id": "", - "lan_name": "", - "ports": [1], - "subnets": ["192.0.2.1"] - }, - "lan_2": { - "lan_id": "", - "lan_name": "", - "ports": [1], - "subnets": ["192.0.2.1"] - }, - "name": "", - "protocols": ["tcp"] - } - ] - }, - "success": true + "errors": [ + { + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" + } + ], + "result": { + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "Allows local traffic between PIN pads and cash register.", + "forward_locally": true, + "lan_1": { + "lan_id": "lan_id", + "lan_name": "lan_name", + "port_ranges": [ + "8080-9000" + ], + "ports": [ + 1 + ], + "subnets": [ + "192.0.2.1" + ] + }, + "lan_2": { + "lan_id": "lan_id", + "lan_name": "lan_name", + "port_ranges": [ + "8080-9000" + ], + "ports": [ + 1 + ], + "subnets": [ + "192.0.2.1" + ] + }, + "name": "PIN Pad - Cash Register", + "protocols": [ + "tcp" + ], + "unidirectional": true + }, + "success": true } ``` @@ -163,18 +182,14 @@ The new policy will ensure that traffic between the specified LANs flows locally -Create a `PUT` request [using the API](/api/operations/magic-site-acls-update-acl) to edit a network policy. +Create a `PUT` request [using the API](/api/resources/magic_transit/subresources/sites/subresources/acls/methods/update/) to edit a network policy. Example: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/acls/{acl_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "acl": { +", "forward_locally": true, "lan_1": { @@ -201,8 +216,37 @@ https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id} "protocols": [ "tcp" ] - } -}' + }} +/> + +```json output +{ + "errors": [ + { + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" + } + ], + "result": { + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "connector_id": "ac60d3d0435248289d446cedd870bcf4", + "description": "description", + "ha_mode": true, + "location": { + "lat": "37.6192", + "lon": "122.3816" + }, + "name": "site_1", + "secondary_connector_id": "8d67040d3835dbcf46ce29da440dc482" + }, + "success": true +} ```
    @@ -224,15 +268,13 @@ https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id} -Create a `DELETE` request [using the API](/api/operations/magic-site-acls-delete-acl) to delete a network policy. +Create a `DELETE` request [using the API](/api/resources/magic_transit/subresources/sites/subresources/acls/methods/delete/) to delete a network policy. Example: -```bash -curl --request DELETE \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/sites/{site_id}/acls/{acl_identifier} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " -``` +
    diff --git a/src/content/docs/magic-wan/configuration/manually/how-to/configure-static-routes.mdx b/src/content/docs/magic-wan/configuration/manually/how-to/configure-static-routes.mdx index cb579911a4dcb5..1d8a08d9d38dcd 100644 --- a/src/content/docs/magic-wan/configuration/manually/how-to/configure-static-routes.mdx +++ b/src/content/docs/magic-wan/configuration/manually/how-to/configure-static-routes.mdx @@ -15,14 +15,14 @@ import { Render } from "~/components" file="static-routes" product="magic-transit" params={{ + magicProduct: "Magic WAN", productName: "Magic WAN", BGPpath: "/magic-wan/configuration/manually/how-to/bgp-peering/", anycastURL: "/magic-wan/reference/tunnels/", trafficSteering: "/magic-wan/reference/traffic-steering/", magicWANecmp: "The maximum number of routes you can have with the same priority is 64.", createPath: "Magic WAN > Configuration", - tunnelEndpoints: "/magic-wan/configuration/manually/how-to/configure-tunnels/", - ipRanges: "
    When using Magic WAN and Cloudflare Tunnel together, remember to consider the IP ranges utilized in the static routes of Cloudflare Tunnel when selecting static routes for Magic WAN. For more information, refer to [Cloudflare Tunnel](/magic-wan/zero-trust/cloudflare-tunnel/).

    " + tunnelEndpoints: "/magic-wan/configuration/manually/how-to/configure-tunnels/" }} /> diff --git a/src/content/docs/magic-wan/configuration/manually/how-to/configure-tunnels.mdx b/src/content/docs/magic-wan/configuration/manually/how-to/configure-tunnels.mdx index 6e89eb8314b82c..42f59e770b6236 100644 --- a/src/content/docs/magic-wan/configuration/manually/how-to/configure-tunnels.mdx +++ b/src/content/docs/magic-wan/configuration/manually/how-to/configure-tunnels.mdx @@ -63,13 +63,12 @@ import { GlossaryTooltip, Render } from "~/components"; params={{ productName: "Magic WAN", productPathDash: "Magic WAN > Configuration", - healthCheck: - "/magic-wan/configuration/common-settings/tunnel-health-checks/", + healthCheck: "/magic-wan/configuration/common-settings/tunnel-health-checks/", productPathProbe: "/magic-wan/reference/tunnel-health-checks/", antiReplayPagePath: "/magic-wan/reference/anti-replay-protection/", - BiVsUniHealthCheck: "bidirectional", - tunnelHealthDash: - "/magic-wan/configuration/common-settings/check-tunnel-health-dashboard/", + biVsUniHealthCheck: "bidirectional", + tunnelHealthDash: "/magic-wan/configuration/common-settings/check-tunnel-health-dashboard/", + biVsUniHealthCheckDefaults: "For Magic WAN this option defaults to bidirectional" }} /> diff --git a/src/content/docs/magic-wan/index.mdx b/src/content/docs/magic-wan/index.mdx index 0b4fa645c1a219..78c55bdd70c4f4 100644 --- a/src/content/docs/magic-wan/index.mdx +++ b/src/content/docs/magic-wan/index.mdx @@ -1,11 +1,11 @@ --- -title: Overview +title: Cloudflare Magic WAN pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Magic WAN + content: Overview --- import { diff --git a/src/content/docs/network-error-logging/index.mdx b/src/content/docs/network-error-logging/index.mdx index d50923bd8190de..699c4773e3714c 100644 --- a/src/content/docs/network-error-logging/index.mdx +++ b/src/content/docs/network-error-logging/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Network Error Logging pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Network Error Logging - + content: Overview --- Network Error Logging (NEL) is a browser-based reporting system that allows users to report their own failures to an external endpoint. You can use Network Error Logging to gain insight into connectivity issues on the Internet to learn when and where an incident is happening, who is impacted, and how they are being impacted. diff --git a/src/content/docs/network-interconnect/express-cni/create-interconnects.mdx b/src/content/docs/network-interconnect/express-cni/create-interconnects.mdx index 41c7b1bbee7ddc..e4ec3b158c08b7 100644 --- a/src/content/docs/network-interconnect/express-cni/create-interconnects.mdx +++ b/src/content/docs/network-interconnect/express-cni/create-interconnects.mdx @@ -8,7 +8,7 @@ sidebar: To create a new interconnect, make sure you are logged in with Admin or higher-level account permissions. This is required for the wizard to successfully request and provision a new Direct CNI connection. 1. Log in to the [Cloudflare dashboard](https://developers.cloudflare.com/), and select your account. -2. Select **Interconnects** > **Create New**. +2. Select **Interconnects**. 3. In **Direct CNI**, select **Create new**. 4. From the list, choose a location that suits you with **Select location**, or search for a location in the search box. :::note @@ -26,8 +26,8 @@ To create a new interconnect, make sure you are logged in with Admin or higher-l The Cloudflare dashboard shows a list of all previously created interconnects, as well as useful information such as IP addresses, speed, type of interconnect, and status. -Direct CNI connections are LACP (Link Aggregation Control Protocol) enabled and use LACP packets to negotiate with other ports. The [Status column](https://dash.cloudflare.com/?to=/:account/interconnects/all) in the dashboard shows three different status: +The [Status column](https://dash.cloudflare.com/?to=/:account/interconnects/all) in the dashboard shows three different status: -- **Pending**: Pending shows up in new interconnects that are not yet active. This is expected and can occur for several reasons: the customer has not received a cross-connect, the device is unresponsive, or physical adjustments may be required, such as swapping RX/TX fibers. The `Pending` status will go away after the customer completes the cross-connect. -- **Active**: The interconnect port on the Customer Connectivity Router (CCR) has established a LACP session with the connected port on the customer device. -- **Unhealthy**: The interconnect port on the CCR has lost a previously established LACP session with the connected port on the customer device. You can take general troubleshooting steps to solve the issue (such as checking cables and status lights for connectivity issues). If you are unable to solve the issue in this way, contact your account team. \ No newline at end of file +- **Active**: The link operational state at the interconnect port on the Customer Connectivity Router (CCR) is up. This means that the CCR port sees sufficient light levels and has negotiated an Ethernet link. +- **Unhealthy**: The link operational state at interconnect port is down. This might mean the CCR does not see light, cannot negotiate an Ethernet signal, or the light levels are below -20 dBm. You can take general troubleshooting steps to solve the issue (such as checking cables and status lights for connectivity issues). If you are unable to solve the issue in this way, contact your account team. +- **Pending**: The link is not yet active. This is expected and can occur for several reasons: the customer has not received a cross-connect, the device is unresponsive, or physical adjustments may be required, such as swapping RX/TX fibers. The `Pending` status will disappear after the customer completes the cross-connect and status moves to `Active`. \ No newline at end of file diff --git a/src/content/docs/network-interconnect/index.mdx b/src/content/docs/network-interconnect/index.mdx index 723f1568224bcf..7732db633cc331 100644 --- a/src/content/docs/network-interconnect/index.mdx +++ b/src/content/docs/network-interconnect/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Network Interconnect pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Network Interconnect - + content: Overview --- import { Description, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/network/index.mdx b/src/content/docs/network/index.mdx index d12e3bb994cf0d..1b8ca3941f829b 100644 --- a/src/content/docs/network/index.mdx +++ b/src/content/docs/network/index.mdx @@ -1,9 +1,11 @@ --- -title: Overview +title: Network settings pcx_content_type: overview sidebar: order: 1 - +head: + - tag: title + content: Overview --- import { Description, Feature, Plan, RelatedProduct } from "~/components" @@ -19,15 +21,15 @@ Manage network settings for your website. ## Features -Include the country code of the visitor location with all requests to your website. +Include the country code of the visitor location with all requests to your website. -Enable IPv6 support and gateway. +Enable IPv6 support and gateway. -Allow WebSockets connections to your origin server. +Allow WebSockets connections to your origin server. *** @@ -35,9 +37,9 @@ Allow WebSockets connections to your origin server. ## Related products -The Cloudflare China Network is a package of selected Cloudflare’s performance and security products running on data centers located in mainland China and operated by Cloudflare’s partner JD Cloud. +The Cloudflare China Network is a package of selected Cloudflare’s performance and security products running on data centers located in mainland China and operated by Cloudflare’s partner JD Cloud. -Managed Transforms allow you to perform common adjustments to HTTP request and response headers with the click of a button. +Managed Transforms allow you to perform common adjustments to HTTP request and response headers with the click of a button. diff --git a/src/content/docs/network/onion-routing.mdx b/src/content/docs/network/onion-routing.mdx index 2a7bd93c7ac74a..e298a42f38af04 100644 --- a/src/content/docs/network/onion-routing.mdx +++ b/src/content/docs/network/onion-routing.mdx @@ -14,20 +14,14 @@ Improve the Tor user experience by enabling Onion Routing, which enables Cloudfl ## How it works -Due to the behavior of some individuals using the Tor network (spammers, distributors of malware, attackers), the IP addresses of Tor exit nodes may earn a bad reputation, elevating their Cloudflare threat score. - -Our [basic protection level](/waf/tools/security-level/) issues challenges to visitors whose IP address has a high threat score, depending on the level chosen by the Cloudflare customer. - -One way to address this threat score is to create [custom WAF rules](/waf/custom-rules/). Cloudflare assigns the two-letter code `T1` for Tor.  There's no geographical country associated with these IPs, but this approach lets Cloudflare customers override the default Cloudflare threat score to define the experience for their Tor visitors. Cloudflare updates its list of Tor exit node IP addresses every hour. - -The other way to improve the Tor user experience is through Onion Routing. This improves Tor browsing as follows: +Onion Routing helps improve Tor browsing as follows: - Tor users no longer access your site via exit nodes, which can sometimes be compromised, and may snoop on user traffic. - Human Tor users and bots can be distinguished by our Onion services, such that interactive challenges are only served to malicious bot traffic. [Tor Browser](https://tb-manual.torproject.org/about/) users receive an [alt-svc header](https://httpwg.org/specs/rfc7838.html#alt-svc) as part of the response to the first request to your website. The browser then creates a Tor Circuit to access this website using the `.onion` TLD service provided by this header. -You should note that the visible domain in the UI remains unchanged, as the host header and the SNI are preserved. However, the underlying connection changes to be routed through Tor, as the [UI denotes on the left of the address bar](https://tb-manual.torproject.org/managing-identities/#managing-identities) with a Tor Circuit. Cloudflare does not provide a certificate for the `.onion` domain provided as part of alt-svc flow, which therefore cannot be accessed via HTTPS. +You should note that the visible domain in the user interface remains unchanged, as the host header and the SNI are preserved. However, the underlying connection changes to be routed through Tor, as the [UI denotes on the left of the address bar](https://tb-manual.torproject.org/managing-identities/#managing-identities) with a Tor Circuit. Cloudflare does not provide a certificate for the `.onion` domain provided as part of alt-svc flow, which therefore cannot be accessed via HTTPS. ## Enable Onion Routing @@ -35,9 +29,9 @@ You should note that the visible domain in the UI remains unchanged, as the host To enable **Onion Routing** in the dashboard: -1. Log in to your [Cloudflare account](https://dash.cloudflare.com) and go to a specific domain. -2. Go to **Network**. -3. For **Onion Routing**, switch the toggle to **On**. +1. Log in to your [Cloudflare account](https://dash.cloudflare.com), and select your account and domain. +2. Go to **Network**. +3. For **Onion Routing**, switch the toggle to **On**.
    diff --git a/src/content/docs/page-shield/policies/create-dashboard.mdx b/src/content/docs/page-shield/policies/create-dashboard.mdx index c0f54455ca9fc7..be65a950a7284d 100644 --- a/src/content/docs/page-shield/policies/create-dashboard.mdx +++ b/src/content/docs/page-shield/policies/create-dashboard.mdx @@ -13,7 +13,8 @@ description: Learn how to create a Page Shield policy in the Cloudflare dashboar 3. Select **Create policy**. -4. Enter a descriptive name for the rule in **Description**. +4. + Enter a descriptive name for the rule in **Description**. 5. Under **If incoming requests match**, define the policy scope. You can use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](/ruleset-engine/rules-language/expressions/edit-expressions/). @@ -23,7 +24,6 @@ description: Learn how to create a Page Shield policy in the Cloudflare dashboar - To refresh the displayed sources based on Page Shield's detected resources, select **Refresh suggestions**. :::note - Page Shield provides suggestions for **Default**, **Scripts**, and **Connections** directives. For the **Default** directive, suggestions are based on monitored scripts and connections resources. ::: diff --git a/src/content/docs/pages/configuration/build-configuration.mdx b/src/content/docs/pages/configuration/build-configuration.mdx index f59ab32ca9d1a7..1a193fd0d1e003 100644 --- a/src/content/docs/pages/configuration/build-configuration.mdx +++ b/src/content/docs/pages/configuration/build-configuration.mdx @@ -34,7 +34,7 @@ If you are not using a preset, use `exit 0` as your **Build command**. ## Environment variables -If your project makes use of environment variables to build your site, provide custom environment variables: +If your project makes use of environment variables to build your site, you can provide custom environment variables: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com) and select your account. 2. In **Account Home**, select **Workers & Pages**. diff --git a/src/content/docs/pages/configuration/build-image.mdx b/src/content/docs/pages/configuration/build-image.mdx index 566a98f72def71..58fc571a5a1773 100644 --- a/src/content/docs/pages/configuration/build-image.mdx +++ b/src/content/docs/pages/configuration/build-image.mdx @@ -47,7 +47,9 @@ For example, if you use Gatsby, your `package.json` should include the following When your build starts, if not already [cached](/pages/configuration/build-caching/), version 5.13.7 of Gatsby will be installed using `npm install`. -## Overriding default versions +## Advanced Settings + +### Override default versions To override default versions of languages and tools in the build system, you can either set the desired version through environment variables or by adding files to your project. @@ -63,6 +65,14 @@ Or, to set the version by adding a file to your project, you can: For example, if you were previously relying on the default version of Node.js in the v1 build system, to migrate to v2, you must specify that you need Node.js `12.18.0` by setting a `NODE_VERSION = 12.18.0` environment variable or by adding a `.node-version` or `.nvmrc` file to your project with `12.18.0` added as the contents to the file. +### Skip dependency install + +You can add the following environment variable to disable automatic dependency installation, and run a custom install command instead. + +| Build variable | Value | +| ------------------------- | ------------- | +| `SKIP_DEPENDENCY_INSTALL` | `1` or `true` | + ## V2 build system The [v2 build system](https://blog.cloudflare.com/moderizing-cloudflare-pages-builds-toolbox/) announced in May 2023 brings several improvements to project builds. diff --git a/src/content/docs/pages/framework-guides/deploy-a-blazor-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-blazor-site.mdx index f87783b11b43dc..7107b1a3478ecf 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-blazor-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-blazor-site.mdx @@ -50,13 +50,7 @@ dotnet new gitignore ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages**. -3. Select **Create application** > **Pages** > **Connect to Git**. - -Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-brunch-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-brunch-site.mdx index 92dd62b5c1f6fd..271f46cda05e9c 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-brunch-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-brunch-site.mdx @@ -29,11 +29,7 @@ brunch new proj -s es6 ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Brunch_ as your **Framework preset**. Your selection will provide the following information. + diff --git a/src/content/docs/pages/framework-guides/deploy-a-docusaurus-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-docusaurus-site.mdx index 6817163c1f8be8..6380601fd4f5eb 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-docusaurus-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-docusaurus-site.mdx @@ -31,9 +31,10 @@ To use `create-cloudflare` to create a new Docusaurus project, run the following ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Docusaurus_ as your **Framework preset**. Your selection will provide the following information. + diff --git a/src/content/docs/pages/framework-guides/deploy-a-gatsby-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-gatsby-site.mdx index 4810899f3ce915..08fd1c34b47839 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-gatsby-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-gatsby-site.mdx @@ -29,11 +29,7 @@ npx gatsby new my-gatsby-site https://github.com/alxshelepenok/gatsby-starter-lu ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-gridsome-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-gridsome-site.mdx index 4b589fc42f70f6..33695ea2811bd7 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-gridsome-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-gridsome-site.mdx @@ -31,9 +31,10 @@ npx gridsome create my-gridsome-website To deploy your site to Pages: -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, the following information will be provided: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-hexo-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-hexo-site.mdx index b80ef5762e4614..8f8755426ccd95 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-hexo-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-hexo-site.mdx @@ -52,11 +52,7 @@ Inside of `hello-hexo.md`, use Markdown to write the content of the article. You ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-hono-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-hono-site.mdx index cb2b2753d6588d..5561420fdb0ae7 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-hono-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-hono-site.mdx @@ -12,7 +12,7 @@ import { TabItem, Tabs, PackageManagers, - Stream, + Stream, } from "~/components"; [Hono](https://honojs.dev/) is a small, simple, and ultrafast web framework for Cloudflare Pages and Workers, Deno, and Bun. Learn more about the creation of Hono by [watching an interview](#creator-interview) with its creator, [Yusuke Wada](https://yusu.ke/). @@ -28,81 +28,16 @@ To use `create-cloudflare` to create a new Hono project, run the following comma -Open your project and create a `src/server.js` file (or `src/server.ts` if you are using TypeScript). Add the following content to your file: - -```javascript -import { Hono } from "hono"; -const app = new Hono(); - -app.get("/", (ctx) => ctx.text("Hello world, this is Hono!!")); - -export default app; -``` - -To serve static files like CSS, image or JavaScript files, add the following to your `src/server.js/ts` file: - -```javascript -app.get("/public/*", async (ctx) => { - return await ctx.env.ASSETS.fetch(ctx.req.raw); -}); -``` - -This will cause all the files in the `public` folder within `dist` to be served in your application. - -:::note - -The `dist` directory is created and used during the bundling process. You will need to create a `public` directory in the `dist` directory. Having `public` inside `dist` is not generally wanted as `dist` is not a directory to commit to your repository whilst `public` is. - -There are different alternatives to fix this issue. For example, you can configure your `.gitignore` file to include the `dist` directory, but ignore all its context except the `public` directory. Alternatively, you can create a `public` directory somewhere else and copy it inside `dist` as part of the bundling process. - -::: - -Open your `package.json` file and update the `scripts` section: - - - -```json - "scripts": { - "dev": "run-p dev:*", - "dev:wrangler": "wrangler pages dev dist --live-reload", - "dev:esbuild": "esbuild --bundle src/server.js --format=esm --watch --outfile=dist/_worker.js", - "build": "esbuild --bundle src/server.js --format=esm --outfile=dist/_worker.js", - "deploy": "wrangler pages publish dist" - }, -``` - - - -```json - "scripts": { - "dev": "run-p dev:*", - "dev:wrangler": "wrangler pages dev dist --live-reload", - "dev:esbuild": "esbuild --bundle src/server.ts --format=esm --watch --outfile=dist/_worker.js", - "build": "esbuild --bundle src/server.ts --format=esm --outfile=dist/_worker.js", - "deploy": "wrangler pages publish dist" - }, -``` - - - -Then, run the following command. - -```sh -npm install npm-run-all --save-dev -``` - -Installing `npm-run-all` enables you to use a single command (`npm run dev`) to run `npm run dev:wrangler` and `npm run dev:esbuild` simultaneously in watch mode. +In your new Hono project, you will find a `public/static` directory for your static files, and a `src/index.ts` file which is the entrypoint for your server-side code. ## Run in local dev -Start your dev workflow by running: +Develop your app locally by running: -```sh -npm run dev -``` + You should be able to review your generated web application at `http://localhost:8788`. @@ -116,9 +51,7 @@ You should be able to review your generated web application at `http://localhost ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    @@ -161,4 +94,8 @@ For demo applications using Hono and Cloudflare Pages, refer to the following re ### Creator Interview - \ No newline at end of file + diff --git a/src/content/docs/pages/framework-guides/deploy-a-hugo-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-hugo-site.mdx index 845d7bbb607430..c85f68b1879aeb 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-hugo-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-hugo-site.mdx @@ -91,11 +91,7 @@ Inside of `hello-world.md`, add some initial content to create your post. Remove ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-jekyll-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-jekyll-site.mdx index 083a947ce7887b..bbcf5743dfd054 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-jekyll-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-jekyll-site.mdx @@ -62,11 +62,7 @@ If you are migrating an existing Jekyll project to Pages, confirm that your `Gem ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-nuxt-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-nuxt-site.mdx index cbe281566ed222..9bc44e0c203dde 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-nuxt-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-nuxt-site.mdx @@ -22,7 +22,11 @@ In this guide, you will create a new Nuxt application and deploy it using Cloudf ### Video Tutorial - + ## Create a new project using the `create-cloudflare` CLI (C3) @@ -74,12 +78,7 @@ git push -u origin main ### Create a Pages project -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Go to **Workers & Pages** > **Create application** > **Pages** > **Connect to Git** and create a new Pages project. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-pelican-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-pelican-site.mdx index a66b70e2733837..29eb7dd288221e 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-pelican-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-pelican-site.mdx @@ -35,11 +35,7 @@ This is the directory name that you will set in the build command. ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Pelican_ as your **Framework preset**. Your selection will provide the following information. The build command `pelican content` refers to the `content` folder you made earlier in this guide. + diff --git a/src/content/docs/pages/framework-guides/deploy-a-preact-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-preact-site.mdx index ed2208106b890b..2f6da012b8530f 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-preact-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-preact-site.mdx @@ -31,14 +31,7 @@ During initialization, you can accept the `Prerender app (SSG)?` option to have ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-qwik-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-qwik-site.mdx index 6f88615e4ea005..ded0f1d7b8ae6b 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-qwik-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-qwik-site.mdx @@ -41,9 +41,7 @@ npm start ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-remix-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-remix-site.mdx index b1e5bb50654052..edb38b4d42c982 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-remix-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-remix-site.mdx @@ -1,9 +1,15 @@ --- pcx_content_type: how-to title: Remix +tags: [Remix] --- -import { PagesBuildPreset, Render, PackageManagers, WranglerConfig } from "~/components"; +import { + PagesBuildPreset, + Render, + PackageManagers, + WranglerConfig, +} from "~/components"; [Remix](https://remix.run/) is a framework that is focused on fully utilizing the power of the web. Like Cloudflare Workers, it uses modern JavaScript APIs, and it places emphasis on web fundamentals such as meaningful HTTP status codes, caching and optimizing for both usability and performance. @@ -48,9 +54,7 @@ npm run dev ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-solid-start-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-solid-start-site.mdx index 2f611539af9561..050e41657c2359 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-solid-start-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-solid-start-site.mdx @@ -61,9 +61,7 @@ export default defineConfig({ ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in **Set up builds and deployments**, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-sphinx-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-sphinx-site.mdx index 52c19e14e17867..a40430c49e8e6d 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-sphinx-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-sphinx-site.mdx @@ -223,11 +223,7 @@ git push -u origin main ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-svelte-kit-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-svelte-kit-site.mdx index 0a9d76bd5f3162..c341e7dc9c0c9c 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-svelte-kit-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-svelte-kit-site.mdx @@ -119,12 +119,10 @@ If you are using any adapter different from the default SvelteKit adapter, remem ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this authorization to deploy your projects from your GitHub account. You may narrow Cloudflare's access to specific repositories. However, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -Select the new GitHub repository that you created and, in **Set up builds and deployments**, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-vitepress-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-vitepress-site.mdx index 10967dd7973e24..d3dfe1569e22af 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-vitepress-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-vitepress-site.mdx @@ -92,11 +92,10 @@ This step makes sure that unnecessary files are not going to be included in the ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, the following information will be provided: + diff --git a/src/content/docs/pages/framework-guides/deploy-a-vue-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-vue-site.mdx index b7508d284b0db3..c6f2601643ede3 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-vue-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-vue-site.mdx @@ -31,9 +31,7 @@ To use `create-cloudflare` to create a new Vue project, run the following comman ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-a-zola-site.mdx b/src/content/docs/pages/framework-guides/deploy-a-zola-site.mdx index 3e4dc33b4076d1..2e2a581537479e 100644 --- a/src/content/docs/pages/framework-guides/deploy-a-zola-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-a-zola-site.mdx @@ -76,11 +76,7 @@ Upon running `zola init`, you will prompted with three questions: ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-analog-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-analog-site.mdx index 25fc4ed6864429..c6b6e09f75f06c 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-analog-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-analog-site.mdx @@ -144,12 +144,7 @@ git push -u origin main ### Create a Pages project -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Go to **Workers & Pages** > **Create application** > **Pages** > **Connect to Git** and create a new Pages project. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-angular-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-angular-site.mdx index 7a4569156bbc9a..9ba9f43070e6c7 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-angular-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-angular-site.mdx @@ -49,12 +49,7 @@ git push -u origin main ### Create a Pages project -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Go to **Workers & Pages** > **Create application** > **Pages** > **Connect to Git** and create a new Pages project. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-astro-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-astro-site.mdx index 7cf3f113c1b777..cd5f6eb0101734 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-astro-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-astro-site.mdx @@ -3,7 +3,12 @@ pcx_content_type: how-to title: Astro --- -import { PagesBuildPreset, Render, PackageManagers, Stream } from "~/components"; +import { + PagesBuildPreset, + Render, + PackageManagers, + Stream, +} from "~/components"; [Astro](https://astro.build) is an all-in-one web framework for building fast, content-focused websites. By default, Astro builds websites that have zero JavaScript runtime code. @@ -13,7 +18,11 @@ In this guide, you will create a new Astro application and deploy it using Cloud ### Video Tutorial - + ## Set up a new project @@ -55,12 +64,7 @@ npm run astro add cloudflare ### Deploy via the Cloudflare dashboard -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    diff --git a/src/content/docs/pages/framework-guides/deploy-an-elderjs-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-elderjs-site.mdx index 3d18cee45911eb..8d573a75021ee6 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-elderjs-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-elderjs-site.mdx @@ -26,14 +26,10 @@ The Elder.js template includes a number of pages and examples showing how to bui ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. - -You will be asked to authorize access to your GitHub account if you have not already done so. Cloudflare needs this so that it can monitor and deploy your projects from the source. You may narrow access to specific repositories if you prefer; however, you will have to manually update this list [within your GitHub settings](https://github.com/settings/installations) when you want to add more repositories to Cloudflare Pages. - -Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-eleventy-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-eleventy-site.mdx index da20b0c4f1abc2..5244c9227c668a 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-eleventy-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-eleventy-site.mdx @@ -39,11 +39,10 @@ git push -u origin main ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Eleventy_ as your **Framework preset**. Your selection will provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-emberjs-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-emberjs-site.mdx index 7eb8e3933ab7ce..eb1cedfc801402 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-emberjs-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-emberjs-site.mdx @@ -36,11 +36,10 @@ npm start ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Ember_ as your **Framework preset**. Your selection will provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-an-mkdocs-site.mdx b/src/content/docs/pages/framework-guides/deploy-an-mkdocs-site.mdx index 232e9fe2888564..36744cb08bbbae 100644 --- a/src/content/docs/pages/framework-guides/deploy-an-mkdocs-site.mdx +++ b/src/content/docs/pages/framework-guides/deploy-an-mkdocs-site.mdx @@ -37,11 +37,7 @@ You have successfully created a GitHub repository and pushed your MkDocs project ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _MkDocs_ as your **Framework preset**. Your selection will provide the following information: + diff --git a/src/content/docs/pages/framework-guides/deploy-anything.mdx b/src/content/docs/pages/framework-guides/deploy-anything.mdx index b11efe58e6bff5..628610031fd58e 100644 --- a/src/content/docs/pages/framework-guides/deploy-anything.mdx +++ b/src/content/docs/pages/framework-guides/deploy-anything.mdx @@ -1,10 +1,9 @@ --- pcx_content_type: how-to title: Static HTML - --- -import { Details, Render } from "~/components" +import { Details, Render } from "~/components"; Cloudflare supports deploying any static HTML website to Cloudflare Pages. If you manage your website without using a framework or static site generator, or if your framework is not listed in [Framework guides](/pages/framework-guides/), you can still deploy it using this guide. @@ -14,11 +13,7 @@ Cloudflare supports deploying any static HTML website to Cloudflare Pages. If yo ## Deploy with Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, provide the following information: +
    @@ -36,20 +31,16 @@ After configuring your site, you can begin your first deploy. Your custom build :::note - For the complete guide to deploying your first site to Cloudflare Pages, refer to the [Get started guide](/pages/get-started/). - ::: After you have deployed your site, you will receive a unique subdomain for your project on `*.pages.dev`. Cloudflare Pages will automatically rebuild your project and deploy it. You will also get access to [preview deployments](/pages/configuration/preview-deployments/) on new pull requests, so you can preview how changes look to your site before deploying them to production. -
    If you are getting `404` errors when visiting your `*.pages.dev` domain, make sure your website has a top-level file for `index.html`. This `index.html` is what Pages will serve on your apex with no page specified. -
    diff --git a/src/content/docs/pages/framework-guides/nextjs/deploy-a-static-nextjs-site.mdx b/src/content/docs/pages/framework-guides/nextjs/deploy-a-static-nextjs-site.mdx index 745d997be8bf3c..88f0742bb6b5c3 100644 --- a/src/content/docs/pages/framework-guides/nextjs/deploy-a-static-nextjs-site.mdx +++ b/src/content/docs/pages/framework-guides/nextjs/deploy-a-static-nextjs-site.mdx @@ -49,11 +49,10 @@ git push -u origin main ### Deploy your application to Cloudflare Pages -To deploy your site to Pages: - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. In Account Home, select **Workers & Pages** > **Create application** > **Pages** > **Connect to Git**. -3. Select the new GitHub repository that you created and, in the **Set up builds and deployments** section, select _Next.js (Static HTML Export)_ as your **Framework preset**. Your selection will provide the following information. + diff --git a/src/content/docs/pages/framework-guides/nextjs/index.mdx b/src/content/docs/pages/framework-guides/nextjs/index.mdx index f677f8ddab5c66..f58b5879d18995 100644 --- a/src/content/docs/pages/framework-guides/nextjs/index.mdx +++ b/src/content/docs/pages/framework-guides/nextjs/index.mdx @@ -13,6 +13,6 @@ import { DirectoryListing, Stream } from "~/components" ### Video Tutorial - + \ No newline at end of file diff --git a/src/content/docs/pages/functions/bindings.mdx b/src/content/docs/pages/functions/bindings.mdx index d7f5cf5272ea13..b613d9c59ced87 100644 --- a/src/content/docs/pages/functions/bindings.mdx +++ b/src/content/docs/pages/functions/bindings.mdx @@ -836,10 +836,5 @@ To add secrets to your Pages project: You use secrets the same way as environment variables. When setting secrets with Wrangler or in the Cloudflare dashboard, it needs to be done before a deployment that uses those secrets. For more guidance, refer to [Environment variables](#environment-variables). -### Interact with your secrets locally - -When developing locally, add secrets by creating a `.dev.vars` file in the root directory of your Pages project. Then add the following code snippet to `.dev.vars`: - -``` -SECRET_NAME= -``` \ No newline at end of file +### Local development with secrets + \ No newline at end of file diff --git a/src/content/docs/pages/functions/examples/ab-testing.mdx b/src/content/docs/pages/functions/examples/ab-testing.mdx index 6b4e35e19b8ece..9d50f8c3910fc5 100644 --- a/src/content/docs/pages/functions/examples/ab-testing.mdx +++ b/src/content/docs/pages/functions/examples/ab-testing.mdx @@ -3,8 +3,6 @@ type: example summary: Set up an A/B test by controlling what page is served based on cookies. This version supports passing the request through to test and control on the origin. -tags: - - Originless pcx_content_type: configuration title: A/B testing with middleware sidebar: @@ -12,42 +10,41 @@ sidebar: description: Set up an A/B test by controlling what page is served based on cookies. This version supports passing the request through to test and control on the origin. - --- ```js -const cookieName = "ab-test-cookie" -const newHomepagePathName = "/test" +const cookieName = "ab-test-cookie"; +const newHomepagePathName = "/test"; const abTest = async (context) => { - const url = new URL(context.request.url) - // if homepage - if (url.pathname === "/") { - // if cookie ab-test-cookie=new then change the request to go to /test - // if no cookie set, pass x% of traffic and set a cookie value to "current" or "new" + const url = new URL(context.request.url); + // if homepage + if (url.pathname === "/") { + // if cookie ab-test-cookie=new then change the request to go to /test + // if no cookie set, pass x% of traffic and set a cookie value to "current" or "new" - let cookie = request.headers.get("cookie") - // is cookie set? - if (cookie && cookie.includes(`${cookieName}=new`)) { - // pass the request to /test - url.pathname = newHomepagePathName - return context.env.ASSETS.fetch(url) - } else { - const percentage = Math.floor(Math.random() * 100) - let version = "current" // default version - // change pathname and version name for 50% of traffic - if (percentage < 50) { - url.pathname = newHomepagePathName - version = "new" - } - // get the static file from ASSETS, and attach a cookie - const asset = await context.env.ASSETS.fetch(url) - let response = new Response(asset.body, asset) - response.headers.append("Set-Cookie", `${cookieName}=${version}; path=/`) - return response - } - } - return context.next() + let cookie = request.headers.get("cookie"); + // is cookie set? + if (cookie && cookie.includes(`${cookieName}=new`)) { + // pass the request to /test + url.pathname = newHomepagePathName; + return context.env.ASSETS.fetch(url); + } else { + const percentage = Math.floor(Math.random() * 100); + let version = "current"; // default version + // change pathname and version name for 50% of traffic + if (percentage < 50) { + url.pathname = newHomepagePathName; + version = "new"; + } + // get the static file from ASSETS, and attach a cookie + const asset = await context.env.ASSETS.fetch(url); + let response = new Response(asset.body, asset); + response.headers.append("Set-Cookie", `${cookieName}=${version}; path=/`); + return response; + } + } + return context.next(); }; export const onRequest = [abTest]; diff --git a/src/content/docs/pages/functions/examples/cors-headers.mdx b/src/content/docs/pages/functions/examples/cors-headers.mdx index 94fc04159c2e65..3e1e9656bbe0f3 100644 --- a/src/content/docs/pages/functions/examples/cors-headers.mdx +++ b/src/content/docs/pages/functions/examples/cors-headers.mdx @@ -2,13 +2,12 @@ type: example summary: A Pages Functions for appending CORS headers. tags: - - CORS + - Headers pcx_content_type: configuration title: Adding CORS headers sidebar: order: 1002 description: A Pages Functions for appending CORS headers. - --- This example is a snippet from our Cloudflare Pages Template repo. @@ -16,23 +15,22 @@ This example is a snippet from our Cloudflare Pages Template repo. ```ts // Respond to OPTIONS method export const onRequestOptions: PagesFunction = async () => { - return new Response(null, { - status: 204, - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': '*', - 'Access-Control-Allow-Methods': 'GET, OPTIONS', - 'Access-Control-Max-Age': '86400', - }, - }); + return new Response(null, { + status: 204, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": "*", + "Access-Control-Allow-Methods": "GET, OPTIONS", + "Access-Control-Max-Age": "86400", + }, + }); }; // Set CORS to all /api responses export const onRequest: PagesFunction = async (context) => { - const response = await context.next(); - response.headers.set('Access-Control-Allow-Origin', '*'); - response.headers.set('Access-Control-Max-Age', '86400'); - return response; + const response = await context.next(); + response.headers.set("Access-Control-Allow-Origin", "*"); + response.headers.set("Access-Control-Max-Age", "86400"); + return response; }; - ``` diff --git a/src/content/docs/pages/functions/routing.mdx b/src/content/docs/pages/functions/routing.mdx index 2abd89390a2a7f..10d11040e07622 100644 --- a/src/content/docs/pages/functions/routing.mdx +++ b/src/content/docs/pages/functions/routing.mdx @@ -100,7 +100,7 @@ The following requests will match the following files: | /users/special | /users/special.js | | /users/daniel/xyz/123 | /users/\[\[catchall]].js | -The URL segment(s) that match the placeholder (`[user]`) will be available in the request [`context`](/pages/functions/api-reference/#eventcontext) object. The [`context.params`](/pages/functions/api-reference/#params) object can be used to find the matched value for a given filename placeholder. +The URL segment(s) that match the placeholder (`[user]`) will be available in the request [`context`](/pages/functions/api-reference/#eventcontext) object. The [`context.params`](/pages/functions/api-reference/#eventcontext) object can be used to find the matched value for a given filename placeholder. For files which match a single URL segment (use a single set of brackets), the values are returned as a string: diff --git a/src/content/docs/pages/functions/typescript.mdx b/src/content/docs/pages/functions/typescript.mdx index d5fbcd9feedaa8..e6e3f0016883db 100644 --- a/src/content/docs/pages/functions/typescript.mdx +++ b/src/content/docs/pages/functions/typescript.mdx @@ -5,15 +5,19 @@ sidebar: order: 8 --- +import { PackageManagers, Render } from "~/components"; + Pages Functions supports TypeScript. Author any files in your `/functions` directory with a `.ts` extension instead of a `.js` extension to start using TypeScript. -To add the runtime types to your project, run: +You can add runtime types and Env types by running: -```sh -npm install --save-dev typescript @cloudflare/workers-types -``` + -Then configure the runtime types by creating a `functions/tsconfig.json` file: +Then configure the types by creating a `functions/tsconfig.json` file: ```json { @@ -21,11 +25,13 @@ Then configure the runtime types by creating a `functions/tsconfig.json` file: "target": "esnext", "module": "esnext", "lib": ["esnext"], - "types": ["@cloudflare/workers-types"] + "types": ["./types.d.ts"] } } ``` +See [the `wrangler types` command docs](/workers/wrangler/commands/#types) for more details. + If you already have a `tsconfig.json` at the root of your project, you may wish to explicitly exclude the `/functions` directory to avoid conflicts. To exclude the `/functions` directory: ```json @@ -36,7 +42,9 @@ If you already have a `tsconfig.json` at the root of your project, you may wish } ``` -Pages Functions can be typed using the `PagesFunction` type. This type accepts an `Env` parameter. To use the `env` parameter: +Pages Functions can be typed using the `PagesFunction` type. This type accepts an `Env` parameter. The `Env` type should have been generated by `wrangler types` and can be found at the top of `types.d.ts`. + +Alternatively, you can define the `Env` type manually. For example: ```ts interface Env { @@ -48,3 +56,22 @@ export const onRequest: PagesFunction = async (context) => { return new Response(value); }; ``` + +If you are using `nodejs_compat`, make sure you have installed `@types/node` and updated your `tsconfig.json`. + +```json +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["esnext"], + "types": ["./types.d.ts", "node"] + } +} +``` + +:::note + +If you were previously using `@cloudflare/workers-types` instead of the runtime types generated by `wrangler types`, you can refer to this [migration guide](/workers/languages/typescript/#migrating). + +::: diff --git a/src/content/docs/pages/get-started/c3.mdx b/src/content/docs/pages/get-started/c3.mdx index 3ea45948dbf00b..1248584c6417d1 100644 --- a/src/content/docs/pages/get-started/c3.mdx +++ b/src/content/docs/pages/get-started/c3.mdx @@ -105,7 +105,7 @@ pnpm create cloudflare@latest [--] [] [OPTIONS] [-- ] - The possible values for this option are: - - `hello-world`: Hello World example + - `hello-world`: Hello World Starter - `web-framework`: Framework Starter - `demo`: Application Starter - `remote-template`: Template from a GitHub repo diff --git a/src/content/docs/pages/get-started/index.mdx b/src/content/docs/pages/get-started/index.mdx index 9704d45fd50804..fe8a6c2163095a 100644 --- a/src/content/docs/pages/get-started/index.mdx +++ b/src/content/docs/pages/get-started/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: navigation -title: Get started +title: Getting started sidebar: order: 2 diff --git a/src/content/docs/pages/how-to/deploy-a-wordpress-site.mdx b/src/content/docs/pages/how-to/deploy-a-wordpress-site.mdx index 92aed7b8f6ebb3..c993a1d99679cb 100644 --- a/src/content/docs/pages/how-to/deploy-a-wordpress-site.mdx +++ b/src/content/docs/pages/how-to/deploy-a-wordpress-site.mdx @@ -1,7 +1,6 @@ --- updated: 2023-04-01 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Deploy a static WordPress site tags: diff --git a/src/content/docs/pages/how-to/preview-with-cloudflare-tunnel.mdx b/src/content/docs/pages/how-to/preview-with-cloudflare-tunnel.mdx index 20b4f1714fde14..eabee3222e986b 100644 --- a/src/content/docs/pages/how-to/preview-with-cloudflare-tunnel.mdx +++ b/src/content/docs/pages/how-to/preview-with-cloudflare-tunnel.mdx @@ -56,6 +56,6 @@ In this example, the randomly-generated URL `https://seasonal-deck-organisms-sf. ## Next Steps -Cloudflare Tunnel can be configured in a variety of ways and can be used beyond providing access to your in-development applications. For example, you can provide `cloudflared` with a [configuration file](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/) to add more complex routing and tunnel setups that go beyond a simple `--url` flag. You can also [attach a Cloudflare DNS record](/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns/) to a domain or subdomain for an easily accessible, long-lived tunnel to your local machine. +Cloudflare Tunnel can be configured in a variety of ways and can be used beyond providing access to your in-development applications. For example, you can provide `cloudflared` with a [configuration file](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/) to add more complex routing and tunnel setups that go beyond a simple `--url` flag. You can also [attach a Cloudflare DNS record](/cloudflare-one/connections/connect-networks/routing-to-tunnel/dns/) to a domain or subdomain for an easily accessible, long-lived tunnel to your local machine. Finally, by incorporating Cloudflare Access, you can provide [secure access to your tunnels](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) without exposing your entire server, or compromising on security. Refer to the [Cloudflare for Teams documentation](/cloudflare-one/) to learn more about what you can do with Cloudflare's entire suite of Zero Trust tools. diff --git a/src/content/docs/pages/how-to/use-direct-upload-with-continuous-integration.mdx b/src/content/docs/pages/how-to/use-direct-upload-with-continuous-integration.mdx index 09e295f54437a7..e2333e4d0daa5a 100644 --- a/src/content/docs/pages/how-to/use-direct-upload-with-continuous-integration.mdx +++ b/src/content/docs/pages/how-to/use-direct-upload-with-continuous-integration.mdx @@ -189,6 +189,6 @@ env: - CLOUDFLARE_API_TOKEN: { $CLOUDFLARE_API_TOKEN } ``` -In the code block above you have specified the language as `node_js` and listed the value as `18.0.0` because Wrangler v2 depends on this Node version or higher. You have also set branches you want your continuous integration to run on. Finally, input your `PROJECT NAME` in the script section and your CI process should work as expected. +This will set the Node.js version to 18. You have also set branches you want your continuous integration to run on. Finally, input your `PROJECT NAME` in the script section and your CI process should work as expected. You can also modify the Wrangler command with any [`wrangler pages deploy` options](/workers/wrangler/commands/#deploy-1). diff --git a/src/content/docs/pages/index.mdx b/src/content/docs/pages/index.mdx index cddc8e9221aa6b..6555d68a21971a 100644 --- a/src/content/docs/pages/index.mdx +++ b/src/content/docs/pages/index.mdx @@ -1,13 +1,12 @@ --- -title: Overview +title: Cloudflare Pages type: overview pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Pages documentation - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, Render } from "~/components" diff --git a/src/content/docs/pages/migrations/migrating-from-firebase.mdx b/src/content/docs/pages/migrations/migrating-from-firebase.mdx index 4b6b91bacb7cf3..1459f28382f5b2 100644 --- a/src/content/docs/pages/migrations/migrating-from-firebase.mdx +++ b/src/content/docs/pages/migrations/migrating-from-firebase.mdx @@ -3,9 +3,6 @@ updated: 2020-09-28 difficulty: Beginner pcx_content_type: tutorial title: Migrating from Firebase -tags: - - Firebase - --- In this tutorial, you will learn how to migrate an existing Firebase application to Cloudflare Pages. You should already have an existing project deployed on Firebase that you would like to host on Cloudflare Pages. @@ -18,7 +15,7 @@ You will use these to tell Cloudflare Pages how to deploy your project. If you h ```json title="firebase.json" { - "public": "public" + "public": "public" } ``` diff --git a/src/content/docs/pages/migrations/migrating-jekyll-from-github-pages.mdx b/src/content/docs/pages/migrations/migrating-jekyll-from-github-pages.mdx index 9b25d5811d93e5..a0e1b5ec7ef1b1 100644 --- a/src/content/docs/pages/migrations/migrating-jekyll-from-github-pages.mdx +++ b/src/content/docs/pages/migrations/migrating-jekyll-from-github-pages.mdx @@ -3,8 +3,6 @@ updated: 2021-07-27 difficulty: Beginner pcx_content_type: tutorial title: Migrating a Jekyll-based site from GitHub Pages -tags: - - Jekyll languages: - Ruby --- @@ -49,7 +47,7 @@ Your existing Jekyll-based repository must specify a `Gemfile` (Ruby's dependenc Specifically, you will need to create a `Gemfile` and install the `github-pages` gem, which includes all of the dependencies that the GitHub Pages environment assumes. -[Version 2 of the Pages build environment](/pages/configuration/build-image/#languages-and-runtime) will use Ruby 3.2.2 for the default Jekyll build. Please make sure your local development environment is compatible. +[Version 2 of the Pages build environment](/pages/configuration/build-image/#languages-and-runtime) will use Ruby 3.2.2 for the default Jekyll build. Please make sure your local development environment is compatible. ```sh title="Set Ruby Version" brew install ruby@3.2 diff --git a/src/content/docs/pages/tutorials/add-a-react-form-with-formspree/index.mdx b/src/content/docs/pages/tutorials/add-a-react-form-with-formspree/index.mdx index 974fbce8f286ad..09fc44ac23eb68 100644 --- a/src/content/docs/pages/tutorials/add-a-react-form-with-formspree/index.mdx +++ b/src/content/docs/pages/tutorials/add-a-react-form-with-formspree/index.mdx @@ -1,7 +1,6 @@ --- updated: 2021-11-30 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Add a React form with Formspree tags: diff --git a/src/content/docs/pages/tutorials/add-an-html-form-with-formspree/index.mdx b/src/content/docs/pages/tutorials/add-an-html-form-with-formspree/index.mdx index 1f9b625513096a..4ce8678c82f1cd 100644 --- a/src/content/docs/pages/tutorials/add-an-html-form-with-formspree/index.mdx +++ b/src/content/docs/pages/tutorials/add-an-html-form-with-formspree/index.mdx @@ -1,7 +1,6 @@ --- updated: 2021-11-30 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Add an HTML form with Formspree tags: diff --git a/src/content/docs/pages/tutorials/build-a-blog-using-nuxt-and-sanity/index.mdx b/src/content/docs/pages/tutorials/build-a-blog-using-nuxt-and-sanity/index.mdx index 15861a6439c976..7f7e38f5e9debb 100644 --- a/src/content/docs/pages/tutorials/build-a-blog-using-nuxt-and-sanity/index.mdx +++ b/src/content/docs/pages/tutorials/build-a-blog-using-nuxt-and-sanity/index.mdx @@ -1,7 +1,6 @@ --- updated: 2022-08-03 pcx_content_type: tutorial -content_type: 📝 Tutorial difficulty: Intermediate title: Build a blog using Nuxt.js and Sanity.io on Cloudflare Pages tags: @@ -355,8 +354,8 @@ In `pages/index.vue`, you can use the `block-content` component to render a summ ``` There are many other things inside of your blog schema that you can add to your project. As an exercise, consider one of the following to continue developing your understanding of how to build with a headless CMS: diff --git a/src/content/docs/pages/tutorials/build-an-api-with-pages-functions/index.mdx b/src/content/docs/pages/tutorials/build-an-api-with-pages-functions/index.mdx index 5570df7f4cf81d..8cdbbd39b61f0c 100644 --- a/src/content/docs/pages/tutorials/build-an-api-with-pages-functions/index.mdx +++ b/src/content/docs/pages/tutorials/build-an-api-with-pages-functions/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-10-01 pcx_content_type: tutorial -content_type: 🎥 Video difficulty: Intermediate title: Build an API for your front end using Pages Functions languages: @@ -20,9 +19,9 @@ If you prefer to work with a headless CMS rather than an API to render your blog ## Video Tutorial ## 1. Build your front end @@ -36,7 +35,8 @@ In your terminal, create a new React project called `blog-frontend` using the `c ```sh title="Create a new React application" npx create-vite -t react blog-frontend cd blog-frontend -npm start +npm install +npm run dev ``` ### Set up your React project diff --git a/src/content/docs/pages/tutorials/forms/index.mdx b/src/content/docs/pages/tutorials/forms/index.mdx index 49ca188ff606a4..578f5099807d18 100644 --- a/src/content/docs/pages/tutorials/forms/index.mdx +++ b/src/content/docs/pages/tutorials/forms/index.mdx @@ -1,7 +1,6 @@ --- updated: 2022-07-28 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Create a HTML form tags: diff --git a/src/content/docs/pages/tutorials/localize-a-website/index.mdx b/src/content/docs/pages/tutorials/localize-a-website/index.mdx index ea94ce012754cf..d1bca547576dac 100644 --- a/src/content/docs/pages/tutorials/localize-a-website/index.mdx +++ b/src/content/docs/pages/tutorials/localize-a-website/index.mdx @@ -1,13 +1,10 @@ --- updated: 2024-05-06 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Localize a website with HTMLRewriter languages: - JavaScript -tags: - - HTMLRewriter --- import { Render, PackageManagers, WranglerConfig } from "~/components"; diff --git a/src/content/docs/pages/tutorials/use-r2-as-static-asset-storage-for-pages/index.mdx b/src/content/docs/pages/tutorials/use-r2-as-static-asset-storage-for-pages/index.mdx index 61a67cd2aa23a2..00e2e93f40d6f1 100644 --- a/src/content/docs/pages/tutorials/use-r2-as-static-asset-storage-for-pages/index.mdx +++ b/src/content/docs/pages/tutorials/use-r2-as-static-asset-storage-for-pages/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-07-22 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Use R2 as static asset storage with Cloudflare Pages products: diff --git a/src/content/docs/privacy-gateway/index.mdx b/src/content/docs/privacy-gateway/index.mdx index 10cf2116f6793d..a94df8f16836ba 100644 --- a/src/content/docs/privacy-gateway/index.mdx +++ b/src/content/docs/privacy-gateway/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare Privacy Gateway pcx_content_type: overview sidebar: order: 1 @@ -7,8 +7,7 @@ sidebar: text: Beta head: - tag: title - content: Cloudflare Privacy Gateway - + content: Overview --- import { Description, Feature, Plan } from "~/components" diff --git a/src/content/docs/pub-sub/index.mdx b/src/content/docs/pub-sub/index.mdx index 43e6dfa1c6325d..46f39ecd0b5935 100644 --- a/src/content/docs/pub-sub/index.mdx +++ b/src/content/docs/pub-sub/index.mdx @@ -1,9 +1,12 @@ --- -title: Overview +title: Pub/Sub pcx_content_type: overview sidebar: badge: text: Beta +head: + - tag: title + content: Overview --- :::note diff --git a/src/content/docs/pulumi/index.mdx b/src/content/docs/pulumi/index.mdx index b1c87eb6dc8a83..06b89dfaf9dfe3 100644 --- a/src/content/docs/pulumi/index.mdx +++ b/src/content/docs/pulumi/index.mdx @@ -1,9 +1,11 @@ --- -title: Overview +title: Pulumi pcx_content_type: overview sidebar: order: 1 - +head: + - tag: title + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, RelatedProduct } from "~/components" @@ -23,11 +25,11 @@ Provision and manage Cloudflare using infrastructure as code through [Pulumi](ht ## Features -[Pulumi](https://github.com/pulumi/pulumi) is open source and uses the Apache 2.0 license. +[Pulumi](https://github.com/pulumi/pulumi) is open source and uses the Apache 2.0 license. -Use TypeScript, JavaScript, Python, Go, .Net, Java, or YAML to write Pulumi programs. Each language is as capable as the other and supports the entire [Pulumi Registry](https://www.pulumi.com/registry/). +Use TypeScript, JavaScript, Python, Go, .Net, Java, or YAML to write Pulumi programs. Each language is as capable as the other and supports the entire [Pulumi Registry](https://www.pulumi.com/registry/). *** @@ -35,15 +37,15 @@ Use TypeScript, JavaScript, Python, Go, .Net, Java, or YAML to write Pulumi prog ## Related products -Pulumi Cloud fully manages infrastructure state and secrets, provides rich search capabilities, and more. +Pulumi Cloud fully manages infrastructure state and secrets, provides rich search capabilities, and more. -Pulumi AI is an experimental feature that lets you use natural-language prompts to generate Pulumi infrastructure-as-code programs in any language. +Pulumi AI is an experimental feature that lets you use natural-language prompts to generate Pulumi infrastructure-as-code programs in any language. - -Pulumi ESC provides centralized management of environments, secrets, and configurations. + +Pulumi ESC provides centralized management of environments, secrets, and configurations. *** @@ -54,12 +56,12 @@ Pulumi ESC provides centralized management of environments, secrets, and configu -To learn more about Pulumi. +To learn more about Pulumi. -Report Pulumi configuration issues via GitHub. +Report Pulumi configuration issues via GitHub. diff --git a/src/content/docs/queues/configuration/consumer-concurrency.mdx b/src/content/docs/queues/configuration/consumer-concurrency.mdx index 8e8a7f3294caab..9868fc9647307a 100644 --- a/src/content/docs/queues/configuration/consumer-concurrency.mdx +++ b/src/content/docs/queues/configuration/consumer-concurrency.mdx @@ -121,7 +121,7 @@ When multiple consumer Workers are invoked, each Worker invocation incurs [CPU t - If you intend to process all messages written to a queue, _the effective overall cost is the same_, even with concurrency enabled. - Enabling concurrency simply brings those costs forward, and can help prevent messages from reaching the [message retention limit](/queues/platform/limits/). -Billing for consumers follows the [Workers standard usage model](/workers/platform/pricing/#example-pricing-standard-usage-model) meaning a developer is billed for the request and for CPU time used in the request. +Billing for consumers follows the [Workers standard usage model](/workers/platform/pricing/#example-pricing) meaning a developer is billed for the request and for CPU time used in the request. ### Example diff --git a/src/content/docs/queues/configuration/pause-purge.mdx b/src/content/docs/queues/configuration/pause-purge.mdx new file mode 100644 index 00000000000000..42f5a25bc181e6 --- /dev/null +++ b/src/content/docs/queues/configuration/pause-purge.mdx @@ -0,0 +1,58 @@ +--- +title: Pause and Purge +pcx_content_type: concept +sidebar: + order: 2 +--- +import { WranglerConfig, Type, MetaInfo } from "~/components"; + +## Pause Delivery + +You can pause delivery of messages from your queue to any connected consumers. Pausing a queue is useful when managing downtime (for example, if your consumer Worker is unhealthy) without losing any messages. + +Queues continue to receive and store messages even while delivery is paused. Messages in a paused queue are still subject to expiry, if the messages become older than the queue message retention period. + +Pausing affects both [push-based consumer Workers](/queues/reference/how-queues-works#consumers) and [pull based consumers](/queues/configuration/pull-consumers). + +### Pause and resume delivery using Wrangler + +The following command will pause message delivery from your queue: + +```sh +$ npx run wrangler queues pause-delivery +``` + +- `queue-name` + - The name of the queue for which delivery should be paused. + +The following command will resume message delivery: + +```sh +$ npx run wrangler queues resume-delivery +``` + +- `queue-name` + - The name of the queue for which delivery should be resumed. + +### What happens to HTTP Pull consumers with a paused queue? +When a queue is paused, messages cannot be pulled by an [HTTP pull based consumer](/queues/configuration/pull-consumers). Requests to pull messages will receive a `409` response, along with an error message stating `queue_delivery_paused`. + +## Purge queue +Purging a queue permanently deletes any messages currently stored in the Queue. Purging is useful while developing a new application, especially to clear out any test data. It can also be useful in production to handle scenarios when a batch of bad messages have been sent to a Queue. + +Note that any in flight messages, which are currently being processed by consumers, might still be processed. Messages sent to a queue during a purge operation might not be purged. Any delayed messages will also be deleted from the queue. + +:::caution +Purging a queue is an irreversible operation. Make sure to use this operation carefully. +::: + +### Purge queue using Wrangler +The following command will purge messages from your queue. You will be prompted to enter the queue name to confirm the operation. +```sh +$ npx run wrangler queues purge + +This operation will permanently delete all the messages in Queue . Type to proceed. +``` + +### Does purging a Queue affect my bill? +Purging a queue counts as a single billable operation, regardless of how many messages are deleted. For example, if you purge a queue which has 100 messages, all 100 messages will be permanently deleted, and you will be billed for 1 billable operation. Refer to the [pricing](/queues/platform/pricing) page for more information about how Queues is billed. diff --git a/src/content/docs/queues/get-started.mdx b/src/content/docs/queues/get-started.mdx index d632a1895a1e14..3d0ef4d6e43247 100644 --- a/src/content/docs/queues/get-started.mdx +++ b/src/content/docs/queues/get-started.mdx @@ -1,11 +1,11 @@ --- -title: Get started +title: Getting started pcx_content_type: get-started sidebar: order: 2 head: - tag: title - content: Get started + content: Getting started --- import { Render, PackageManagers, WranglerConfig } from "~/components"; @@ -35,7 +35,7 @@ To create a producer Worker, run: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -188,8 +188,6 @@ Each queue can only have one consumer Worker connected to it. If you try to conn To connect your queue to your consumer Worker, open your Wrangler file and add this to the bottom: - - ```toml diff --git a/src/content/docs/queues/index.mdx b/src/content/docs/queues/index.mdx index 15519b6ff62c6f..89088438f2aa9d 100644 --- a/src/content/docs/queues/index.mdx +++ b/src/content/docs/queues/index.mdx @@ -1,13 +1,12 @@ --- -title: Overview +title: Cloudflare Queues type: overview pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Queues - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/queues/observability/index.mdx b/src/content/docs/queues/observability/index.mdx index 1b2796e8c4c883..38d228aa7776e3 100644 --- a/src/content/docs/queues/observability/index.mdx +++ b/src/content/docs/queues/observability/index.mdx @@ -3,6 +3,8 @@ title: Observability pcx_content_type: navigation sidebar: order: 4 + group: + hideIndex: true --- diff --git a/src/content/docs/queues/platform/index.mdx b/src/content/docs/queues/platform/index.mdx index a6302f438ce0ba..22b7b68f3bffa0 100644 --- a/src/content/docs/queues/platform/index.mdx +++ b/src/content/docs/queues/platform/index.mdx @@ -3,6 +3,8 @@ title: Platform pcx_content_type: navigation sidebar: order: 7 + group: + hideIndex: true --- diff --git a/src/content/docs/queues/reference/index.mdx b/src/content/docs/queues/reference/index.mdx index fe7986e68faf8b..b9579b8b6281fe 100644 --- a/src/content/docs/queues/reference/index.mdx +++ b/src/content/docs/queues/reference/index.mdx @@ -3,6 +3,8 @@ title: Reference pcx_content_type: navigation sidebar: order: 8 + group: + hideIndex: true --- diff --git a/src/content/docs/queues/tutorials/handle-rate-limits/index.mdx b/src/content/docs/queues/tutorials/handle-rate-limits/index.mdx index 56a620c0323f2b..c3a3be035377f5 100644 --- a/src/content/docs/queues/tutorials/handle-rate-limits/index.mdx +++ b/src/content/docs/queues/tutorials/handle-rate-limits/index.mdx @@ -3,7 +3,6 @@ updated: 2024-09-25 difficulty: Beginner title: Handle rate limits of external APIs summary: Example of how to use Queues to handle rate limits of external APIs. -content_type: 📝 Tutorial pcx_content_type: tutorial products: - Workers @@ -49,7 +48,7 @@ To get started, create a Worker application using the [`create-cloudflare` CLI]( product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -97,8 +96,6 @@ It is important to include the `max_batch_size` of two to the consumer queue is Your final Wrangler file should look similar to the example below. - - ```toml title="wrangler.toml" diff --git a/src/content/docs/queues/tutorials/web-crawler-with-browser-rendering/index.mdx b/src/content/docs/queues/tutorials/web-crawler-with-browser-rendering/index.mdx index a58457d74210f6..9e8711dead7701 100644 --- a/src/content/docs/queues/tutorials/web-crawler-with-browser-rendering/index.mdx +++ b/src/content/docs/queues/tutorials/web-crawler-with-browser-rendering/index.mdx @@ -3,7 +3,6 @@ updated: 2024-08-06 difficulty: Intermediate title: Build a web crawler with Queues and Browser Rendering summary: Example of how to use Queues and Browser Rendering to power a web crawler. -content_type: 📝 Tutorial pcx_content_type: tutorial products: - Workers @@ -46,7 +45,7 @@ To get started, create a Worker application using the [`create-cloudflare` CLI]( product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -110,8 +109,6 @@ npm install robots-parser Then, add a Browser Rendering binding. Adding a Browser Rendering binding gives the Worker access to a headless Chromium instance you will control with Puppeteer. - - ```toml @@ -137,8 +134,6 @@ Created queue queues-web-crawler. Then, in your Wrangler file, add the following: - - ```toml @@ -157,8 +152,6 @@ Adding the `max_batch_timeout` of 60 seconds to the consumer queue is important Your final Wrangler file should look similar to the one below. - - ```toml diff --git a/src/content/docs/r2/api/workers/workers-api-usage.mdx b/src/content/docs/r2/api/workers/workers-api-usage.mdx index 2c40d0b32a88f7..f6f78e0d143d42 100644 --- a/src/content/docs/r2/api/workers/workers-api-usage.mdx +++ b/src/content/docs/r2/api/workers/workers-api-usage.mdx @@ -23,7 +23,7 @@ To get started, open a terminal window and run: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/r2/buckets/bucket-locks.mdx b/src/content/docs/r2/buckets/bucket-locks.mdx index b3c8cd09a76146..d4ca07e172a7c8 100644 --- a/src/content/docs/r2/buckets/bucket-locks.mdx +++ b/src/content/docs/r2/buckets/bucket-locks.mdx @@ -7,20 +7,42 @@ Bucket locks prevent the deletion and overwriting of objects in an R2 bucket for ## Get started with bucket locks -### Prerequisites - Before getting started, you will need: - An existing R2 bucket. If you do not already have an existing R2 bucket, refer to [Create buckets](/r2/buckets/create-buckets/). -- An API token with [permissions](/r2/api/s3/tokens/#permissions) to edit R2 bucket configuration. +- (API only) An API token with [permissions](/r2/api/s3/tokens/#permissions) to edit R2 bucket configuration. -:::note +### Enable bucket lock via dashboard -Currently, Bucket locks are only configurable via API. -::: +1. From the Cloudflare dashboard, select **R2** from the sidebar. +2. Select the bucket you would like to add bucket lock rule to. +3. Switch to the **Settings** tab, then scroll down to the **Bucket lock rules** card. +4. Select **Add rule** and enter the rule name, prefix, and retention period. +5. Select **Save changes**. + +### Enable bucket lock via Wrangler + +1. Install [`npm`](https://docs.npmjs.com/getting-started). +2. Install [Wrangler, the Developer Platform CLI](/workers/wrangler/install-and-update/). +3. Log in to Wrangler with the [`wrangler login` command](/workers/wrangler/commands/#login). +4. Add a bucket lock rule to your bucket by running the [`r2 bucket lock add` command](/workers/wrangler/commands/#r2-bucket-lock-add). + +```sh +npx wrangler r2 bucket lock add [OPTIONS] +``` + +Alternatively, you can set the entire bucket lock configuration for a bucket from a JSON file using the [`r2 bucket lock set` command](/workers/wrangler/commands/#r2-bucket-lock-set). + +```sh +npx wrangler r2 bucket lock set --file +``` + +The JSON file should be in the format of the request body of the [put bucket lock configuration API](/api/resources/r2/subresources/buckets/subresources/locks/methods/update/). ### Enable bucket lock via API +For information about getting started with the Cloudflare API, refer to [Make API calls](/fundamentals/api/how-to/make-api-calls/). For information on required parameters and more examples of how to set bucket lock configuration, refer to the [API documentation](/api/resources/r2/subresources/buckets/subresources/locks/methods/update/). + Below is an example of setting a bucket lock configuration (a collection of rules): ```bash @@ -55,15 +77,56 @@ This request creates two rules: - `lock-logs-7d`: Objects under the `logs/` prefix are retained for 7 days (604800 seconds). - `lock-images-indefinite`: Objects under the `images/` prefix are locked indefinitely. -For more information on required parameters and examples of how to enable bucket lock, refer to the [API documentation](/api/resources/r2/subresources/buckets/subresources/locks/methods/update/). For information about getting started with the Cloudflare API, refer to [Make API calls](/fundamentals/api/how-to/make-api-calls/). +:::note + +If your bucket is setup with [jurisdictional restrictions](/r2/reference/data-location/#jurisdictional-restrictions), you will need to pass a `cf-r2-jurisdiction` request header with that jurisdiction. For example, `cf-r2-jurisdiction: eu`. + +::: + +## Get bucket lock rules for your R2 bucket + +### Dashboard + +1. From the Cloudflare dashboard, select **R2** from the sidebar. +2. Select the bucket you would like to add bucket lock rule to. +3. Switch to the **Settings** tab, then scroll down to the **Bucket lock rules** card. + +### Wrangler -### Get bucket lock rules via API +To list bucket lock rules, run the [`r2 bucket lock list` command](/workers/wrangler/commands/#r2-bucket-lock-list): + +```sh +npx wrangler r2 bucket lock list +``` + +### API For more information on required parameters and examples of how to get bucket lock rules, refer to the [API documentation](/api/resources/r2/subresources/buckets/subresources/locks/methods/get/). +## Remove bucket lock rules from your R2 bucket + +### Dashboard + +1. From the Cloudflare dashboard, select **R2** from the sidebar. +2. Select the bucket you would like to add bucket lock rule to. +3. Switch to the **Settings** tab, then scroll down to the **Bucket lock rules** card. +4. Locate the rule you want to remove, select the `...` icon next to it, and then select **Delete**. + +### Wrangler + +To remove a bucket lock rule, run the [`r2 bucket lock remove` command](/workers/wrangler/commands/#r2-bucket-lock-remove): + +```sh +npx wrangler r2 bucket lock remove --id +``` + +### API + +To remove bucket lock rules via API, exclude them from your updated configuration and use the [put bucket lock configuration API](/api/resources/r2/subresources/buckets/subresources/locks/methods/update/). + ## Bucket lock rules -A bucket lock configuration can include up to 1,000 rules. Each rule specifies which object it covers (via prefix) and how long those objects must remain locked. You can: +A bucket lock configuration can include up to 1,000 rules. Each rule specifies which objects it covers (via prefix) and how long those objects must remain locked. You can: - Lock objects for a specific duration. For example, 90 days. - Retain objects until a certain date. For example, until January 1, 2026. diff --git a/src/content/docs/r2/buckets/create-buckets.mdx b/src/content/docs/r2/buckets/create-buckets.mdx index c747815d03c8d5..689d5376d9c919 100644 --- a/src/content/docs/r2/buckets/create-buckets.mdx +++ b/src/content/docs/r2/buckets/create-buckets.mdx @@ -48,4 +48,3 @@ wrangler r2 bucket delete BUCKET_TO_DELETE - Bucket names and buckets are not public by default. To allow public access to a bucket, [visit the public bucket documentation](/r2/buckets/public-buckets/). - Invalid (unauthorized) access attempts to private buckets do not incur R2 operations charges against that bucket. Refer to the [R2 pricing FAQ](/r2/pricing/#frequently-asked-questions) to understand what operations are billed vs. not billed. -- The TLS (SSL) certificate created for each R2 bucket uses a wildcard certificate of the form `*.r2.cloudflarestorage.com`, which prevents account IDs and names from showing up in Certificate Transparency logs. diff --git a/src/content/docs/r2/data-migration/super-slurper.mdx b/src/content/docs/r2/data-migration/super-slurper.mdx index fed96c92ddfafe..5e472f0a4578a5 100644 --- a/src/content/docs/r2/data-migration/super-slurper.mdx +++ b/src/content/docs/r2/data-migration/super-slurper.mdx @@ -6,18 +6,17 @@ learning_center: link: https://www.cloudflare.com/learning/cloud/what-is-data-migration/ sidebar: order: 1 - --- -import { InlineBadge, Render } from "~/components" +import { InlineBadge, Render } from "~/components"; Super Slurper allows you to quickly and easily copy objects from other cloud providers to an R2 bucket of your choice. Migration jobs: -* Preserve custom object metadata from source bucket by copying them on the migrated objects on R2. -* Do not delete any objects from source bucket. -* Use TLS encryption over HTTPS connections for safe and private object transfers. +- Preserve custom object metadata from source bucket by copying them on the migrated objects on R2. +- Do not delete any objects from source bucket. +- Use TLS encryption over HTTPS connections for safe and private object transfers. ## When to use Super Slurper @@ -52,10 +51,27 @@ This setting determines what happens when an object being copied from the source Cloudflare currently supports copying data from the following cloud object storage providers to R2: -* Amazon S3 -* Cloudflare R2 -* Google Cloud Storage (GCS) -* All S3-compatible storage providers +- Amazon S3 +- Cloudflare R2 +- Google Cloud Storage (GCS) +- All S3-compatible storage providers + +### Tested S3-compatible storage providers + +The following S3-compatible storage providers have been tested and verified to work with Super Slurper: + +- Backblaze B2 +- DigitalOcean Spaces +- Scaleway Object Storage +- Wasabi Cloud Object Storage + +Super Slurper should support transfers from all S3-compatible storage providers, but the ones listed have been explicitly tested. + +:::note + +Have you tested and verified another S3-compatible provider? [Open a pull request](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/r2/data-migration/super-slurper.mdx) or [create a GitHub issue](https://github.com/cloudflare/cloudflare-docs/issues/new). + +::: ## Create credentials for storage providers @@ -70,20 +86,14 @@ To create credentials with the correct permissions: ```json { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:Get*", - "s3:List*" - ], - "Resource": [ - "arn:aws:s3:::", - "arn:aws:s3:::/*" - ] - } - ] + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["s3:Get*", "s3:List*"], + "Resource": ["arn:aws:s3:::", "arn:aws:s3:::/*"] + } + ] } ``` @@ -124,5 +134,5 @@ You can now use this JSON key file when enabling Super Slurper. Objects stored using AWS S3 [archival storage classes](https://aws.amazon.com/s3/storage-classes/#Archive) will be skipped and need to be copied separately. Specifically: -* Files stored using S3 Glacier tiers (not including Glacier Instant Retrieval) will be skipped and logged in the migration log. -* Files stored using S3 Intelligent Tiering and placed in Deep Archive tier will be skipped and logged in the migration log. +- Files stored using S3 Glacier tiers (not including Glacier Instant Retrieval) will be skipped and logged in the migration log. +- Files stored using S3 Intelligent Tiering and placed in Deep Archive tier will be skipped and logged in the migration log. diff --git a/src/content/docs/r2/examples/ssec.mdx b/src/content/docs/r2/examples/ssec.mdx index 60a07508920e14..d0f3d06915d992 100644 --- a/src/content/docs/r2/examples/ssec.mdx +++ b/src/content/docs/r2/examples/ssec.mdx @@ -2,7 +2,6 @@ title: Use SSE-C pcx_content_type: tutorial difficulty: Intermediate -content_type: 📝 Tutorial updated: 2024-09-27 --- diff --git a/src/content/docs/r2/get-started.mdx b/src/content/docs/r2/get-started.mdx index 62dee80f00777a..1dfd25c522ca9a 100644 --- a/src/content/docs/r2/get-started.mdx +++ b/src/content/docs/r2/get-started.mdx @@ -1,11 +1,11 @@ --- -title: Get started +title: Getting started pcx_content_type: get-started sidebar: order: 2 head: - tag: title - content: Get started guide + content: Getting started guide --- diff --git a/src/content/docs/r2/index.mdx b/src/content/docs/r2/index.mdx index bb561e69c93f8f..2fd1bd005e4283 100644 --- a/src/content/docs/r2/index.mdx +++ b/src/content/docs/r2/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare R2 type: overview pcx_content_type: overview sidebar: @@ -7,8 +7,7 @@ sidebar: description: Cloudflare R2 is a cost-effective, scalable object storage solution for cloud-native apps, web content, and data lakes without egress fees. head: - tag: title - content: Cloudflare R2 - + content: Overview --- import { CardGrid, Description, Feature, LinkButton, LinkTitleCard, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/r2/platform/changelog.mdx b/src/content/docs/r2/platform/release-notes.mdx similarity index 95% rename from src/content/docs/r2/platform/changelog.mdx rename to src/content/docs/r2/platform/release-notes.mdx index 25c12d08017c1c..035df17dbd91cc 100644 --- a/src/content/docs/r2/platform/changelog.mdx +++ b/src/content/docs/r2/platform/release-notes.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: changelog -title: Changelog +title: Release-notes release_notes_file_name: - r2 --- diff --git a/src/content/docs/r2/tutorials/cloudflare-access.mdx b/src/content/docs/r2/tutorials/cloudflare-access.mdx index bf80c7027cdb61..0277baf0a21636 100644 --- a/src/content/docs/r2/tutorials/cloudflare-access.mdx +++ b/src/content/docs/r2/tutorials/cloudflare-access.mdx @@ -1,7 +1,6 @@ --- title: Protect an R2 Bucket with Cloudflare Access pcx_content_type: tutorial -content_type: 📝 Tutorial updated: 2024-04-16 --- diff --git a/src/content/docs/r2/tutorials/mastodon.mdx b/src/content/docs/r2/tutorials/mastodon.mdx index 44bd9085a5bae3..018551f39405cf 100644 --- a/src/content/docs/r2/tutorials/mastodon.mdx +++ b/src/content/docs/r2/tutorials/mastodon.mdx @@ -2,7 +2,6 @@ title: Mastodon pcx_content_type: tutorial difficulty: Beginner -content_type: 📝 Tutorial updated: 2023-01-31 --- diff --git a/src/content/docs/r2/tutorials/postman.mdx b/src/content/docs/r2/tutorials/postman.mdx index 02d2dc9fb82124..edb3c6a936a738 100644 --- a/src/content/docs/r2/tutorials/postman.mdx +++ b/src/content/docs/r2/tutorials/postman.mdx @@ -1,7 +1,6 @@ --- title: Postman summary: Learn how to configure Postman to interact with R2. -content_type: 📝 Tutorial pcx_content_type: tutorial description: Learn how to configure Postman to interact with R2. updated: 2022-07-15 diff --git a/src/content/docs/r2/tutorials/summarize-pdf.mdx b/src/content/docs/r2/tutorials/summarize-pdf.mdx index 79aed17692a561..5a5e74be97c0ab 100644 --- a/src/content/docs/r2/tutorials/summarize-pdf.mdx +++ b/src/content/docs/r2/tutorials/summarize-pdf.mdx @@ -1,7 +1,6 @@ --- title: Use event notification to summarize PDF files on upload pcx_content_type: tutorial -content_type: 📝 Tutorial products: - Queues - Workers @@ -48,7 +47,7 @@ Create a new Worker project by running the following commands: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/r2/tutorials/upload-logs-event-notifications.mdx b/src/content/docs/r2/tutorials/upload-logs-event-notifications.mdx index 17eae7b3a5f833..7a1f5065740f0c 100644 --- a/src/content/docs/r2/tutorials/upload-logs-event-notifications.mdx +++ b/src/content/docs/r2/tutorials/upload-logs-event-notifications.mdx @@ -1,7 +1,6 @@ --- title: Log and store upload events in R2 with event notifications pcx_content_type: tutorial -content_type: 📝 Tutorial products: - Queues - Workers @@ -72,7 +71,7 @@ Create a new Worker with C3 (`create-cloudflare` CLI). [C3](/pages/get-started/c product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/radar/glossary.mdx b/src/content/docs/radar/glossary.mdx index 952fd1fe36288d..9da9e6788bd8f1 100644 --- a/src/content/docs/radar/glossary.mdx +++ b/src/content/docs/radar/glossary.mdx @@ -50,7 +50,7 @@ Learn more about our route leak detection system design and usages in [How we d ## BGP origin hijacks -[BGP origin hijack](https://en.wikipedia.org/wiki/bgp_hijacking) is one type of BGP anomaly where networks falsely announce +[BGP origin hijack](https://www.cloudflare.com/learning/security/glossary/bgp-hijacking/) is one type of BGP anomaly where networks falsely announce ownership for groups of IP addresses (prefixes) that they do not own, control, or route to. A BGP origin hijack can redirect Internet traffic to the hijacker from its legitimate destination, causing data loss with potential leak of private/confidential information. @@ -90,7 +90,7 @@ Cloudflare Speed Test measures latency multiple times over the course of the tes ## Content categories -Cloudflare uses a variety of data sources to categorize domains. Using Cloudflare Radar, you can view the content categories associated with a given domain. Cloudflare customers using Cloudflare Gateway or [1.1.1.1 for Families](https://one.one.one.one/family/) can decide to block certain categories, like "Adult Content", in addition to security threats like malware and phishing. +Cloudflare uses a variety of data sources to categorize domains. Using Cloudflare Radar, you can view the content categories associated with a given domain. Cloudflare customers using Cloudflare Gateway or [1.1.1.1 for Families](/1.1.1.1/setup/#1111-for-families) can decide to block certain categories, like "Adult Content", in addition to security threats like malware and phishing. In some cases, a domain may be miscategorized. For example, a social media site might be categorized as "Shopping & Auctions". If you believe a domain is miscategorized, or a domain has not yet been categorized, please provide your suggested category using [this form](https://radar.cloudflare.com/domains/feedback) to bring it to our attention. @@ -99,11 +99,11 @@ In some cases, a domain may be miscategorized. For example, a social media site The [Domain Name System (DNS)](https://www.cloudflare.com/learning/dns/what-is-dns/) is a network service that is most commonly used to translate human-readable domain names into numerical IP addresses that computers can use to talk to each other. It is an essential Internet service, and is also used to look up other network-related information. -The data displayed on Radar for DNS is based on aggregated and anonymized DNS lookups to Cloudflare's [1.1.1.1](https://one.one.one.one/dns/) public resolver service. +The data displayed on Radar for DNS is based on aggregated and anonymized DNS lookups to Cloudflare's [1.1.1.1](/1.1.1.1/) public resolver service. ## Domain rankings -Domain Rankings is based on our anonymized and aggregated [1.1.1.1 resolver](https://one.one.one.one/dns/) data, complies with our [privacy policy](https://www.cloudflare.com/en-gb/privacypolicy/), and aims to identify the top most popular domains that reflect how people use the Internet globally. Domain Rankings’ popularity metric is best described as the estimated number of unique users that access a domain over some period of time. +Domain Rankings is based on our anonymized and aggregated [1.1.1.1 DNS resolver](/1.1.1.1/) data, complies with our [privacy policy](https://www.cloudflare.com/en-gb/privacypolicy/), and aims to identify the top most popular domains that reflect how people use the Internet globally. Domain Rankings’ popularity metric is best described as the estimated number of unique users that access a domain over some period of time. Trending domains are domains which are currently experiencing an increase in popularity. Domains Trending Today are domains spiking in popularity, reflecting increased interest potentially related to a particular event or a topic. Domains Trending This Week are domains that have steadily grown in popularity, reflecting an increase of their user base over the week. @@ -119,7 +119,7 @@ An early warning signal that an Internet outage may be underway on a given netwo ## Internet services ranking -Internet services ranking is based on our anonymized and aggregated [1.1.1.1 resolver](https://one.one.one.one/dns/) data, complies with our [privacy policy](https://www.cloudflare.com/en-gb/privacypolicy/), and aims to identify the top most popular Internet services that reflect how people use the Internet globally. A service represents one or more domains aggregated together. Ranking popularity metric is best described as the estimated number of unique users that access domains associated with a service, over some period of time. +Internet services ranking is based on our anonymized and aggregated [1.1.1.1 DNS resolver](/1.1.1.1/) data, complies with our [privacy policy](https://www.cloudflare.com/en-gb/privacypolicy/), and aims to identify the top most popular Internet services that reflect how people use the Internet globally. A service represents one or more domains aggregated together. Ranking popularity metric is best described as the estimated number of unique users that access domains associated with a service, over some period of time. ## Internet traffic trends @@ -145,6 +145,10 @@ The Internet Quality Index estimates connection performance under average utiliz The IQI methodology requires a minimum number of measurements to generate estimates. As a result, graphs for smaller countries and ASNs may display occasional gaps, especially during nighttime. These gaps do not indicate outages. The number of measurements underlying IQI does not necessarily correlate with the volume of traffic observed by Cloudflare in a specific country or ASN. +## Leaked credentials + +[Leaked credentials detection](/waf/detections/leaked-credentials/) scans incoming HTTP requests for known authentication patterns from common web apps and any custom detection locations that were configured. Cloudflare Radar provides visibility into aggregate trends in authentication requests, including the detection of leaked credentials. + ## Mobile operating systems The Mobile Operating Systems graph shows the distribution of mobile device requests by operating system, representing trends observed in Internet traffic originating globally or within a given location or autonomous system within the selected time range, based on aggregated data from our network. "Mobile device" includes phones and tablets only, and does not include other types of devices, such as those classified as desktops/laptops, smart TVs, or gaming consoles. diff --git a/src/content/docs/radar/index.mdx b/src/content/docs/radar/index.mdx index d5585e69f3891b..43aa79c2c54d8f 100644 --- a/src/content/docs/radar/index.mdx +++ b/src/content/docs/radar/index.mdx @@ -1,39 +1,122 @@ --- -title: Overview +title: Cloudflare Radar pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Radar - + content: Overview --- -import { Description, Feature, Plan } from "~/components" +import { + CardGrid, + Description, + Feature, + LinkButton, + LinkTitleCard, + Plan, +} from "~/components"; - -Get access to Cloudflare's data on global Internet traffic. +Get access to Cloudflare's data on global Internet traffic. - - -[Cloudflare Radar](https://radar.cloudflare.com) is a hub that showcases global Internet traffic, attacks, and technology trends and insights. It is powered by data from Cloudflare’s global network, as well as aggregated and [anonymized](/1.1.1.1/privacy/public-dns-resolver/) data from Cloudflare’s [1.1.1.1 public DNS resolver](/1.1.1.1/). + -Using Radar's API you can access Cloudflare's data on global Internet traffic. +[Cloudflare Radar](https://radar.cloudflare.com) is a hub that showcases global Internet traffic, attacks, and technology trends and insights. It is powered by data from [Cloudflare’s global network](https://www.cloudflare.com/network/), as well as aggregated and [anonymized data](/1.1.1.1/privacy/public-dns-resolver/) from Cloudflare’s [1.1.1.1 public DNS resolver](/1.1.1.1/). -Radar's API is free, allowing academics, data sleuths and other web enthusiasts to investigate Internet usage across the globe. +Using [Radar's API](/api/resources/radar/) you can access Cloudflare's data on global Internet traffic. +Radar's API is free, allowing academics, technology professionals, and other web enthusiasts to investigate Internet usage across the globe. Data available via Radar API endpoints is made available under the [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/) license. -*** + + Get started + + + + Radar website + + +--- ## Features - -Start learning how to use Radar's API by making your first request. + + Start learning how to use Radar's API by making your first request. + + + + What to know before making comparisons between locations, [autonomous + systems](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-an-autonomous-system/), and more. - -What to know before making comparisons between locations, [autonomous systems](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-an-autonomous-system/) and more. + + Understand the security, performance, technology, and network details of a URL with a publicly shareable report. + +--- + +## More resources + + + + + Explore the diverse data available in Cloudflare Radar, including NetFlows, HTTP requests, DNS queries, and much more. + + + + Follow @CloudflareRadar on X to learn about Internet trends, as seen by the Cloudflare global network. + + + + Follow @cloudflareradar on Mastodon to learn about Internet trends, as seen by the Cloudflare global network. + + + + Follow @radar.cloudflare.com on Bluesky to learn about Internet trends, as seen by the Cloudflare global network. + + + + Read articles about the latest trends and updates on Cloudflare Radar. + + + diff --git a/src/content/docs/radar/investigate/application-layer-attacks.mdx b/src/content/docs/radar/investigate/application-layer-attacks.mdx index f948e7699d5b83..7177d4d37cfdca 100644 --- a/src/content/docs/radar/investigate/application-layer-attacks.mdx +++ b/src/content/docs/radar/investigate/application-layer-attacks.mdx @@ -17,7 +17,7 @@ Since we are examining attacks, we can inspect both sides of an attack — both This ability to filter by both sides of the attack is only available in the `top locations` endpoints. Unless otherwise specified, other endpoints are filtered by source location, like the origin location of the attack. -The magnitude of the attack is defined by the total number of mitigated requests, unless otherwise specified. +The magnitude of the attack is defined by the total number of mitigated requests. Like in [HTTP requests](/radar/investigate/http-requests), these endpoints can be split into the ability to fetch a timeseries, a single value summarizing the entire date range, and a list of top locations. @@ -167,10 +167,8 @@ For more information refer to [Get layer 7 top target locations](/api/resources/ Which source-target location pairs constitute the biggest attacks in the last 24 hours? -How big an attack is, or the attack magnitude, can be defined by the number of mitigated requests (the default) or by the number of total zones under attack. - ```bash -curl "https://api.cloudflare.com/client/v4/radar/attacks/layer7/top/attacks?limit=5&dateRange=1d&magnitude=MITIGATED_REQUESTS&format=json" \ +curl "https://api.cloudflare.com/client/v4/radar/attacks/layer7/top/attacks?limit=5&dateRange=1d&format=json" \ --header "Authorization: Bearer " ``` @@ -232,8 +230,6 @@ A typical response will be similar to the following: This means that 3.79% of all mitigated requests are from and to the US, 3.6% of all mitigated requests are from the US to Belgium, etc.. -This response came from a query that is using attack `magnitude` as the sum of mitigated requests. To use the number of unique zones attacked as the metric, for example, use `attack_magnitude=AFFECTED_ZONES`. - For more information refer to [Get layer 7 top attack pairs](/api/resources/radar/subresources/attacks/subresources/layer7/subresources/top/methods/attacks/). ## Next steps diff --git a/src/content/docs/radar/investigate/bgp-anomalies.mdx b/src/content/docs/radar/investigate/bgp-anomalies.mdx index 1b66b1ecb18488..ddeb0ba12f1396 100644 --- a/src/content/docs/radar/investigate/bgp-anomalies.mdx +++ b/src/content/docs/radar/investigate/bgp-anomalies.mdx @@ -187,7 +187,7 @@ First, create a new Workers app in a local directory: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -216,8 +216,6 @@ crons = [ "*/5 * * * *" ] In this example, we will also need to use Cloudflare KV to save the latest checked event IDs which allows us to know what events are new. Once you have created a KV, you can head back to the `wranglers.toml` file and add the following sections: - - ```toml @@ -372,8 +370,6 @@ If you have [Email Routing][email-routing] enabled for your domain, you can also For this alert to work, you will need to configure the proper email bindings in the [Wrangler configuration file][wrangler-send-email]. - - ```toml diff --git a/src/content/docs/radar/investigate/url-scanner.mdx b/src/content/docs/radar/investigate/url-scanner.mdx index 291368d48f8945..66b7a3634312c8 100644 --- a/src/content/docs/radar/investigate/url-scanner.mdx +++ b/src/content/docs/radar/investigate/url-scanner.mdx @@ -6,7 +6,7 @@ sidebar: --- -To better understand Internet usage around the world, use Cloudflare's URL Scanner. With Cloudflare's URL Scanner, you have the ability to investigate the details of a domain, IP, URL, or ASN. Cloudflare's URL Scanner is available in the Security Center of the Cloudflare dashboard, [Cloudflare Radar](https://radar.cloudflare.com/scan) and the Cloudflare [API](/api/resources/url_scanner/subresources/scans/). +To better understand Internet usage around the world, use Cloudflare's URL Scanner. With Cloudflare's URL Scanner, you have the ability to investigate the details of a domain, IP, URL, or ASN. Cloudflare's URL Scanner is available in the Security Center of the Cloudflare dashboard, [Cloudflare Radar](https://radar.cloudflare.com/scan), and the Cloudflare [API](/api/resources/url_scanner/). ## Use the API @@ -41,6 +41,8 @@ A successful response will have a status code of `200` and be similar to the fol } ``` +You can submit up to 100 URLs at the same time via the [API](https://developers.cloudflare.com/api/resources/url_scanner/subresources/scans/methods/bulk_create/). + The `uuid` property in the response above identifies the scan and will be required when fetching the scan report. #### Submit a custom URL Scan diff --git a/src/content/docs/radar/changelog.mdx b/src/content/docs/radar/release-notes.mdx similarity index 90% rename from src/content/docs/radar/changelog.mdx rename to src/content/docs/radar/release-notes.mdx index 6b289e5b3fff8e..fc4ea517989aa3 100644 --- a/src/content/docs/radar/changelog.mdx +++ b/src/content/docs/radar/release-notes.mdx @@ -1,6 +1,6 @@ --- -pcx_content_type: changelog -title: Changelog +pcx_content_type: release-notes +title: Release notes release_notes_file_name: - radar sidebar: diff --git a/src/content/docs/randomness-beacon/index.mdx b/src/content/docs/randomness-beacon/index.mdx index 142cad565cc9cc..cb02ebee417f81 100644 --- a/src/content/docs/randomness-beacon/index.mdx +++ b/src/content/docs/randomness-beacon/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Randomness Beacon pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Randomness Beacon - + content: Overview --- drand (pronounced "dee-rand") is a distributed randomness beacon daemon written in Golang. Servers running drand can be linked to each other to produce collective, publicly verifiable, unbiased, unpredictable random values at fixed intervals using bilinear pairings and threshold cryptography. diff --git a/src/content/docs/reference-architecture/architectures/load-balancing.mdx b/src/content/docs/reference-architecture/architectures/load-balancing.mdx index 641d98ea5099c3..d0c1e19b19098e 100644 --- a/src/content/docs/reference-architecture/architectures/load-balancing.mdx +++ b/src/content/docs/reference-architecture/architectures/load-balancing.mdx @@ -457,9 +457,9 @@ The public endpoint method allows organizations to define a tunnel that points t When configured via the Dashboard, Cloudflare automatically creates a CNAME record in the DNS zone that refers to the cfargotunnel.com hostname. For example, a CNAME record of myTunnelService.example.com could be created to point the A record of d74b3a46-f3a3-4596-9049-da7e72c876f5.cfargotunnel.com. The main benefit being the ease of use and administration as the CNAME record is much more suggestive about its purpose and belongs to the customer DNS zone. -Another option is to create these tunnels and services on the host running cloudflared. This is called a [locally-managed tunnel](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/). When working with locally-managed tunnels, the CNAME entry is not created automatically however, so the organization would have to configure this manually, after the tunnel and service is defined. +Another option is to create these tunnels and services on the host running cloudflared. This is called a [locally-managed tunnel](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/). When working with locally-managed tunnels, the CNAME entry is not created automatically however, so the organization would have to configure this manually, after the tunnel and service is defined. -From a load balancer perspective, it's very important to understand how these tunnels can be used as an endpoint. An endpoint can only be defined by using the cfargotunnel.com hostname. Using a public CNAME record that points to the cfargotunnel.com address will not work properly and is not supported. This is especially important for endpoint services that don’t operate on ports 80 or 443. Cloudflare Load Balancers default to these two ports to access the services running on the endpoints. If an organization has services running on other ports, they will need to configure a Cloudflare Tunnel with a [catch-all rule](/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/#how-traffic-is-matched) to reach that port. This configuration allows a Cloudflare Load Balancer to reach the service via port 443 while having Cloudflare tunnel proxy the connection to the desired port on the endpoint. +From a load balancer perspective, it's very important to understand how these tunnels can be used as an endpoint. An endpoint can only be defined by using the cfargotunnel.com hostname. Using a public CNAME record that points to the cfargotunnel.com address will not work properly and is not supported. This is especially important for endpoint services that don’t operate on ports 80 or 443. Cloudflare Load Balancers default to these two ports to access the services running on the endpoints. If an organization has services running on other ports, they will need to configure a Cloudflare Tunnel with a [catch-all rule](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/#how-traffic-is-matched) to reach that port. This configuration allows a Cloudflare Load Balancer to reach the service via port 443 while having Cloudflare tunnel proxy the connection to the desired port on the endpoint. ###### Private IP diff --git a/src/content/docs/reference-architecture/architectures/sase.mdx b/src/content/docs/reference-architecture/architectures/sase.mdx index 9955606b5904ce..766aa87d70414d 100644 --- a/src/content/docs/reference-architecture/architectures/sase.mdx +++ b/src/content/docs/reference-architecture/architectures/sase.mdx @@ -468,7 +468,7 @@ But, before organizations define policies to manage that access, they need to kn The first step in any access decision is to determine who is making the request – i.e., to authenticate the user. -Cloudflare integrates with identity providers that manage secure access to resources for organizations' employees, contractors, partners, and other users. This includes support for integrations with any [SAML](/cloudflare-one/identity/idp-integration/generic-saml/) - or OpenID Connect ([OIDC](/cloudflare-one/identity/idp-integration/generic-oidc/)) - compliant service; Cloudflare One also includes pre-built integrations with [Okta](/cloudflare-one/identity/idp-integration/okta/), [Microsoft Entra ID (formerly Azure Active Directory)](/cloudflare-one/identity/idp-integration/entra-id/), [Google Workspace](/cloudflare-one/identity/idp-integration/gsuite/), as well as consumer IdPs such as [Facebook](/cloudflare-one/identity/idp-integration/facebook-login/), [GitHub](/cloudflare-one/identity/idp-integration/github/) and [LinkedIn](/cloudflare-one/identity/idp-integration/linkedin/). +Cloudflare integrates with identity providers that manage secure access to resources for organizations' employees, contractors, partners, and other users. This includes support for integrations with any [SAML](/cloudflare-one/identity/idp-integration/generic-saml/) - or OpenID Connect ([OIDC](/cloudflare-one/identity/idp-integration/generic-oidc/)) - compliant service; Cloudflare One also includes pre-built integrations with [Okta](/cloudflare-one/identity/idp-integration/okta/), [Microsoft Entra ID (formerly Azure Active Directory)](/cloudflare-one/identity/idp-integration/entra-id/), [Google Workspace](/cloudflare-one/identity/idp-integration/google-workspace/), as well as consumer IdPs such as [Facebook](/cloudflare-one/identity/idp-integration/facebook-login/), [GitHub](/cloudflare-one/identity/idp-integration/github/) and [LinkedIn](/cloudflare-one/identity/idp-integration/linkedin/). Multiple IdPs can be integrated, allowing organizations to apply policies to a wide range of both internal and external users. When a user attempts to access a Cloudflare secured application or service, they are redirected to authenticate via one of the integrated IdPs. When using the device agent, users must also authenticate to one of their organization's configured IdPs. diff --git a/src/content/docs/reference-architecture/design-guides/extending-cloudflares-benefits-to-saas-providers-end-customers.mdx b/src/content/docs/reference-architecture/design-guides/extending-cloudflares-benefits-to-saas-providers-end-customers.mdx index 9d3db2005f092b..8b4f6dfee33444 100644 --- a/src/content/docs/reference-architecture/design-guides/extending-cloudflares-benefits-to-saas-providers-end-customers.mdx +++ b/src/content/docs/reference-architecture/design-guides/extending-cloudflares-benefits-to-saas-providers-end-customers.mdx @@ -56,7 +56,7 @@ The following products are used to deliver this solution. | [DDoS Protection](/ddos-protection/) | Volumetric attack protection is automatically enabled for [proxied](/dns/proxy-status/) hostnames. | | [Regional Services](/data-localization/regional-services/) (part of the Data Localization Suite) | Restrict inspection of data (processing) to only those data centers within jurisdictional boundaries. | | [Load Balancer](/load-balancing/) | Distributes traffic across your endpoints, which reduces endpoint strain and latency and improves the experience for end users. | -| [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/) | Secure method to connect to customers' networks and servers without creating holes in [firewalls](/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/). cloudflared is the daemon (software) installed on origin servers to create a secure tunnel from applications back to Cloudflare. | +| [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/) | Secure method to connect to customers' networks and servers without creating holes in [firewalls](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-with-firewall/). cloudflared is the daemon (software) installed on origin servers to create a secure tunnel from applications back to Cloudflare. | ## Cloudflare for SaaS examples diff --git a/src/content/docs/reference-architecture/design-guides/network-vpn-migration.mdx b/src/content/docs/reference-architecture/design-guides/network-vpn-migration.mdx index c1d5ed4939f759..5594d1bd163e4e 100644 --- a/src/content/docs/reference-architecture/design-guides/network-vpn-migration.mdx +++ b/src/content/docs/reference-architecture/design-guides/network-vpn-migration.mdx @@ -138,14 +138,14 @@ Cloudflare offers two types of software connectors: As discussed in the introduction, `cloudflared` is the preferred method for Zero Trust Network Access, but only supports inbound connectivity to your networks and application servers, any server initiated connection will not go via the tunnel and instead follow the server's default network path. WARP connector is designed to create tunnels that facilitate both inbound and outbound connectivity, but it doesn't currently have the same level of failover support and ease of configuration. For this guide, we will be discussing using `cloudflared` as it supports the internal DNS use case described. -For large remote access use cases, Cloudflare recommends deploying connectors to dedicated hosts. See the [System Requirements documentation](/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/) for more deployment recommendations and server sizing. Where to deploy these servers depends on the access they need and the internal firewall rules and segmentation of the network. Some customers start with their first deployment in their DMZ, while others install it deeper in their network and evolve from there. +For large remote access use cases, Cloudflare recommends deploying connectors to dedicated hosts. See the [System Requirements documentation](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/) for more deployment recommendations and server sizing. Where to deploy these servers depends on the access they need and the internal firewall rules and segmentation of the network. Some customers start with their first deployment in their DMZ, while others install it deeper in their network and evolve from there. Installing `cloudflared` is best done in an automated manner, so we recommend deploying using a virtualization technology such as Docker or deploying as VMware guests and configuring via Ansible. Preferably, as traffic using `cloudflared` tunnels increases, such systems can scale the deployment automatically based on real-time metrics collected from the hosts. `cloudflared` instances can be monitored using the [Prometheus metrics endpoint](/cloudflare-one/connections/connect-networks/monitor-tunnels/metrics/). Prometheus is an HTTP-based monitoring and alerting system similar in functionality to SNMP, exposing metrics that can be polled from the resource to be monitored. Most monitoring systems on the market today support Prometheus as a format to collect the metrics needed for alerting and automatically scaling the deployment. For more information about deploying `cloudflared` connectors at scale: -- [Various guides to deploy and update](/cloudflare-one/connections/connect-networks/deploy-tunnels/deployment-guides/) connectors in environments such as Ansible, Terraform and Kubernetes -- High availability using [replicas](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/#cloudflared-replicas) +- [Various guides to deploy and update](/cloudflare-one/connections/connect-networks/deployment-guides/) connectors in environments such as Ansible, Terraform and Kubernetes +- High availability using [replicas](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/#cloudflared-replicas) - [Monitor tunnels with Grafana](/cloudflare-one/tutorials/grafana/) ### DNS resolution with Resolver Policies diff --git a/src/content/docs/reference-architecture/design-guides/secure-application-delivery.mdx b/src/content/docs/reference-architecture/design-guides/secure-application-delivery.mdx index 071aa6260a688d..e59709867000b3 100644 --- a/src/content/docs/reference-architecture/design-guides/secure-application-delivery.mdx +++ b/src/content/docs/reference-architecture/design-guides/secure-application-delivery.mdx @@ -106,7 +106,7 @@ We can also use Cloudflare Tunnel over the Internet to provide for more security To create and manage tunnels, you need to install and authenticate cloudflared on your origin server. cloudflared is what connects your server to Cloudflare’s global network. -There are two options for creating a tunnel - [via the dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) or [via the command line](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/). It’s recommended getting started with the dashboard, since it will allow you to manage the tunnel from any machine. +There are two options for creating a tunnel - [via the dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/) or [via the command line](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/). It’s recommended getting started with the dashboard, since it will allow you to manage the tunnel from any machine. A remotely-managed tunnel only requires the tunnel token to run. Anyone with access to the token will be able to run the tunnel. You can get a tunnel’s token from the dashboard or via the API as shown below. The command provided in the dashboard will install and configure cloudflared to run as a service using an auth token. diff --git a/src/content/docs/reference-architecture/diagrams/serverless/programmable-platforms.mdx b/src/content/docs/reference-architecture/diagrams/serverless/programmable-platforms.mdx new file mode 100644 index 00000000000000..61023f4be634c9 --- /dev/null +++ b/src/content/docs/reference-architecture/diagrams/serverless/programmable-platforms.mdx @@ -0,0 +1,121 @@ +--- +title: Programmable Platforms +pcx_content_type: reference-architecture-diagram +products: + - WorkersForPlatforms + - KV +sidebar: + order: 1 + label: Programmable Platforms +updated: 2025-03-16 +--- + + +## Introduction + +A programmable platform allows customers to customize a product by writing code. Unlike traditional SaaS with fixed features, it enables users to extend functionality, deploy backend logic, and build full-stack experiences—all within the platform’s infrastructure. + +Hosting the infrastructure for these platforms presents several challenges, including security, scalability, cost efficiency, and performance isolation. Allowing customers to run custom code introduces risks such as untrusted execution, potential abuse, and resource contention, all of which must be managed without compromising platform reliability. Running millions of single-tenant applications is inherently costly, making efficient resource utilization critical. The ability to scale workloads to zero when idle is key to ensuring economic viability while maintaining rapid startup times when demand spikes. Additionally, ensuring seamless global execution with low-latency performance requires a resilient, distributed architecture. Robust monitoring, debugging, and governance capabilities are also essential to provide visibility and control over customer-deployed code without restricting innovation. + +[Workers for Platforms](/cloudflare-for-platforms/workers-for-platforms/) provides the ideal infrastructure for building programmable platforms by offering secure, isolated environments where customers can safely execute custom code at scale, with automatic scaling to zero and a globally distributed runtime that optimizes performance and cost. + + +## Core Architecture Components + +The Workers for Platforms architecture consists of several key components that work together to provide a secure, scalable, and efficient solution for multi-tenant applications. In the following core concepts are outlined. + +1. **Main Request Flow**: An overview over the a request flow in a programmable platform. + +2. **Invocation & Metadata Flow**: commonly, incoming requests and enriched with metadata to provide the function invocation with relevant context or perform routing logic. + +3. **Egress Control**: controlling outbound connections to ensure compliant behaviour. + +4. **Utilizing Storage & Data Resources**: leveraging databases & storage to build even richer end-user expierences at scale. + +5. **Observability Tools**: Logging and metrics collection services to monitor platform performance and troubleshoot issues. + +## Main Request Flow + +![Figure 1: Workers for Platforms: Main Flow](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-1.svg "Figure 1: Workers for Platforms: Main Flow") + + +1. **Client Request**: Send request from a client application to the platform's [Dynamic Dispatch Worker](/cloudflare-for-platforms/workers-for-platforms/reference/how-workers-for-platforms-works/#dynamic-dispatch-worker). + +2. **Routing**: Identify the correct workload to execute and route the request to the respective [User Worker](/cloudflare-for-platforms/workers-for-platforms/reference/how-workers-for-platforms-works/#user-workers) in the [Dispatch Namespace](/cloudflare-for-platforms/workers-for-platforms/reference/how-workers-for-platforms-works/#dispatch-namespace). Each customer's workload runs in an isolated User Worker with its own resources and security boundaries. + + +## Invocation & Metadata Flow + +![Figure 2: Workers for Platforms: Main Flow](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-2.svg "Figure 2: Workers for Platforms: Main Flow") + +For many use cases, it makes sense to retrieve additional metadata, user data, or configuration to process incoming requests and provide the User Worker invocation with additional context. + +1. **Incoming Request**: Send requests to custom hostnames or a Worker using a Workers wildcard route. + +2. **Metadata Lookup**: Retrieve customer-specific configuration data from [KV](/kv/) storage. These lookups are typically based on the hostname of the incoming request or custom metadata in the case of custom hostnames. + +3. **Worker Invocation**: Route requests to the appropriate User Worker in the Dispatch Namespace based on metadata. Optionally, provide additional context during function invocation. + +## Egress Control Pattern + +![Figure 3: Workers for Platforms: Egress Control](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-3.svg "Figure 3: Workers for Platforms: Egress Control") + +Data observability and control is crucial for security. [Outbound Workers](/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/) allow for interception of all outgoing requests in User Worker scripts. + +1. **Worker Invocation**: Route requests to the appropriate User Worker in the Dispatch Namespace. Optionally pass additional parameters to the Outbound Worker during User Worker invocation. + +2. **External requests**: Send requests via `fetch()` calls to external services through a controlled Outbound Worker. + +3. **Request interception**: Evaluate outgoing requests and perform core functions like centralized policy enforcement and audit logging. + + +## Metrics & Logging Architecture + +![Figure 4: Workers for Platforms: Metrics & Logging](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-4.svg "Figure 4: Workers for Platforms: Metrics & Logging") + + +1. **Logging**: Collect logs throughout all Workers in the request flow via [Tail Worker](/cloudflare-for-platforms/workers-for-platforms/configuration/observability/#tail-workers) and [Workers Trace Events Logpush](/cloudflare-for-platforms/workers-for-platforms/configuration/observability/#workers-trace-events-logpush) services. + +2. **Metrics**: Collect custom metrics via [Workers Analytics Engine](/analytics/analytics-engine/) and out-of-the-box [Analytics](/analytics/graphql-api/) that can readily be queried via GraphQL API. + +3. **Third-party Integration**: Export logs and metrics to various external monitoring and analytics platforms like Datadog, Splunk, Grafana, and others via [Analytics integrations](/analytics/analytics-integrations/). + +## Resource Isolation Model + +![Figure 5: Workers for Platforms: Resources](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-5.svg "Figure 5: Workers for Platforms: Resources") + +1. **Incoming Request**: Send requests to custom hostnames or a Worker using a Workers wildcard route. + +2. **Worker Invocation**: Route requests to the appropriate User Worker in the Dispatch Namespace. + +3. **Resource Access**: Interact with per-script-specific resources: + - D1 for relational database storage + - Durable Objects for strongly consistent data + - KV for high-read, eventually consistent key-value storage + - R2 for object storage + +## Deployment & Management Flow + +![Figure 6: Workers for Platforms: Deployment & Management Flow](~/assets/images/reference-architecture/programmable-platforms/programmable-platforms-6.svg "Figure 6: Workers for Platforms: Deployment & Management Flow") + + +1. **Management Interface**: Interact with the platform through GUI, API, or CLI interfaces. + +2. **Platform Processing**: Process these interactions to: + - Transform and bundle code + - Perform security checks + - Apply configuration + +3. **Change Management**: Deploy changes to Cloudflare using the Cloudflare REST API. + + +## Conclusion + +Cloudflare Workers for Platforms provides a robust foundation for building multi-tenant SaaS applications with strong isolation, global distribution, and scalable performance. By leveraging this architecture, platform providers can focus on delivering value to their customers while Cloudflare handles the underlying infrastructure complexity. + +## Related resources + +- [Workers for Platforms: Get started](/cloudflare-for-platforms/workers-for-platforms/get-started/) +- [Workers for Platforms: Outbound Workers](/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/) +- [Workers for Platforms: Observability](/cloudflare-for-platforms/workers-for-platforms/configuration/observability/) + diff --git a/src/content/docs/registrar/index.mdx b/src/content/docs/registrar/index.mdx index 7d7ec788dcc183..d38a2cfaa1371e 100644 --- a/src/content/docs/registrar/index.mdx +++ b/src/content/docs/registrar/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Registrar pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Registrar - + content: Overview --- import { Description, Feature, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/rules/configuration-rules/create-api.mdx b/src/content/docs/rules/configuration-rules/create-api.mdx index f6f0857daae471..011e62613fe17b 100644 --- a/src/content/docs/rules/configuration-rules/create-api.mdx +++ b/src/content/docs/rules/configuration-rules/create-api.mdx @@ -61,9 +61,9 @@ https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/{ruleset_id} \ -
    +
    -The following example sets the rules of an existing phase ruleset (`{ruleset_id}`) to a single configuration rule — turning on I'm Under Attack mode for the administration area — using the [Update a zone ruleset](/api/resources/rulesets/methods/update/) operation: +The following example sets the rules of an existing phase ruleset (`{ruleset_id}`) to a single configuration rule — turning on Under Attack mode for the administration area — using the [Update a zone ruleset](/api/resources/rulesets/methods/update/) operation: ```bash title="Request" curl --request PUT \ diff --git a/src/content/docs/rules/configuration-rules/settings.mdx b/src/content/docs/rules/configuration-rules/settings.mdx index 95bc990fd8ce5a..093449f930de8a 100644 --- a/src/content/docs/rules/configuration-rules/settings.mdx +++ b/src/content/docs/rules/configuration-rules/settings.mdx @@ -262,30 +262,21 @@ API configuration property name: `"rocket_loader"` (boolean).
    -## Security Level +## I'm Under Attack -[Security Level](/waf/tools/security-level/) controls Managed Challenges for requests from low reputation IP addresses. +When enabled, [Under Attack mode](/fundamentals/reference/under-attack-mode/) performs additional security checks to help mitigate layer 7 DDoS attacks. Validated users access your website and suspicious traffic is blocked. -Use this setting to select the security level for matching requests: - -- Off -- Essentially Off -- Low -- Medium -- High -- I'm Under Attack - -Refer to [Security levels](/waf/tools/security-level/#security-levels) for more information on these values. +Use this setting to turn on or off Under Attack mode for matching requests.
    API configuration property name: `"security_level"` (string). -API values: `"off"`, `"essentially_off"`, `"low"`, `"medium"`, `"high"`, `"under_attack"`. +API values: `"off"`, `"essentially_off"`, `"under_attack"`. ```json title="API configuration example" "action_parameters": { - "security_level": "low" + "security_level": "under_attack" } ``` diff --git a/src/content/docs/rules/normalization/manage.mdx b/src/content/docs/rules/normalization/manage.mdx index a74da842717c3c..53069aaf4dc51b 100644 --- a/src/content/docs/rules/normalization/manage.mdx +++ b/src/content/docs/rules/normalization/manage.mdx @@ -9,7 +9,7 @@ description: How to configure URL normalization in the Cloudflare dashboard. 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and website. -2. Go to **Rules** > **Overview** and select **URL Normalization**. +2. Go to **Rules** > **Settings** and select the **URL Normalization** tab. 3. Configure the [available URL normalization settings](/rules/normalization/settings/). diff --git a/src/content/docs/rules/page-rules/how-to/override-url-or-ip-address.mdx b/src/content/docs/rules/page-rules/how-to/override-url-or-ip-address.mdx deleted file mode 100644 index c8f32ebd47a6a8..00000000000000 --- a/src/content/docs/rules/page-rules/how-to/override-url-or-ip-address.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -pcx_content_type: how-to -source: https://support.cloudflare.com/hc/en-us/articles/206190798-Using-Resolve-Override-in-Page-Rules -title: Override URL or IP address -head: - - tag: title - content: Override URL or IP address | Page Rules ---- - -import { Render } from "~/components"; - -Cloudflare Page Rules allows you to override the URL or IP address of a request. This feature is currently available for domains on the Enterprise plan. - - - -A common use case for this functionality is when you are serving an application from a particular URI (`mydomain.com/app`). In this case, the app may live on another server and may even be hosted by a third party. Requests to this endpoint must be directed to the server for that third party application. You can specify a `CNAME` host, as long as the `CNAME` record exists within the Cloudflare DNS. - -To make sure you have full control of these records, it is recommended that you set the Resolve Override within the same zone name. - ---- - -To configure a resolve override in Page Rules, do the following: - -1. [Create a DNS record](/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) (either `CNAME` or `A` record) for your domain. - - - This example shows a `CNAME` record setup to point to `domain.s3.amazonaws.com`. - - - **Type:** `CNAME` - - **Name:** `resolve.example.com` - - **Target:** `domain.s3.amazonaws.com` - - **TTL:** Auto - - **Proxy status:** Proxied - - - This example uses an `A` record to point to a web server IP address. - - - **Type:** `A` - - **Name:** `resolve.example.com` - - **IPv4 address:** `1.2.3.4` - - **TTL:** Auto - - **Proxy status:** Proxied - -2. [Create a page rule](/rules/page-rules/manage/) to override a URL or an IP address. - - The following example page rule configuration would send all requests from a folder (`/app`) to an AWS S3 bucket: - - - **If the URL matches:** `example.com/app/*` - - **Setting:** _Resolve Override_ | **Value:** `resolve.example.com` - - **Setting:** _Host Header Override_ | **Value:** `examplebucket.s3.amazonaws.com` - -:::caution[Important remarks] - -- Page Rules require a [proxied DNS record](/dns/proxy-status/) to work. Page Rules will not apply to subdomains that do not exist in DNS or are not being directed to Cloudflare. - -- The _Resolve Override_ setting only allows override of the hostname, not the path. If you need to modify the path also, you will need to either use a [Worker](/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties) or combine the page rule with a [transform rule](/rules/transform/url-rewrite/). - -::: diff --git a/src/content/docs/rules/page-rules/how-to/rewrite-host-headers.mdx b/src/content/docs/rules/page-rules/how-to/rewrite-host-headers.mdx deleted file mode 100644 index 481e683b170841..00000000000000 --- a/src/content/docs/rules/page-rules/how-to/rewrite-host-headers.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -pcx_content_type: how-to -source: https://support.cloudflare.com/hc/en-us/articles/206652947-Using-Page-Rules-to-rewrite-Host-Headers -title: Rewrite Host headers -head: - - tag: title - content: Rewrite Host headers | Page Rules - ---- - -import { Render } from "~/components" - -Customers can rewrite `Host` headers using different Cloudflare rules. This feature is currently available for domains on the Enterprise plan. - - - -A common use case for this functionality is when your content is hosted on an Amazon S3 bucket. Amazon has designed their system to only accept host headers that have the same name as the bucket hosting your content. In this way, a request to `Host: your-domain.com` must be rewritten to `Host: your-bucket.s3.amazonaws.com`, or else the request will be denied. - -In some cases, you can adjust your Amazon S3 Bucket to accept `Host` headers that are not the bucket name. - -*** - -To rewrite the `Host` header: - -1. Log in to your [Cloudflare account](https://dash.cloudflare.com), and select your account and domain. -2. Go to **Rules** > **Page Rules**. -3. Select **Create Page Rule**. -4. Specify the URL to match. -5. In **Pick a Setting,** select *Host Header Override*. Then, enter the override value. -6. Select **Save and Deploy Page Rule**. - -Now, any request matching the URL you specified will have the `Host` header overridden to the one you entered in the **Host Header Override** text box. - - diff --git a/src/content/docs/rules/page-rules/reference/recommended-rules.mdx b/src/content/docs/rules/page-rules/reference/recommended-rules.mdx index 45531f17124502..655085bf82e12c 100644 --- a/src/content/docs/rules/page-rules/reference/recommended-rules.mdx +++ b/src/content/docs/rules/page-rules/reference/recommended-rules.mdx @@ -5,40 +5,38 @@ title: Recommended rules head: - tag: title content: Recommended rules | Page Rules - --- -import { Example, Render } from "~/components" +import { Example, Render } from "~/components"; -Use Cloudflare Page Rules to improve the user experience of your domain with hardened security and enhanced site performance, while increasing reliability and minimizing bandwidth usage for your origin server. +Use Cloudflare Page Rules to improve the user experience of your domain with hardened security and enhanced site performance, while increasing reliability and minimizing bandwidth usage for your origin server. Keep in mind that not all rules will be right for everyone, but these are some of the most popular. -* 301/302 Forwarding URL -* Security Level and Cache Level -* Edge Cache TTL, Always Online, and Browser Cache TTL +- 301/302 Forwarding URL +- Cache Level in specific paths +- Edge Cache TTL, Always Online, and Browser Cache TTL ### 301/302 Forwarding URL :::note - -Consider using [Single Redirects](/rules/url-forwarding/single-redirects/) or [Bulk Redirects](/rules/url-forwarding/bulk-redirects/) to forward or redirect traffic to a different URL due to ease of use, maintenance, and cost. You should only use Page Rules when Dynamic or Bulk Redirects do not meet your use case. +Consider using [Single Redirects](/rules/url-forwarding/single-redirects/) or [Bulk Redirects](/rules/url-forwarding/bulk-redirects/) to forward or redirect traffic to a different URL due to ease of use, maintenance, and cost. You should only use Page Rules when Dynamic or Bulk Redirects do not meet your use case. ::: Two common examples for using forwarding URLs are: -* Defining the root as the canonical version of your domain. -* Directing visitors to a specific page with an easy to remember URL. +- Defining the root as the canonical version of your domain. +- Directing visitors to a specific page with an easy to remember URL. This example page rule configuration defines the root as the canonical version of your domain: -* **If the URL matches**: `*www.example.com/*` -* **Setting**: *Forwarding URL* | **Select status code**: *301 Permanent Redirect* -* **Enter destination URL**: `https://example.com/$2` +- **If the URL matches**: `*www.example.com/*` +- **Setting**: _Forwarding URL_ | **Select status code**: _301 Permanent Redirect_ +- **Enter destination URL**: `https://example.com/$2` @@ -46,24 +44,22 @@ This example redirects visitors to a specific page with an easy to remember URL: -* **If the URL matches**: `*www.example.com/fb*` -* **Setting**: *Forwarding URL* | **Select status code**: *302 Temporary Redirect* -* **Enter destination URL**: `https://www.facebook.com/username` +- **If the URL matches**: `*www.example.com/fb*` +- **Setting**: _Forwarding URL_ | **Select status code**: _302 Temporary Redirect_ +- **Enter destination URL**: `https://www.facebook.com/username` -### Security Level and Cache Level +### Cache Level in specific paths Certain sections of a website, like the login or admin section, have different security and performance requirements than your general public-facing pages. -The following example page rule configuration performs several security and cache adjustments for requests targeting a specific path: +The following example page rule configuration bypasses cache for requests targeting a specific path: -* **If the URL matches**: `example.com/user*` -* **Setting**: *Security Level* | **Value**: *High* -* **Setting**: *Cache Level* | **Value**: *Bypass* -* **Setting**: *Disable Apps* +- **If the URL matches**: `example.com/user*` +- **Setting**: _Cache Level_ | **Value**: _Bypass_ @@ -73,14 +69,14 @@ Certain resources on your domain will likely not change often. For these resourc #### Examples -In the following example page rule configuration, the target is a folder that holds the majority of the image assets as well as some other types of multimedia. +In the following example page rule configuration, the target is a folder that holds the majority of the image assets as well as some other types of multimedia. -* **If the URL matches**: `example.com/sites/default/files*` -* **Setting**: *Browser Cache TTL* | **Value**: *a day* -* **Setting**: *Cache Level |* **Value**: *Cache Everything* -* **Setting**: *Edge Cache TTL |* **Value**: *7 days* +- **If the URL matches**: `example.com/sites/default/files*` +- **Setting**: _Browser Cache TTL_ | **Value**: _a day_ +- **Setting**: _Cache Level |_ **Value**: _Cache Everything_ +- **Setting**: _Edge Cache TTL |_ **Value**: _7 days_ @@ -88,10 +84,10 @@ The following example page rule configuration applies unique rules for critical -* **If the URL matches**: `example.com/terms-of-service` -* **Setting**: *Browser Cache TTL* | **Value**: *a day* -* **Setting**: *Always Online |* **Value**: *On* -* **Setting**: *Cache Level* | **Value**: *Cache Everything* -* **Setting**: *Edge Cache TTL* | **Value**: *a month* +- **If the URL matches**: `example.com/terms-of-service` +- **Setting**: _Browser Cache TTL_ | **Value**: _a day_ +- **Setting**: _Always Online |_ **Value**: _On_ +- **Setting**: _Cache Level_ | **Value**: _Cache Everything_ +- **Setting**: _Edge Cache TTL_ | **Value**: _a month_ diff --git a/src/content/docs/rules/page-rules/reference/settings.mdx b/src/content/docs/rules/page-rules/reference/settings.mdx index b56275f3520562..6d750cd2627a28 100644 --- a/src/content/docs/rules/page-rules/reference/settings.mdx +++ b/src/content/docs/rules/page-rules/reference/settings.mdx @@ -42,7 +42,7 @@ Below is the full list of settings available, presented in the order that they a | Edge Cache TTL | Specify how long to cache a resource in the Cloudflare global network. *Edge Cache TTL* is not visible in response headers. | All | | [Email Obfuscation](/waf/tools/scrape-shield/email-address-obfuscation/) | Turn on or off **Email Obfuscation**. | All | | Forwarding URL | Redirects one URL to another using an `HTTP 301/302` redirect. Refer to [Wildcard matching and referencing](/rules/page-rules/reference/wildcard-matching/). | All | -| [Host Header Override](/rules/page-rules/how-to/rewrite-host-headers/) | Apply a specific host header. | Enterprise | +| Host Header Override | Apply a specific host header. | Enterprise | | IP Geolocation Header | Cloudflare adds a `CF-IPCountry` HTTP header containing the country code that corresponds to the visitor. | All | | [Mirage](/speed/optimization/images/mirage/) | Turn on or off **Mirage**. | Pro and above | | [Opportunistic Encryption](/ssl/edge-certificates/additional-options/opportunistic-encryption/) | Turn on or off the **Opportunistic Encryption**.  | All | @@ -50,7 +50,7 @@ Below is the full list of settings available, presented in the order that they a | Origin Error Page Pass-thru | Turn on or off Cloudflare error pages generated from issues sent from the origin server. If enabled, this setting triggers error pages issued by the origin. | Enterprise | | [Polish](/images/polish/) | Apply options from the **Polish** feature of the Cloudflare **Speed** app. | Pro and above | | [Query String Sort](/cache/advanced-configuration/query-string-sort/) | Turn on or off the reordering of query strings. When query strings have the same structure, caching improves. | Enterprise | -| [Resolve Override](/rules/page-rules/how-to/override-url-or-ip-address/) | Change the origin address to the value specified in this setting. | Enterprise | +| Resolve Override | Change the origin address to the value specified in this setting. | Enterprise | | [Respect Strong ETags](/cache/reference/etag-headers/) | Turn on or off byte-for-byte equivalency checks between the Cloudflare cache and the origin server. | Enterprise | | Response Buffering | Turn on or off whether Cloudflare should wait for an entire file from the origin server before forwarding it to the site visitor. By default, Cloudflare sends packets to the client as they arrive from the origin server. | Enterprise | | [Rocket Loader](/speed/optimization/content/rocket-loader/) | Turn on or off **Rocket Loader** in the Cloudflare **Speed** app. | All | diff --git a/src/content/docs/rules/snippets/create-dashboard.mdx b/src/content/docs/rules/snippets/create-dashboard.mdx index b8750d95ad7b16..809b3a19541e46 100644 --- a/src/content/docs/rules/snippets/create-dashboard.mdx +++ b/src/content/docs/rules/snippets/create-dashboard.mdx @@ -13,20 +13,24 @@ import { Render } from "~/components"; 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and website. -2. Go to **Rules** > **Snippets**, and select **Create a Snippet**. +2. Go to **Rules** > **Snippets**. -3. In **Snippet name**, enter a descriptive name for the snippet. You cannot change the name after creating the snippet. +3. (Optional) If you have not created any snippets yet, select one of the snippet templates that addresses a common use case. Then, review and adjust the proposed snippet code. -4. Enter the snippet's JavaScript code in the code editor. You can test how your snippet will handle incoming requests using the **HTTP** and **Preview** tabs. + To start from scratch, select **Create Snippet**. -5. Select **Snippet rule** to configure when the snippet will run. +4. In **Snippet name**, enter a descriptive name for the snippet. You cannot change the name after creating the snippet. -6. Under **Run this Snippet if incoming requests match**, select if you wish to run the snippet only for requests that match a custom filter expression or for all incoming requests. +5. Enter the snippet's JavaScript code in the code editor. You can test how your snippet will handle incoming requests using the **HTTP** and **Preview** tabs. -7. (Optional) To define a custom expression, use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](/ruleset-engine/rules-language/expressions/edit-expressions/). +6. Select **Snippet rule** to configure when the snippet will run. -8. Select **Done**. +7. Under **Run this Snippet if incoming requests match**, select if you wish to run the snippet only for requests that match a custom filter expression or for all incoming requests. -9. To deploy your snippet, select **Deploy**. If you are not ready to deploy your snippet, open the dropdown next to **Deploy** and select **Save as Draft**. +8. (Optional) To define a custom expression, use the Expression Builder (specifying one or more values for **Field**, **Operator**, and **Value**) or manually enter an expression using the Expression Editor. For more information, refer to [Edit expressions in the dashboard](/ruleset-engine/rules-language/expressions/edit-expressions/). - +9. Select **Done**. + +10. To deploy your snippet, select **Deploy**. If you are not ready to deploy your snippet, open the dropdown next to **Deploy** and select **Save as Draft**. + + diff --git a/src/content/docs/rules/snippets/errors.mdx b/src/content/docs/rules/snippets/errors.mdx index 7399b203d540ff..5a0deb1bbeada2 100644 --- a/src/content/docs/rules/snippets/errors.mdx +++ b/src/content/docs/rules/snippets/errors.mdx @@ -1,16 +1,16 @@ --- -title: Common errors +title: Snippets troubleshooting pcx_content_type: troubleshooting sidebar: order: 8 + label: Troubleshooting head: - tag: title - content: Common errors + content: Snippets troubleshooting --- import { GlossaryTooltip } from "~/components"; -Cloudflare Snippets may encounter specific errors during execution. Here are the common errors: ## Error 1201: Snippet tried to continue to origin multiple times @@ -27,3 +27,11 @@ This error occurs when the number of subrequest [limits](/rules/snippets/#availability) for your plan. Each subrequest counts against your limit, including any redirects within a subrequest chain. + +## Snippets cannot be renamed + +The name you define when creating a Snippet will be used as the Snippet ID and cannot be edited afterwards. + +### Resolution + +To change the name of your Snippet, create a new Snippet and delete the old one. diff --git a/src/content/docs/rules/snippets/index.mdx b/src/content/docs/rules/snippets/index.mdx index a7ba864ae60f6e..b8bc56c8b51aec 100644 --- a/src/content/docs/rules/snippets/index.mdx +++ b/src/content/docs/rules/snippets/index.mdx @@ -11,7 +11,7 @@ head: content: Cloudflare Snippets (beta) --- -import { FeatureTable, GlossaryTooltip, Render } from "~/components"; +import { FeatureTable, GlossaryTooltip, Render, Card } from "~/components"; Cloudflare Snippets (beta) provide a powerful and flexible way to customize the behavior of your website or application using short pieces of JavaScript code. With Snippets, you can modify HTTP response headers, implement JWT validation, perform complex redirects, and much more. @@ -24,12 +24,16 @@ For code samples addressing common use cases, please refer to the [Examples](/ru ## Snippets elements -To create and deploy a Snippet, you need to define the following elements: +To create and deploy a snippet, you need to define the following elements: - **Code snippet**: JavaScript code to be executed during the request-handling process. -- **Snippet rule**: A [filter expression](/ruleset-engine/rules-language/expressions/) that determines which requests the Snippet will be applied to. Each Snippet can only be associated with one Snippet Rule. +- **Snippet rule**: A [filter expression](/ruleset-engine/rules-language/expressions/) that determines which requests the Snippet will be applied to. Each snippet can only be associated with one snippet rule. -For more information, refer to the [How it works](/rules/snippets/how-it-works/) and [Create a snippet in the dashboard](/rules/snippets/create-dashboard/) sections. +For more information, refer to [How it works](/rules/snippets/how-it-works/) and [Create a snippet in the dashboard](/rules/snippets/create-dashboard/). + +:::note +If you have used the Cloudflare API to create a code snippet that is not associated with a snippet rule, the Cloudflare dashboard will show that code snippet in a separate tab called **Unused Snippets**. You can either edit the snippet code and associate it with a snippet rule, or delete the unused code snippet. +::: ## Templates @@ -41,13 +45,11 @@ For more information, refer to the [How it works](/rules/snippets/how-it-works/) -:::caution[Redirects will count as subrequests] Each subrequest in a redirect chain counts against the subrequest limit. This means that if a subrequest was redirected it would count as two subrequests. To avoid issues, ensure that you make a subrequest to the end location of the redirect chain. -::: ## Limits -Cloudflare Snippets are lightweight compared to [Cloudflare Workers](/workers/). The following limits apply: +Cloudflare Snippets are designed for fast, lightweight edge logic. The following limits apply: | Description | All plans | | -------------------------- | --------- | @@ -55,6 +57,12 @@ Cloudflare Snippets are lightweight compared to [Cloudflare Workers](/workers/). | Maximum memory | 2 MB | | Maximum total package size | 32 KB | + + +Explore our [detailed guide](/rules/snippets/when-to-use/) for best practices, real-world use cases, and example implementations. + + + ## Execution order diff --git a/src/content/docs/rules/snippets/when-to-use.mdx b/src/content/docs/rules/snippets/when-to-use.mdx new file mode 100644 index 00000000000000..00fb178abc15ec --- /dev/null +++ b/src/content/docs/rules/snippets/when-to-use.mdx @@ -0,0 +1,571 @@ +--- +title: When to use Snippets vs Workers +pcx_content_type: design-guide +sidebar: + order: 8 +--- + +This guide helps you determine when to use Snippets or Workers on Cloudflare's global network. It provides best practices, comparisons, and real-world use cases to help you choose the right product for your workload. + +## What are Snippets? + +Cloudflare Snippets provide a fast, declarative way to modify HTTP requests and responses at the edge — without requiring a full-stack compute platform. Snippets extend [Cloudflare Rules](/rules/) by allowing you to write JavaScript-based logic that modifies requests before they reach an origin and responses after they return from upstream. + +Snippets enable you to: + +- Modify headers, validate JWTs, and implement complex rewrites or redirects. +- Retry failed requests to different origins and apply custom caching strategies. +- Execute multiple Snippets sequentially, with each Snippet modifying the request or response before handing it off to the next. + +Snippets are included at no additional cost in [all paid plans](/rules/snippets/#availability), making them the preferred solution for lightweight edge logic. + +## What are Workers? + +By contrast, [Cloudflare Workers](/workers/) provide a full-stack compute platform designed for applications requiring state, compute, and integrations with Cloudflare’s [Developer Platform](/learning-paths/workers/devplat/intro-to-devplat/). Workers operate on a [usage-based pricing model](/workers/platform/pricing/) and include a free tier. + +--- + +## Choosing the right product + +Snippets are ideal for fast, cost-free request and response modifications at the edge. They extend [Cloudflare Rules](/rules/) without requiring additional infrastructure or external solutions. + +### When to use Snippets + +- Ultra-fast traffic modifications applied directly on Cloudflare's network. +- Extend Cloudflare Rules beyond built-in actions for greater control. +- Simplify CDN migrations by replacing VCL, EdgeWorkers, or on-premise logic. +- Modify headers, cache responses, and perform redirects. +- Integrate edge logic into development workflows using JavaScript. + +### What Snippets are not designed for + +- Persistent state management (for example, session storage or databases). +- Compute-intensive tasks (for example, image transformations or [AI inference](/workers-ai/)). +- Deep integrations with [Developer Platform](/learning-paths/workers/devplat/intro-to-devplat/) services like [Durable Objects](/durable-objects/) or [D1](/d1/). +- Use cases requiring advanced runtime features, such as: + - [Environment variables](/workers/configuration/environment-variables/) + - [Bindings](/workers/runtime-apis/bindings/) + - [Cron triggers](/workers/configuration/cron-triggers/) + - High [compute limits](/rules/snippets/#limits) + +### Key features + +- Ultra-fast, edge-optimized execution, powered by [Ruleset Engine](/ruleset-engine/) and [Workers runtime](/workers/runtime-apis/). +- Included at no additional cost on [all paid plans](/rules/snippets/#availability). +- Granular request matching using dozens of request attributes, such as [URI](/ruleset-engine/rules-language/fields/reference/http.request.full_uri/), [user-agent](/ruleset-engine/rules-language/fields/reference/http.user_agent/), and [cookies](/ruleset-engine/rules-language/fields/reference/http.request.cookies/). +- Sequential execution – multiple Snippets [can run](/rules/snippets/how-it-works/) on the same request, applying modifications step by step. +- Native integration with [Cloudflare Rules](/rules/) – Snippets inherit request modifications from other products running in earlier [request phases](/ruleset-engine/reference/phases-list/#request-phases). +- JavaScript and Web APIs support, including: + - [Fetch API](/workers/runtime-apis/fetch/) + - [Cache API](/workers/runtime-apis/cache/) +- Essential [Workers runtime](/workers/runtime-apis/) features, such as: + - [`request.cf` object](/workers/runtime-apis/request/#incomingrequestcfproperties) + - [`HTMLRewriter`](/workers/runtime-apis/html-rewriter/) +- Automated deployment and versioning via [Terraform](/rules/snippets/create-terraform/). + +--- + +## Snippets vs Workers: Feature comparison + +| Feature | Snippets | Workers | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------: | :-----: | +| Execute scripts based on request attributes (for example, headers, geolocation, and cookies) | ✅ | ❌ | +| Execute code on a specific URL route | ✅ | ✅ | +| Modify HTTP requests/responses or serve a [different response](/rules/snippets/examples/maintenance/) | ✅ | ✅ | +| [Add](/rules/snippets/examples/hex-timestamp/), [remove](/rules/snippets/examples/remove-response-headers/), or [rewrite](/rules/snippets/examples/override-set-cookies-value/) headers dynamically | ✅ | ✅ | +| [Cache](/rules/snippets/examples/custom-cache/) assets at the edge | ✅ | ✅ | +| Route traffic dynamically between [origin servers](/rules/snippets/examples/serve-different-origin/) | ✅ | ✅ | +| [Authenticate](/rules/snippets/examples/auth-with-headers/) requests, [pre-sign](/cache/interaction-cloudflare-products/waf-snippets/) URLs, run [A/B testing](/rules/snippets/examples/ab-testing-same-url/) | ✅ | ✅ | +| Define logic using [JavaScript and Web APIs](/workers/languages/javascript/) | ✅ | ✅ | +| Perform compute-heavy tasks (for example, [AI](/workers-ai/), [image transformations](/images/transform-images/transform-via-workers/)) | ❌ | ✅ | +| Store persistent data (for example, [KV](/kv/), [Durable Objects](/durable-objects/), and [D1](/d1/)) | ❌ | ✅ | +| Build [APIs](/d1/tutorials/build-a-comments-api/) and [full-stack applications](/pages/framework-guides/deploy-an-astro-site/#video-tutorial) | ❌ | ✅ | +| Use TypeScript, Python, Rust, or other programming [languages](/workers/languages/) | ❌ | ✅ | +| Support non-HTTP [protocols](/workers/reference/protocols/) | ❌ | ✅ | +| Analyze execution [logs](/workers/observability/logs/workers-logs/) and track performance metrics | ❌ | ✅ | +| Deploy via [command-line interface (CLI)](/workers/wrangler/) | ❌ | ✅ | +| Roll out gradually, roll back to previous [versions](/workers/configuration/versions-and-deployments/) | ❌ | ✅ | +| Optimize execution with [Smart Placement](/workers/configuration/smart-placement/) | ❌ | ✅ | + +--- + +## Code examples: Common Snippets templates + +Below are practical use cases demonstrating Snippets in action. You can find more templates to get started in the [Examples](/rules/snippets/examples/) section. + +### Modify HTTP headers + +Modifies request and response headers dynamically. + +```javascript +export default { + async fetch(request) { + // Get the current timestamp + const timestamp = Date.now(); + + // Convert the timestamp to hexadecimal format + const hexTimestamp = timestamp.toString(16); + + // Clone the request and add the custom header with HEX timestamp + const modifiedRequest = new Request(request, { + headers: new Headers(request.headers), + }); + modifiedRequest.headers.set("X-Hex-Timestamp", hexTimestamp); + + // Pass the modified request to the origin + const response = await fetch(modifiedRequest); + + // Clone the response so that it's no longer immutable + const newResponse = new Response(response.body, response); + + // Add a custom header with a value to the response + newResponse.headers.append( + "x-snippets-hello", + "Hello from Cloudflare Snippets", + ); + + // Delete headers from the response + newResponse.headers.delete("x-header-to-delete"); + newResponse.headers.delete("x-header2-to-delete"); + + // Adjust the value for an existing header in the response + newResponse.headers.set("x-header-to-change", "NewValue"); + + // Serve modified response to the visitor + return newResponse; + }, +}; +``` + +### Serve a custom maintenance page + +Routes traffic to a maintenance page when your origin is undergoing a planned maintenance. + +```javascript +export default { + async fetch(request) { + return new Response( + ` + + + + + We'll Be Right Back! + + + +

    We'll Be Right Back!

    +

    Our site is undergoing maintenance. Check back soon!

    + + + `, + { status: 503, headers: { "Content-Type": "text/html" } }, + ); + }, +}; +``` + +### Custom cache + +Performs programmatic caching at the edge to reduce origin load. + +```javascript +const CACHE_DURATION = 30 * 24 * 60 * 60; // 30 days + +export default { + async fetch(request) { + const cache = caches.default; + const cacheKey = new Request(request.url, { method: "GET" }); + + let response = await cache.match(cacheKey); + if (!response) { + response = await fetch(request); + response = new Response(response.body, response); + response.headers.set("Cache-Control", `s-maxage=${CACHE_DURATION}`); + await cache.put(cacheKey, response.clone()); + } + return response; + }, +}; +``` + +### Redirect based on country code + +Redirects visitors based on their geographic location. + +```javascript +export default { + async fetch(request) { + const country = request.cf.country; + const redirectMap = { + US: "https://example.com/us", + EU: "https://example.com/eu", + }; + if (redirectMap[country]) + return Response.redirect(redirectMap[country], 301); + return fetch(request); + }, +}; +``` + +### Redirect 403 Forbidden to a different page + +If the origin responded with `403 Forbidden` error code, redirects visitor to a different page. + +```javascript +export default { + async fetch(request) { + // Send original request to the origin + const response = await fetch(request); + // Check if origin responded with 403 status code + if (response.status == 403) { + // If so, redirect to this URL + const destinationURL = "https://example.com"; + // With this status code + const statusCode = 301; + // Serve redirect + return Response.redirect(destinationURL, statusCode); + } + // Otherwise, serve origin's response + else { + return response; + } + }, +}; +``` + +### Retry to another origin + +If the response to the original request is not `200 OK` or a redirect, sends to another origin. + +```javascript +export default { + async fetch(request) { + // Send original request to the origin + const response = await fetch(request); + + // If response is not 200 OK or a redirect, send to another origin + if (!response.ok && !response.redirected) { + // First, clone the original request to construct a new request + const newRequest = new Request(request); + // Add a header to identify a re-routed request at the new origin + newRequest.headers.set("X-Rerouted", "1"); + // Clone the original URL + const url = new URL(request.url); + // Send request to a different origin / hostname + url.hostname = "example.com"; + // Serve response to the new request from the origin + return await fetch(url, newRequest); + } + + // If response is 200 OK or a redirect, serve it + return response; + }, +}; +``` + +### Remove fields from API response + +If the origin responds with JSON, deletes sensitive fields before returning a response to the visitor. + +```javascript +export default { + async fetch(request) { + // Send original request to the origin + const response = await fetch(request); + // Check if origin responded with JSON + try { + // Parse API response as JSON + var api_response = response.json(); + // Specify the fields you want to delete. For example, to delete "botManagement" array from parsed JSON: + delete api_response.botManagement; + // Serve modified API response + return Response.json(api_response); + } catch (err) { + // On failure, serve unmodified origin's response + return response; + } + }, +}; +``` + +### Set CORS headers + +Adjusts [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers and handles preflight requests. + +```javascript +// Define CORS headers +const corsHeaders = { + "Access-Control-Allow-Origin": "*", // Replace * with your allowed origin(s) + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", // Adjust allowed methods as needed + "Access-Control-Allow-Headers": "Content-Type, Authorization", // Adjust allowed headers as needed + "Access-Control-Max-Age": "86400", // Adjust max age (in seconds) as needed +}; + +export default { + async fetch(request) { + // Make a copy of the request to modify its headers + const modifiedRequest = new Request(request); + + // Handle preflight requests (OPTIONS) + if (request.method === "OPTIONS") { + return new Response(null, { + headers: { + ...corsHeaders, + }, + status: 200, // Respond with OK status for preflight requests + }); + } + + // Pass the modified request through to the origin + const response = await fetch(modifiedRequest); + + // Make a copy of the response to modify its headers + const modifiedResponse = new Response(response.body, response); + + // Set CORS headers on the response + Object.keys(corsHeaders).forEach((header) => { + modifiedResponse.headers.set(header, corsHeaders[header]); + }); + + return modifiedResponse; + }, +}; +``` + +### Rewrite links on HTML pages + +Replaces outdated links without having to make changes on your origin. + +```javascript +export default { + async fetch(request) { + // Define the old hostname here. + const OLD_URL = "oldsite.com"; + // Then add your new hostname that should replace the old one. + const NEW_URL = "newsite.com"; + + class AttributeRewriter { + constructor(attributeName) { + this.attributeName = attributeName; + } + element(element) { + const attribute = element.getAttribute(this.attributeName); + if (attribute) { + element.setAttribute( + this.attributeName, + attribute.replace(OLD_URL, NEW_URL), + ); + } + } + } + + const rewriter = new HTMLRewriter() + .on("a", new AttributeRewriter("href")) + .on("img", new AttributeRewriter("src")); + + const res = await fetch(request); + const contentType = res.headers.get("Content-Type"); + + // If the response is HTML, it can be transformed with + // HTMLRewriter -- otherwise, it should pass through + if (contentType.startsWith("text/html")) { + return rewriter.transform(res); + } else { + return res; + } + }, +}; +``` + +### Slow down requests + +Defines a delay to be used when incoming requests match your rule. Useful for suspicious requests. + +```javascript +export default { + async fetch(request) { + // Define delay + const delay_in_seconds = 5; + // Introduce a delay + await new Promise((resolve) => + setTimeout(resolve, delay_in_seconds * 1000), + ); // Set delay in milliseconds + + // Pass the request to the origin + const response = await fetch(request); + return response; + }, +}; +``` + +--- + +## Using Snippets and Workers together + +While Snippets and Workers have distinct capabilities, they can work together to handle complex traffic workflows. + +To avoid conflicts, Snippets and Workers should operate on separate request paths rather than running on the same URL. Have them fetch their respective URLs as a subrequest within their logic, ensuring smooth execution and caching behavior. + +### Example 1: Passing data between Snippets and Workers + +Snippets can modify incoming requests before they reach a Worker, and Workers can read these modifications, perform additional transformations, and pass them downstream. + +#### Snippet: Add a custom header + +```javascript +export default { + async fetch(request) { + // Get the current timestamp + const timestamp = Date.now(); + const hexTimestamp = timestamp.toString(16); + + // Clone request and add a custom header + const modifiedRequest = new Request(request, { + headers: new Headers(request.headers), + }); + modifiedRequest.headers.set("X-Hex-Timestamp", hexTimestamp); + + console.log(`X-Hex-Timestamp: ${hexTimestamp}`); + + // Pass modified request to origin + return fetch(modifiedRequest); + }, +}; +``` + +#### Worker: Read a header and add it to the response + +```javascript +export default { + async fetch(request) { + const response = await fetch("https://{snippets_url}", request); // Ensure {snippets_url} points to the endpoint modified by Snippets + const newResponse = new Response(response.body, response); + + let hexTimestamp = request.headers.get("X-Hex-Timestamp") || "null"; + console.log(hexTimestamp); + + newResponse.headers.set("X-Hex-Timestamp", hexTimestamp); + return newResponse; + }, +}; +``` + +**Result:** The Snippet sets `X-Hex-Timestamp`, which the Worker reads and forwards to the origin. + +### Example 2: Caching Worker responses using Snippets + +A Worker performs compute-heavy processing (for example, image transformation), while a Snippet serves cached results to avoid unnecessary Worker execution. This can be helpful in situations when running Workers [before cache](/cache/interaction-cloudflare-products/workers/) is not desirable. + +#### Worker: Transform and cache responses + +```javascript +export default { + async fetch(request) { + const url = new URL(request.url); + url.hostname = "origin.example.com"; // Ensure this hostname points to the origin where the resource is hosted + + const newRequest = new Request(url, request); + const customKey = `https://${url.hostname}${url.pathname}`; // This custom cache key should be the same in both Worker and Snippet configuration for cache to work + + // Fetch and modify response + const response = await fetch(newRequest); + const newResponse = new Response(response.body, response); + + // Cache the transformed response + const cache = caches.default; + const cachedResponse = newResponse.clone(); + cachedResponse.headers.set("X-Cached-In-Workers", "true"); + await cache.put(customKey, cachedResponse); + + newResponse.headers.set("X-Retrieved-From-Workers", "true"); + return newResponse; + }, +}; +``` + +#### Snippet: Serve cached responses or forward to Worker + +```javascript +export default { + async fetch(request) { + const url = new URL(request.url); + url.hostname = "origin.example.com"; // Ensure this hostname points to the origin where the resource is hosted + const cacheKey = `https://${url.hostname}${url.pathname}`; // This custom cache key should be the same in both Worker and Snippet configuration for cache to work + + // Access cache + const cache = caches.default; + let response = await cache.match(cacheKey); + + if (!response) { + console.log(`Cache miss for: ${cacheKey}. Fetching from Worker...`); + url.hostname = "worker.example.com"; // Ensure this hostname points to the Workers route + response = await fetch(new Request(url, request)); + + // Cache the response for future use + response = new Response(response.body, response); + response.headers.set("Cache-Control", `s-maxage=3600`); + response.headers.set("x-snippets-cache", "stored"); + } else { + console.log(`Cache hit for: ${cacheKey}`); + response = new Response(response.body, response); + response.headers.set("x-snippets-cache", "hit"); + } + + return response; + }, +}; +``` + +**Result:** The transformed response (`X-Cached-In-Workers: true`) is served from cache, avoiding redundant Worker execution (`X-Retrieved-From-Workers` is not present). When cache expires, the Snippet fetches a fresh version. + +--- + +## Migration between Snippets and Workers + +Snippets and Workers share the same [Workers runtime](/workers/runtime-apis/), meaning JavaScript code that does not rely on bindings, persistent storage, or advanced execution features can be migrated seamlessly between them. + +### When to migrate workloads to Snippets + +You should consider migrating a Worker to Snippets if it: + +- Only modifies headers, redirects, caching rules, or origin routing. +- Does not require bindings, persistent storage, or external integrations. +- Is a lightweight JavaScript function with simple logic. +- Needs to run an unlimited number of times for free on a Pro, Business, or Enterprise plan. + +Migrating to Snippets allows you to: + +- Leverage advanced request matching via the [Ruleset Engine](/ruleset-engine/). +- Eliminate usage-based billing — Snippets are [included at no cost](/rules/snippets/#availability) on all paid plans. +- Simplify management by integrating traffic modifications directly into Cloudflare Rules. + +### When to migrate workloads to Workers + +You should migrate from Snippets to Workers if your logic: + +- Exceeds execution time, memory, or other [limits](/rules/snippets/#limits). +- Requires persistent state management, such as: + - [Key-Value (KV) storage](/kv/) + - [SQL databases (D1)](/d1/) + - [Durable Objects](/durable-objects/) +- Performs compute-intensive operations, including: + - [AI inference](/workers-ai/) + - [Vector search](/vectorize/) + - [Image transformations](/images/transform-images/transform-via-workers/) +- Interacts with Cloudflare's [Developer Platform](/learning-paths/workers/devplat/intro-to-devplat/). +- Requires [unit testing](/workers/testing/). +- Needs deployment automation via CLI ([Wrangler](/workers/wrangler/)). + +If your Snippet reaches the limits of execution time, memory, or functionality, transitioning to Workers ensures your logic can scale without restrictions. + +--- + +## Conclusion + +Cloudflare Snippets provide a production-ready solution for fast, declarative edge traffic logic, bridging the gap between [Cloudflare Rules](/rules/) and [Developer Platform](/learning-paths/workers/devplat/intro-to-devplat/). + +Snippets and Workers solve different problems: + +- Use Snippets for fast, lightweight traffic modifications at the edge, including header rewrites, caching, redirects, origin routing, custom responses, A/B testing and authentication. +- Workers are built for advanced compute, persistent state, and full-stack applications. diff --git a/src/content/docs/rules/transform/examples/normalize-encoded-slash.mdx b/src/content/docs/rules/transform/examples/normalize-encoded-slash.mdx new file mode 100644 index 00000000000000..484ef3933f5bf2 --- /dev/null +++ b/src/content/docs/rules/transform/examples/normalize-encoded-slash.mdx @@ -0,0 +1,38 @@ +--- +pcx_content_type: example +summary: Create a rewrite URL rule (part of Transform Rules) to normalize encoded forward slashes (`%2F`) in the request path to standard slashes (`/`). +products: + - Transform Rules +operation: + - Rewrite URL +title: Normalize encoded slashes in URL path +description: Create a rewrite URL rule (part of Transform Rules) to normalize encoded forward slashes (`%2F`) in the request path to standard slashes (`/`). +--- + +import { Example } from "~/components"; + +Different web servers and applications handle encoded forward slashes (`%2F`) in URLs differently. Cloudflare follows [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986), which specifies that `%2F` **should not** be automatically normalized to `/` because `/` is a reserved character in URLs, and decoding it might change the intended meaning of the path. + +However, many origin servers **do** automatically decode `%2F` into `/` when processing requests. If your origin server behaves this way, you may want to apply the same normalization at Cloudflare’s edge to ensure consistency in request handling, rule evaluation, and logging. + +## How to normalize `%2F` + +To normalize encoded forward slashes (`%2F`) to standard slashes (`/`) in the request path before [subsequent](/ruleset-engine/reference/phases-list/) rule evaluation, create a new rewrite URL rule and define a dynamic URL path rewrite using [`url_decode()`](/ruleset-engine/rules-language/functions/#url_decode) function: + + + +Text in **Expression Editor**: + +```txt +(lower(raw.http.request.full_uri) wildcard "*%2f*") +``` + +Text after **Path** > **Rewrite to...** > _Dynamic_: + +```txt +url_decode(http.request.uri.path) +``` + + + +This transformation ensures that `%2F` is always treated as `/` in the request path. This is particularly useful when setting up rules that depend on URL path matching, as it prevents discrepancies caused by differing normalization behaviors. \ No newline at end of file diff --git a/src/content/docs/rules/transform/managed-transforms/configure.mdx b/src/content/docs/rules/transform/managed-transforms/configure.mdx index 7256d5fac1210a..c4be6f3e786903 100644 --- a/src/content/docs/rules/transform/managed-transforms/configure.mdx +++ b/src/content/docs/rules/transform/managed-transforms/configure.mdx @@ -3,7 +3,6 @@ title: Configure Managed Transforms pcx_content_type: how-to sidebar: order: 1 -head: [] description: Learn how to configure Managed Transforms. --- @@ -13,11 +12,9 @@ import { Details, TabItem, Tabs, Render } from "~/components"; 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and website. -2. Go to **Rules** > **Overview**. +2. Go to **Rules** > **Settings**. -3. Next to **Request Header Transform Rules** or **Response Header Transform Rules**, select **Go to Managed Transforms**. - -4. Enable or disable the [desired Managed Transforms](/rules/transform/managed-transforms/reference/) by selecting the toggle next to each entry. The Cloudflare dashboard will only list available Managed Transforms according to your Cloudflare plan and product subscriptions. +3. In the **Managed Transforms** tab, enable or disable the [desired Managed Transforms](/rules/transform/managed-transforms/reference/) by selecting the toggle next to each entry. Some Managed Transforms may not be available in your Cloudflare plan or product subscriptions. diff --git a/src/content/docs/rules/transform/managed-transforms/reference.mdx b/src/content/docs/rules/transform/managed-transforms/reference.mdx index 9aa6936bd4b4d4..26bcaf3b8f79a1 100644 --- a/src/content/docs/rules/transform/managed-transforms/reference.mdx +++ b/src/content/docs/rules/transform/managed-transforms/reference.mdx @@ -1,6 +1,7 @@ --- title: Available Managed Transforms pcx_content_type: reference +description: Learn about Cloudflare's Managed Transforms for modifying HTTP headers, including bot protection, TLS client auth, and leaked credentials checks. sidebar: order: 2 --- diff --git a/src/content/docs/rules/transform/request-header-modification/index.mdx b/src/content/docs/rules/transform/request-header-modification/index.mdx index 8b8d8e126e5b10..7f16dd49e7c2dd 100644 --- a/src/content/docs/rules/transform/request-header-modification/index.mdx +++ b/src/content/docs/rules/transform/request-header-modification/index.mdx @@ -6,6 +6,7 @@ sidebar: head: - tag: title content: HTTP request header modification rules +description: Learn how to modify HTTP request headers with Cloudflare's rules. --- import { Render } from "~/components"; diff --git a/src/content/docs/rules/transform/url-rewrite/index.mdx b/src/content/docs/rules/transform/url-rewrite/index.mdx index 4435823590d01e..faa17dc5a8dbbb 100644 --- a/src/content/docs/rules/transform/url-rewrite/index.mdx +++ b/src/content/docs/rules/transform/url-rewrite/index.mdx @@ -20,7 +20,7 @@ Use a URL rewrite to return the content of a URL while displaying a different UR :::caution -You cannot rewrite the hostname using a rewrite URL rule. To rewrite the hostname, use an [origin rule](/rules/origin-rules/) or a [Page Rule](/rules/page-rules/how-to/override-url-or-ip-address/). +You cannot rewrite the hostname using a rewrite URL rule. To rewrite the hostname, use an [origin rule](/rules/origin-rules/features/#dns-record). diff --git a/src/content/docs/rules/url-forwarding/bulk-redirects/create-dashboard.mdx b/src/content/docs/rules/url-forwarding/bulk-redirects/create-dashboard.mdx index 89b2bfb51b7c99..2f2fe5c8ed5e2d 100644 --- a/src/content/docs/rules/url-forwarding/bulk-redirects/create-dashboard.mdx +++ b/src/content/docs/rules/url-forwarding/bulk-redirects/create-dashboard.mdx @@ -16,9 +16,7 @@ To create Bulk Redirects in the Cloudflare dashboard you must: You can create Bulk Redirect Lists and Bulk Redirect Rules in the Cloudflare dashboard: - At the account level, in **Bulk Redirects**. -- At the zone level: - 1. Go to **Rules** > **Overview**. - 2. Next to **Redirect Rules** select **Go to Bulk Redirects**. +- At the zone level, go to **Rules** > **Settings** and select the **Bulk Redirects** tab. However, the lists and rules only exist at the account level and every zone in the same account will show the same items. diff --git a/src/content/docs/ruleset-engine/rules-language/expressions/index.mdx b/src/content/docs/ruleset-engine/rules-language/expressions/index.mdx index 37f0451375640b..53b4441379d613 100644 --- a/src/content/docs/ruleset-engine/rules-language/expressions/index.mdx +++ b/src/content/docs/ruleset-engine/rules-language/expressions/index.mdx @@ -41,7 +41,7 @@ Where: For example, this expression uses the `and` operator to target requests to `www.example.com` that are not on ports 80 or 443: ```txt -host eq www.example.com and not cf.edge.server_port in {80 443} +http.host eq "www.example.com" and not cf.edge.server_port in {80 443} ``` Compound expressions have the following general syntax: diff --git a/src/content/docs/ruleset-engine/rules-language/values.mdx b/src/content/docs/ruleset-engine/rules-language/values.mdx index d4703dbc36e7ca..4b6cf55607e1e6 100644 --- a/src/content/docs/ruleset-engine/rules-language/values.mdx +++ b/src/content/docs/ruleset-engine/rules-language/values.mdx @@ -14,7 +14,7 @@ The values that populate the lookup tables of the Rules language are drawn from - **Primitive properties** are obtained directly from the request (`http.request.uri.path`, for example). - **Derived values** are the product of a transformation, composition, or basic operation. For example, the transformation `lower(http.request.uri.path)` converts the value of `http.request.uri.path` to lowercase. -- **Computed values** are the product of a lookup, computation, or other intelligence. For example, Cloudflare uses a machine learning process to dynamically calculate threat scores, represented by the `cf.threat_score` field. +- **Computed values** are the product of a lookup, computation, or other intelligence. For example, Cloudflare uses a machine learning process to dynamically calculate attack scores, represented by `cf.waf.score*` fields. Besides these values, expressions may also contain literal values. These are static, known values that you incorporate into expressions to compare them with values from request/response fields with or without any transformations. diff --git a/src/content/docs/security-center/brand-protection.mdx b/src/content/docs/security-center/brand-protection.mdx index cd853605956d4b..b930b157a28f32 100644 --- a/src/content/docs/security-center/brand-protection.mdx +++ b/src/content/docs/security-center/brand-protection.mdx @@ -11,7 +11,7 @@ sidebar: import { AvailableNotifications, Render } from "~/components" :::note[User permission] -While the Brand Protection tool is in beta, you will need to request access by filling in the [sign-up form](http://cloudflare.com/lp/brandprotection). Only Super Admin and users with a Brand Protection role can access Brand Protection. +While the Brand Protection tool is in beta, all Cloudflare Enterprise customers have automatic access to Brand Protection, including five saved queries. Only Admin, Super Admin and users with a Brand Protection role can access Brand Protection ::: @@ -39,6 +39,19 @@ To start searching for new domains that might be trying to impersonate your bran In the section **Monitor Strings**, you can check all the string queries that you selected to monitor. You can delete, clone, or create notifications for a string query. Refer to [Brand Protection Alerts](#brand-protection-alerts) to set up notifications. +### Report abuse + +:::note[Submit abuse report] +You can only submit an abuse report if your domain is with [Cloudflare Registrar](https://www.cloudflare.com/products/registrar/), or if the IP used by the domain is hosted by Cloudflare. +::: + +To submit abuse reports directly from the dashboard: + +1. Go to the **Query name** you want to report. +2. Select **Report to Cloudflare**. +3. Fill in the details to submit an abuse report. +4. Select **Submit**. + ## Logo queries To set up a new logo query: diff --git a/src/content/docs/security-center/cloudforce-one/index.mdx b/src/content/docs/security-center/cloudforce-one/index.mdx index 7debafebc708d8..d81ee887f1a8b2 100644 --- a/src/content/docs/security-center/cloudforce-one/index.mdx +++ b/src/content/docs/security-center/cloudforce-one/index.mdx @@ -12,22 +12,28 @@ You must have a Cloudforce One subscription to access Cloudforce One on the dash Cloudforce One is a threat intelligence solution that offers threat research reports, brand protection, Request for Information (RFIs), and more. -## Cloudforce One Requests +To access Cloudforce One: -Cloudforce One allows you to review and manage Request for Information (RFIs) from the dashboard. +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. Go to **Security Center** > **Threat Intelligence**. -To review and manage Request for Information: +You can also use Cloudforce One via [REST API](https://developers.cloudflare.com/api/resources/cloudforce_one/subresources/requests/subresources/assets/). -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Go to **Security Center** > **Cloudforce One Requests**, then populate the required fields. +Cloudforce One Threat Intelligence displays the following information: -### Submit RFIs +- **Threat Events** to analyze threat intelligence data. +- **Priority Intelligence Requirements** to review and manage Cloudforce One Priority Intelligence Requirements (PIRs). PIRs are a structured approach to identifying intelligence gaps. +- **Requests for Information** to submit specific queries and requests directly into Cloudforce One's analysis queue. +- **Reports** to get the latest Cloudforce One Threat reports. + +## Submit RFIs To submit RFIs (Request for Information): 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Select **Cloudforce One Requests** > Select **New Request**. -3. Fill in the required fields, then select **Save**. +2. Go to **Security Center** > **Threat Intelligence** > **Requests for Information**. +3. Select **New Request**. +4. Fill in the required fields, then select **Save**. Once you select **Save**, the dashboard will display an overview of the shared information consisting of: @@ -40,10 +46,39 @@ The **Responses** section allows you to add clarifying questions and comments. To view your RFI, select **Cloudforce One Requests** on the sidebar, locate your RFI, then select **View**. From here, you can also choose to edit your existing RFI by selecting **Edit**. +To delete your RFI, the status must be `Open`. Go to the RFI you want to delete, and select **Delete**. On the pop-up, select **Delete** to confirm deletion. Once Cloudflare accepts and begins processing RFIs, you will not be able to delete RFIs. + ### Upload and download attachment You can also choose to upload and download an attachment. Under **Attachments**, select the file you want to upload, then select **Save**. -To download an attachment, select **Download** on the attachment. \ No newline at end of file +To download an attachment, select **Download** on the attachment. + +## Analyze threat events + +Threat events allow you to protect your assets and respond to emerging threats. + +To access and analyze threat intelligence data on the dashboard: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. Select **Security Center** > **Threat Intelligence**. + +You can also access threat events via the [API](/api/resources/cloudforce_one/subresources/threat_events/). + +You can filter **Threat Events** by: + +- Attacker +- Attacker Country +- Target Country +- Target Industry +- TLP (Traffic Light Protocol) +- Indicator Type +- [Kill Chain](https://en.wikipedia.org/wiki/Cyber_kill_chain) +- Tags +- Event Category + +You can also filter by **Date range**. + +Some events will not display **Target Country** and **Target Industry** because they are unknown information. There may be situations where the attacker's information is unknown. When Cloudflare finds a new attacker, the attacker will be assigned a new name. \ No newline at end of file diff --git a/src/content/docs/security-center/cloudforce-one/open-port-scanning.mdx b/src/content/docs/security-center/cloudforce-one/open-port-scanning.mdx new file mode 100644 index 00000000000000..adb331fa2dae8b --- /dev/null +++ b/src/content/docs/security-center/cloudforce-one/open-port-scanning.mdx @@ -0,0 +1,192 @@ +--- +pcx_content_type: how-to +title: Open Port Scanning +sidebar: + order: 11 + badge: + text: Beta +--- + +import { Details } from "~/components" + + + +Open Port Scanning allows [Magic Transit](/magic-transit/) and [Bring your Own IPs](/byoip/) users to efficiently monitor IP ranges for security vulnerabilities. This API enables users to scan their designated IP ranges, detect any open ports, and receive daily notifications regarding newly opened ports. + +You can access this feature via the [API](/api/resources/cloudforce_one/subresources/scans/subresources/config/). + +## Prerequisites + +- Cloudforce One Administrator, Administrator and Super Administrator roles. +- Account token: **Custom API Token** > **Cloudforce One:Edit**. + +To create a custom API token: + +1. From the [Cloudflare dashboard](https://dash.cloudflare.com/profile/api-tokens/), go to **My Profile** > **API Tokens** for user tokens. Go to **Create Custom Token** > **Get started**. +2. Enter a **Token name**, for example, `Open Port Scanning`. +3. In **Permissions**: + - Choose **Account**. + - Select **Cloudforce One** as the account. + - Choose **Edit** access. +4. In Client IP Address Filtering: + - In **Operator**, select `is in`. + - In **Value**, enter a valid IP address. +5. Select **Continue to summary**. +6. Review the token, then select **Create Token**. + +:::note +The Open Port Scanner will run from a predetermined set of IPs. The Cloudforce One team recommends you to allowlist these IPs in your rules. +::: + +## Configure Open Port Scanning + +To configure Open Port Scanning, follow these steps: + +1. **Create a new scan config**: + - **IPs**: Enter the IP ranges you wish to monitor. Ensure that the ranges are correctly formatted to avoid scanning errors. The API will validate if the IPs requested are onboarded to Cloudflare and associated to the account belonging to the API token used. + - **Frequency**: Enter the scan frequency in days. + - **Ports**: Select the ports to scan. Choose among: + - All + - Default (refer to [Default ports](/security-center/cloudforce-one/open-port-scanning/#default-ports) for a comprehensive list) + - List of specific ports +2. **Scan IPs**: Initiate the scanning process. The system will analyze the specified IP ranges to identify any open ports. +3. **Generate list of open ports**: Once the scan is complete, the API will generate a list of detected open ports for review and action. +4. **Select open ports to list**: Choose which open ports you would like to be notified about. You can exclude any ports that do not require immediate attention. +5. **View differences from previous scan**: The API will highlight any changes in open ports since the last scan, allowing you to quickly assess new vulnerabilities. +6. **Stop scanning**: If necessary, you can stop the scanning process at any time. +7. **Set up alerts**: Configure alerts for specific ports of interest. You will be notified immediately via email or webhook if any of these designated ports become newly open. + +:::note[Beta feature notice] +Open Port Scanning feature is currently in closed beta. The Cloudforce One team appreciates your feedback as the team works to enhance its functionality and user experience. +If you want to subscribe to this feature or participate in the beta program, [join our closed beta for Port Scanning](https://www.cloudflare.com/lp/open-port-scanning-beta/). +::: + +## Default ports + +
    +- `80` +- `631` +- `161` +- `137` +- `123` +- `138` +- `1434` +- `445` +- `135` +- `67` +- `23` +- `53` +- `443` +- `21` +- `139` +- `22` +- `500` +- `68` +- `520` +- `1900` +- `25` +- `4500` +- `514` +- `49152` +- `162` +- `69` +- `5353` +- `111` +- `49154` +- `3389` +- `110` +- `1701` +- `998` +- `996` +- `997` +- `999` +- `3283` +- `49153` +- `445` +- `1812` +- `136` +- `139` +- `143` +- `53` +- `2222` +- `135` +- `3306` +- `2049` +- `32768` +- `5060` +- `8080` +- `1025` +- `1433` +- `3456` +- `80` +- `1723` +- `111` +- `995` +- `993` +- `20031` +- `1026` +- `7` +- `5900` +- `1646` +- `1645` +- `593` +- `1025` +- `518` +- `2048` +- `626` +- `1027` +- `587` +- `177` +- `1719` +- `427` +- `497` +- `8888` +- `4444` +- `1023` +- `65024` +- `199` +- `19` +- `9` +- `49193` +- `1029` +- `1720` +- `49` +- `465` +- `88` +- `1028` +- `17185` +- `1718` +- `49186` +- `548` +- `113` +- `81` +- `6001` +- `2000` +- `10000` +- `31337` +
    + +## Frequently Asked Questions + +1. What IPs will the scan come from? + + - `2a09:bac0:1008:5000:1000:0000:0000:0050/104.30.128.13` + - `2a09:bac0:1008:5000:1000:0000:0000:0048/104.30.129.33` + - `2001:19f0:1000:2941:5400:4ff:fe70:2a7a/140.82.60.241` + +2. Can the Port Scanner bypass other security rules configured? + + - The Cloudforce One team asks customers to ensure they allow the IPs for the scanner to run correctly. + +3. How long do scans take? + + - Depending on the number of IP addresses and number of ports scanned, scans can take between a few minutes and up to 10 hours. + +4. Can I stop automatic scanning? + + - Yes, you can decide at any point to stop scan and restart scans when it is convenient for you. + +5. What are the limitations for the scans? + + - Scans are limited to ranges of up to 5,000 IPs. + - The API scans both IPv4 and IPv6 IP addresses. \ No newline at end of file diff --git a/src/content/docs/security-center/index.mdx b/src/content/docs/security-center/index.mdx index 2c73ce4a4b5d61..cafb4ef37a38d7 100644 --- a/src/content/docs/security-center/index.mdx +++ b/src/content/docs/security-center/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Security Center pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Security Center - + content: Overview --- import { LinkButton, Render } from "~/components" diff --git a/src/content/docs/security-center/intel-apis/index.mdx b/src/content/docs/security-center/intel-apis/index.mdx index cbb44b1f1e0c42..f753315ade6803 100644 --- a/src/content/docs/security-center/intel-apis/index.mdx +++ b/src/content/docs/security-center/intel-apis/index.mdx @@ -23,6 +23,7 @@ Cloudflare provides a series of endpoints covering various areas of internet sec | [Request for Information](/api/resources/cloudforce_one/subresources/requests/methods/create/) | Creates a targeted inquiry for specific intelligence insights to help organizations understand and respond to imminent security threats and vulnerabilities. | | [WHOIS](/api/resources/intel/subresources/whois/methods/get/) | Provides the WHOIS registration information for a specific domain. | | [DDoS Botnet Threat Feed](/ddos-protection/botnet-threat-feed/)
    (early access) | Provides information to service providers about their own IP addresses that have participated in HTTP DDoS attacks as observed from Cloudflare's global network. | +| [Cloudforce One](/api/resources/cloudforce_one/subresources/requests/subresources/assets/methods/create/)| Enable users to list, delete, get, or update a request asset. | ## API Examples diff --git a/src/content/docs/security-center/security-insights/index.mdx b/src/content/docs/security-center/security-insights/index.mdx index ddb10dcd671b95..889e39fe09760e 100644 --- a/src/content/docs/security-center/security-insights/index.mdx +++ b/src/content/docs/security-center/security-insights/index.mdx @@ -8,7 +8,7 @@ sidebar: import { Render } from "~/components"; :::note[User permission] -Only Super Admin users with edit permissions can start scans, turn scans off, or manage issues. +Ensure your user has one of the necessary roles to access Security Insights. Refer to [Roles and permissions](/security-center/security-insights/roles-and-permissions/) for more information. ::: diff --git a/src/content/docs/security-center/security-insights/roles-and-permissions.mdx b/src/content/docs/security-center/security-insights/roles-and-permissions.mdx new file mode 100644 index 00000000000000..a97a666607df7c --- /dev/null +++ b/src/content/docs/security-center/security-insights/roles-and-permissions.mdx @@ -0,0 +1,17 @@ +--- +pcx_content_type: concept +title: Roles and permissions +sidebar: + order: 5 +--- + +Cloudflare users with the following [roles](/fundamentals/setup/manage-members/roles/) have access to Security Insights in the Cloudflare dashboard: + +- Administrator +- Administrator Read Only +- Super Administrator - All Privileges +- SSL/TLS, Caching, Performance, Page Rules, and Customization +- DNS +- Page Shield +- Page Shield Read +- Firewall \ No newline at end of file diff --git a/src/content/docs/security/analytics.mdx b/src/content/docs/security/analytics.mdx new file mode 100644 index 00000000000000..3f0f8ac5573a86 --- /dev/null +++ b/src/content/docs/security/analytics.mdx @@ -0,0 +1,58 @@ +--- +title: Security analytics +pcx_content_type: concept +sidebar: + order: 3 +description: Security analytics shows information about all incoming HTTP requests or mitigated requests (rule matches). +--- + +import { GlossaryTooltip } from "~/components"; + +Security analytics shows information about all incoming HTTP requests or only about requests mitigated by Cloudflare. + +Use Security analytics as your starting point to understand and analyze traffic patterns, and to create security rules based on the filters you applied. + +## Traffic + +The **Traffic** tab displays information about all incoming HTTP requests for your domain, including requests not handled by Cloudflare security products. + +In this tab you can perform several tasks: + +- View the traffic distribution for your domain. +- Understand which traffic is being mitigated by Cloudflare security products, and where non-mitigated traffic is being served from (Cloudflare global network or [origin server](https://www.cloudflare.com/learning/cdn/glossary/origin-server/)). +- Analyze suspicious traffic and create tailored custom [security rules](/security/rules/) based on applied filters. +- [Find an appropriate rate limit](/waf/rate-limiting-rules/find-rate-limit/) for incoming traffic. + +For information on how to use the **Traffic** tab, refer to [Security Analytics](/waf/analytics/security-analytics/#adjusting-displayed-data). + +If you need to modify existing security-related rules you already configured, consider also using the [Events](#events) tab. This tab displays information about requests affected by Cloudflare security products. + +### Suspicious activity + +The suspicious activity gives you information about suspicious requests that were identified by the Cloudflare detections you have enabled. The supported detections include: + +- [Account takeover](/bots/concepts/detection-ids/#account-takeover-detections) +- [Leaked credential check](/waf/detections/leaked-credentials/) (only for user and password leaked) +- [Malicious uploads](/waf/detections/malicious-uploads/) +- [WAF attack score](/waf/detections/attack-score/) +- [Firewall for AI](/waf/detections/firewall-for-ai/) + +Each suspicious activity is classified with a severity score that can vary from critical to low. You can use the filter option to investigate further. + +:::note +The **Traffic** tab includes functionality available in the [Security Analytics](/waf/analytics/security-analytics/) page in the previous dashboard navigation structure. However, some page elements will appear in a different order, or they may be unavailable in the **Traffic** tab, such as Insights or the score-based analyses sidebar. +::: + +## Events + +Use the **Events** tab to review mitigated requests and to tailor your security configurations. + +The **Events** tab displays information about requests actioned or flagged by Cloudflare security products. Each incoming HTTP request might generate one or more security events. The tab only shows these events, not the HTTP requests themselves. To obtain information on all incoming HTTP requests, use the [Traffic](#traffic) tab. + +Users on a Free plan can view summarized events by date in sampled logs. Customers on paid plans have access to additional graphs and dashboards that summarize the most relevant information about the current behavior of Cloudflare's security features on your domain. + +For more information on the **Events** tab, refer to [Security Events](/waf/analytics/security-events/). + +:::note +The **Events** tab corresponds to the [Security Events](/waf/analytics/security-events/) page in the previous dashboard navigation structure. +::: diff --git a/src/content/docs/security/index.mdx b/src/content/docs/security/index.mdx new file mode 100644 index 00000000000000..367b4280c67424 --- /dev/null +++ b/src/content/docs/security/index.mdx @@ -0,0 +1,76 @@ +--- +title: Application security dashboard (beta) +pcx_content_type: overview +sidebar: + order: 1 +description: The application security dashboard (beta) helps you understand the current security posture of your web applications and allows you configure different security rules for those applications. +head: + - tag: title + content: Overview +--- + +import { + Card, + CardGrid, + Feature, + LinkTitleCard, + RelatedProduct, +} from "~/components"; + +The application security dashboard (beta) is your starting point to better understand the security posture of your web applications, and to configure rules to protect them. + + + +The new **Security** navigation in the Cloudflare dashboard is currently available in beta for users that opt in to the new user interface. To opt in: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com), and select your account and domain. +2. Open any page under **Security**. +3. In the top right-hand corner of the page, select **Try new security dashboard**. + +You can swap back to the previous dashboard at any time by selecting **Return to old security dashboard** in the same page location. + + + +## Features + + + Get a high-level overview of your domain's security posture. + + + + Shows information about all incoming HTTP requests or mitigated requests (rule + matches). Tailor your security configurations based on sampled logs. + + + + Discover your web assets (including API endpoints) and instruct Cloudflare how + to best protect them. + + + + Perform security actions on incoming requests that match specified filters. + + +--- + +## More resources + + + + + Compare available Cloudflare plans + + + diff --git a/src/content/docs/security/overview.mdx b/src/content/docs/security/overview.mdx new file mode 100644 index 00000000000000..fdd78c13ced23c --- /dev/null +++ b/src/content/docs/security/overview.mdx @@ -0,0 +1,17 @@ +--- +title: Security overview +pcx_content_type: concept +sidebar: + order: 2 +--- + +Security overview provides a high-level security overview of your domain. Security overview allows you to review the security posture of your domain. The security overview page is available on both the new security dashboard as well as the existing security dashboard. + +The Security overview page will display the following information: + +- **Traffic last 7 days**: Review traffic from the last seven days that has been mitigated, served by Cloudflare, and served by origin. +- **Security posture**: + - **Configurations**: Review your currently enabled configurations, and whether additional configurations are required for them. + - **Suggestions**: Review security suggestions to improve your security posture. +- **Rules with the most activity**: Review the number of times a security rule has been activated by matching requests. +- **Last updated rules**: Review rules you recently changed. \ No newline at end of file diff --git a/src/content/docs/security/rules.mdx b/src/content/docs/security/rules.mdx new file mode 100644 index 00000000000000..eae6db572f26d2 --- /dev/null +++ b/src/content/docs/security/rules.mdx @@ -0,0 +1,51 @@ +--- +title: Security rules +pcx_content_type: concept +sidebar: + order: 5 +description: Security rules perform security actions on incoming requests that match specified filters. +--- + +Security rules perform security-related actions on incoming requests that match specified filters. Rules are evaluated and executed in order, from first to last. + +## Security rules + +The **Security rules** tab includes a list of different types of rules configured in your domain / zone to protect your applications and resources. + +To create a security rule: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. +2. Go to **Security** > **Security rules**. +3. (Optional) Select **Templates**, and then select a template from the list. You can customize the default configuration of the template before deploying the new rule. Refer to the resources listed in the next step. +4. Select **Create rule** > select the type of rule you want to create. Refer to the following resources about each rule type: + - [Custom rules](/waf/custom-rules/create-dashboard/#rule-form) + - [Rate limiting rules](/waf/rate-limiting-rules/create-zone-dashboard/#rule-form) + - [API sequence rules](/api-shield/security/sequence-mitigation/#rule-form) + - [API JWT validation rules](/api-shield/security/jwt-validation/#rule-form) (requires a [token configuration](/security/settings/#all-settings)) + - [Managed rules exceptions](/waf/managed-rules/waf-exceptions/define-dashboard/#2-define-basic-exception-parameters) + - [Content security rules](/page-shield/policies/create-dashboard/#rule-form) (previously known as Page Shield policies) + +:::note[Notes] + +The **Security rules** tab includes functionality available in different products in the previous dashboard navigation structure, such as the [WAF](/waf/), [API Shield](/api-shield/), and [Page Shield](/page-shield/). + +The tab may show additional rule types if you have configured at least one of the following: + +- [IP access rules](/waf/tools/ip-access-rules/) +- [User agent blocking rules](/waf/tools/user-agent-blocking/) +- [Zone lockdown rules](/waf/tools/zone-lockdown/) + +::: + +## DDoS protection + +The **DDoS Protection** tab shows the multiple DDoS mitigation services provided by Cloudflare. You can create rules to override these mitigation tools. DDoS attack protection overrides are only available to Enterprise customers with the Advanced DDoS Protection subscription. + +To learn more about DDoS protection overrides, refer to the following resources: + +- [HTTP DDoS attack protection overrides](/ddos-protection/managed-rulesets/http/override-expressions/) +- [Network-layer DDoS attack protection overrides](/ddos-protection/managed-rulesets/network/override-expressions/) + +:::note +You define overrides for the Network-layer DDoS attack protection managed ruleset at the account level in Account Home > **L3/4 DDoS** > **Network-layer DDoS Protection**. +::: diff --git a/src/content/docs/security/settings.mdx b/src/content/docs/security/settings.mdx new file mode 100644 index 00000000000000..ef639f1745c0e6 --- /dev/null +++ b/src/content/docs/security/settings.mdx @@ -0,0 +1,114 @@ +--- +title: Security settings +pcx_content_type: concept +sidebar: + order: 6 + label: Settings +description: Configure different Cloudflare security features that protect your web applications, APIs, and resources. +--- + +This page describes the settings available in **Security** > **Settings** for a given domain. + +## Security modules + +### Web application exploits module + +In the **Web application exploits** security module you can enable and configure the following managed rulesets and detections: + +- [Cloudflare Managed Ruleset](/waf/managed-rules/reference/cloudflare-managed-ruleset/) +- [Cloudflare OWASP Core Ruleset](/waf/managed-rules/reference/owasp-core-ruleset/) +- [Leaked credentials detection](/waf/detections/leaked-credentials/) +- [Malicious upload detection](/waf/detections/malicious-uploads/) +- [Sensitive data detection ruleset](/waf/managed-rules/reference/sensitive-data-detection/) +- [Firewall for AI](/waf/detections/firewall-for-ai/) + +Refer to each linked page for details. + +:::note +The web application exploits module includes features and settings from the [Cloudflare WAF](/waf/) in the previous dashboard navigation structure. +::: + +### DDoS attacks module + +The **DDoS protection** security module shows the multiple DDoS mitigation services provided by Cloudflare. You can create rules to override these mitigation tools. DDoS attack protection overrides are only available to Enterprise customers with the Advanced DDoS Protection subscription. + +To learn more about DDoS protection overrides, refer to the following resources: + +- [HTTP DDoS attack protection overrides](/ddos-protection/managed-rulesets/http/override-expressions/) +- [Network-layer DDoS attack protection overrides](/ddos-protection/managed-rulesets/network/override-expressions/) + +:::note +You define overrides for the Network-layer DDoS attack protection managed ruleset at the account level in Account Home > **L3/4 DDoS** > **Network-layer DDoS Protection**. +::: + +### Bot traffic module + +In the **Bot traffic** security module you can perform the following tasks: + +- Enable [Bot fight mode](/bots/get-started/free/) (depending on your Cloudflare plan). +- Enable [Super Bot fight mode](/bots/get-started/pro/) (depending on your Cloudflare plan). +- Review information about [Bot Management](/bots/get-started/bm-subscription/) (always enabled if included in your Enterprise subscriptions). +- Turn on [Block AI Bots](/bots/concepts/bot/#ai-bots). +- Turn on [AI Labyrinth](/bots/get-started/free/#enable-ai-labyrinth). + +:::note +The bot traffic module includes features and settings from [Bots](/bots/) in the previous dashboard navigation structure. +::: + +### API abuse module + +In the **API abuse** security module you can perform the following tasks: + +- Review information about [Endpoint Discovery](/api-shield/security/api-discovery/) (always enabled if included in your Enterprise subscriptions). +- Enable [Sequence Discovery](/api-shield/security/sequence-analytics/) (requires that you configure a session identifier). +- Enable [Schema Validation](/api-shield/security/schema-validation/) (requires that you upload a schema or apply a learned schema). +- Enable [JWT Validation](/api-shield/security/jwt-validation/) (requires that you add a [JWT configuration](/api-shield/security/jwt-validation/configure/#token-configurations)). + +:::note +The API abuse module includes features and settings from [API Shield](/api-shield/) in the previous dashboard navigation structure. +::: + +### Client-side abuse module + +In the **Client-side abuse** security module you can perform the following tasks: + +- Turn [continuous script monitoring](/page-shield/how-it-works/) on or off (previously you turned [Page Shield](/page-shield/) on or off). +- Create a [client-side resource alert](/page-shield/reference/alerts/) (also known as a Page Shield alert). +- Set the [reporting endpoint](/page-shield/reference/settings/#reporting-endpoint) to use your hostname instead of a Cloudflare-owned endpoint (only for Enterprise customers with a paid add-on). +- Adjust the [data logged in client-side abuse reports](/page-shield/reference/settings/#connection-target-details) (only the hostname or the full URI). + +:::note +The client-side abuse module includes features and settings from [Page Shield](/page-shield/) in the previous dashboard navigation structure. +::: + +## All settings + +This section allows you to configure multiple security-related settings. The following table links to additional information about each setting: + +| Setting | Location in previous dashboard navigation | +| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| [Endpoint labels](/api-shield/management-and-monitoring/endpoint-labels/) | **Security** > **Settings** > **Labels** | +| [Session identifiers](/api-shield/management-and-monitoring/session-identifiers/#rule-form) | **Security** > **API Shield** > **Settings** | +| [Schemas default action](/api-shield/security/schema-validation/#change-the-global-default-action-of-schema-validation) | **Security** > **API Shield** > **Schema Validation** | +| [Uploaded schemas](/api-shield/security/schema-validation/) | **Security** > **API Shield** > **Schema Validation** | +| [Learned schemas](/api-shield/security/schema-validation/) | **Security** > **API Shield** > **Schema Validation** | +| [Token configuration](/api-shield/security/jwt-validation/#add-a-token-validation-configuration) | **Security** > **API Shield** > **Settings** | +| [Client-side resource alerts](/page-shield/detection/configure-alerts/#rule-form) | **Security** > **Page Shield** > **Settings**
    Account Home > **Notifications** | +| [Reporting endpoint](/page-shield/reference/settings/#reporting-endpoint) | **Security** > **Page Shield** > **Settings** | +| [Data processing](/page-shield/reference/settings/#connection-target-details) | **Security** > **Page Shield** > **Settings** | +| [IP lists](/waf/tools/lists/custom-lists/#lists-with-ip-addresses-ip-lists) | Account Home > **Manage Account** > **Configurations** | +| [Custom username and password location](/waf/detections/leaked-credentials/#custom-detection-locations) | **Security** > **Settings** | +| [Custom content location](/waf/detections/malicious-uploads/#custom-scan-expressions) | **Security** > **Settings** | +| [Custom sensitive data deployment](/waf/managed-rules/reference/sensitive-data-detection/#configure-in-the-dashboard) | **Security** > **Sensitive Data** | +| [Block definitely automated traffic](/bots/get-started/biz-and-ent/#bot-settings) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [Block likely bots](/bots/get-started/biz-and-ent/#bot-settings) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [Allow verified bots](/bots/get-started/biz-and-ent/#bot-settings) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [Static resource protection](/bots/reference/static-resources/) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [Optimize for WordPress](/bots/reference/wordpress-loopback-issue/) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [JavaScript detections](/bots/reference/javascript-detections/) | **Security** > **Bots** > **Configure Super Bot Fight Mode
    Security** > **Bots** > **Configure Bot Management** | +| [Auto-update machine learning model](/bots/reference/machine-learning-models/) | **Security** > **Bots** > **Configure Bot Management** | +| [Enable Security.txt](/security-center/infrastructure/security-file/) | **Security** > **Settings** | +| [Challenge Passage](/waf/tools/challenge-passage/) | **Security** > **Settings** | +| [Browser Integrity Check](/waf/tools/browser-integrity-check/) | **Security** > **Settings** | +| [Replace insecure JavaScript libraries](/waf/tools/replace-insecure-js-libraries/) | **Security** > **Settings** | +| [Security Level](/waf/tools/security-level/) | **Security** > **Settings** | diff --git a/src/content/docs/security/web-assets.mdx b/src/content/docs/security/web-assets.mdx new file mode 100644 index 00000000000000..18b98c282a19ee --- /dev/null +++ b/src/content/docs/security/web-assets.mdx @@ -0,0 +1,84 @@ +--- +title: Web assets +pcx_content_type: concept +sidebar: + order: 4 +description: Discover web assets such as your API endpoints and instruct Cloudflare how to best protect them. +--- + +Discover web assets such as your API endpoints and instruct Cloudflare how to best protect them. + +## Endpoints + +Use the **Endpoints** tab to manage endpoints available on your domain and monitor their health. + +You can save endpoints directly from [API Discovery](/api-shield/security/api-discovery/), [manually](/api-shield/management-and-monitoring/#add-endpoints-manually) by method, path, and host, or via [Schema Validation](/api-shield/management-and-monitoring/#add-endpoints-from-schema-validation). + +This will add the specified endpoints to your list of managed endpoints. You can view your list of managed endpoints in the **Endpoints** tab. + +For saved endpoints: + +- Cloudflare will start collecting [performance data](/api-shield/management-and-monitoring/#endpoint-analysis) per endpoint. +- You can use the [labeling service](/api-shield/management-and-monitoring/endpoint-labels/) to organize your endpoints by use case. + +For more information on how to manage your endpoints, refer to the following resources. + +- [Endpoint Management](/api-shield/management-and-monitoring/) +- [Endpoint schema learning](/api-shield/management-and-monitoring/#endpoint-schema-learning) +- [Endpoint Analysis](/api-shield/management-and-monitoring/#endpoint-analysis) + +## Discovery + +**Discovery** continuously finds your active API endpoints via path normalization. + +[Add endpoints](/api-shield/management-and-monitoring/#add-endpoints-from-api-discovery) to produce recommendations and analytics of your APIs. Your [session identifiers](/api-shield/management-and-monitoring/session-identifiers/) must match your API traffic. Otherwise, API endpoints are also discoverable via [Machine Learning](/api-shield/security/api-discovery/#machine-learning-based-discovery). + +:::note +**Discovery** is only available for Enterprise customers. If you are an Enterprise customer and interested in this product, contact your account team. +::: + +## Sequences + +Use **Sequences** to discover how users interact with your API, by tracking the order of API session requests over time. Sequences will group and highlight popular user journeys across your API. + +Once you configure [session identifiers](/api-shield/management-and-monitoring/session-identifiers/), the **Sequences** tab will start grouping and highlighting important user journeys (sequences) across your API. + +To configure session identifiers, go to **Security** > **Settings** > **All settings** tab and select **Edit** next to **Session identifiers**. + +For more information on how Cloudflare identifies API sequences and how you can configure API sequence rules, refer to the following resources: + +- [Sequence analytics](/api-shield/security/sequence-analytics/) +- [Sequence mitigation](/api-shield/security/sequence-mitigation/) + +:::note +The **Sequences** tab includes functionality available in [API Shield](/api-shield/) in the previous dashboard navigation structure. +::: + +## Schema validation + +Use **Schema validation** to check if your incoming traffic complies with a previously supplied API Schema. + +API Schemas are defined by the validity of the API request's properties such as target endpoint, path or query variable format, and HTTP method. A rule is created for incoming traffic and defines which traffic is allowed and which traffic is logged or blocked based on the API schema that you provide or select from the list of learned schemas. + +You can add schema validation by: + +- [Uploading a schema](/api-shield/security/schema-validation/#add-validation-by-uploading-a-schema) +- [Applying a learned schema to a single endpoint](/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-a-single-endpoint) +- [Applying a learned schema to an entire hostname](/api-shield/security/schema-validation/#add-validation-by-applying-a-learned-schema-to-an-entire-hostname) +- [Adding a fallthrough rule](/api-shield/security/schema-validation/#add-validation-by-adding-a-fallthrough-rule) + +:::note +The **Schema validation** tab includes functionality available in [API Shield](/api-shield/) in the previous dashboard navigation structure. +::: + +## Client-side resources + +Use **Client-side resources** to [monitor scripts, connections, and cookies](/page-shield/detection/monitor-connections-scripts/) on your domain. + +If you notice unexpected scripts or connections on the dashboard, check them for signs of malicious activity. You should also check for any new or unexpected cookies. + +Enterprise customers with a paid add-on will have their connections and scripts [classified as potentially malicious](/page-shield/how-it-works/malicious-script-detection/) based on threat feeds. + +:::note +The **Client-side resources** tab includes functionality available in [Page Shield](/page-shield/) in the previous dashboard navigation structure. +::: diff --git a/src/content/docs/speed/optimization/content/compression.mdx b/src/content/docs/speed/optimization/content/compression.mdx index 4cc316fb8fd6f7..3db0908bccd8f3 100644 --- a/src/content/docs/speed/optimization/content/compression.mdx +++ b/src/content/docs/speed/optimization/content/compression.mdx @@ -1,6 +1,7 @@ --- pcx_content_type: reference title: Content compression +description: Learn how Cloudflare compresses content for faster web performance. sidebar: order: 2 head: diff --git a/src/content/docs/speed/optimization/protocol/http2-to-origin.mdx b/src/content/docs/speed/optimization/protocol/http2-to-origin.mdx index 756b64d1ef2ffb..1cabfc93330b48 100644 --- a/src/content/docs/speed/optimization/protocol/http2-to-origin.mdx +++ b/src/content/docs/speed/optimization/protocol/http2-to-origin.mdx @@ -4,7 +4,7 @@ title: HTTP/2 to Origin --- -import { FeatureTable } from "~/components" +import { FeatureTable, Details, Render } from "~/components" A protocol is a set of rules governing the exchange or transmission of data between devices. One of the most important protocols that run on the human-computer interaction layer, where applications can access the network services, is HTTP (Hypertext Transfer Protocol). @@ -29,7 +29,36 @@ If you wish to disable HTTP/2 to Origin, you can follow these steps: Cloudflare’s HTTP/2 multiplexing to origin reduces active connections by pooling many requests into fewer TCP connections. If a request arrives and the current connection has not reached the stream limit, Cloudflare reuses the existing connection. If the limit has not been reached, Cloudflare may open additional connections to handle more requests. Because multiplexing reuses fewer TCP connections, the overall number of active connections to your origin will typically be lower, which is often helpful for systems sensitive to connection overhead. During surges (like failovers), Cloudflare scales connections by first using available streams, then opening new ones as needed. -Connection multiplexing is enabled by default on Free, Pro and Business zones and uses up to 100 concurrent streams by default. For Enterprise plans, you can explicitly configure the maximum number of concurrent streams (often called the “multiplexing ratio”) for a zone. +### Configuration + +Connection multiplexing is enabled by default on Free, Pro and Business zones and uses up to 100 concurrent streams by default. Enterprise plans can explicitly configure the maximum number of concurrent streams (often called the “multiplexing ratio”) for a zone in the dashboard or via API. + +
    + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account. +2. Choose the domain that will use HTTP/2 to Origin. +3. Select **Speed > Optimization**. +4. Open the **Protocol Optimization** tab. +5. Under **HTTP/2 to Origin**, select **Configure** and adjust the stream settings as needed. + +
    + +
    + +```bash +curl --request PATCH \ +https://api.cloudflare.com/client/v4/zones//settings/origin_h2_max_streams \ +--header 'Content-Type: application/json' \ +--header "X-Auth-Email: " \ +--header "X-Auth-Key: " \ +--data '{ + "value": + }' +``` + +Refer to the [API documentation](/api/python/resources/zones/subresources/settings/methods/edit/) for more information. + +
    :::note If your origin does not support multiplexing, enabling HTTP/2 to origin may result in 5xx errors, particularly 520s. diff --git a/src/content/docs/speed/optimization/protocol/troubleshooting/protocol-troubleshooting.mdx b/src/content/docs/speed/optimization/protocol/troubleshooting/protocol-troubleshooting.mdx new file mode 100644 index 00000000000000..60a8af835947e5 --- /dev/null +++ b/src/content/docs/speed/optimization/protocol/troubleshooting/protocol-troubleshooting.mdx @@ -0,0 +1,35 @@ +--- +pcx_content_type: troubleshooting +title: Troubleshoot protocol issues + +--- + +This guide covers common HTTP/2 and HTTP/3 issues, including origin incompatibility, multiplexing errors, and browser errors, with steps to diagnose and resolve them. + +## H2 to Origin - Origin incompatibility + +- The origin's `max_concurrent_streams` is negotiated during the handshake process. +- If a `GOAWAY(0)` is received, it is likely due to a server restart or another reason causing the server to refuse new streams. +- For more information, refer to [RFC 9113 - SETTINGS_MAX_CONCURRENT_STREAMS](https://datatracker.ietf.org/doc/html/rfc9113). + +## H2 Multiplexing - Origin incompatibility/issues + +- Multiplexing issues can arise due to incorrect server configurations. +- Use [netlogs](https://www.chromium.org/developers/design-documents/network-stack/netlog/) to identify `SETTINGS_MAX_CONCURRENT_STREAMS` violations or unexpected `GOAWAY` frames. +- For more information, refer to [Stream Concurrency Issues](https://datatracker.ietf.org/doc/html/rfc9113#name-stream-concurrency). + +## Generic browser errors + +Common browser errors include: + +- `ERR_HTTP2_PROTOCOL_ERROR` +- `ERR_HTTP3_PROTOCOL_ERROR` +- `ERR_QUIC_PROTOCOL_ERROR` + +These errors do not necessarily indicate a protocol-level issue. Follow these steps: + +1. Attempt reproduction using HTTP/1.1. +2. If the issue persists in HTTP/1.1, address the underlying error before testing HTTP/2 or HTTP/3. +3. If the issue does not persist, analyze netlogs for HTTP/2 or HTTP/3-specific issues. + +For more information, refer to [Chromium URL Request Header](https://chromium.googlesource.com/chromium/src/+/HEAD/net/url_request/url_request.h). diff --git a/src/content/docs/speed/speed-test/rum-beacon.mdx b/src/content/docs/speed/speed-test/rum-beacon.mdx index 60daef5fa67720..8125c803c2a45c 100644 --- a/src/content/docs/speed/speed-test/rum-beacon.mdx +++ b/src/content/docs/speed/speed-test/rum-beacon.mdx @@ -6,7 +6,7 @@ sidebar: --- -The RUM beacon is a JavaScript snippet that runs when a Cloudflare customer enables RUM through [Web Analytics](/web-analytics/) or [Observatory](/speed/speed-test/#observatory). This script runs in users' browsers when they visit the customer's site, and its purpose is to collect performance-related data, for example, page load time, and send it to Cloudflare's systems for processing. This [data](/web-analytics/data-metrics/) is then presented to the customer, providing valuable insights into the website's performance and usage. +The RUM beacon is a JavaScript snippet that runs when a Cloudflare customer enables RUM through [Web Analytics](/web-analytics/) or [Observatory](/speed/speed-test/). This script runs in users' browsers when they visit the customer's site, and its purpose is to collect performance-related data, for example, page load time, and send it to Cloudflare's systems for processing. This [data](/web-analytics/data-metrics/) is then presented to the customer, providing valuable insights into the website's performance and usage. The RUM beacon script can be enabled into a webpage in two ways: diff --git a/src/content/docs/ssl/client-certificates/configure-your-mobile-app-or-iot-device.mdx b/src/content/docs/ssl/client-certificates/configure-your-mobile-app-or-iot-device.mdx index 7acf04816204eb..4c9a4093e3f8d0 100644 --- a/src/content/docs/ssl/client-certificates/configure-your-mobile-app-or-iot-device.mdx +++ b/src/content/docs/ssl/client-certificates/configure-your-mobile-app-or-iot-device.mdx @@ -415,4 +415,4 @@ After creating Cloudflare-issued certificates, the next step is to [enable mTLS] ## 6. Configure API Shield to require client certificates -To configure API Shield to require client certificates, [create a mTLS rule](/api-shield/security/mtls/configure/#create-an-mtls-rule/). +To configure API Shield to require client certificates, [create a mTLS rule](/api-shield/security/mtls/configure/#create-an-mtls-rule). diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/compliance-status.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/compliance-status.mdx index cf921a9463998e..7c11fc5d6f365d 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/compliance-status.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/compliance-status.mdx @@ -9,43 +9,39 @@ head: --- -import { Render } from "~/components" +import { Render, Details } from "~/components" Consider the following recommendations on custom [cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/) for when your organization needs to comply with regulatory standards. Refer to [Customize cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) to learn how to specify cipher suites at zone level or per hostname. +:::caution Also [enable TLS 1.3](/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) on your zone and, when opting for [PCI DSS](#pci-dss), make sure to up your [Minimum TLS version](/ssl/edge-certificates/additional-options/minimum-tls/) to `1.2`. Refer to [Cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/) and [TLS protocols](/ssl/reference/protocols/) to learn more. +::: ## PCI DSS Recommended cipher suites for compliance with the [Payment Card Industry Data Security Standard (PCI DSS)](https://www.pcisecuritystandards.org/standards/pci-dss/). Enhances payment card data security. -* Cipher suites: +
    `AEAD-AES128-GCM-SHA256`[^1], `AEAD-AES256-GCM-SHA384`[^2], `AEAD-CHACHA20-POLY1305-SHA256`[^3], `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-CHACHA20-POLY1305` -* Formatted array to copy: + - - -```txt -["ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-CHACHA20-POLY1305", "ECDHE-RSA-CHACHA20-POLY1305"] -``` + ## FIPS-140-2 Recommended cipher suites for compliance with the [Federal Information Processing Standard (140-2)](https://csrc.nist.gov/pubs/fips/140-2/upd2/final). Used to approve cryptographic modules. -* Cipher suites: +
    `AES128-GCM-SHA256`, `AES128-SHA`, `AES128-SHA256`, `AES256-SHA`, `AES256-SHA256`, `DES-CBC3-SHA`, `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-SHA`, `ECDHE-RSA-AES256-SHA384` -* Formatted array to copy: + -```txt -["AES128-GCM-SHA256", "AES128-SHA", "AES128-SHA256", "AES256-SHA", "AES256-SHA256", "DES-CBC3-SHA", "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-ECDSA-AES128-SHA", "ECDHE-ECDSA-AES128-SHA256", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-ECDSA-AES256-SHA384", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-SHA", "ECDHE-RSA-AES128-SHA256", "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-SHA", "ECDHE-RSA-AES256-SHA384"] -``` + [^1]: Same as `TLS_AES_128_GCM_SHA256`. Refer to [TLS 1.3 cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. [^2]: Same as `TLS_AES_256_GCM_SHA384`. Refer to [TLS 1.3 cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api.mdx similarity index 68% rename from src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites.mdx rename to src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api.mdx index e1dc5a3b3a1a68..8d64ecfb2e7c26 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api.mdx @@ -1,56 +1,20 @@ --- -title: Customize cipher suites +title: Customize cipher suites via API pcx_content_type: how-to sidebar: - order: 1 -head: - - tag: title - content: Customize cipher suites - + order: 2 + label: Use the API --- -import { Render, TabItem, Tabs } from "~/components" - -With [Advanced Certificate Manager](/ssl/edge-certificates/advanced-certificate-manager/) or within [Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), you can restrict connections between Cloudflare and clients — such as your visitor's browser — to specific [cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/). - -You may want to do this to follow specific [recommendations](/ssl/edge-certificates/additional-options/cipher-suites/recommendations/), to [disable weak cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/#ssl-labs-weak-ciphers-report), or to comply with [industry standards](/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/). +import { Render, TabItem, Tabs } from "~/components"; -Customizing cipher suites will not lead to any downtime in your SSL/TLS protection. + :::note -This documentation only refers to connections [between clients and the Cloudflare network](/ssl/concepts/#edge-certificate). For connections between Cloudflare and your origin server, refer to [Origin server > Cipher suites](/ssl/origin-configuration/cipher-suites/). + ::: -## How it works - -Custom cipher suites is a hostname-level setting, which implies that: - -* When you customize cipher suites for a [zone](/fundamentals/setup/accounts-and-zones/#zones), this will affect all hostnames within that zone. -* The configuration is applicable to all edge certificates used to connect to the hostname(s), regardless of [certificate type](/ssl/edge-certificates/) (universal, advanced, or custom). -* If you need to use a per-hostname cipher suite customization, you must ensure that the hostname is specified on the certificate. - -### Scope - -Currently, you can only customize cipher suites when using the API: - -* [Zone](/api/resources/zones/subresources/settings/methods/edit/) (using `ciphers` as the setting name in the URI path) -* [Per-hostname](/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/) (regular zones only) -* [Custom hostname](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites) (Cloudflare for SaaS zones only) - -### Settings priority and ciphers order - -Cloudflare uses the [hostname priority logic](/ssl/reference/certificate-and-hostname-priority/) to determine which setting to apply. - -ECDSA cipher suites are prioritized over RSA, and Cloudflare preserves the specified cipher suites in the order they are set. This means that, if both ECDSA and RSA are used, Cloudflare presents the ECDSA ciphers first - in the order they were set - and then the RSA ciphers, also in the order they were set. - -## Set up - - -:::note -For guidance around custom hostnames, refer to [TLS settings - Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites). -::: - -### Before you begin +## Before you begin Note that: @@ -58,18 +22,17 @@ Note that: * You cannot set specific TLS 1.3 ciphers. Instead, you can [enable TLS 1.3](/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use all applicable [TLS 1.3 cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/). * Each cipher suite also supports a specific algorithm (RSA or ECDSA) so you should consider the algorithms in use by your edge certificates when making your ciphers selection. You can find this information under each certificate listed in [**SSL/TLS** > **Edge Certificates**](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates). * It is not possible to configure minimum TLS version nor cipher suites for [Cloudflare Pages](/pages/) hostnames. +* If setting up a per-hostname cipher suite customization, make sure that the hostname is specified on the certificate (instead of being covered by a wildcard). * If you use Windows you might need to adjust the `curl` syntax, refer to [Making API calls on Windows](/fundamentals/api/how-to/make-api-calls/#making-api-calls-on-windows) for further guidance. -### Steps and API examples +## Steps and API examples 1. Decide which cipher suites you want to specify and which ones you want to disable (meaning they will not be included in your selection). Below you will find samples covering the recommended ciphers [by security level](/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) and [compliance standards](/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/), but you can also refer to the [full list](/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/) of supported ciphers and customize your choice. 2. Log in to the Cloudflare dashboard and get your Global API Key in [**My Profile** > **API Tokens**](https://dash.cloudflare.com/?to=/:account/profile/api-tokens/). - 3. Get the Zone ID from the [Overview page](https://dash.cloudflare.com/?to=/:account/:zone/) of the domain you want to specify cipher suites for. - 4. Make an API call to either the [Edit zone setting](/api/resources/zones/subresources/settings/methods/edit/) endpoint or the [Edit TLS setting for hostname](/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/) endpoint, specifying `ciphers` in the URL. List your array of chosen cipher suites in the `value` field. :::note @@ -151,7 +114,7 @@ curl --request PATCH \ -## Reset to default values +### Reset to default values @@ -180,4 +143,4 @@ curl --request DELETE \ -For guidance around custom hostnames, refer to [TLS settings - Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites). + diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard.mdx new file mode 100644 index 00000000000000..44f11542727db3 --- /dev/null +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard.mdx @@ -0,0 +1,35 @@ +--- +title: Customize cipher suites via dashboard +pcx_content_type: how-to +sidebar: + order: 1 + label: Use the dashboard +--- + +import { Render, Details } from "~/components"; + + + +When configuring cipher suites via dashboard, you can use three different selection modes: + +- **By security level**: allows you to select between the predefined [Cloudflare recommendations](/ssl/edge-certificates/additional-options/cipher-suites/recommendations/) (Modern, Compatible, or Legacy). +- **By compliance standard**: allows you to select cipher suites grouped according to [industry standards](/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/) (PCI DSS or FIPS-140-2). +- **Custom**: allows you to individually select the cipher suites you would like to support. + +For any of the modes, you should keep in mind the following configuration conditions. If using the **security level** or the **compliance standard** mode, some actions may be blocked and explained referencing these conditions. + +
    +* Cipher suites are used in combination with other [SSL/TLS settings](/ssl/edge-certificates/additional-options/cipher-suites/#related-ssltls-settings). +* You cannot set specific TLS 1.3 ciphers. Instead, you can [enable TLS 1.3](/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) for your entire zone and Cloudflare will use all applicable [TLS 1.3 cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/supported-cipher-suites/). +* Each cipher suite also supports a specific algorithm (RSA or ECDSA), so you should consider the algorithms in use by your edge certificates when making your ciphers selection. You can find this information under each certificate listed in [**SSL/TLS** > **Edge Certificates**](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates). +* It is not possible to configure minimum TLS version nor cipher suites for [Cloudflare Pages](/pages/) hostnames. + + +## Steps + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account and domain. +2. Go to **SSL/TLS** > **Edge Certificates**. +3. For the **Cipher suites** setting select **Configure**. +4. Choose a mode to select your cipher suites and select **Next**. +5. Select a predefined set of cipher suites or, if you opted for **Custom**, specify which cipher suites you want to allow. Make sure you are aware of how your selection will interact with Minimum TLS version, TLS 1.3, and the certificate algorithm (ECDSA or RSA). +6. Select **Save** to confirm. \ No newline at end of file diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/index.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/index.mdx new file mode 100644 index 00000000000000..8d854540668e40 --- /dev/null +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/index.mdx @@ -0,0 +1,49 @@ +--- +title: Customize cipher suites +pcx_content_type: how-to +sidebar: + order: 1 +head: + - tag: title + content: Customize cipher suites + +--- + +import { Render, TabItem, Tabs, DirectoryListing } from "~/components"; + +With an [Advanced Certificate Manager](/ssl/edge-certificates/advanced-certificate-manager/) subscription, you can restrict connections between Cloudflare and clients — such as your visitor's browser — to specific [cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/). + +You may want to do this to follow specific [recommendations](/ssl/edge-certificates/additional-options/cipher-suites/recommendations/), to [disable weak cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/troubleshooting/#ssl-labs-weak-ciphers-report), or to comply with [industry standards](/ssl/edge-certificates/additional-options/cipher-suites/compliance-status/). + +Customizing cipher suites will not lead to any downtime in your SSL/TLS protection. + +:::note +This documentation only refers to connections [between clients and the Cloudflare network](/ssl/concepts/#edge-certificate). For connections between Cloudflare and your origin server, refer to [Origin server > Cipher suites](/ssl/origin-configuration/cipher-suites/). +::: + +## How it works + +Custom cipher suites is a hostname-level setting, which implies that: + +* When you customize cipher suites for a zone, this will affect all hostnames within that zone. If you are not familiar with what a Cloudflare zone is, refer to [Fundamentals](/fundamentals/setup/accounts-and-zones/#zones). +* The configuration is applicable to all edge certificates used to connect to the hostname(s), regardless of the [certificate type](/ssl/edge-certificates/) (universal, advanced, or custom). +* If you need to use a per-hostname cipher suite customization, you must ensure that the hostname is specified on the certificate. + +## Scope + +Currently, you have the following options: + +- Set custom cipher suites for a zone: either [via API](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/) or [on the dashboard](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/dashboard/). +- Set custom cipher suites per-hostname: only available [via API](/api/resources/hostnames/subresources/settings/subresources/tls/methods/update/). Refer to the [how-to](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/) for details. + +### Cloudflare for SaaS + +If you are a SaaS provider looking to restrict cipher suites for connections to your custom hostnames, refer to [TLS settings - Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites). + +To restrict cipher suites for connections to your own zone, continue on this guide. In this case, you must also have purchased [Advanced Certificate Manager](/ssl/edge-certificates/advanced-certificate-manager/). + +## Settings priority and ciphers order + +Cloudflare uses the [hostname priority logic](/ssl/reference/certificate-and-hostname-priority/) to determine which setting to apply. + +ECDSA cipher suites are prioritized over RSA, and Cloudflare preserves the specified cipher suites in the order they are set. This means that, if both ECDSA and RSA are used, Cloudflare presents the ECDSA ciphers first - in the order they were set - and then the RSA ciphers, also in the order they were set. \ No newline at end of file diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/index.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/index.mdx index 749f3b6dafcfc7..98cf4aac29cb94 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/index.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/index.mdx @@ -3,6 +3,7 @@ title: Cipher suites pcx_content_type: concept sidebar: order: 1 + label: About head: [] description: Consider information about supported cipher suites, how to meet your security requirements, and how to troubleshoot compatibility and other @@ -10,7 +11,7 @@ description: Consider information about supported cipher suites, how to meet --- -import { DirectoryListing, Render } from "~/components" +import { DirectoryListing, Render } from "~/components";
    diff --git a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/recommendations.mdx b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/recommendations.mdx index eb791cfea6397b..4e0630b3793ae3 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/recommendations.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/cipher-suites/recommendations.mdx @@ -1,5 +1,5 @@ --- -title: Recommendations +title: Security levels pcx_content_type: reference sidebar: order: 2 @@ -9,54 +9,50 @@ head: --- -import { Render } from "~/components" +import { Render, Details } from "~/components"; Refer to the sections below for three different security levels and how Cloudflare recommends that you set them up if you need to restrict the [cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/) used between Cloudflare and clients that access your website or application. Refer to [Customize cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/) to learn how to specify cipher suites at zone level or per hostname. +:::caution When opting for [compatible](#compatible) or [modern](#modern), make sure to up your [Minimum TLS version](/ssl/edge-certificates/additional-options/minimum-tls/) to `1.2` and [enable TLS 1.3](/ssl/edge-certificates/additional-options/tls-13/#enable-tls-13) on your zone. +::: ## Modern Offers the best security and performance, limiting your range of clients to modern devices and browsers. Supports TLS 1.2-1.3 cipher suites. All suites are forward-secret and support authenticated encryption (AEAD). -* Cipher suites: +
    `AEAD-AES128-GCM-SHA256`[^1], `AEAD-AES256-GCM-SHA384`[^2], `AEAD-CHACHA20-POLY1305-SHA256`[^3],`ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384` -* Formatted array to copy: + - - -```txt -["ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-ECDSA-CHACHA20-POLY1305", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-CHACHA20-POLY1305", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-GCM-SHA384"] -``` + ## Compatible Provides broader compatibility with somewhat weaker security. Supports TLS 1.2-1.3 cipher suites. All suites are forward-secret. -* Cipher suites: +
    `AEAD-AES128-GCM-SHA256`, `AEAD-AES256-GCM-SHA384`, `AEAD-CHACHA20-POLY1305-SHA256`, `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA384` -* Formatted array to copy: - - + -```txt -["ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-ECDSA-CHACHA20-POLY1305", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-CHACHA20-POLY1305", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-AES128-SHA256", "ECDHE-RSA-AES128-SHA256", "ECDHE-ECDSA-AES256-SHA384", "ECDHE-RSA-AES256-SHA384"] -``` + ## Legacy (default) Includes all cipher suites that Cloudflare supports today. Broadest compatibility with the weakest security. Supports TLS 1.0-1.3 cipher suites. -* Cipher suites: +
    `AEAD-AES128-GCM-SHA256`, `AEAD-AES256-GCM-SHA384`, `AEAD-CHACHA20-POLY1305-SHA256`, `ECDHE-ECDSA-AES128-GCM-SHA256`, `ECDHE-ECDSA-CHACHA20-POLY1305`, `ECDHE-RSA-AES128-GCM-SHA256`, `ECDHE-RSA-CHACHA20-POLY1305`, `ECDHE-ECDSA-AES256-GCM-SHA384`, `ECDHE-RSA-AES256-GCM-SHA384`, `ECDHE-ECDSA-AES128-SHA256`, `ECDHE-RSA-AES128-SHA256`, `ECDHE-ECDSA-AES256-SHA384`, `ECDHE-RSA-AES256-SHA384`, `ECDHE-ECDSA-AES128-SHA`, `ECDHE-RSA-AES128-SHA`, `AES128-GCM-SHA256`, `AES128-SHA256`, `AES128-SHA`, `ECDHE-RSA-AES256-SHA`, `AES256-GCM-SHA384`, `AES256-SHA256`, `AES256-SHA`, `DES-CBC3-SHA` + + To reset your option to the default, [use an empty array](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/#reset-to-default-values). [^1]: Same as `TLS_AES_128_GCM_SHA256`. Refer to [TLS 1.3 cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/#tls-13) for details. diff --git a/src/content/docs/ssl/edge-certificates/additional-options/tls-13.mdx b/src/content/docs/ssl/edge-certificates/additional-options/tls-13.mdx index 33eb9407de13ba..81f7a347392192 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/tls-13.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/tls-13.mdx @@ -35,7 +35,7 @@ To enable TLS 1.3 in the dashboard: -To adjust your TLS 1.3 settings with the API, send a [`PATCH`](/api/resources/zones/subresources/settings/methods/edit/) request with `tls_1_3` as the setting name in the URI path, and set the `value` parameter to your desired setting (`"on"` or `"off"`). +To adjust your TLS 1.3 settings with the API, send a [`PATCH`](/api/resources/zones/subresources/settings/methods/edit/) request with `tls_1_3` as the setting name in the URI path, and set the `value` parameter to your desired setting (`"on"`, `"zrt"` or `"off"`). `zrt` refers to [Zero Round Trip Time Resumption (0-RTT)](https://blog.cloudflare.com/introducing-0-rtt/). diff --git a/src/content/docs/ssl/edge-certificates/additional-options/total-tls/index.mdx b/src/content/docs/ssl/edge-certificates/additional-options/total-tls/index.mdx index 728218b069d17d..9546c76bf05f8b 100644 --- a/src/content/docs/ssl/edge-certificates/additional-options/total-tls/index.mdx +++ b/src/content/docs/ssl/edge-certificates/additional-options/total-tls/index.mdx @@ -32,6 +32,7 @@ Total TLS does not issue certificates for any hostnames used with: * [Cloudflare Load Balancing](/load-balancing/) * [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) +* [Cloudflare Spectrum](/spectrum/) You can use other types of certificates or manually [order advanced certificates](/ssl/edge-certificates/advanced-certificate-manager/manage-certificates/#create-a-certificate) for these hostnames. diff --git a/src/content/docs/ssl/edge-certificates/changing-dcv-method/troubleshooting.mdx b/src/content/docs/ssl/edge-certificates/changing-dcv-method/troubleshooting.mdx index 2e7dd2fa79dba2..eae847e8019831 100644 --- a/src/content/docs/ssl/edge-certificates/changing-dcv-method/troubleshooting.mdx +++ b/src/content/docs/ssl/edge-certificates/changing-dcv-method/troubleshooting.mdx @@ -6,10 +6,9 @@ sidebar: head: - tag: title content: Troubleshooting Domain Control Validation - --- -import { GlossaryTooltip, Render } from "~/components" +import { GlossaryTooltip, Render } from "~/components"; Taking into account the [steps involved in DCV](/ssl/edge-certificates/changing-dcv-method/dcv-flow/), some situations may interfere with certificate issuance and renewal. @@ -24,12 +23,14 @@ If you are using the Cloudflare API, error messages are presented under the `val If you have issues while HTTP DCV is in place, review the following settings: -* **Anything affecting `/.well-known/*`**: Review [WAF custom rules](/waf/custom-rules/), [IP Access Rules](/waf/tools/ip-access-rules/), and other [configuration rules](/rules/configuration-rules/) to make sure that your rules *do not* enable interactive challenge on the validation URL. +- **Anything affecting `/.well-known/*`**: Review [WAF custom rules](/waf/custom-rules/), [IP Access Rules](/waf/tools/ip-access-rules/), and other [configuration rules](/rules/configuration-rules/) to make sure that your rules _do not_ enable interactive challenge on the validation URL. -* **Cloudflare Account Settings** and **Page Rules**: Review your [account settings](/fundamentals/reference/under-attack-mode/), [Configuration Rules](/rules/configuration-rules/), and [Page Rules](/rules/page-rules/) to ensure you have not enabled **I'm Under Attack Mode** on the validation URL. +- **Cloudflare Account Settings** and **Page Rules**: Review your [account settings](/fundamentals/reference/under-attack-mode/), [Configuration Rules](/rules/configuration-rules/), and [Page Rules](/rules/page-rules/) to ensure you have not enabled Under Attack mode on the validation URL. :::caution - + + + ::: ## Redirection @@ -44,14 +45,14 @@ When using [Redirect Rules](/rules/url-forwarding/single-redirects/) the `/.well The errors below refer to situations that have to be addressed at the authoritative DNS provider: -* `the Certificate Authority had trouble performing a DNS lookup: dns problem: looking up caa for nsheiapp.codeacloud.com: dnssec: bogus` -* `Certificate authority encountered a SERVFAIL during DNS lookup, please check your DNS reachability.` +- `the Certificate Authority had trouble performing a DNS lookup: dns problem: looking up caa for nsheiapp.codeacloud.com: dnssec: bogus` +- `Certificate authority encountered a SERVFAIL during DNS lookup, please check your DNS reachability.` Consider the following when troubleshooting: -* [DNSSEC](https://www.cloudflare.com/learning/dns/dns-security/) must be configured correctly. You can use [DNSViz](https://dnsviz.net/) to understand and troubleshoot the deployment of DNSSEC. -* Your [CAA records](/ssl/edge-certificates/caa-records/) should allow Cloudflare's partner [certificate authorities (CAs)](/ssl/reference/certificate-authorities/) to issue certificates on your behalf. -* The HTTP verification process is done preferably over **IPv6**, so if any `AAAA` record exists and does not point to the same dual-stack location as the `A` record, the validation will fail. +- [DNSSEC](https://www.cloudflare.com/learning/dns/dns-security/) must be configured correctly. You can use [DNSViz](https://dnsviz.net/) to understand and troubleshoot the deployment of DNSSEC. +- Your [CAA records](/ssl/edge-certificates/caa-records/) should allow Cloudflare's partner [certificate authorities (CAs)](/ssl/reference/certificate-authorities/) to issue certificates on your behalf. +- The HTTP verification process is done preferably over **IPv6**, so if any `AAAA` record exists and does not point to the same dual-stack location as the `A` record, the validation will fail. ## CA errors diff --git a/src/content/docs/ssl/edge-certificates/universal-ssl/limitations.mdx b/src/content/docs/ssl/edge-certificates/universal-ssl/limitations.mdx index 516e22a8cc32eb..14fd22d4a71e90 100644 --- a/src/content/docs/ssl/edge-certificates/universal-ssl/limitations.mdx +++ b/src/content/docs/ssl/edge-certificates/universal-ssl/limitations.mdx @@ -3,6 +3,7 @@ title: Limitations pcx_content_type: reference sidebar: order: 5 +description: Review the limitations of Universal certificates, such as hostname coverage, certificate authority choice, and compatibility with other products. head: - tag: title content: Limitations for Universal SSL diff --git a/src/content/docs/ssl/edge-certificates/universal-ssl/troubleshooting.mdx b/src/content/docs/ssl/edge-certificates/universal-ssl/troubleshooting.mdx index ac4ab00a19f98a..744cb25a80e170 100644 --- a/src/content/docs/ssl/edge-certificates/universal-ssl/troubleshooting.mdx +++ b/src/content/docs/ssl/edge-certificates/universal-ssl/troubleshooting.mdx @@ -6,11 +6,8 @@ sidebar: head: - tag: title content: Troubleshooting Universal SSL -description: Review how to troubleshoot issues when using Cloudflare Universal - SSL certificate. - +description: Review how to troubleshoot issues such as certificate timeouts when using Cloudflare Universal SSL. --- - ## Resolve a timed out state If a certificate issuance times out, Cloudflare tells you where in the chain of issuance the timeout occurred: Initializing, Validation, Issuance, Deployment, or Deletion. diff --git a/src/content/docs/ssl/keyless-ssl/hardware-security-modules/index.mdx b/src/content/docs/ssl/keyless-ssl/hardware-security-modules/index.mdx index e1decd9d2b33a1..ba37f1aa1085a5 100644 --- a/src/content/docs/ssl/keyless-ssl/hardware-security-modules/index.mdx +++ b/src/content/docs/ssl/keyless-ssl/hardware-security-modules/index.mdx @@ -42,6 +42,4 @@ Also, the following cloud HSM offerings have been tested with Keyless SSL: - [Azure Managed HSM](/ssl/keyless-ssl/hardware-security-modules/azure-managed-hsm/) - [Fortanix DSM](/ssl/keyless-ssl/hardware-security-modules/fortanix-dsm/) - [IBM Cloud HSM](/ssl/keyless-ssl/hardware-security-modules/ibm-cloud-hsm/) -- [Google Cloud HSM](/ssl/keyless-ssl/hardware-security-modules/google-cloud-hsm/) - -If you have deployed Keyless SSL with an HSM model not listed above, please email [keyless@cloudflare.com](mailto:keyless@cloudflare.com) with details. +- [Google Cloud HSM](/ssl/keyless-ssl/hardware-security-modules/google-cloud-hsm/) \ No newline at end of file diff --git a/src/content/docs/ssl/post-quantum-cryptography/index.mdx b/src/content/docs/ssl/post-quantum-cryptography/index.mdx index 26e5b0d72e7b36..b4eb0c46320364 100644 --- a/src/content/docs/ssl/post-quantum-cryptography/index.mdx +++ b/src/content/docs/ssl/post-quantum-cryptography/index.mdx @@ -12,7 +12,7 @@ description: Get an overview of how Cloudflare is deploying post-quantum cryptog Post-quantum cryptography (PQC) refers to cryptographic algorithms that have been designed to resist attacks from [quantum computers](https://www.cloudflare.com/learning/ssl/quantum/what-is-quantum-computing/). Cloudflare has been researching and [writing about post-quantum](https://blog.cloudflare.com/tag/post-quantum/) since 2017. -To protect you against the risk of [harvest now, decrypt later](https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later), and considering all the [connections](#three-connections-in-the-life-of-a-request) that take place when your website or application is on Cloudflare, we have deployed and are actively expanding the use of [post-quantum hybrid key agreement](#hybrid-key-agreement). +To protect you against the risk of [harvest now, decrypt later attacks](https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later), and considering all the [connections](#three-connections-in-the-life-of-a-request) that take place when your website or application is on Cloudflare, we have deployed and are actively expanding the use of [post-quantum hybrid key agreement](#hybrid-key-agreement). Refer to [Cloudflare Radar](https://radar.cloudflare.com/adoption-and-usage#post-quantum-encryption-adoption) for current statistics on the adoption of PQ encryption in requests to Cloudflare, and visit [pq.cloudflareresearch.com](https://pq.cloudflareresearch.com) to check if your connection is secured using PQ key agreement. @@ -32,7 +32,7 @@ As explained in our [blog post](https://blog.cloudflare.com/pq-2024/#two-migrati ### Hybrid key agreement -With TLS 1.3, [X25519](https://en.wikipedia.org/wiki/Curve25519) - an Elliptic Curve Diffie-Hellman (ECDH) protocol - is the most commonly used algorithm in key agreement. However, its security can be easily broken by quantum computers using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). +With TLS 1.3, [X25519](https://en.wikipedia.org/wiki/Curve25519) - an Elliptic Curve Diffie-Hellman (ECDH) protocol - is the most commonly used algorithm in key agreement. However, its security can be broken by quantum computers using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). It is urgent to migrate key agreement to post-quantum algorithms as soon as possible. The objective is to protect against an adversary capable of harvesting today's encrypted communications and storing it until some time in the future when they can gain access to a sufficiently powerful quantum computer to decrypt it. @@ -83,6 +83,10 @@ As announced in [September 2023](https://blog.cloudflare.com/post-quantum-crypto ### 3. Cloudflare to your origin -Finally, Cloudflare also supports [hybrid key agreements](#hybrid-key-agreement) when connecting to origins. In this case, post-quantum secured connections will depend on the origin servers also supporting PQC. +Finally, Cloudflare also supports [hybrid key agreements](#hybrid-key-agreement) when connecting to origins. In this case, post-quantum secured connections will depend on the origin servers also supporting PQC. Customers can also configure connections to origin servers via [PQ Cloudflare Tunnel](/ssl/post-quantum-cryptography/pqc-and-zero-trust/). -Refer to [Post-quantum cryptography between Cloudflare and origin servers](/ssl/post-quantum-cryptography/pqc-to-origin/) for details. \ No newline at end of file +Refer to [Post-quantum cryptography between Cloudflare and origin servers](/ssl/post-quantum-cryptography/pqc-to-origin/) for details. + +## Protect corporate network traffic + +With [Zero Trust](/cloudflare-one/), Cloudflare allows organizations to upgrade their sensitive network traffic to PQC without the hassle of individually upgrading each and every corporate application, system, or network connection. Refer to [Post-quantum cryptography in Cloudflare's Zero Trust platform](/ssl/post-quantum-cryptography/pqc-and-zero-trust/) for details. \ No newline at end of file diff --git a/src/content/docs/ssl/post-quantum-cryptography/pqc-and-zero-trust.mdx b/src/content/docs/ssl/post-quantum-cryptography/pqc-and-zero-trust.mdx new file mode 100644 index 00000000000000..96c50bfb6683cf --- /dev/null +++ b/src/content/docs/ssl/post-quantum-cryptography/pqc-and-zero-trust.mdx @@ -0,0 +1,56 @@ +--- +pcx_content_type: reference +title: Post-quantum cryptography in Cloudflare's Zero Trust platform +sidebar: + order: 4 + label: PQC and Zero Trust +--- + +The [Cloudflare Zero Trust platform](/cloudflare-one/) replaces legacy corporate security perimeters with Cloudflare's global network, making access to the Internet and to corporate resources faster and safer for teams around the world. + +Refer to the sections below to learn about the use cases supported by the Zero Trust platform in this [first phase of quantum readiness](/ssl/post-quantum-cryptography/). + +## Agentless Cloudflare Access + +You can use [Cloudflare Access](/cloudflare-one/policies/access/) [self-hosted applications](/cloudflare-one/applications/configure-apps/self-hosted-public-app/) in an agentless configuration to protect your organization's Internet traffic to internal web applications. Refer to the [learning path](/learning-paths/zero-trust-web-access/initial-setup/) for detailed guidance. + +Even if the applications themselves have not yet migrated to post-quantum (PQ) cryptography, they will be protected against quantum threats. + +![Diagram of how post-quantum cryptography works in clientless connections to Access applications](~/assets/images/ssl/pqc-clientless-access.png). + +Here is how it works today: + +**1. PQ connection via browser** + +As long as the end-user uses a modern web browser that supports post-quantum key agreement (for example, Chrome, Edge, or Firefox), the connection from the device to Cloudflare's network is secured via TLS 1.3 with post-quantum key agreement. + +**2. PQ within Cloudflare's global network** + +If the user and origin server are geographically distant, then the user's traffic will enter Cloudflare's global network in one geographic location (such as Frankfurt), and exit at another (such as San Francisco). As this traffic moves from one data center to another inside Cloudflare's global network, these hops through the network are secured via TLS 1.3 with post-quantum key agreement. + +**3. PQ Cloudflare Tunnel** + +Customers establish a [Cloudflare Tunnel](/cloudflare-one/connections/connect-networks/) from their data center or public cloud — where their corporate web application is hosted — to Cloudflare's network. This tunnel is secured using TLS 1.3 with post-quantum key agreement, safeguarding it from [harvest now, decrypt later attacks](https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later). + +Putting it together, Cloudflare Access can provide end-to-end quantum safety for accessing corporate HTTPS applications, without requiring customers to upgrade the security of corporate web applications. + +## Secure Web Gateway + +A [secure web gateway (SWG)](https://www.cloudflare.com/learning/access-management/what-is-a-secure-web-gateway/) is used to secure access to third-party websites on the public Internet by intercepting and inspecting TLS traffic. + +[Cloudflare Gateway](/cloudflare-one/policies/gateway/http-policies/) is now a [quantum-safe SWG for HTTPS traffic](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#post-quantum-support). As long as the third-party website that is being inspected supports post-quantum key agreement, then Cloudflare's SWG also supports post-quantum key agreement. This is true regardless of the on-ramp that you use to get to Cloudflare's network, and only requires the use of a browser that supports post-quantum key agreement. + +![Diagram of how post-quantum cryptography works with Cloudflare's Secure Web Gateway](~/assets/images/ssl/pqc-secure-web-gateway.png). + +Cloudflare Gateway's HTTPS filtering feature involves two post-quantum TLS connections, as follows: + +**1. PQ connection via browsers** + +A TLS connection is initiated from the user's browser to a data center in Cloudflare's network that performs the TLS inspection. As long as the end-user uses a modern web browser that supports post-quantum key agreement (for example, Chrome, Edge, or Firefox), this connection is secured by TLS 1.3 with post-quantum key agreement. + +**2. PQ connection to the origin server** + +A TLS connection is initiated from a data center in Cloudflare's network to the origin server, which is typically controlled by a third party. The connection from Cloudflare's SWG currently supports post-quantum key agreement, as long as the third-party's origin server also already supports post-quantum key agreement. You can test this out by using https://pq.cloudflareresearch.com/ as your third-party origin server. + +Putting it together, Cloudflare Gateway is quantum-ready to support secure access to any third-party website that is quantum ready today or in the future. + diff --git a/src/content/docs/ssl/post-quantum-cryptography/pqc-support.mdx b/src/content/docs/ssl/post-quantum-cryptography/pqc-support.mdx index 47d3d0ee2f9ec6..d43e210dedbc26 100644 --- a/src/content/docs/ssl/post-quantum-cryptography/pqc-support.mdx +++ b/src/content/docs/ssl/post-quantum-cryptography/pqc-support.mdx @@ -21,12 +21,18 @@ The list below is for reference only. Responsibility for third-party software li - Default for recent [Opera](https://opera.com) and [Brave](https://brave.com) - Cloudflare's [fork of Go](https://github.com/cloudflare/go) - Default for [Go 1.24+](https://go.dev/doc/go1.24#cryptotlspkgcryptotls) +- [OpenSSL 3.5.0+](https://www.openssl.org/) (Alpha) - [BoringSSL](https://boringssl.googlesource.com/boringssl/) +- [GnuTLS](https://www.gnutls.org) + - 3.8.9+ compiled with leancrypto 1.2.0+ + - 3.8.8+ compiled with liboqs 0.11.0+ - [rustls 0.23.22+](https://crates.io/crates/rustls) - Default for [rpxy 0.9.4+](https://github.com/junkurihara/rust-rpxy) +- [NGINX](https://github.com/nginx/nginx) compiled with OpenSSL 3.5+ ([instructions](https://github.com/nginx/nginx/issues/288)) - [Open Quantum Safe](https://openquantumsafe.org/) - C library: liboqs 0.10.0+ - OpenSSL provider: oqs-provider 0.7.0+ +- [Zig 0.14.0+](https://ziglang.org/) - [Caddy HTTP server](https://caddyserver.com/) nightly compiled with Go 1.24+ ([instructions](https://gist.github.com/bwesterb/2f7bfa7ae689de0d242b56ea3ecac424)) - [Botan C++ library 3.7.0+](https://botan.randombit.net/) @@ -40,6 +46,9 @@ The list below is for reference only. Responsibility for third-party software li - Cloudflare's [fork of Go](https://github.com/cloudflare/go) - Default for [Go 1.23](https://github.com/golang/go/issues/67061) - [BoringSSL](https://boringssl.googlesource.com/boringssl/) +- [GnuTLS](https://www.gnutls.org) + - 3.8.8+ compiled with liboqs 0.11.0-0.12.0 + - 3.8.7 compiled with liboqs 0.10.1-0.12.0 - Cloudflare's [fork of QUIC-go](https://github.com/cloudflare/qtls-pq) - Goutam Tamvada's [fork of Firefox](https://github.com/xvzcf/firefox-pq-demos) - [Open Quantum Safe](https://openquantumsafe.org/) diff --git a/src/content/docs/ssl/post-quantum-cryptography/pqc-to-origin.mdx b/src/content/docs/ssl/post-quantum-cryptography/pqc-to-origin.mdx index 96d8e788dce855..661c0536b2c2aa 100644 --- a/src/content/docs/ssl/post-quantum-cryptography/pqc-to-origin.mdx +++ b/src/content/docs/ssl/post-quantum-cryptography/pqc-to-origin.mdx @@ -16,6 +16,8 @@ With X25519, the [ClientHello](https://www.cloudflare.com/learning/ssl/what-happ This poses a question of how the origin servers - as well as other middleboxes (routers, load balancers, etc) - will handle this change in behavior. Although allowed by the TLS 1.3 standard ([RFC 8446](https://www.rfc-editor.org/rfc/rfc8446.html)), a split ClientHello risks not being handled well due to [protocol ossification](https://en.wikipedia.org/wiki/Protocol_ossification) and implementation bugs. Refer to our [blog post](https://blog.cloudflare.com/post-quantum-to-origins/) for details. +Customers can also configure connections to origin servers via [PQ Cloudflare Tunnel](/ssl/post-quantum-cryptography/pqc-and-zero-trust/). + ## ClientHello from Cloudflare To reduce the risk of any issues when connecting to servers that are not ready for hybrid key agreements, Cloudflare leverages HelloRetryRequest. This means that, instead of sending [X25519MLKEM768](/ssl/post-quantum-cryptography/#hybrid-key-agreement) immediately as a keyshare [^1], Cloudflare will by default only advertise support for it. diff --git a/src/content/docs/ssl/reference/certificate-and-hostname-priority.mdx b/src/content/docs/ssl/reference/certificate-and-hostname-priority.mdx index 14182f41af91ec..d128a95fa3f7d3 100644 --- a/src/content/docs/ssl/reference/certificate-and-hostname-priority.mdx +++ b/src/content/docs/ssl/reference/certificate-and-hostname-priority.mdx @@ -4,8 +4,7 @@ title: Certificate and hostname priority sidebar: order: 4 head: [] -description: Learn about how Cloudflare decides which certificate (and the - associated SSL/TLS settings) apply to individual hostnames. +description: Learn about how Cloudflare decides which certificate and associated SSL/TLS settings to apply to individual hostnames. --- diff --git a/src/content/docs/ssl/reference/certificate-statuses.mdx b/src/content/docs/ssl/reference/certificate-statuses.mdx index 26ef9357433368..b2b811bc1a0ea8 100644 --- a/src/content/docs/ssl/reference/certificate-statuses.mdx +++ b/src/content/docs/ssl/reference/certificate-statuses.mdx @@ -3,10 +3,10 @@ pcx_content_type: reference title: Certificate statuses sidebar: order: 8 +description: Understand certificate statuses in Cloudflare SSL/TLS, including stages like Initializing, Pending Validation, and Active. Monitor via dashboard or command line. --- Certificates statuses show which stage of the issuance process each certificate is in. - ## New certificates When you order a new certificate, either an [edge certificate](/ssl/edge-certificates/) or a certificate used for a [custom hostname](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), its status will move through various stages as it progresses to Cloudflare’s global network: diff --git a/src/content/docs/ssl/reference/certificate-validity-periods.mdx b/src/content/docs/ssl/reference/certificate-validity-periods.mdx index ce1a929d109130..0164f644a8ab91 100644 --- a/src/content/docs/ssl/reference/certificate-validity-periods.mdx +++ b/src/content/docs/ssl/reference/certificate-validity-periods.mdx @@ -6,8 +6,7 @@ sidebar: head: - tag: title content: Validity periods and renewal -description: Review information about available validity periods for your - Cloudflare SSL certificates. +description: Learn about Cloudflare SSL certificate validity periods, auto renewal processes, and the benefits of shorter validity periods for enhanced security. --- @@ -20,7 +19,6 @@ If a certificate fails to renew and another valid certificate exists for the hos :::note For information regarding custom certificates (managed by you), consider this other page on [renewal and expiration](/ssl/edge-certificates/custom-certificates/renewing/). ::: - ## Universal SSL diff --git a/src/content/docs/ssl/reference/protocols.mdx b/src/content/docs/ssl/reference/protocols.mdx index 49788370ef7920..43394e0baca57e 100644 --- a/src/content/docs/ssl/reference/protocols.mdx +++ b/src/content/docs/ssl/reference/protocols.mdx @@ -4,8 +4,7 @@ title: TLS protocols sidebar: order: 3 head: [] -description: Cloudflare supports a variety of TLS protocols, ranging from TLS - 1.0 to TLS 1.3. +description: Explore Cloudflare's support for TLS protocols from 1.0 to 1.3. Learn about differences, security standards, and recommendations on what version to use. --- @@ -19,7 +18,6 @@ Cloudflare supports the following TLS protocols: TLS 1.0 is the [version that Cloudflare sets by default](/ssl/edge-certificates/additional-options/minimum-tls/) for all customers using certificate-based encryption. For information about which cipher suites are supported between clients and the Cloudflare network, refer to [Cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/). - ## Understand TLS versions A higher TLS version implies a stronger cryptographic standard. TLS 1.2 includes fixes for known vulnerabilities found in previous versions. diff --git a/src/content/docs/stream/examples/obs-from-scratch/index.mdx b/src/content/docs/stream/examples/obs-from-scratch/index.mdx index dbbecf9d1b0b49..85a7c2ec927bab 100644 --- a/src/content/docs/stream/examples/obs-from-scratch/index.mdx +++ b/src/content/docs/stream/examples/obs-from-scratch/index.mdx @@ -2,14 +2,11 @@ type: example summary: Set up and start your first Live Stream using OBS (Open Broadcaster Software) Studio -tags: - - Live pcx_content_type: example title: First Live Stream with OBS weight: 0 description: Set up and start your first Live Stream using OBS (Open Broadcaster Software) Studio - --- ## Overview @@ -20,9 +17,9 @@ Stream empowers customers and their end-users to broadcast a live stream quickly To go live on Stream, you will need any of the following: -* A paid Stream subscription -* A Pro or Business zone plan — these include 100 minutes of video storage and 10,000 minutes of video delivery -* An enterprise contract with Stream enabled +- A paid Stream subscription +- A Pro or Business zone plan — these include 100 minutes of video storage and 10,000 minutes of video delivery +- An enterprise contract with Stream enabled Also, you will also need to be able to install the application on your computer. @@ -32,9 +29,9 @@ If your computer and network connection are good enough for video calling, you s You need a Live Input on Stream. Follow the [Start a live stream](/stream/stream-live/start-stream-live/) guide. Make note of three things: -* **RTMPS URL**, which will most likely be `rtmps://live.cloudflare.com:443/live/` -* **RTMPS Key**, which is specific to the new live input -* Whether you selected the beta "Low-Latency HLS Support" or not. For your first test, leave this *disabled.* ([What's that?](https://blog.cloudflare.com/cloudflare-stream-low-latency-hls-open-beta)) +- **RTMPS URL**, which will most likely be `rtmps://live.cloudflare.com:443/live/` +- **RTMPS Key**, which is specific to the new live input +- Whether you selected the beta "Low-Latency HLS Support" or not. For your first test, leave this _disabled._ ([What's that?](https://blog.cloudflare.com/cloudflare-stream-low-latency-hls-open-beta)) ## 2. Install OBS @@ -44,16 +41,16 @@ Download [OBS Studio](https://obsproject.com/) for Windows, macOS, or Linux. The When you first launch OBS, the Auto-Configuration Wizard will ask a few questions and offer recommended settings. See their [Quick Start Guide](https://obsproject.com/kb/quick-start-guide) for more details. For a quick start with Stream, use these settings: -* **Step 1: "Usage Information"** - * Select "Optimize for streaming, recording is secondary." -* **Step 2: "Video Settings"** - * **Base (Canvas) Resolution:** 1920x1080 - * **FPS:** "Either 60 or 30, but prefer 60 when possible" -* **Step 3: "Stream Information"** - * **Service:** "Custom" - * For **Server**, enter the RTMPS URL from Stream - * For **Stream Key**, enter the RTMPS Key from Stream - * If available, select both **"Prefer hardware encoding"** and **"Estimate bitrate with a bandwidth test."** +- **Step 1: "Usage Information"** + - Select "Optimize for streaming, recording is secondary." +- **Step 2: "Video Settings"** + - **Base (Canvas) Resolution:** 1920x1080 + - **FPS:** "Either 60 or 30, but prefer 60 when possible" +- **Step 3: "Stream Information"** + - **Service:** "Custom" + - For **Server**, enter the RTMPS URL from Stream + - For **Stream Key**, enter the RTMPS Key from Stream + - If available, select both **"Prefer hardware encoding"** and **"Estimate bitrate with a bandwidth test."** ## 4. Set up a Stage @@ -77,21 +74,21 @@ Return to OBS, click "Stop Streaming." Then click "Settings" and open the "Outpu ![OBS Output Settings - Simple Mode](~/assets/images/stream/examples/obs-from-scratch/obs-output-settings-1.png) -* Change **Output Mode** to "Advanced" +- Change **Output Mode** to "Advanced" ![OBS Output Settings - Advanced Mode](~/assets/images/stream/examples/obs-from-scratch/obs-output-settings-2.png) -*Your available options in the "Video Encoder" menu, as well as the resulting "Encoder Settings," may look slightly different than these because the options vary by hardware.* +_Your available options in the "Video Encoder" menu, as well as the resulting "Encoder Settings," may look slightly different than these because the options vary by hardware._ -* **Video Encoder:** may have several options. Start with the default selected, which was "x264" in this example. Other options to try, which will leverage improved hardware acceleration when possible, include "QuickSync H.264" or "NVIDIA NVENC." See OBS's guide to Hardware Encoding for more information. H.264 is the required output codec. -* **Rate Control:** confirm "CBR" (constant bitrate) is selected. -* **Bitrate:** depending on the content of your stream, a bitrate between 3000 Kbps and 8000 Kbps should be sufficient. Lower bitrate is more tolerant to network congestion and is suitable for content with less detail or less motion (speaker, slides, etc.) where a higher bitrate requires a more stable network connection and is best for content with lots of motion or details (events, moving cameras, video games, screen share, higher framerates). -* **Keyframe Interval**, sometimes referred to as *GOP Size*: - * If you did *not* select Low-Latency HLS Beta, set this to 4 seconds. Raise it to 8 if your stream has stuttering or freezing. - * If you *did* select the Low-Latency HLS Beta, set this to 2 seconds. Raise it to 4 if your stream has stuttering or freezing. Lower it to 1 if your stream has smooth playback. - * In general, higher keyframe intervals make more efficient use of bandwidth and CPU for encoding, at the expense of higher glass-to-glass latency. Lower keyframe intervals reduce latency, but are more resource intensive and less tolerant to network disruptions and congestion. -* **Profile** and **Tuning** can be left at their default settings. -* **B Frames** (available only for some encoders) should be set to 0 for LL-HLS Beta streams. +- **Video Encoder:** may have several options. Start with the default selected, which was "x264" in this example. Other options to try, which will leverage improved hardware acceleration when possible, include "QuickSync H.264" or "NVIDIA NVENC." See OBS's guide to Hardware Encoding for more information. H.264 is the required output codec. +- **Rate Control:** confirm "CBR" (constant bitrate) is selected. +- **Bitrate:** depending on the content of your stream, a bitrate between 3000 Kbps and 8000 Kbps should be sufficient. Lower bitrate is more tolerant to network congestion and is suitable for content with less detail or less motion (speaker, slides, etc.) where a higher bitrate requires a more stable network connection and is best for content with lots of motion or details (events, moving cameras, video games, screen share, higher framerates). +- **Keyframe Interval**, sometimes referred to as _GOP Size_: + - If you did _not_ select Low-Latency HLS Beta, set this to 4 seconds. Raise it to 8 if your stream has stuttering or freezing. + - If you _did_ select the Low-Latency HLS Beta, set this to 2 seconds. Raise it to 4 if your stream has stuttering or freezing. Lower it to 1 if your stream has smooth playback. + - In general, higher keyframe intervals make more efficient use of bandwidth and CPU for encoding, at the expense of higher glass-to-glass latency. Lower keyframe intervals reduce latency, but are more resource intensive and less tolerant to network disruptions and congestion. +- **Profile** and **Tuning** can be left at their default settings. +- **B Frames** (available only for some encoders) should be set to 0 for LL-HLS Beta streams. For more information about these settings and our recommendations for Live, see the "[Recommendations, requirements and limitations](/stream/stream-live/start-stream-live/#recommendations-requirements-and-limitations)" section of [Start a live stream](/stream/stream-live/start-stream-live/). @@ -99,5 +96,5 @@ For more information about these settings and our recommendations for Live, see With these steps, you have created a Live Input on Stream, broadcast a test from OBS, and you saw it played back in via the Stream built-in player in Dash. Up next, consider trying: -* Embedding your live stream into a website -* Find and replay the recording of your live stream +- Embedding your live stream into a website +- Find and replay the recording of your live stream diff --git a/src/content/docs/stream/index.mdx b/src/content/docs/stream/index.mdx index 098b22884b8886..03934e58231d78 100644 --- a/src/content/docs/stream/index.mdx +++ b/src/content/docs/stream/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Stream pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Stream - + content: Overview --- import { CardGrid, Description, Feature, LinkButton, LinkTitleCard, Render } from "~/components" @@ -67,7 +66,7 @@ Understand and analyze which videos and live streams are viewed most and break d - Join the Stream developer community + Join the Stream developer community diff --git a/src/content/docs/stream/transform-videos/index.mdx b/src/content/docs/stream/transform-videos/index.mdx new file mode 100644 index 00000000000000..f594eab877b092 --- /dev/null +++ b/src/content/docs/stream/transform-videos/index.mdx @@ -0,0 +1,132 @@ +--- +pcx_content_type: concept +title: Transform videos +sidebar: + order: 5 + badge: + text: Beta +--- + +Media Transformations let you optimize and manipulate videos stored _outside_ of the Cloudflare Stream. Transformed videos and images are served from one of your zones on Cloudflare. + +To transform a video or image, you must [enable transformations](/stream/transform-videos/#getting-started) for your zone. If your zone already has Image Transformations enabled, you can also optimize videos with Media Transformations. + +## Getting started + +You can dynamically optimize and generate still images from videos that are stored _outside_ of Cloudflare Stream with Media Transformations. + +Cloudflare will automatically cache every transformed video or image on our global network so that you store only the original image at your origin. + +To enable transformations on your zone: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account. +2. Go to **Stream** > **Transformations**. +3. Locate the specific zone where you want to enable transformations. +4. Select **Enable** for zone. + +## Transform a video by URL + +You can convert and resize videos by requesting them via a specially-formatted URL, without writing any code. The URL format is: + +``` +https://example.com/cdn-cgi/media// +``` + +- `example.com`: Your website or zone on Cloudflare, with Transformations enabled. +- `/cdn-cgi/media/`: A prefix that identifies a special path handled by Cloudflare's built-in media transformation service. +- ``: A comma-separated list of options. Refer to the available options below. +- ``: A full URL (starting with `https://` or `http://`) of the original asset to resize. + +For example, this URL will source an HD video from an R2 bucket, shorten it, crop and resize it as a square, and remove the audio. + +``` +https://example.com/cdn-cgi/media/mode=video,time=5s,duration=5s,width=500,height=500,fit=crop,audio=false/https://pub-8613b7f94d6146408add8fefb52c52e8.r2.dev/aus-mobile-demo.mp4 +``` + +The result is an MP4 that can be used in an HTML video element without a player library. + +## Options + +### `mode` + +Specifies the kind of output to generate. + +- `video`: Outputs an H.264/AAC optimized MP4 file. +- `frame`: Outputs a still image. +- `spritesheet`: Outputs a JPEG with multiple frames. + +### `time` + +Specifies when to start extracting the output in the input file. Depends on `mode`: + +- When `mode` is `spritesheet` or `video`, specifies the timestamp where the output will start. +- When `mode` is `frame`, specifies the timestamp from which to extract the still image. +- Formats as a time string, for example: 5s, 2m +- Acceptable range: 0 – 30s +- Default: 0 + +### `duration` + +The duration of the output video or spritesheet. Depends on `mode`: + +- When `mode` is `video`, specifies the duration of the output. +- When `mode` is `spritesheet`, specifies the time range from which to select frames. + +### `fit` + +In combination with `width` and `height`, specifies how to resize and crop the output. If the output is resized, it will always resize proportionally so content is not stretched. + +- `contain`: Respecting aspect ratio, scales a video up or down to be entirely contained within output dimensions. +- `scale-down`: Same as contain, but downscales to fit only. Do not upscale. +- `cover`: Respecting aspect ratio, scales a video up or down to entirely cover the output dimensions, with a center-weighted crop of the remainder. + +### `height` + +Specifies maximum height of the output in pixels. Exact behavior depends on `fit`. + +- Acceptable range: 10-2000 pixels + +### `width` + +Specifies the maximum width of the image in pixels. Exact behavior depends on `fit`. + +- Acceptable range: 10-2000 pixels + +### `audio` + +When `mode` is `video`, specifies whether or not to include the source audio in the output. + +- `true`: Includes source audio. +- `false`: Output will be silent. +- Default: `true` + +### `format` + +If `mode` is `frame`, specifies the image output format. + +- Acceptable options: `jpg`, `png` + +## Source video requirements + +Input video must be less than 40MB. Contact Stream if the input limitation is unacceptable. + +Input video should be an MP4 with H.264 encoded video and AAC or MP3 encoded audio. Other formats may work but are untested. + +## Limitations + +Media Transformations are currently in beta. During this period: + +- Transformations are available for all enabled zones free-of-charge. +- Restricting allowed origins for transformations are coming soon. +- Outputs from Media Transformations will be cached, but if they must be regenerated, the origin fetch is not cached and may result in subsequent requests to the origin asset. + +## Pricing + +Media Transformations will be free for all customers while in beta. + +After that, Media Transforamtions and Image Transformations will use the same subscriptions and usage metrics. + +- Generating a still frame (single image) from a video counts as 1 transformation. +- Generating an optimized video counts as 1 transformation _per second of the output_ video. +- Each unique transformation is only billed once per month. +- All Media and Image Transformations cost $0.50 per 1,000 monthly unique transformation operations, with a free monthly allocation of 5,000. diff --git a/src/content/docs/style-guide/api-content-strategy/guidelines-for-curl-commands.mdx b/src/content/docs/style-guide/api-content-strategy/guidelines-for-curl-commands.mdx index 1f6cb2b69f8cee..130ff9d756526a 100644 --- a/src/content/docs/style-guide/api-content-strategy/guidelines-for-curl-commands.mdx +++ b/src/content/docs/style-guide/api-content-strategy/guidelines-for-curl-commands.mdx @@ -6,6 +6,17 @@ sidebar: --- +We follow several formatting conventions for cURL commands. + +## Components + +To automatically incorporate our conventions into your examples, use: + +- [`APIRequest`](/style-guide/components/api-request/): For examples hitting endpoints in the Cloudflare API schema. +- [`CURL`](/style-guide/components/curl/): For other cURL commands. + +## Paramter names + Use long parameter names for clarity: * `--header` (instead of `-H`) diff --git a/src/content/docs/style-guide/components/anchor-heading.mdx b/src/content/docs/style-guide/components/anchor-heading.mdx index 90b2ff1ab0c817..d1bd2f9b686232 100644 --- a/src/content/docs/style-guide/components/anchor-heading.mdx +++ b/src/content/docs/style-guide/components/anchor-heading.mdx @@ -1,5 +1,7 @@ --- title: Anchor heading +styleGuide: + component: AnchorHeading --- The `AnchorHeading` component defines headings. Specifically, `AnchorHeading` performs the following: diff --git a/src/content/docs/style-guide/components/api-request.mdx b/src/content/docs/style-guide/components/api-request.mdx new file mode 100644 index 00000000000000..1f0d65aca09e6e --- /dev/null +++ b/src/content/docs/style-guide/components/api-request.mdx @@ -0,0 +1,86 @@ +--- +title: API request +styleGuide: + component: APIRequest +--- + +## Import + +```mdx +import { APIRequest } from "~/components"; +``` + +## Usage + +```mdx live +import { APIRequest } from "~/components"; + + + + + + +``` + +## `` Props + +### `path` + +**required** + +**type:** `string` + +The path for the API endpoint. + +This can be found in our [API documentation](https://api.cloudflare.com), under the name of the endpoint. + +### `method` + +**required** + +**type:** `"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD"` + +The HTTP method to use. + +### `parameters` + +**type:** `Record` + +The path parameters to substitute. + +If not provided, the component will default to an environment variable. For example, `{setting_id}` will be replaced with `$SETTING_ID`. + +### `json` + +**type:** `Record` + +The JSON payload to send. + +If required properties are missing, the component will throw an error. + +### `form` + +**type:** `Record` + +The FormData payload to send. + +This field is not currently validated against the schema. \ No newline at end of file diff --git a/src/content/docs/style-guide/components/available-notifications.mdx b/src/content/docs/style-guide/components/available-notifications.mdx index aa71beb8a5d67b..d6913459932af4 100644 --- a/src/content/docs/style-guide/components/available-notifications.mdx +++ b/src/content/docs/style-guide/components/available-notifications.mdx @@ -1,5 +1,7 @@ --- title: Available notifications +styleGuide: + component: AvailableNotifications --- ## Components diff --git a/src/content/docs/style-guide/components/buttons.mdx b/src/content/docs/style-guide/components/buttons.mdx index da596ef6c20a56..ff69a53b59aca9 100644 --- a/src/content/docs/style-guide/components/buttons.mdx +++ b/src/content/docs/style-guide/components/buttons.mdx @@ -1,5 +1,7 @@ --- title: Buttons +styleGuide: + component: LinkButton --- ```mdx live diff --git a/src/content/docs/style-guide/components/cards.mdx b/src/content/docs/style-guide/components/cards.mdx index 957bf084a2bae4..ed846001936661 100644 --- a/src/content/docs/style-guide/components/cards.mdx +++ b/src/content/docs/style-guide/components/cards.mdx @@ -1,5 +1,7 @@ --- title: Cards +styleGuide: + component: Card --- Cards are a built-in component provided by [Starlight](https://starlight.astro.build/components/cards/). diff --git a/src/content/docs/style-guide/components/code.mdx b/src/content/docs/style-guide/components/code.mdx index 241f877a3e0a9a..5015d825d0cb75 100644 --- a/src/content/docs/style-guide/components/code.mdx +++ b/src/content/docs/style-guide/components/code.mdx @@ -1,5 +1,7 @@ --- title: Code blocks +styleGuide: + component: Code --- Code blocks are powered by [Expressive Code](https://expressive-code.com/), a project by Astro. diff --git a/src/content/docs/style-guide/components/compatibility-flag.mdx b/src/content/docs/style-guide/components/compatibility-flag.mdx index ae0716693dd3f9..3b6e87e745f334 100644 --- a/src/content/docs/style-guide/components/compatibility-flag.mdx +++ b/src/content/docs/style-guide/components/compatibility-flag.mdx @@ -1,5 +1,7 @@ --- title: Compatibility flag +styleGuide: + component: CompatibilityFlag --- This component will create an aside with the `enable_date` (if present) and the `enable_flag` of a given flag. diff --git a/src/content/docs/style-guide/components/curl.mdx b/src/content/docs/style-guide/components/curl.mdx new file mode 100644 index 00000000000000..36cdbad5c74609 --- /dev/null +++ b/src/content/docs/style-guide/components/curl.mdx @@ -0,0 +1,87 @@ +--- +title: CURL +styleGuide: + component: CURL +--- + +The `CURL` component is used to display a cURL command for making HTTP requests. + +## Import + +```mdx +import { CURL } from "~/components"; +``` + +## Usage + +```mdx live +import { CURL } from "~/components"; + + + + +``` + +## `` Props + +### `url` + +**required** + +**type:** `string` + +The URL to make the request to. + +### `method` + +**type:** `"GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "PATCH"` + +**default:** `"GET"` + +The HTTP method to use for the request. + +### `headers` + +**type:** `Record` + +The headers to include in the request. + +### `json` + +**type:** `Record` + +JSON data to include in the request. + +### `form` + +**type:** `Record` + +The FormData payload to send. + +### `code` + +**type:** `object` + +An object of Expressive Code props, the following props are available: + +- [Base Props](https://expressive-code.com/key-features/code-component/#available-props) +- [Line Marker Props](https://expressive-code.com/key-features/text-markers/#props) +- [Collapsible Sections Props](https://expressive-code.com/plugins/collapsible-sections/#props) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/description.mdx b/src/content/docs/style-guide/components/description.mdx index 398752d61aa7a8..36a3abe1a85d54 100644 --- a/src/content/docs/style-guide/components/description.mdx +++ b/src/content/docs/style-guide/components/description.mdx @@ -1,5 +1,7 @@ --- title: Descriptions +styleGuide: + component: Description --- ```mdx live diff --git a/src/content/docs/style-guide/components/details.mdx b/src/content/docs/style-guide/components/details.mdx index 0159a2f1fcf4d8..91e218c62b0cf5 100644 --- a/src/content/docs/style-guide/components/details.mdx +++ b/src/content/docs/style-guide/components/details.mdx @@ -1,5 +1,7 @@ --- title: Details +styleGuide: + component: Details --- When you want to provide additional information in context, but you do not want it to clutter up the more important content, use `
    ` to add a collapsible container. diff --git a/src/content/docs/style-guide/components/directory-listing.mdx b/src/content/docs/style-guide/components/directory-listing.mdx index b2b09a6770c30b..4cae4b1b23caa8 100644 --- a/src/content/docs/style-guide/components/directory-listing.mdx +++ b/src/content/docs/style-guide/components/directory-listing.mdx @@ -1,8 +1,12 @@ --- title: Directory listing +styleGuide: + component: DirectoryListing --- -Use `` to display the directory of a specific folder, which appears as a list of links. +import { Render } from "~/components"; + + We also have an optional `descriptions` parameter which - if present - adds in the text from the [front matter `description`](/style-guide/frontmatter/) field. @@ -11,3 +15,7 @@ import { DirectoryListing } from "~/components"; ``` + +## Associated content types + +- [Navigation](/style-guide/documentation-content-strategy/content-types/navigation/) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/example.mdx b/src/content/docs/style-guide/components/example.mdx index 3092b5a0f25e63..00fa5cd9515c31 100644 --- a/src/content/docs/style-guide/components/example.mdx +++ b/src/content/docs/style-guide/components/example.mdx @@ -1,5 +1,7 @@ --- title: Example +styleGuide: + component: Example --- Use the `` component to add a box around some content. This can be useful when you want to demonstrate or showcase something without it being confused by the surrounding text. diff --git a/src/content/docs/style-guide/components/external-resources.mdx b/src/content/docs/style-guide/components/external-resources.mdx index 747414487cc7ab..43458b318f0afc 100644 --- a/src/content/docs/style-guide/components/external-resources.mdx +++ b/src/content/docs/style-guide/components/external-resources.mdx @@ -1,5 +1,7 @@ --- title: External resources +styleGuide: + component: ExternalResources --- The `ExternalResources` component pulls from a central list of [apps](https://github.com/cloudflare/cloudflare-docs/blob/production/src/content/apps/index.yaml) and [videos](https://github.com/cloudflare/cloudflare-docs/blob/production/src/content/videos/index.yaml). @@ -38,6 +40,8 @@ The type of resources to show, apps or videos. Filter resources down to those where the `tags` property contains any of these strings. +To see a list of the available tags, and which pages are associated with them, refer to [this list](/style-guide/frontmatter/tags/). + ### `products` **type:** `string[]` diff --git a/src/content/docs/style-guide/components/feature-table.mdx b/src/content/docs/style-guide/components/feature-table.mdx index be0ed3741bbb7c..2ab991bfc0f1cd 100644 --- a/src/content/docs/style-guide/components/feature-table.mdx +++ b/src/content/docs/style-guide/components/feature-table.mdx @@ -1,5 +1,7 @@ --- title: Feature table +styleGuide: + component: FeatureTable --- Use when you need all the available information about a specific feature. For the id property, use dot notation to access the specific feature you want to share the information about. This will always be one below the grouped product, so `.` diff --git a/src/content/docs/style-guide/components/feature.mdx b/src/content/docs/style-guide/components/feature.mdx index 852a1c52cf8f86..57b81002f59d20 100644 --- a/src/content/docs/style-guide/components/feature.mdx +++ b/src/content/docs/style-guide/components/feature.mdx @@ -1,5 +1,7 @@ --- title: Feature +styleGuide: + component: Feature --- The `` component lists features available in the product and provides a link button to use the feature. diff --git a/src/content/docs/style-guide/components/file-tree.mdx b/src/content/docs/style-guide/components/file-tree.mdx index 39908195ab9a4e..807acbf012b9f1 100644 --- a/src/content/docs/style-guide/components/file-tree.mdx +++ b/src/content/docs/style-guide/components/file-tree.mdx @@ -1,5 +1,7 @@ --- title: File tree +styleGuide: + component: FileTree --- File tree is a built-in component provided by [Starlight](https://starlight.astro.build/components/file-tree/). diff --git a/src/content/docs/style-guide/components/flex.mdx b/src/content/docs/style-guide/components/flex.mdx index 418ce06ecca7e7..cdc89844f1643a 100644 --- a/src/content/docs/style-guide/components/flex.mdx +++ b/src/content/docs/style-guide/components/flex.mdx @@ -1,5 +1,7 @@ --- title: Flex container +styleGuide: + component: Flex --- The `` component is intended for showing multiple images in a responsive layout. diff --git a/src/content/docs/style-guide/components/github-code.mdx b/src/content/docs/style-guide/components/github-code.mdx index 2a2c73eb952619..9a61c1a95946e8 100644 --- a/src/content/docs/style-guide/components/github-code.mdx +++ b/src/content/docs/style-guide/components/github-code.mdx @@ -142,4 +142,8 @@ This should be represented as starting `` and closin **type**: `object` -Props to pass to the [Expressive Code component](https://expressive-code.com/key-features/code-component/). \ No newline at end of file +Props to pass to the [Expressive Code component](https://expressive-code.com/key-features/code-component/). + +## Associated content types + +- [Tutorial](/style-guide/documentation-content-strategy/content-types/tutorial/) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/glossary-definition.mdx b/src/content/docs/style-guide/components/glossary-definition.mdx index 002f58bdbfef0b..f564d5e319533d 100644 --- a/src/content/docs/style-guide/components/glossary-definition.mdx +++ b/src/content/docs/style-guide/components/glossary-definition.mdx @@ -1,5 +1,7 @@ --- title: Glossary definition +styleGuide: + component: GlossaryDefinition --- Use the this component to add extra information to an existing glossary entry. `term` defines which glossary entry you want to prepend information to, while `prepend=` adds the extra info. diff --git a/src/content/docs/style-guide/components/glossary-tooltip.mdx b/src/content/docs/style-guide/components/glossary-tooltip.mdx index 26f7a3537d7f14..16f6307a66a54f 100644 --- a/src/content/docs/style-guide/components/glossary-tooltip.mdx +++ b/src/content/docs/style-guide/components/glossary-tooltip.mdx @@ -1,5 +1,7 @@ --- title: Glossary tooltip +styleGuide: + component: GlossaryTooltip --- Use this component to add tooltips to words in your markdown files. The info for the tooltips is pulled in from the glossary yaml file. diff --git a/src/content/docs/style-guide/components/glossary.mdx b/src/content/docs/style-guide/components/glossary.mdx index 94fec1e2b56629..515c28e292fa7e 100644 --- a/src/content/docs/style-guide/components/glossary.mdx +++ b/src/content/docs/style-guide/components/glossary.mdx @@ -1,5 +1,7 @@ --- title: Glossary +styleGuide: + component: Glossary --- Use the glossary definition shortcode to render the defined glossary definition. Additionally, you can include a [prepend value](/style-guide/components/glossary-definition/) to add words to the start of the definition. diff --git a/src/content/docs/style-guide/components/inline-badge.mdx b/src/content/docs/style-guide/components/inline-badge.mdx index af6375f6a0a168..7e11a4f124cde4 100644 --- a/src/content/docs/style-guide/components/inline-badge.mdx +++ b/src/content/docs/style-guide/components/inline-badge.mdx @@ -1,5 +1,7 @@ --- title: Inline badge +styleGuide: + component: InlineBadge --- :::caution[Recommendation: Avoid inline badges] diff --git a/src/content/docs/style-guide/components/last-reviewed.mdx b/src/content/docs/style-guide/components/last-reviewed.mdx index cd10dd179b428d..81abd3c3eea0d3 100644 --- a/src/content/docs/style-guide/components/last-reviewed.mdx +++ b/src/content/docs/style-guide/components/last-reviewed.mdx @@ -23,4 +23,8 @@ import { LastReviewed } from "~/components" title: My Tutorial updated: 2024-07-01 --- -``` \ No newline at end of file +``` + +## Associated content types + +- [Tutorial](/style-guide/documentation-content-strategy/content-types/tutorial/) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/link-cards.mdx b/src/content/docs/style-guide/components/link-cards.mdx index 792c84e74e3031..9c134ea2b74961 100644 --- a/src/content/docs/style-guide/components/link-cards.mdx +++ b/src/content/docs/style-guide/components/link-cards.mdx @@ -1,5 +1,7 @@ --- title: Link cards +styleGuide: + component: LinkCard --- ```mdx live wrap diff --git a/src/content/docs/style-guide/components/list-examples.mdx b/src/content/docs/style-guide/components/list-examples.mdx index 07aacaf9ea4fe6..451b59d4fe05ab 100644 --- a/src/content/docs/style-guide/components/list-examples.mdx +++ b/src/content/docs/style-guide/components/list-examples.mdx @@ -1,5 +1,7 @@ --- title: List examples +styleGuide: + component: ListExamples --- ```mdx live diff --git a/src/content/docs/style-guide/components/list-tutorials.mdx b/src/content/docs/style-guide/components/list-tutorials.mdx index dff99c9bf16d01..d366beb49baafc 100644 --- a/src/content/docs/style-guide/components/list-tutorials.mdx +++ b/src/content/docs/style-guide/components/list-tutorials.mdx @@ -1,9 +1,15 @@ --- title: List tutorials +styleGuide: + component: ListTutorials --- ```mdx live import { ListTutorials } from "~/components"; -``` \ No newline at end of file +``` + +## Associated content types + +- [Tutorial](/style-guide/documentation-content-strategy/content-types/tutorial/) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/markdown.mdx b/src/content/docs/style-guide/components/markdown.mdx index f3248a3fdacea0..e658b6cd19a3d1 100644 --- a/src/content/docs/style-guide/components/markdown.mdx +++ b/src/content/docs/style-guide/components/markdown.mdx @@ -1,5 +1,7 @@ --- title: Markdown +styleGuide: + component: Markdown --- This component uses [`marked`](https://marked.js.org/) to render [CommonMark and various other Markdown flavours](https://marked.js.org/#specifications). diff --git a/src/content/docs/style-guide/components/package-managers.mdx b/src/content/docs/style-guide/components/package-managers.mdx index 9df8a834ed7d68..48623087ad1eed 100644 --- a/src/content/docs/style-guide/components/package-managers.mdx +++ b/src/content/docs/style-guide/components/package-managers.mdx @@ -1,5 +1,7 @@ --- title: Package Managers +styleGuide: + component: PackageManagers --- This component is provided by the [`starlight-package-managers` package.](https://github.com/HiDeoo/starlight-package-managers) diff --git a/src/content/docs/style-guide/components/pages-build-environment.mdx b/src/content/docs/style-guide/components/pages-build-environment.mdx index 62ae8b28338cc1..0e83645805e399 100644 --- a/src/content/docs/style-guide/components/pages-build-environment.mdx +++ b/src/content/docs/style-guide/components/pages-build-environment.mdx @@ -1,5 +1,7 @@ --- title: Pages build environment +styleGuide: + component: PagesBuildEnvironmentLanguages --- ## Languages diff --git a/src/content/docs/style-guide/components/pages-build-preset.mdx b/src/content/docs/style-guide/components/pages-build-preset.mdx index 8909128848acdb..c21e9b07b71478 100644 --- a/src/content/docs/style-guide/components/pages-build-preset.mdx +++ b/src/content/docs/style-guide/components/pages-build-preset.mdx @@ -1,5 +1,7 @@ --- title: Pages build preset +styleGuide: + component: PagesBuildPreset --- ```mdx live diff --git a/src/content/docs/style-guide/components/pages-build-presets-table.mdx b/src/content/docs/style-guide/components/pages-build-presets-table.mdx index 4782c814a21a18..4f27d1a8431a03 100644 --- a/src/content/docs/style-guide/components/pages-build-presets-table.mdx +++ b/src/content/docs/style-guide/components/pages-build-presets-table.mdx @@ -1,5 +1,7 @@ --- title: Pages build presets table +styleGuide: + component: PagesBuildPresetsTable --- ```mdx live diff --git a/src/content/docs/style-guide/components/plan-info.mdx b/src/content/docs/style-guide/components/plan-info.mdx index 841e65815718fc..d95ec008923e77 100644 --- a/src/content/docs/style-guide/components/plan-info.mdx +++ b/src/content/docs/style-guide/components/plan-info.mdx @@ -1,5 +1,7 @@ --- title: Plan info +styleGuide: + component: PlanInfo --- Use when you need a single piece of information from the `index.json` file in `src/content/plans/`. For the id property, use dot notation to access the property you want to share. diff --git a/src/content/docs/style-guide/components/plan.mdx b/src/content/docs/style-guide/components/plan.mdx index d7b376f2b943af..cb54bbe8e76864 100644 --- a/src/content/docs/style-guide/components/plan.mdx +++ b/src/content/docs/style-guide/components/plan.mdx @@ -1,5 +1,7 @@ --- title: Plan +styleGuide: + component: Plan --- The plan component lets you define what type of plan your product needs. There are two ways to use it: in the main [Overview page](/style-guide/documentation-content-strategy/content-types/overview/) of your product, or in a page where you need to talk about a specific feature with additional requirements. diff --git a/src/content/docs/style-guide/components/product-features.mdx b/src/content/docs/style-guide/components/product-features.mdx index f6c28b0785d694..90dad818797cf8 100644 --- a/src/content/docs/style-guide/components/product-features.mdx +++ b/src/content/docs/style-guide/components/product-features.mdx @@ -1,5 +1,7 @@ --- title: Product features +styleGuide: + component: ProductFeatures --- Use when you need to list all available features within a product grouping inside of the `index.json` file in `src/content/plans/`. For the id property, specify the product object you want to use. diff --git a/src/content/docs/style-guide/components/products-by-tag.mdx b/src/content/docs/style-guide/components/products-by-tag.mdx index ae1fd2fcb21b70..1dbd1821ec26b3 100644 --- a/src/content/docs/style-guide/components/products-by-tag.mdx +++ b/src/content/docs/style-guide/components/products-by-tag.mdx @@ -1,11 +1,15 @@ --- title: Products by tag +styleGuide: + component: ProductsByTag --- +To see a list of the available tags, and which pages are associated with them, refer to [this list](/style-guide/frontmatter/tags/). + ```mdx live import { ProductsByTag } from "~/components"; - ``` \ No newline at end of file diff --git a/src/content/docs/style-guide/components/public-stats.mdx b/src/content/docs/style-guide/components/public-stats.mdx index 7f4eb36331314a..d86c83872fc422 100644 --- a/src/content/docs/style-guide/components/public-stats.mdx +++ b/src/content/docs/style-guide/components/public-stats.mdx @@ -1,8 +1,12 @@ --- title: Public stats +styleGuide: + component: PublicStats --- -The `PublicStats` component allows you to reference specific values about Cloudflare's network without maintaining those values in multiple files. +import { Render } from "~/components"; + + Refer to the examples below for more information. @@ -21,3 +25,11 @@ Cloudflare also has . If you need more stats or to update these stats, submit a pull request to update [PublicStats.astro](https://github.com/cloudflare/cloudflare-docs/blob/production/src/components/PublicStats.astro) ::: + +## Associated content types + +The `PublicStats` component is commonly used on the following type of pages: + +- [Overview](/style-guide/documentation-content-strategy/content-types/overview/) +- [Reference Architecture](/style-guide/documentation-content-strategy/content-types/reference-architecture/) +- [Reference Architecture Diagrams](/style-guide/documentation-content-strategy/content-types/reference-architecture-diagram/) \ No newline at end of file diff --git a/src/content/docs/style-guide/components/related-product.mdx b/src/content/docs/style-guide/components/related-product.mdx index d230556f28f906..91c8db095bdd60 100644 --- a/src/content/docs/style-guide/components/related-product.mdx +++ b/src/content/docs/style-guide/components/related-product.mdx @@ -1,5 +1,7 @@ --- title: Related product +styleGuide: + component: RelatedProduct --- The `` component lists products related or connected to the current product. diff --git a/src/content/docs/style-guide/components/render.mdx b/src/content/docs/style-guide/components/render.mdx index 57060bbe4d84a5..7e56b798bc5d3b 100644 --- a/src/content/docs/style-guide/components/render.mdx +++ b/src/content/docs/style-guide/components/render.mdx @@ -1,5 +1,7 @@ --- title: Render +styleGuide: + component: Render --- import { Code, Details, Type, MetaInfo } from "~/components"; diff --git a/src/content/docs/style-guide/components/resources-by-selector.mdx b/src/content/docs/style-guide/components/resources-by-selector.mdx index 17d14548714595..edce3eb18b6170 100644 --- a/src/content/docs/style-guide/components/resources-by-selector.mdx +++ b/src/content/docs/style-guide/components/resources-by-selector.mdx @@ -1,5 +1,7 @@ --- title: Resources by selector +styleGuide: + component: ResourcesBySelector --- import { Type, MetaInfo } from "~/components"; @@ -27,6 +29,8 @@ import { ResourcesBySelector } from "~/components"; An array of `tags` values to filter by. + To see a list of the available tags, and which pages are associated with them, refer to [this list](/style-guide/frontmatter/tags/). + - `products` An array of `products` values to filter by. \ No newline at end of file diff --git a/src/content/docs/style-guide/components/rule-id.mdx b/src/content/docs/style-guide/components/rule-id.mdx index 9ea7bb4faebedb..22d389251a1664 100644 --- a/src/content/docs/style-guide/components/rule-id.mdx +++ b/src/content/docs/style-guide/components/rule-id.mdx @@ -1,5 +1,7 @@ --- title: Rule ID +styleGuide: + component: RuleID --- ```mdx live diff --git a/src/content/docs/style-guide/components/spotlight-author-details.mdx b/src/content/docs/style-guide/components/spotlight-author-details.mdx index 1b7213ab4dd12a..db49a9039ce374 100644 --- a/src/content/docs/style-guide/components/spotlight-author-details.mdx +++ b/src/content/docs/style-guide/components/spotlight-author-details.mdx @@ -1,5 +1,7 @@ --- title: Spotlight author details +styleGuide: + component: SpotlightAuthorDetails --- ## Component diff --git a/src/content/docs/style-guide/components/steps.mdx b/src/content/docs/style-guide/components/steps.mdx index 7c88828572b16f..6063b06c85f5b5 100644 --- a/src/content/docs/style-guide/components/steps.mdx +++ b/src/content/docs/style-guide/components/steps.mdx @@ -1,5 +1,7 @@ --- title: Steps +styleGuide: + component: Steps --- ```mdx live diff --git a/src/content/docs/style-guide/components/stream.mdx b/src/content/docs/style-guide/components/stream.mdx index ddff5441a84a3d..f2a7564feee797 100644 --- a/src/content/docs/style-guide/components/stream.mdx +++ b/src/content/docs/style-guide/components/stream.mdx @@ -1,23 +1,81 @@ --- title: Stream +styleGuide: + component: Stream --- +## Import + ```mdx import { Stream } from "~/components" +``` + +## Usage + +import { Stream } from "~/components" + + +```mdx ``` ---- +## `` Props -import { Stream } from "~/components" +### `id` - \ No newline at end of file +**required** + +**type:** `string` + +The ID of the Stream video. + +### `title` + +**required** + +**type:** `string` + +The title of the Stream video. + +### `thumbnail` + +**type:** `string` + +Either a timestamp (i.e `2.5s` or `1m35s`) or a URL to an image. + +### `chapters` + +**type:** `Record` + +Optional chapters displayed as cards below the video. + +### `showMoreVideos` + +**type:** `boolean` + +**default:** `true` + +Whether to show the "Watch more videos on our Developer Channel" link below the video. \ No newline at end of file diff --git a/src/content/docs/style-guide/components/subtract-ip-calculator.mdx b/src/content/docs/style-guide/components/subtract-ip-calculator.mdx new file mode 100644 index 00000000000000..82d9a89e5fb0c8 --- /dev/null +++ b/src/content/docs/style-guide/components/subtract-ip-calculator.mdx @@ -0,0 +1,54 @@ +--- +title: Subtract IP calculator +styleGuide: + component: SubtractIPCalculator +--- + +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; + +## Import + +```mdx +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; +``` + +## Usage + +
    + + +```mdx +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; + + +``` + +## `` Props + +### `defaults` + +**type:** `object` + +An optional object containing `base` (`string`) and `exclude` (`string[]`) properties, to set default inputs. + +**example:** + + + +```mdx +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; + + +``` \ No newline at end of file diff --git a/src/content/docs/style-guide/components/tabs.mdx b/src/content/docs/style-guide/components/tabs.mdx index b95fb600293608..35efc85cbf564c 100644 --- a/src/content/docs/style-guide/components/tabs.mdx +++ b/src/content/docs/style-guide/components/tabs.mdx @@ -1,5 +1,7 @@ --- title: Tabs +styleGuide: + component: Tabs --- import { Tabs, TabItem } from '~/components'; diff --git a/src/content/docs/style-guide/components/type-highlighting.mdx b/src/content/docs/style-guide/components/type-highlighting.mdx index 8626e875b64675..f536ec2b1365d5 100644 --- a/src/content/docs/style-guide/components/type-highlighting.mdx +++ b/src/content/docs/style-guide/components/type-highlighting.mdx @@ -1,6 +1,8 @@ --- title: Type highlighting description: Components for styling type information for CLI/function parameters. +styleGuide: + component: Type --- ## Type diff --git a/src/content/docs/style-guide/components/typescript-example.mdx b/src/content/docs/style-guide/components/typescript-example.mdx index bf9c38b7d981cb..54c13c28ab1c09 100644 --- a/src/content/docs/style-guide/components/typescript-example.mdx +++ b/src/content/docs/style-guide/components/typescript-example.mdx @@ -1,5 +1,7 @@ --- title: TypeScript example +styleGuide: + component: TypeScriptExample --- ## TypeScript examples diff --git a/src/content/docs/style-guide/components/usage.mdx b/src/content/docs/style-guide/components/usage.mdx new file mode 100644 index 00000000000000..5bf4431882052e --- /dev/null +++ b/src/content/docs/style-guide/components/usage.mdx @@ -0,0 +1,11 @@ +--- +title: Usage +sidebar: + order: 1 +--- + +import { ComponentsUsage } from "~/components"; + +This page contains a breakdown of each component and the pages where they are used. + + \ No newline at end of file diff --git a/src/content/docs/style-guide/components/worker-starter.mdx b/src/content/docs/style-guide/components/worker-starter.mdx index 076159fa1d9267..c173a5b27009fc 100644 --- a/src/content/docs/style-guide/components/worker-starter.mdx +++ b/src/content/docs/style-guide/components/worker-starter.mdx @@ -1,5 +1,7 @@ --- title: Worker Starter +styleGuide: + component: WorkerStarter --- ```mdx diff --git a/src/content/docs/style-guide/components/youtube.mdx b/src/content/docs/style-guide/components/youtube.mdx index add507a1fbd22f..507e32cd00e8a4 100644 --- a/src/content/docs/style-guide/components/youtube.mdx +++ b/src/content/docs/style-guide/components/youtube.mdx @@ -1,5 +1,7 @@ --- title: YouTube +styleGuide: + component: YouTube --- import { YouTube } from "~/components" diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/3rd-party-integration-guide.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/3rd-party-integration-guide.mdx index dcc19cd924adb2..05cd2e741c26d6 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/3rd-party-integration-guide.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/3rd-party-integration-guide.mdx @@ -13,7 +13,11 @@ instructional, straightforward ## content_type -`integration-guide` +```yaml +pcx_content_type: integration-guide +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/changelog.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/changelog.mdx index 2086baf7e2c058..b306fc1bb6c9dd 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/changelog.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/changelog.mdx @@ -13,7 +13,11 @@ instructional, straightforward ## content_type -`changelog` +```yaml +pcx_content_type: changelog +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Ownership diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/concept.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/concept.mdx index b9fb73cc9d6f54..f5d019fdccd23f 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/concept.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/concept.mdx @@ -13,7 +13,11 @@ instructional, descriptive, approachable, supportive ## content_type -`concept` +```yaml +pcx_content_type: concept +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/configuration.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/configuration.mdx index 81f5a3358cb1c4..afe96354497368 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/configuration.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/configuration.mdx @@ -14,7 +14,11 @@ plain, descriptive, straightforward ## content\_type -`configuration` +```yaml +pcx_content_type: configuration +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## When to use @@ -39,46 +43,46 @@ Configurations are useful for parts of the product that are very configuration-i ``` --- -weight: xx +weight: xx pcx_content_type: configuration --- # Title - + Write an overview of the high-level feature here, not more than 2-3 sentences. Outline what users can achieve with it, and if necessary, link to other parts of the docs. - + * [Feature 1](/feature-1) * [Feature 2](/feature-2) * [Feature 3](/feature-3) - + ## Feature 1 - + (Feature 1) allows you to (placeholder). For example, the following configuration (placeholder). - + | Setting 1 | Setting 2 | Setting 3 | - -| - | - | - | - + +| - | - | - | + | Value 1 | Value 2 | Value 3 | - + ## Feature 2 - + (Feature 2) allows you to (placeholder). For example, the following configuration (placeholder). - + | Setting 1 | Setting 2 | Setting 3 | - -| - | - | - | - + +| - | - | - | + | Value 1 | Value 2 | Value 3 | - + ## Feature 3 - + (Feature 3) allows you to (placeholder). For example, the following configuration (placeholder). - + | Setting 1 | Setting 2 | Setting 3 | - -| - | - | - | - + +| - | - | - | + | Value 1 | Value 2 | Value 3 | ``` diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/design-guide.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/design-guide.mdx index 8e488f83d88303..a56ecb50a90859 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/design-guide.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/design-guide.mdx @@ -14,7 +14,11 @@ instructional, straightforward ## content\_type -`design-guide` +```yaml +pcx_content_type: design-guide +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Examples @@ -57,7 +61,7 @@ meta: # Design guide title ## Introduction -Provide context to what this guide is going to cover. Ensure you describe the end state of the solution this guide will detail. +Provide context to what this guide is going to cover. Ensure you describe the end state of the solution this guide will detail. ### Who is this for? This reference architecture is designed for IT or security professionals with some responsibility over or familiarity with their organization’s existing infrastructure. It is useful to have some experience with technologies important to securing hybrid work, including identity providers (IdPs), user directories, single sign on (SSO), endpoint security or management (EPP, XDR, UEM, MDM), firewalls, routers, and point solutions like packet or content inspection hardware, threat prevention, and data loss prevention technologies. diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/faq.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/faq.mdx index 745f8830366e82..a3f32fa4762652 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/faq.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/faq.mdx @@ -13,7 +13,11 @@ Guiding, straightforward, educational, authoritative ## content_type -`faq` +```yaml +pcx_content_type: faq +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Overview diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/get-started.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/get-started.mdx index fd106a563ff16e..2d609d477ca7c0 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/get-started.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/get-started.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: concept -title: Get started page template +title: Get started --- @@ -10,7 +10,11 @@ The purpose of Get started content is to help users go from not using a product ## content\_type -`get-started` +```yaml +pcx_content_type: get-started +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/how-to.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/how-to.mdx index 16b04191b2e36e..30fbed25bf4e34 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/how-to.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/how-to.mdx @@ -18,7 +18,11 @@ instructional, straightforward ## content\_type -`how-to` +```yaml +pcx_content_type: how-to +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure @@ -60,11 +64,11 @@ Single procedure how-to weight: xx pcx_content_type: how-to --- - + # Second-person imperative verb phrase - + Context for procedure (optional) - + 1. Step one 1. Step two 1. Step three @@ -81,22 +85,22 @@ How-to with multiple procedures weight: xx pcx_content_type: how-to --- - + # Second-person imperative verb phrase - + Context for procedures on page (optional) - + ## Second-person imperative verb phrase - + 1. Step one 1. Step two 1. Step three 1. ... - + Next steps sentence - what users should see as the end result and/or actionable next steps. - + ## Second-person imperative verb phrase - + 1. Step one 1. Step two 1. Step three @@ -113,35 +117,35 @@ How-to with multiple procedures that must be completed in order weight: xx pcx_content_type: how-to --- - + # Second-person imperative verb phrase - + Context for procedures on page (optional) - + ## 1. Second-person imperative verb phrase - + 1. Step one 1. Step two 1. Step three 1. ... - + Next steps sentence - what users should see as the end result and/or actionable next steps. - + ## 2. Second-person imperative verb phrase - + 1. Step one 1. Step two 1. Step three 1. ... - + Next steps sentence - what users should see as the end result and/or actionable next steps. - + ## 3. Second-person imperative verb phrase - + 1. Step one 1. Step two 1. Step three 1. ... - + Next steps sentence - what users should see as the end result and/or actionable next steps. ``` diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/implementation-guide.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/implementation-guide.mdx index 0ec5c47afc0f0c..36c33425a078bd 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/implementation-guide.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/implementation-guide.mdx @@ -13,11 +13,15 @@ instructional, straightforward ## content\_type -`implementation-guide` +```yaml +pcx_content_type: implementation-guide +``` -## Structure +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). -### Required components +## Components + +### Required [**Title**](/style-guide/documentation-content-strategy/component-attributes/titles/): Short verb phrase in second-person imperative. Do not use gerund phrases. @@ -25,7 +29,7 @@ instructional, straightforward [**Next steps**](/style-guide/documentation-content-strategy/component-attributes/next-steps/): What users should see as the end result of the steps and/or actionable next steps. -### Optional components +### Optional [**Prerequisites**](/style-guide/documentation-content-strategy/component-attributes/prerequisites/): Tasks or conditions that must be completed before a user can complete a series of steps. diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/navigation.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/navigation.mdx index 718ae098a732fc..4f8318eeff9511 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/navigation.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/navigation.mdx @@ -4,19 +4,23 @@ pcx_content_type: concept --- +import { Render } from "~/components"; + ## Purpose The purpose of a navigation page is to direct users deeper into the doc set and act as a sub-landing page for a specific area of the docs. ## content_type -`navigation` +```yaml +pcx_content_type: navigation +``` -## Structure +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). -Use the `{{}}` component +## Components -**Title**: Verb or noun phrase that describes the sub-pages in the section. +[`DirectoryListing`](/style-guide/components/directory-listing/): ## Template @@ -27,9 +31,9 @@ pcx_content_type: navigation --- import { DirectoryListing } from "~/components" - + # Name of section - + ``` diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/overview.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/overview.mdx index cd6768da040053..c556e6ab0e6865 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/overview.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/overview.mdx @@ -4,6 +4,8 @@ title: Overview --- +import { Render } from "~/components"; + ## Purpose The purpose of a landing page is to welcome users and provide an overview of the product. @@ -14,10 +16,18 @@ Accessible, welcoming, conversational, outspoken ## content\_type -`overview` +```yaml +pcx_content_type: overview +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure +### Most used components + +- [`PublicStats`](/style-guide/components/public-stats/): + ### Required components **Metadata title**: Overview @@ -99,7 +109,7 @@ Description of external resource related to current product. ## Additional Information -Overview pages are the default "first" page in any nested navigation. In some cases, to ensure good information architecture and navigability, you may need to rename or remove overview pages. +Overview pages are the default "first" page in any nested navigation. In some cases, to ensure good information architecture and navigability, you may need to rename or remove overview pages. ### When to consider removing an verview page diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture-diagram.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture-diagram.mdx index 50567e893b39df..9b36229ca99e87 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture-diagram.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture-diagram.mdx @@ -4,6 +4,8 @@ title: Reference architecture diagram --- +import { Render } from "~/components"; + ## Purpose To provide a visual reference and explanation of using Cloudflare for a specific solution. @@ -14,17 +16,26 @@ instructional, straightforward ## content\_type -`reference-architecture-diagram` +```yaml +pcx_content_type: reference-architecture-diagram +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). + +## Components + +### Most used -## Structure +- [`PublicStats`](/style-guide/components/public-stats/): +- [Diagrams](/style-guide/documentation-content-strategy/component-attributes/diagrams/): Particularly helpful for image captions. -### Required components +### Required [**Title**](/style-guide/documentation-content-strategy/component-attributes/titles/): Short verb phrase in second-person imperative. Do not use gerund phrases. [**Reference diagram**](/style-guide/documentation-content-strategy/component-attributes/reference-diagram/): A single diagram that reflects the overall reference architecture. -### Optional components +### Optional [**Notes/warnings**](/style-guide/documentation-content-strategy/component-attributes/notes-tips-warnings/) diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture.mdx index 0b41c7e9f20307..7f144b0b32ae19 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference-architecture.mdx @@ -4,6 +4,8 @@ title: Reference architecture --- +import { Render } from "~/components"; + ## Purpose The purpose of a reference architecture is to provide a high-level view of how all or part of the Cloudflare platform is built and how Cloudflare products would fit into a customer's existing infrastructure. Reference architectures are designed to show where our platform fits in with a customer's current environment and describe key aspects of a Cloudflare feature/service. Reference architectures should also map customer use cases to Cloudflare solutions. @@ -14,9 +16,13 @@ Reference architectures are typically very detailed. To describe a single archit guiding, straightforward -## content\_type +## content_type + +```yaml +pcx_content_type: reference-architecture +``` -`reference-architecture` +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Examples @@ -26,9 +32,14 @@ guiding, straightforward [Evolving to a SASE architecture with Cloudflare](/reference-architecture/architectures/sase/) -## Structure +## Components -### Required components +### Most used + +- [`PublicStats`](/style-guide/components/public-stats/): +- [Diagrams](/style-guide/documentation-content-strategy/component-attributes/diagrams/): Particularly helpful for image captions. + +### Required [**Title**](/style-guide/documentation-content-strategy/component-attributes/titles/): Short verb phrase in second-person imperative. Do not use gerund phrases. @@ -38,7 +49,7 @@ guiding, straightforward [**Reference diagram**](/style-guide/documentation-content-strategy/component-attributes/reference-diagram/): A single diagram that reflects the overall reference architecture. -### Optional components +### Optional [**Notes/warnings**](/style-guide/documentation-content-strategy/component-attributes/notes-tips-warnings/) @@ -61,11 +72,11 @@ weight: 1 meta: title: "Reference Architecture: An example Cloudflare solution" --- - + # Cloudflare Reference Architecture - + ## Introduction -Cloudflare provides software as a service solutions (SaaS) solutions for performance, security, reliability, and developer services. This reference architecture focuses on the security of the platform and the network these services are built on, as well as the broad security capabilities the services offer for both public facing and internal facing assets. +Cloudflare provides software as a service solutions (SaaS) solutions for performance, security, reliability, and developer services. This reference architecture focuses on the security of the platform and the network these services are built on, as well as the broad security capabilities the services offer for both public facing and internal facing assets. ### Who is this document for? This reference architecture is designed for IT or security professionals with some responsibility over or familiarity with their organization’s existing infrastructure. It is useful to have some experience with technologies important to securing hybrid work, including identity providers (IdPs), user directories, single sign on (SSO), endpoint security or management (EPP, XDR, UEM, MDM), firewalls, routers, and point solutions like packet or content inspection hardware, threat prevention, and data loss prevention technologies. diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference.mdx index 52587eb312f20e..ef73d3330dd5ee 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/reference.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/reference.mdx @@ -12,9 +12,13 @@ The purpose of reference content is to provide supplemental information for furt plain, straightforward -## content\_type +## content_type -`reference` +```yaml +pcx_content_type: reference +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure @@ -54,18 +58,18 @@ Single reference page weight: xx pcx_content_type: reference --- - + # Reference - + Write an overview of the reference information on this page. If this section has child pages, add navigation links below using the DirectoryListing snippet to add links for each child page in a bulleted list. - + - + ## Concise noun title - + Brief description of content in this section. - + ## Concise noun title - + Brief description of content in this section. ``` diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/support-content.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/support-content.mdx deleted file mode 100644 index 1d343a2c352e34..00000000000000 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/support-content.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -pcx_content_type: concept -title: Support content - ---- - -## Purpose - -The purpose of support content is to provide guidance for solving specific problems with Cloudflare. - -## Tone - -Guiding, straightforward, solution-oriented - -## content_type - -Use the metadata tag for the Content Type you create within the Support tile. - -### Required components - -**Title** - -**Context** - -### Optional components - -**Steps/Tasks/Procedures** - -**Examples** - -**Next steps** - -## Structure - -The structure of a page within the support tile will depend on the purpose that content serves. - -## Boundaries - -The general guidance is that anything related to a specific product (DNS, Security Center) or platform (Cloudflare One) belongs in a [product](/products/) tile. Anything that is specific to interacting with Cloudflare support or details niche troubleshooting steps belongs in the [support](/support/) tile. - -Support content should not duplicate content that already exists in a product tile. - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Support content examplesProduct content examples
    How to interact with Cloudflare supportProduct documentation - feature information, functionality, configuration, known limitations
    Niche troubleshooting information (multiple product configurations affecting each other)Troubleshooting a specific product or platform
    Third-party integrations and partnerships that are not specific to a product (like WordPress)Product-specific integration guides
    Runtime errors when integrating with external productsRuntime errors specific to a product
    How Cloudflare charges for specific things (rates, usage)Process documentation for how to set up billing information, etc. - no pricing content
    - -## Additional information - -Migrating content from /support/ to other areas of dev docs - -When you migrate content from the Support tile to other, relevant product areas: - -1. Move over the English version of the page to your desired location. -2. Make edits to bring the content into alignment with our style guide. diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/troubleshooting.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/troubleshooting.mdx index 8c5fb17666bca1..838458ddb99be6 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/troubleshooting.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/troubleshooting.mdx @@ -16,7 +16,11 @@ Guiding, straightforward, solution-oriented ## content\_type -`troubleshooting` +```yaml +pcx_content_type: troubleshooting +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). ## Structure diff --git a/src/content/docs/style-guide/documentation-content-strategy/content-types/tutorial.mdx b/src/content/docs/style-guide/documentation-content-strategy/content-types/tutorial.mdx index 8ee4833f45b981..e7621bbc842373 100644 --- a/src/content/docs/style-guide/documentation-content-strategy/content-types/tutorial.mdx +++ b/src/content/docs/style-guide/documentation-content-strategy/content-types/tutorial.mdx @@ -9,10 +9,6 @@ import { GlossaryDefinition, Render } from "~/components"; -## Template - -We have a [tutorial template](https://github.com/cloudflare/cloudflare-docs/blob/production/templates/tutorial-template.mdx) that helps you follow our general structure and content guidelines. - ## Guidelines **A tutorial is:** @@ -40,11 +36,21 @@ Guiding, straightforward, educational, authoritative ### content_type -`tutorial` +```yaml +pcx_content_type: tutorial +``` + +For more details, refer to [`pcx_content_type`](/style-guide/frontmatter/custom-properties/#pcx_content_type). + +### Components + +#### Most used -### Structure +- [`GitHubCode`](/style-guide/components/github-code/) +- [`LastReviewed`](/style-guide/components/last-reviewed/) +- [`ListTutorials`](/style-guide/components/list-tutorials/) -#### Required components +#### Required [**Title**](/style-guide/documentation-content-strategy/component-attributes/titles/): Short verb phrase in second-person imperative. @@ -54,7 +60,7 @@ Guiding, straightforward, educational, authoritative [**Steps**](/style-guide/documentation-content-strategy/component-attributes/steps-tasks-procedures/): Numbered steps that complete a task. -#### Optional components +#### Optional [**Notes/warnings**](/style-guide/documentation-content-strategy/component-attributes/notes-tips-warnings/) diff --git a/src/content/docs/style-guide/frontmatter/custom-properties.mdx b/src/content/docs/style-guide/frontmatter/custom-properties.mdx new file mode 100644 index 00000000000000..2353033b6aaacc --- /dev/null +++ b/src/content/docs/style-guide/frontmatter/custom-properties.mdx @@ -0,0 +1,14 @@ +--- +title: Custom properties +sidebar: + order: 4 +--- + +import { Type, MetaInfo } from "~/components"; +import BaseSchemaProperties from "~/components/BaseSchemaProperties.astro"; + +We have added specific custom [frontmatter](/style-guide/frontmatter/) properties to meet specific needs. + +## Properties + + diff --git a/src/content/docs/style-guide/frontmatter/tags.mdx b/src/content/docs/style-guide/frontmatter/tags.mdx new file mode 100644 index 00000000000000..6dd5ce4fe3d3ea --- /dev/null +++ b/src/content/docs/style-guide/frontmatter/tags.mdx @@ -0,0 +1,22 @@ +--- +title: Tags +--- + +import { TagsUsage } from "~/components"; + +Tags are currently used to filter content in the [`ExternalResources`](/style-guide/components/external-resources/), [`ProductsByTag`](/style-guide/components/products-by-tag/) and the [`ResourcesBySelector`](/style-guide/components/resources-by-selector/) components. + +## Examples + +```mdx +--- +title: Example +tags: + - foo + - bar +--- +``` + +## Tags + + \ No newline at end of file diff --git a/src/content/docs/style-guide/grammar/parts-of-speech/nouns-and-pronouns.mdx b/src/content/docs/style-guide/grammar/parts-of-speech/nouns-and-pronouns.mdx index e7eb50b8bd25b1..e02ee7c31fa755 100644 --- a/src/content/docs/style-guide/grammar/parts-of-speech/nouns-and-pronouns.mdx +++ b/src/content/docs/style-guide/grammar/parts-of-speech/nouns-and-pronouns.mdx @@ -10,7 +10,7 @@ Make sure it is clear who or what pronouns are in reference to. Pronouns act as ## First person -Substitute "we" or "I" with "Cloudflare" if you need to represent Cloudflare. +Substitute "we" or "I" with "Cloudflare" if you need to represent Cloudflare. You do not need to use "we" constantly. However, use it when it is the best choice grammatically. | ✅ | ❌ | | ----------------------------------------------------------- | ----------------------------------------------------------------- | diff --git a/src/content/docs/style-guide/index.mdx b/src/content/docs/style-guide/index.mdx index 212044c6d88488..3d0ab6d49838d2 100644 --- a/src/content/docs/style-guide/index.mdx +++ b/src/content/docs/style-guide/index.mdx @@ -1,6 +1,7 @@ --- title: Style Guide pcx_content_type: overview +description: Improve your contributions to Cloudflare's documentation. Ensure consistency, professionalism, and clarity in your content across all products. sidebar: order: 1 --- diff --git a/src/content/docs/support/third-party-software/content-management-system-cms/cloudflare-and-joomla-recommended-first-steps.mdx b/src/content/docs/support/third-party-software/content-management-system-cms/cloudflare-and-joomla-recommended-first-steps.mdx index 24cddedd063581..dff3a31b8dffa3 100644 --- a/src/content/docs/support/third-party-software/content-management-system-cms/cloudflare-and-joomla-recommended-first-steps.mdx +++ b/src/content/docs/support/third-party-software/content-management-system-cms/cloudflare-and-joomla-recommended-first-steps.mdx @@ -2,14 +2,13 @@ pcx_content_type: troubleshooting source: https://support.cloudflare.com/hc/en-us/articles/201997250-Cloudflare-and-Joomla-Recommended-First-Steps title: Cloudflare and Joomla Recommended First Steps - --- ## Overview These basic steps will help reduce common areas of confusion for Joomla users that are new to the Cloudflare services. In addition, these steps are very quick and will generally take you only a few minutes of your time to help you make your experience using Cloudflare better. -*** +--- ## Restore visitor IP @@ -17,60 +16,43 @@ Restore visitor IP by following the directions in [this article](/support/troubl Why should you restore visitor IP? -If you receive a lot of comments or spam on your blog, you may mistakenly believe that Cloudflare is spamming you. Some other Joomla plugins or extensions  may also rely on the original visitor IP for the  services to work properly and reduce false alerts. +If you receive a lot of comments or spam on your blog, you may mistakenly believe that Cloudflare is spamming you. Some other Joomla plugins or extensions may also rely on the original visitor IP for the services to work properly and reduce false alerts. :::note - -You don't need to worry about this if you activated through a hosting -partner, since they already restore visitor IP addresses on their -servers by default. +You don't need to worry about this if you activated through a hosting partner, since they already restore visitor IP addresses on their servers by default. ::: -*** +--- -## Create a PageRule to exclude Joomla +## Create a Page Rule to exclude Joomla -Create a [PageRule](https://support.cloudflare.com/hc/en-us/articles/200168306-Is-there-a-tutorial-for-Page-Rules-) to exclude the Joomla admin or Joomla login sections from Cloudflare’s caching and performance features. You can access PageRules in your [Cloudflare 'Settings' options](https://support.cloudflare.com/hc/en-us/articles/200172336-How-do-I-create-a-PageRule-). +Create a [Page Rule](/rules/page-rules/) to exclude the Joomla admin or Joomla login sections from Cloudflare's caching and performance features. Why do this? While there is not always an issue, we have seen instances where optional performance features like Rocket Loader may inadvertently break certain functions (editors, etc.) in your Joomla back end. -*** +--- ## Allow IP addresses via Cloudflare Threat Control panel Log in to your Cloudflare Threat Control panel and allow IP addresses you want traffic from or expect traffic from. Some common services you probably want to allow include: -* APIs you’re pulling from -* Monitoring services you use to monitor your site's uptime -* Security services -* IP addresses you frequently login from +- APIs you are pulling from +- Monitoring services you use to monitor your site's uptime +- Security services +- IP addresses you frequently login from Why do this? -If Cloudflare has an IP address with a high threat score going to your site, or if you have [Cloudflare's Web Application Firewall](https://cloudflare.com/waf) turned on, you may get challenged working in your back end and/or services you want to access your site may get challenged. Taking the steps to allow in the beginning will help prevent future surprises on your site. +If Cloudflare has an IP address with a high threat score going to your site, or if you have [Cloudflare's Web Application Firewall](https://cloudflare.com/waf) turned on, you may get challenged working in your back end and/or services you want to access your site may get challenged. Taking the steps to allow in the beginning will help prevent future surprises on your site. :::note -We allow all known search engine and social media crawlers in our macro -list. If you decide to block countries in Threat Control, please use -care because you may end up inadvertently blocking their crawlers -(blocking the USA, for example, could mean that their crawler gets -challenged). +We allow all known search engine and social media crawlers in our macro list. If you decide to block specific countries, you must use care because you may end up inadvertently blocking their crawlers (blocking the USA, for example, could mean that their crawler gets challenged). ::: -*** - -## Review your basic security settings - -If your site is  frequently the target of spam attacks or botnet attacks, changing your security level to a higher setting will help further reduce the amount of spam you get on your site. We default all users to a medium setting when they first add the domain to Cloudflare. - -Why do this? - -If you want your site to have less security and protection from various attacks, then you would want to change your settings to a lower level (please keep in mind this makes your site more vulnerable). If you want your site to have higher security, please keep in mind that you may get more false positives from visitors complaining about a challenge page that they have to pass to enter your site. - -*** +--- ## Ensure requests from Cloudflare's IP ranges aren't blocked or limited diff --git a/src/content/docs/support/third-party-software/content-management-system-cms/using-cloudflare-and-drupal-five-easy-recommended-steps.mdx b/src/content/docs/support/third-party-software/content-management-system-cms/using-cloudflare-and-drupal-five-easy-recommended-steps.mdx index c289cb3616c76d..9ed0256109d3f7 100644 --- a/src/content/docs/support/third-party-software/content-management-system-cms/using-cloudflare-and-drupal-five-easy-recommended-steps.mdx +++ b/src/content/docs/support/third-party-software/content-management-system-cms/using-cloudflare-and-drupal-five-easy-recommended-steps.mdx @@ -2,59 +2,48 @@ pcx_content_type: troubleshooting source: https://support.cloudflare.com/hc/en-us/articles/201883834-Using-Cloudflare-and-Drupal-Five-Easy-Recommended-Steps title: Using Cloudflare and Drupal Five Easy Recommended Steps - --- ## Overview -These basic steps will help reduce common areas of confusion for Drupal users that are new to using Cloudflare to speed up and protect their sites. In addition, these steps are very quick and will generally take only a few minutes of your time to go through. +These basic steps will help reduce common areas of confusion for Drupal users that are new to using Cloudflare to speed up and protect their sites. In addition, these steps are very quick and will generally take only a few minutes of your time to go through. **Step #1** -Install the [Cloudflare Drupal plugin](https://drupal.org/project/cloudflare) to restore visitor IP information. Since Cloudflare acts as a proxy for sites using our network, Cloudflare’s IPs are going to show in your logs, including comments, unless you install something to restore the original visitor IP. +Install the [Cloudflare Drupal plugin](https://drupal.org/project/cloudflare) to restore visitor IP information. Since Cloudflare acts as a proxy for sites using our network, Cloudflare’s IPs are going to show in your logs, including comments, unless you install something to restore the original visitor IP. Why should you install the plugin? -If you receive a lot of comments or spam on your blog, you may mistakenly believe that Cloudflare is spamming you. Some other Drupal plugins or extensions may also rely on the original visitor IP for the  services to work properly and reduce false alerts. +If you receive a lot of comments or spam on your blog, you may mistakenly believe that Cloudflare is spamming you. Some other Drupal plugins or extensions may also rely on the original visitor IP for the services to work properly and reduce false alerts. -Note: You don’t need to worry about this if you activated through a certified Cloudflare [certified Cloudflare Hosting partner](https://www.cloudflare.com/partners/technology-partners/), since they already [restore visitor IPs](https://support.cloudflare.com/hc/articles/200170786) by default. +Note: You don’t need to worry about this if you activated through a certified Cloudflare [certified Cloudflare Hosting partner](https://www.cloudflare.com/partners/technology-partners/), since they already [restore visitor IPs](/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/) by default. **Step #2** -Create a [Page Rule](/rules/page-rules/) to exclude the Drupal admin or Drupal login sections from Cloudflare’s caching and performance features. You can access Page Rules in the [Rules app](/rules/page-rules/). +Create a [Page Rule](/rules/page-rules/) to exclude the Drupal admin or Drupal login sections from Cloudflare’s caching and performance features. You can access Page Rules in the [Rules app](/rules/page-rules/). Why do this? -While there is not always an issue, we have seen some optional performance features like Rocket Loader inadvertently breaking certain functions (editors, etc.) in your site's admin area.. +While there is not always an issue, we have seen some optional performance features like Rocket Loader inadvertently breaking certain functions (editors, etc.) in your site's admin area.. **Step #3** -Allow IP addresses you expect traffic from in the Cloudflare **Firewall** App. Some common services you probably want to allow include: +Allow IP addresses you expect traffic from in the Cloudflare **Firewall** App. Some common services you probably want to allow include: -* APIs you’re pulling from -* Monitoring services you use to monitor your site's uptime -* Security services -* IP addresses you frequently login from +- APIs you’re pulling from +- Monitoring services you use to monitor your site's uptime +- Security services +- IP addresses you frequently login from Why do this? -If Cloudflare has an IP address with a high threat score going to your site, or if you have [Cloudflare's Web Application Firewall](https://www.cloudflare.com/waf) turned on, you may get challenged working in your back end and/or services you want to access your site may get challenged. Taking the steps to allow in the beginning will help prevent future surprises on your site. +If Cloudflare has an IP address with a high threat score going to your site, or if you have [Cloudflare's Web Application Firewall](https://www.cloudflare.com/waf) turned on, you may get challenged working in your back end and/or services you want to access your site may get challenged. Taking the steps to allow in the beginning will help prevent future surprises on your site. -**Note:** We allow all known search engine and social media crawlers in our macro list. If you decide to block countries in Threat Control, please use care because you may end up inadvertently blocking their crawlers (blocking the USA, for example, could mean that a good crawler gets challenged). +**Note:** We allow all known search engine and social media crawlers in our macro list. If you decide to block specific countries, please use care because you may end up inadvertently blocking their crawlers (blocking the USA, for example, could mean that a good crawler gets challenged). **Step #4** -Review your basic security settings - -If your site is frequently the target of spam attacks or botnet attacks, changing your security level to a higher level will reduce the amount of spam you get on your site. We default all users to a medium setting when they first add the domain to Cloudflare. - -Why do this? - -If you want your site to have less security and protection from various attacks, then you would want to [change your settings](https://support.cloudflare.com/hc/articles/200170056) to a lower level (please keep in mind this makes your site more vulnerable). If you want your site to have higher security, please keep in mind that you may get more false positives from visitors complaining about a challenge page that they have to pass to enter your site. - -**Step #5** - -If you are using services like .htaccess, firewalls or server mods to manage access to your site from visitors, it is vitally important to make sure requests from [Cloudflare’s IP ranges](https://www.cloudflare.com/ips) are not being blocked or limited in any way. The number one cause of site offline issues in our support channel is something blocking or restricting requests from our IPs, so please take the time to make sure that all of Cloudflare’s IPs are allowed on your server and with your hosting provider. +If you are using services like `.htaccess`, firewalls, or server mods to manage access to your site from visitors, it is vitally important to make sure requests from [Cloudflare's IP ranges](https://www.cloudflare.com/ips) are not being blocked or limited in any way. The number one cause of site offline issues in our support channel is something blocking or restricting requests from our IPs, so please take the time to make sure that all of Cloudflare's IPs are allowed on your server and with your hosting provider. Why do this? diff --git a/src/content/docs/support/third-party-software/content-management-system-cms/what-settings-are-applied-when-i-click-optimize-cloudflare-for-wordpress-in-cloudflares-wordpress-plugin.mdx b/src/content/docs/support/third-party-software/content-management-system-cms/what-settings-are-applied-when-i-click-optimize-cloudflare-for-wordpress-in-cloudflares-wordpress-plugin.mdx index ca47dcee122db3..b0d9da2e1a3d20 100644 --- a/src/content/docs/support/third-party-software/content-management-system-cms/what-settings-are-applied-when-i-click-optimize-cloudflare-for-wordpress-in-cloudflares-wordpress-plugin.mdx +++ b/src/content/docs/support/third-party-software/content-management-system-cms/what-settings-are-applied-when-i-click-optimize-cloudflare-for-wordpress-in-cloudflares-wordpress-plugin.mdx @@ -3,18 +3,16 @@ pcx_content_type: troubleshooting source: https://support.cloudflare.com/hc/en-us/articles/227342487-What-settings-are-applied-when-I-click-Optimize-Cloudflare-for-WordPress-in-Cloudflare-s-WordPress-plugin- title: What settings are applied when I click Optimize Cloudflare for WordPress in Cloudflare's WordPress plugin - --- ## Overview -If you're using Cloudflare's Wordpress plugin, our "Optimize Cloudflare for WordPress" one-click configuration applies the following settings to your Cloudflare account: +If you're using Cloudflare's WordPress plugin, our "Optimize Cloudflare for WordPress" one-click configuration applies the following settings to your Cloudflare account: -![Cloudflare's one-click configuration Wordpress plugin.](~/assets/images/support/dash-optimize_wordpress.png) +![Cloudflare's one-click configuration WordPress plugin.](~/assets/images/support/dash-optimize_wordpress.png) | **Setting** | **Value** | | -------------------------------------- | ---------------------------------- | -| Security level | Medium | | Caching level | Standard | | Browser Cache TTL | 4 hours | | Always Online | On | diff --git a/src/content/docs/support/third-party-software/forum-software/using-cloudflare-with-various-forums-vbulletin-xenforo-mybb.mdx b/src/content/docs/support/third-party-software/forum-software/using-cloudflare-with-various-forums-vbulletin-xenforo-mybb.mdx index a3b4bbb0028a2e..cd59eef5947f92 100644 --- a/src/content/docs/support/third-party-software/forum-software/using-cloudflare-with-various-forums-vbulletin-xenforo-mybb.mdx +++ b/src/content/docs/support/third-party-software/forum-software/using-cloudflare-with-various-forums-vbulletin-xenforo-mybb.mdx @@ -22,7 +22,7 @@ If you have a forum using these platforms, you can increase its speed and safety ## Steps -**1**. Cloudflare acts as a reverse proxy, meaning that all visitor IP addresses will become Cloudflare-affiliated IP addresses. If you are using services like **Stopforumspan** or blocking registration by IP address, you need to [restore original visitor IPs](https://support.cloudflare.com/hc/articles/200170786). +**1**. Cloudflare acts as a reverse proxy, meaning that all visitor IP addresses will become Cloudflare-affiliated IP addresses. If you are using services like **Stopforumspan** or blocking registration by IP address, you need to [restore original visitor IPs](/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/). **2**. To prevent admin functions from being affected by caching or performance features, create a [Page Rule](https://support.cloudflare.com/hc/articles/218411427) to exclude the admin section of your site. diff --git a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-10xxx-errors.mdx b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-10xxx-errors.mdx index 8c4f169a103823..8409b49dff2c58 100644 --- a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-10xxx-errors.mdx +++ b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-10xxx-errors.mdx @@ -2,9 +2,9 @@ pcx_content_type: troubleshooting source: https://support.cloudflare.com/hc/en-us/articles/4425107232525-Troubleshooting-Cloudflare-10XXX-errors title: Troubleshooting Cloudflare 10XXX errors +description: Troubleshoot Cloudflare 10XXX errors with detailed solutions for common issues like duplicate list items, invalid URLs, and redirect conflicts. --- - ## Error 10028: The add list items operation contains duplicate items This error indicates that the operation to add items to a list contains duplicate entries within the same request. diff --git a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors.mdx b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors.mdx index 510be074971bff..d6adbcf604f21f 100644 --- a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors.mdx +++ b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors.mdx @@ -7,50 +7,36 @@ title: Troubleshooting Cloudflare 1XXX errors import { GlossaryTooltip } from "~/components"; ---- - -## Overview - -The errors described in this document might occur when visiting a website proxied by Cloudflare. For Cloudflare API or dashboard errors, review our [Cloudflare API documentation](/api/). HTTP 409, 530, 403, and 429 errors are the HTTP error codes returned in the HTTP status header for a response. 1XXX errors appear in the HTML body of the response. - -:::note - -Cloudflare **[Custom Error -Pages](https://support.cloudflare.com/hc/articles/200172706)** allows -customers to change the appearance of the default error pages discussed -in this article. -::: - -If the resolutions within each error description below do not resolve the error, [contact Cloudflare Support](/support/contacting-cloudflare-support/). +The errors covered in this document may occur when accessing a website proxied by Cloudflare. For issues related to the Cloudflare API or dashboard, refer to our [Cloudflare API documentation](/api/). -:::note +HTTP errors such as `409`, `530`, `403`, and `429` are returned in the HTTP status header of a response, while 1XXX errors appear in the HTML body of the response. -Only the site owner may contact Cloudflare for technical support. Lookup -contact information for a domain via the [Whois -database](https://lookup.icann.org/). +:::note[Custom Error Pages] +Cloudflare **[Custom Error Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/)** allows customers to customize the default error pages discussed in this article. ::: -:::note +### Support and assistance -Dedicated email support is available for all Pro, Business, and -Enterprise Plan users. Business and Enterprise plan users also have -access to chat support. If you require additional support, explore [our -plans](https://www.cloudflare.com/plans/). -::: +If the suggested resolutions for each error do not resolve the issue, contact [Cloudflare Support](/support/contacting-cloudflare-support/). ---- +- Only the website owner can contact Cloudflare for technical support. You can find a domain's contact details via the [Whoisdatabase](https://lookup.icann.org/). +- Pro, Business and Enterprise plan users have access to email support. +- Business and Enterprise users can also access chat support. +- For additional support options, refer to the [Cloudflare plans](https://www.cloudflare.com/plans/). ## Error 1000: DNS points to prohibited IP +This error indicates that a Cloudflare DNS record points to a prohibited IP, blocking access to the requested domain. + ### Common causes Cloudflare halted the request for one of the following reasons: - An A record within your Cloudflare DNS app points to a [Cloudflare IP address](https://www.cloudflare.com/ips/), or a Load Balancer Origin points to a proxied record. - Your Cloudflare DNS A or CNAME record references another reverse proxy (such as an nginx web server that uses the proxy_pass function) that then proxies the request to Cloudflare a second time. -- The request X-Forwarded-For header is longer than 100 characters. -- The request includes two X-Forwarded-For headers. -- The request includes a CF-Connecting-IP header. +- The request `X-Forwarded-For` header is longer than 100 characters. +- The request includes two `X-Forwarded-For` headers. +- The request includes a `CF-Connecting-IP` header. - A Server Name Indication (SNI) issue or mismatch at the origin. ### Resolution @@ -58,30 +44,30 @@ Cloudflare halted the request for one of the following reasons: - If an A record within your Cloudflare DNS app points to a [Cloudflare IP address](https://www.cloudflare.com/ips/), update the IP address to your origin web server IP address. Reach out to your hosting provider if you need help obtaining the origin IP address. - There is a reverse-proxy at your origin that sends the request back through the Cloudflare proxy. Instead of using a reverse-proxy, contact your hosting provider or site administrator to configure an HTTP redirect at your origin. ---- - ## Error 1001: DNS resolution error +This error indicates a DNS resolution failure preventing access to the requested domain. + ### Common causes - A web request was sent to a Cloudflare IP address for a non-existent Cloudflare domain. - An external domain that is not on using Cloudflare has a CNAME record to a domain active on Cloudflare - The target of the DNS CNAME record does not resolve. - A CNAME record in your Cloudflare DNS app requires resolution via a DNS provider that is currently offline. -- [Always Online](/cache/how-to/always-online/) is enabled for a [Custom Hostname (Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/)) domain. +- [Always Online](/cache/how-to/always-online/) is enabled for a [Custom Hostname (Cloudflare for SaaS)](/cloudflare-for-platforms/cloudflare-for-saas/) domain. ### Resolution -A non-Cloudflare domain cannot CNAME to a Cloudflare domain unless the non-Cloudflare domain is added to a Cloudflare account. +A non-Cloudflare domain cannot CNAME to a Cloudflare domain, unless the non-Cloudflare domain is added to a Cloudflare account. -Attempting to directly access DNS records used for [Cloudflare CNAME setups](/dns/zone-setups/partial-setup) also causes error 1001 (For example: *[www.example.com.cdn.cloudflare.net](http://www.example.com.cdn.cloudflare.net)*). +Attempting to directly access DNS records used for [Cloudflare CNAME setups](/dns/zone-setups/partial-setup) also causes error 1001. For example, `www.example.com.cdn.cloudflare.net`. -Disable [Always Online](/cache/how-to/always-online/#enable-always-online) if using [Custom Hostname (Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/)) domain. - ---- +Disable [Always Online](/cache/how-to/always-online/#enable-always-online), if using [Custom Hostname (Cloudflare for SaaS)](/cloudflare-for-platforms/cloudflare-for-saas/) domain. ## Error 1002: DNS points to Prohibited IP +This error indicates that a Cloudflare DNS record points to a prohibited IP, preventing proper domain resolution. + ### Common causes - A DNS record in your Cloudflare DNS app points to one of [Cloudflare's IP addresses](https://www.cloudflare.com/ips/). @@ -90,27 +76,27 @@ Disable [Always Online](/cache/how-to/always-online/#enable-always-online) if ### Resolution -Update your Cloudflare *A* or *CNAME record* to point to your origin IP address instead of a Cloudflare IP address: +Update your Cloudflare A or CNAME record to point to your origin IP address instead of a Cloudflare IP address: -1. Contact your hosting provider to confirm your origin IP address or CNAME record target. +1. Contact your hosting provider to confirm your origin IP address or CNAME record target. 2. Log in to your Cloudflare account. 3. Select the domain that generates error 1002. 4. Select the **DNS** app. -5. Click **Value** for the _A_ record to update. -6. Update the _A_ record. +5. Click **Value** for the A record to update. +6. Update the A record. -To ensure your origin web server doesn’t proxy its own requests through Cloudflare, configure your origin webserver to resolve your Cloudflare domain to: +To ensure your origin web server does not proxy its own requests through Cloudflare, configure your origin webserver to resolve your Cloudflare domain to: -- The internal NAT’d IP address, or +- The internal NAT'd IP address, or - The public IP address of the origin web server. ---- - ## Error 1002: Restricted +This error indicates that the domain resolves to a restricted or disallowed IP address. + ### Common cause -The Cloudflare domain resolves to a local or disallowed IP address or an IP address not associated with the domain. +The Cloudflare domain resolves to a local or disallowed IP address or an IP address not associated with the domain. ### Resolution @@ -118,40 +104,40 @@ If you own the website: 1. Confirm your origin web server IP addresses with your hosting provider, 2. Log in to your Cloudflare account, and -3. Update the A records in the Cloudflare DNS app to the IP address confirmed by your hosting provider. - ---- +3. Update the A records in the Cloudflare DNS app to the IP address confirmed by your hosting provider. ## Error 1003 Access Denied: Direct IP Access Not Allowed +This error indicates that direct access to a Cloudflare IP address is not allowed. + ### Common cause -A client or browser directly accesses a [Cloudflare IP address](https://www.cloudflare.com/ips). +A client or browser directly accesses a [Cloudflare IP address](https://www.cloudflare.com/ips). ### Resolution -Browse to the website domain name in your URL instead of the Cloudflare IP address. - ---- +Browse to the website domain name in your URL instead of the Cloudflare IP address. ## Error 1004: Host Not Configured to Serve Web Traffic +This error indicates that the host is not configured to serve web traffic. + ### Common causes - Cloudflare staff disabled proxying for the domain due to abuse or terms of service violations. -- DNS changes have not yet propagated or the site owner’s DNS _A records_ point to [Cloudflare IP addresses](https://www.cloudflare.com/ips). +- DNS changes have not yet propagated or the site owner's DNS A records point to [Cloudflare IP addresses](https://www.cloudflare.com/ips). ### Resolution -If the issue persists beyond 5 minutes, [contact Cloudflare Support](/support/contacting-cloudflare-support/). - ---- +If the issue persists beyond five minutes, [contact Cloudflare Support](/support/contacting-cloudflare-support/). ## Errors 1005 Access Denied: Autonomous System Number (ASN) banned +This error indicates that access to the website is denied due to the banning of the Autonomous System Number (ASN). + ### Common causes -The owner of the website (e.g. example.com) has banned the autonomous system number (ASN) from accessing the website. +The owner of the website (for example, `example.com`) has banned the autonomous system number (ASN) from accessing the website. ### Resolution @@ -159,24 +145,22 @@ If you are not the website owner, provide the website owner with a screenshot of If you are the website owner: -1. Retrieve a screenshot of the 1005 error from your customer -2. Search the [**Security Events log**](/waf/analytics/security-events/) (available at **Security** > **Events**) for the **RayID**, or client IP Address from the visitor’s 1005 error message. +1. Retrieve a screenshot of the `1005` error from your customer +2. Search the [**Security Events log**](/waf/analytics/security-events/) (available at **Security** > **Events**) for the **RayID**, or client IP Address from the visitor's 1005 error message. :::note - -Convert the UTC timestamp of the 1005 error to your local timezone when -searching in the **Security Events log**. +Convert the UTC timestamp of the `1005` error to your local timezone when searching in the **Security Events log**. ::: -3\. Assess the cause of the block and ensure the ASN is allowed under the [IP Access Rules](/waf/tools/ip-access-rules/) security feature. - ---- +3. Assess the cause of the block and ensure the ASN is allowed under the [IP Access Rules](/waf/tools/ip-access-rules/) security feature. ## Errors 1006, 1007, 1008 or 1106 Access Denied: Your IP address has been banned +This error indicates that access is denied because your IP address has been banned. + ### Common causes -A Cloudflare customer blocked traffic from your client or browser. +A Cloudflare customer blocked traffic from your client or browser. :::note @@ -185,112 +169,101 @@ Error 1006 also occurs in the Cloudflare **Workers** app under the **Preview** t ### Resolution -Request the website owner to investigate their Cloudflare security settings or allow your client IP address. Since the website owner blocked your request, Cloudflare support cannot override a customer’s security settings. - ---- +Request the website owner to investigate their Cloudflare security settings or allow your client IP address. Since the website owner blocked your request, Cloudflare support cannot override a customer's security settings. ## Errors 1009 Access Denied: Country or region banned +This error indicates that access to the website is denied from your country or region. + ### Common causes -The owner of the website (e.g. example.com) has banned the country or region your IP address from accessing the website. +The owner of the website (for example, `example.com`) has banned the country or region your IP address from accessing the website. ### Resolution Ensure your IP address is allowed under the [IP Access Rules](/waf/tools/ip-access-rules/) security feature. ---- - ## Error 1010: The owner of this website has banned your access based on your browser's signature +This error indicates that access to the website is denied based on your browser's signature. + ### Common cause -A website owner blocked your request based on your client's web browser. +A website owner blocked your request based on your client's web browser. ### Resolution -Notify the website owner of the blocking. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/). Site owners disable **Browser** **Integrity Check** via the **Settings** tab of the **Security** app. +Notify the website owner of the blocking. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/). Site owners disable **Browser** **Integrity Check** via the **Settings** tab of the **Security** app. :::note - -Since the website owner performed the blocking, Cloudflare support -cannot override a customer's security settings. +Since the website owner performed the blocking, Cloudflare support cannot override a customer's security settings. ::: ---- - ## Error 1011: Access Denied (Hotlinking Denied) +This error indicates that access to the resource is denied due to hotlinking protection. + ### Common cause -A request is made for a resource that uses [Cloudflare hotlink protection](/waf/tools/scrape-shield/hotlink-protection/). +A request is made for a resource that uses [Cloudflare hotlink protection](/waf/tools/scrape-shield/hotlink-protection/). ### Resolution -Notify the website owner of the blocking. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/).  **Hotlink Protection** is managed via the Cloudflare **Scrape Shield** app. +Notify the website owner of the blocking. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/). **Hotlink Protection** is managed via the Cloudflare **Scrape Shield** app. :::note - -Since the website owner performed the blocking, Cloudflare support -cannot override a customer's security settings. +Since the website owner performed the blocking, Cloudflare support cannot override a customer's security settings. ::: ---- - ## Error 1012: Access Denied +This error indicates that access to the website is denied. + ### Common cause -A website owner forbids access based on malicious activity detected from the visitor’s computer or network (ip_address). The most likely cause is a virus or malware infection on the visitor’s computer. +A website owner forbids access based on malicious activity detected from the visitor's computer or network (ip_address). The most likely cause is a virus or malware infection on the visitor's computer. ### Resolution -Update your antivirus software and run a full system scan. Cloudflare can not override the security settings the site owner has set for the domain. To request website access, contact the site owner to allow your IP address. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/). +Update your antivirus software and run a full system scan. Cloudflare can not override the security settings the site owner has set for the domain. To request website access, contact the site owner to allow your IP address. If you cannot determine how to contact the website owner, lookup contact information for the domain via the [Whois database](https://lookup.icann.org/). :::note - -Since the website owner performed the blocking, Cloudflare support -cannot override a customer's security settings. +Since the website owner performed the blocking, Cloudflare support cannot override a customer's security settings. ::: ---- - ## Error 1013: HTTP hostname and TLS SNI hostname mismatch +This error indicates a mismatch between the HTTP hostname and the TLS SNI hostname. + ### Common cause -The hostname sent by the client or browser via Server Name Indication (SNI) does not match the request host header. +The hostname sent by the client or browser via Server Name Indication (SNI) does not match the request host header. ### Resolution -Error 1013 is commonly caused by the following: +Error `1013` is commonly caused by the following: -- your local browser setting the incorrect SNI host header, or -- a network proxying SSL traffic caused a mismatch between SNI and the Host header of the request. +- Your local browser setting the incorrect SNI host header, or +- A network proxying SSL traffic caused a mismatch between SNI and the Host header of the request. -Test for an SNI mismatch via an online tool such as: [SSL Shopper](https://www.sslshopper.com/ssl-checker.html). +Test for an SNI mismatch via an online tool, such as [SSL Shopper](https://www.sslshopper.com/ssl-checker.html). Provide Cloudflare Support the following information: -1. A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error. - ---- +- A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error. ## Error 1014: CNAME Cross-User Banned +This error indicates that a CNAME record between domains in different Cloudflare accounts is prohibited. + ### Common cause -By default, Cloudflare prohibits a DNS *CNAME record* between domains in different Cloudflare accounts. *CNAME records* are permitted within a domain (*[www.example.com](http://www.example.com)* CNAME to *api.example.com*) and across zones within the same user account (*[www.example.com](http://www.example.com)* CNAME to *[www.example.net](http://www.example.net)*) or using our [Cloudflare for SaaS](https://www.cloudflare.com/saas/) solution. +By default, Cloudflare prohibits a DNS CNAME record between domains in different Cloudflare accounts. CNAME records are permitted within a domain ([`www.example.com`](http://www.example.com) CNAME to `api.example.com`) and across zones within the same user account ([`www.example.com`](http://www.example.com) CNAME to [`www.example.net`](http://www.example.net)) or using our [Cloudflare for SaaS](https://www.cloudflare.com/saas/) solution. Another common cause is connecting a custom domain to an R2 bucket, where the domain is an active zone with the [zone hold](/fundamentals/setup/account/account-security/zone-holds/) feature enabled. :::caution - -[Cloudflare Apps](https://www.cloudflare.com/apps/) are not currently -supported by [Cloudflare for -SaaS](/cloudflare-for-platforms/cloudflare-for-saas/), therefore -any app using a domain configured on our SaaS solution may produce 1014 -errors. +[Cloudflare Apps](https://www.cloudflare.com/apps/) are not currently supported by [Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/), therefore any app using a domain configured on our SaaS solution may produce 1014 errors. ::: ### Resolution @@ -298,89 +271,77 @@ errors. - To allow CNAME record resolution to a domain in a different Cloudflare account, the domain owner of the CNAME target must use [Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/). - To allow connecting to a R2 bucket with a custom domain, disable the [zone hold](/fundamentals/setup/account/account-security/zone-holds/) feature on the custom domain target zone to resolve the 1014 error. ---- - ## Error 1015: You are being rate limited +This error indicates that you are being rate limited by the website. + ### Common cause -The site owner implemented [Rate Limiting](/waf/reference/legacy/old-rate-limiting/) that affects your visitor traffic. +The site owner implemented [Rate Limiting](/waf/reference/legacy/old-rate-limiting/) that affects your visitor traffic. :::note - -_Unable to purge_ is another 1015 error code relating to [Cloudflare -cache -purge](/cache/how-to/purge-cache). -Retry the cache purge and contact [Cloudflare -support](/support/contacting-cloudflare-support/) if errors -persist. +_Unable to purge_ is another `1015` error code relating to [Cloudflare cache purge](/cache/how-to/purge-cache).Retry the cache purge and contact [Cloudflare support](/support/contacting-cloudflare-support/) if errors persist. ::: ### Resolution -- If you are a site visitor, contact the site owner to request exclusion of your IP from rate limiting. -- If you are the site owner, review [Cloudflare Rate Limiting thresholds](/waf/reference/legacy/old-rate-limiting/) and adjust your Rate Limiting configuration. +- If you are a site visitor, contact the site owner to request exclusion of your IP from rate limiting. +- If you are the site owner, review [Cloudflare Rate Limiting thresholds](/waf/reference/legacy/old-rate-limiting/) and adjust your Rate Limiting configuration. - If your Rate Limiting blocks requests in a short time period (i.e. 1 second) try increasing the time period to 10 seconds. :::note - -If you expect a new Cloudflare Worker to exceed rate limits, refer to -the [Workers -documentation](/workers/platform/limits) -for guidance. +If you expect a new Cloudflare Worker to exceed rate limits, refer to the [Workers documentation](/workers platform/limits) for guidance. ::: ---- - ## Error 1016: Origin DNS error -### Common cause +This error indicates that Cloudflare cannot resolve the origin web server's IP address. -Cloudflare cannot resolve the origin web server’s IP address. +### Common cause Common causes for Error 1016 are: -- A missing DNS _A record_ that mentions origin IP address. -- A _CNAME record_ in the Cloudflare DNS points to an unresolvable external domain. +- A missing DNS A record that mentions origin IP address. +- A CNAME record in the Cloudflare DNS points to an unresolvable external domain. - The origin hostnames (CNAMEs) in your Cloudflare [Load Balancer](/load-balancing/) default, region, and fallback pools are unresolvable. Use a fallback pool configured with an origin IP as a backup in case all other pools are unavailable. -- When creating a Spectrum app with a CNAME origin, you need first to create a CNAME on the Cloudflare DNS side that points to the origin. Please see [Spectrum CNAME origins](/spectrum/get-started/#create-a-spectrum-application-using-a-cname-record) for more details -- There is no DNS record for the hostname in the Cloudflare for SaaS target zone -- There is no DNS record for the hostname in the target [Partial (CNAME) setup zone](/dns/zone-setups/partial-setup/) of a Workers subrequest ([Fetch API](/workers/runtime-apis/fetch/)) +- When creating a Spectrum app with a CNAME origin, you need first to create a CNAME on the Cloudflare DNS side that points to the origin. Please see [Spectrum CNAME origins](/spectrum/get-started/#create-a-spectrum-application-using-a-cname-record) for more details. +- There is no DNS record for the hostname in the Cloudflare for SaaS target zone. +- There is no DNS record for the hostname in the target [Partial (CNAME) setup zone](/dns/zone-setups/partial-setup/) of a Workers subrequest ([Fetch API](/workers/runtime-apis/fetch/)). ### Resolution To resolve error 1016: -1. Verify your Cloudflare DNS settings include an *A record* that points to a valid IP address that resolves via a [DNS lookup tool](https://dnschecker.org/). -2. For a CNAME record pointing to a different domain, ensure that the target domain resolves via a [DNS lookup tool](https://dnschecker.org/). +1. Verify your Cloudflare DNS settings include an A record that points to a valid IP address that resolves via a [DNS lookup tool](https://dnschecker.org/). +2. For a CNAME record pointing to a different domain, ensure that the target domain resolves via a [DNS lookup tool](https://dnschecker.org/). 3. For a Workers subrequest to a Partial (CNAME) setup zone, ensure that the hostname exists on the Cloudflare zone (and not only at the authoritative DNS) ---- - ## Error 1018: Could not find host +This error indicates that the host could not be found. + ### Common causes -- The Cloudflare domain was recently activated and there is a delay propagating the domain’s settings to the Cloudflare edge network. -- The Cloudflare domain was created via a Cloudflare partner (e.g., a hosting provider) and the provider's DNS failed. +- The Cloudflare domain was recently activated and there is a delay propagating the domain's settings to the Cloudflare edge network. +- The Cloudflare domain was created via a Cloudflare partner (for example, a hosting provider) and the provider's DNS failed. :::note - Error 1018 is returned via a HTTP 409 response code. ::: ### Resolution -Contact [Cloudflare Support](/support/contacting-cloudflare-support/) with the following details: +Contact [Cloudflare Support](/support/contacting-cloudflare-support/) with the following details: -1. Your domain name -2. A screenshot of the 1018 error including the **RayID** mentioned in the error message -3. A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error +- Your domain name. +- A screenshot of the 1018 error including the **RayID** mentioned in the error message. +- A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error. ---- ## Error 1019: Compute server error +This error indicates a compute server error related to a Cloudflare Worker. + ### Common cause A Cloudflare Worker script recursively references itself. @@ -389,13 +350,13 @@ A Cloudflare Worker script recursively references itself. Ensure your Cloudflare Worker does not access a URL that calls the same Workers script. ---- - ## Error 1020: Access denied +This error indicates that access to the website is denied by a Cloudflare firewall rule. + ### Common cause -A client or browser is blocked by a Cloudflare customer’s Firewall Rules (deprecated). +A client or browser is blocked by a Cloudflare customer's Firewall Rules (deprecated). ### Resolution @@ -403,81 +364,78 @@ If you are not the website owner, provide the website owner with a screenshot of If you are the website owner: -1. Retrieve a screenshot of the 1020 error from your customer -2. Search the [**Security Events log**](/waf/analytics/security-events/) (available at **Security** > **Events**) for the **RayID** or client IP Address from the visitor’s 1020 error message. +1. Retrieve a screenshot of the 1020 error from your customer. +2. Search the [**Security Events log**](/waf/analytics/security-events/) (available at **Security** > **Events**) for the **RayID** or client IP Address from the visitor's 1020 error message. :::note - -Convert the UTC timestamp of the 1020 error to your local timezone when +Convert the UTC timestamp of the `1020` error to your local timezone when searching in the **Security Events log**. ::: -3\. Assess the cause of the block and either update the **Firewall Rule** or allow the visitor’s IP address in [**IP Access Rules**](/waf/tools/ip-access-rules/). - ---- +3. Assess the cause of the block and either update the **Firewall Rule** or allow the visitor's IP address in [**IP Access Rules**](/waf/tools/ip-access-rules/). ## Error 1023: Could not find host +This error indicates that the host could not be found due to a configuration issue or propagation delay. + ### Common causes - If the owner just signed up for Cloudflare it can take a few minutes for the website's information to be distributed to our global network. Something is wrong with the site's configuration. -- Usually, this happens when accounts have been signed up with a partner organization (e.g., hosting provider) and the provider's DNS fails. +- Usually, this happens when accounts have been signed up with a partner organization (for example, hosting provider) and the provider's DNS fails. :::note - -Error 1023 is returned via a HTTP 409 response code. +Error `1023` is returned via a HTTP `409` response code. ::: ### Resolution -Contact [Cloudflare Support](/support/contacting-cloudflare-support/) with the following details: - -1. Your domain name -2. A screenshot of the 1023 error including the **RayID** mentioned in the error message -3. A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error -4. +Contact [Cloudflare Support](/support/contacting-cloudflare-support/) with the following details: ---- +- Your domain name. +- A screenshot of the 1023 error including the **RayID** mentioned in the error message. +- A [HAR file](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/) captured while duplicating the error. ## Error 1025: Please check back later +This error indicates that the domain has reached its plan limits for Cloudflare Workers. + ### Common cause -A request is not serviced because the domain has reached [plan limits for Cloudflare Workers](/workers/platform/limits). +A request is not serviced because the domain has reached [plan limits for Cloudflare Workers](/workers/platform/limits). ### Resolution: -Purchase the Unlimited Workers plan via the [Plans page](https://dash.cloudflare.com/redirect?account=workers/plans) on the Workers dashboard. - ---- +Purchase the Unlimited Workers plan via the [Plans page](https://dash.cloudflare.com/redirect?account=workers/plans) on the Workers dashboard. ## Error 1033: Argo Tunnel error +This error indicates an issue with resolving an Argo Tunnel. + ### Common cause -You've requested a page on a website (`tunnel.example.com`) that is on the Cloudflare network. The host (`tunnel.example.com`) is configured as an Argo Tunnel, and Cloudflare is currently unable to resolve it. +You have requested a page on a website (`tunnel.example.com`) that is on the Cloudflare network. The host (`tunnel.example.com`) is configured as an Argo Tunnel, and Cloudflare is currently unable to resolve it. ### Resolution - **If you are a visitor of this website**: Please try again in a few minutes. - **If you are the owner of this website**: Ensure that _cloudflared_ is running and can reach the network. You may wish to enable [load balancing](/cloudflare-one/connections/connect-networks/routing-to-tunnel/lb) for your tunnel. ---- - ## Error 1034: Edge IP Restricted +This error indicates that the IP address used for the domain is restricted by Cloudflare's edge validation. + ### Common cause -Customers who previously pointed their domains to `1.1.1.1` will now encounter **1034 error**. This is due to a new edge validation check in Cloudflare's systems to prevent misconfiguration and/or potential abuse. +Customers who previously pointed their domains to `1.1.1.1` will now encounter **1034 error**. This is due to a new edge validation check in Cloudflare's systems to prevent misconfiguration and/or potential abuse. ### Resolution -Ensure DNS records are pointed to IP addresses you control, and in the case a placeholder IP address is needed for “originless” setups, use the IPv6 reserved address `100::` or the IPv4 reserved address `192.0.2.0`. - ---- +Ensure DNS records are pointed to IP addresses you control, and in the case a placeholder IP address is needed for “originless” setups, use the IPv6 reserved address `100::` or the IPv4 reserved address `192.0.2.0`. ## Error 1035: Invalid request rewrite (invalid URI path) +This error indicates an invalid URI path in a request rewrite. + ### Common cause The value or expression of your rewritten URI path is not valid. @@ -496,10 +454,10 @@ To fix the expression above, add a `/` prefix: `concat("/", lower(ip.src.country), http.request.uri.path)` ---- - ## Error 1036: Invalid request rewrite (maximum length exceeded) +This error indicates that the rewritten URI path or query string exceeds the maximum allowed length. + ### Common cause The value or expression of your rewritten URI path or query string is too long. @@ -508,13 +466,13 @@ The value or expression of your rewritten URI path or query string is too long. Use a shorter value or expression for the new URI path/query string value. ---- - ## Error 1037: Invalid rewrite rule (failed to evaluate expression) +This error indicates that the rewrite rule expression could not be evaluated. + ### Common cause -The expression of the rewrite rule could not be evaluated. There are several causes for this error, but it can mean that one expression element contained an undefined value when it was evaluated. +There are several causes for this error, but it can mean that one expression element contained an undefined value when it was evaluated. For example, you get a 1037 error when using the following URL rewrite dynamic expression and the `X-Source` header is not included in the request: @@ -524,10 +482,10 @@ For example, you get a 1037 error when using the following URL rewrite dynamic e Make sure that all the elements of your rewrite expression are defined. For example, if you are referring to a header value, ensure the header is set. ---- - ## Error 1040: Invalid request rewrite (header modification not allowed) +This error indicates that an attempt was made to modify a restricted HTTP header. + ### Common cause You are trying to modify an HTTP header that HTTP Request Header Modification Rules cannot change. @@ -536,10 +494,10 @@ You are trying to modify an HTTP header that HTTP Request Header Modification Ru Make sure you are not trying to modify one of the [reserved HTTP request headers](/rules/transform/request-header-modification/#important-remarks). ---- - ## Error 1041: Invalid request rewrite (invalid header value) +This error indicates that the header value is not valid. + ### Common causes The added/modified header value is too long or it contains characters that are not allowed. @@ -549,34 +507,34 @@ The added/modified header value is too long or it contains characters that are n - Use a shorter value or expression to define the header value. - Remove the characters that are not allowed. See [Format of HTTP request header names and values](/rules/transform/request-header-modification/reference/header-format/) in Developer Docs for more information on the allowed characters. ---- - ## Error 1101: Rendering error +This error indicates a rendering issue. + ### Common cause -A Cloudflare Worker throws a runtime JavaScript exception. +This error typically occurs when a Cloudflare Worker encounters a runtime JavaScript exception. ### Resolution: -[Provide appropriate issues details](/support/contacting-cloudflare-support/) to Cloudflare Support. - ---- +[Provide appropriate issues details](/support/contacting-cloudflare-support/) to Cloudflare Support. ## Error 1102: Rendering error +This error indicates that a Cloudflare Worker has exceeded the CPU time limit. + ### Common cause -A Cloudflare Worker exceeds a [CPU time limit](/workers/observability/errors/). CPU time is the time spent executing code (for example, loops, parsing JSON, etc). Time spent on network requests (fetching, responding) does not count towards CPU time. +A Cloudflare Worker exceeds a [CPU time limit](/workers/observability/errors/). CPU time is the time spent executing code (for example, loops, parsing JSON, etc). Time spent on network requests (fetching, responding) does not count towards CPU time. ### Resolution Contact the developer of your Workers code to optimize code for a reduction in CPU usage in the active Workers scripts. ---- - ## Error 1104: A variation of this email address is already taken in our system. Only one variation is allowed. +This error indicates that the email address you are trying to add is already taken in the system. + ### Common cause This error can occur if an email has been added with some variation of the email you're trying to add. For example, `my+user@example.com` and `my.user@example.com` will be treated the same in our system. @@ -585,21 +543,14 @@ This error can occur if an email has been added with some variation of the email Log in as the old user and change email to a "throwaway" address, which will free up the new email. ---- - ## Error 1200: Cache connection limit +This error indicates that the number of requests queued on Cloudflare's edge exceeds the limit. + ### Common cause -There are too many requests queued on Cloudflare's edge that are awaiting process by your origin web server.  This limit protects Cloudflare's systems. +There are too many requests queued on Cloudflare's edge that are awaiting process by your origin web server. This limit protects Cloudflare's systems. ### Resolution -Tune your origin webserver to accept incoming connections faster.  Adjust your caching settings to improve cache-hit rates so that fewer requests reach your origin web server.  Reach out to your hosting provider or web administrator for assistance. - ---- - -## Related resources - -- [Customizing Cloudflare error pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/) -- [Contacting Cloudflare Support](/support/contacting-cloudflare-support/) +Tune your origin webserver to accept incoming connections faster. Adjust your caching settings to improve cache-hit rates so that fewer requests reach your origin web server. Reach out to your hosting provider or web administrator for assistance. diff --git a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors.mdx b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors.mdx index 141c197704b2fc..17e14654c01edd 100644 --- a/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors.mdx +++ b/src/content/docs/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors.mdx @@ -6,7 +6,10 @@ source: null import { GlossaryTooltip } from "~/components"; -When troubleshooting most 5XX errors, the correct course of action is to first contact your hosting provider or site administrator to troubleshoot and gather data. +When troubleshooting most `5XX` errors, the correct course of action is to first contact your hosting provider or site administrator to troubleshoot and gather data. The following sections outline: + +- The [information](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#required-error-details-for-hosting-provider) to provide your hosting provider to help resolve the errors +- The steps to access [error analytics](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#error-analytics) in the Cloudflare dashboard. :::note @@ -14,224 +17,235 @@ Cloudflare Support only assists the domain owner to resolve issues. If you are a ::: -## Required error details for hosting provider +### Required error details for hosting provider -When contacting your hosting provider, give them the following information: +When contacting your hosting provider, share the following information: -1. Specific 5XX error code and message. -2. Time and timezone the 5XX error occurred. -3. URL that resulted in the HTTP 5XX error (for example: `https://www.example.com/images/icons/image1.png`). +- The specific `5XX` error code and message. +- The time and timezone when the `5XX` error occurred. +- The URL that resulted in the HTTP `5XX` error (for example, `https://www.example.com/images/icons/image1.png`). -The error cause is not always found in the origin server error logs. Check logs of all load balancers, caches, proxies, or firewalls between Cloudflare and the origin web server. +The cause of the error is not always found in the origin server's error logs. Be sure to check the logs of any load balancers, caches, proxies, or firewalls between Cloudflare and the origin web server. -Additional details to provide to your hosting provider or site administrator are listed within each error description below. Cloudflare [Custom Error Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/) change the appearance of default error pages discussed in this article. +Additional details to provide to your hosting provider or site administrator can be found in the error descriptions below. Note that Cloudflare [Custom Error Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/) can alter the appearance of default error pages discussed in this page. -## Error analytics +### Error analytics -Error Analytics per domain are available within [Zone Analytics](/analytics/account-and-zone-analytics/zone-analytics/). Error Analytics allows insight into overall errors by HTTP error code and provides the URLs, source IP addresses, and Cloudflare data centers needed to diagnose and resolve the issue. Error Analytics are based on a 1% traffic sample. +Error analytics per domain are available within [Zone Analytics](/analytics/account-and-zone-analytics/zone-analytics/). Error analytics provides insights into overall errors by HTTP error code and offers details such as the URLs, source IP addresses, and Cloudflare data centers needed to diagnose and resolve issues. Error Analytics are based on a 1% traffic sample. To view Error Analytics: -- Log in to the Cloudflare dashboard. -- Click the appropriate Cloudflare **account** for your site, then pick the **domain**. -- Next, click the **Analytics & Logs** app icon. -- Click **Add filter**, select **Edge status code** or **Origin status code** and choose any 5xx error code that you want to diagnose. +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com). +2. Select your account and domain. +3. Go to **Analytics & Logs**. +4. Select **Add filter**, select **Edge status code** or **Origin status code** and choose any `5xx` error code that you want to diagnose. --- ## Error 500: internal server error -Error 500 generally indicates an issue with your origin web server. _Error establishing database_ _connection_ is a common HTTP 500 error message generated by your origin web server. [Contact your hosting provider](#required-error-details-for-hosting-provider) to resolve. +This error indicates a problem with your origin web server, preventing it from fulfilling the request. + +### Common causes + +The `Error establishing database connection message` is a common HTTP `500` error, typically indicating an origin web server issue. If you encounter this error, contact your hosting provider for assistance. -**Resolution** +### Resolution -[Provide details to your hosting provider](#required-error-details-for-hosting-provider) to assist troubleshooting the issue. +When dealing with most `5XX` errors, the first step is to reach out to your hosting provider or site administrator to help troubleshoot the issue. Share the necessary [error details](#required-error-details-for-hosting-provider) to your hosting provider to assist troubleshooting the issue. -However, if the 500 error contains "cloudflare" or "cloudflare-nginx" in the HTML response body, provide [Cloudflare support](/support/contacting-cloudflare-support/) with the following information: +However, if the `500` error contains `cloudflare` or `cloudflare-nginx` in the HTML response body, contact [Cloudflare support](/support/contacting-cloudflare-support/) and provide the following details: -1. Your domain name -2. The time and timezone of the 500 error occurrence -3. The output of `www.example.com/cdn-cgi/trace` from the browser where the 500 error was observed (replace `www.example.com` with your actual domain and hostname) +- Your domain name +- The time and timezone of the `500` error occurrence +- The output of `www.example.com/cdn-cgi/trace` from the browser where the `500` error was observed (replace `www.example.com` with your actual domain and hostname) :::note -If you observe blank or white pages when visiting your website, confirm -whether the issue occurs when [temporarily pausing -Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/) -and contact your hosting provider for assistance. +If you observe blank or white pages when visiting your website, confirm whether the issue occurs when [temporarily pausing Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/) and contact your hosting provider for assistance. ::: ---- - ## Error 502 bad gateway or error 504 gateway timeout -An HTTP 502 or 504 error occurs when Cloudflare is unable to establish contact with your origin web server. +An HTTP `502` or `504` error indicates that Cloudflare is unable to establish contact with your origin web server. + +### Common causes There are two possible causes: -- (Most common cause) [502/504 from your origin web server](#502504-from-your-origin-web-server) -- [502/504 from Cloudflare](#502504-from-cloudflare) +- [`502/504` errors from your origin web server](#502504-from-your-origin-web-server) (most common). +- [`502/504` errors from Cloudflare](#502504-from-cloudflare). -You may also see 504 status codes in logs or analytics caused by [cache MISS responses from Early Hints](/cache/advanced-configuration/early-hints/#emit-early-hints). +You may also see `504` status codes in logs or analytics caused by [cache MISS responses from Early Hints](/cache/advanced-configuration/early-hints/#emit-early-hints). -### 502/504 from your origin web server +### Resolution -Cloudflare returns a Cloudflare-branded HTTP 502 or 504 error when your origin web server responds with a standard HTTP 502 bad gateway or 504 gateway timeout error: +To resolve `502/504` errors, it is essential to identify whether the issue originates from your origin web server or Cloudflare. In the following sections, you can find more details for troubleshooting and resolving errors from both sources. -![Example of a Cloudflare-branded error 502.](~/assets/images/support/image1.png) +#### 502/504 from your origin web server -**Resolution** +Cloudflare returns a Cloudflare-branded HTTP `502` or `504` error when your origin web server responds with a standard HTTP `502 bad gateway` or `504 gateway timeout` error: + +![Example of a Cloudflare-branded error 502.](~/assets/images/support/image1.png) Contact your hosting provider to troubleshoot these common causes at your origin web server: -- Ensure the origin server responds to requests for the hostname and domain within the visitor's URL that generated the 502 or 504 error. +- Ensure the origin server responds to requests for the hostname and domain within the visitor's URL that generated the `502` or `504` error. - Investigate excessive server loads, crashes, or network failures. - Identify applications or services that timed out or were blocked. -### 502/504 from Cloudflare +#### 502/504 from Cloudflare -A 502 or 504 error originating from Cloudflare appears as follows: +A `502` or a `504` error originating from Cloudflare appears as follows: ![Example of an unbranded error 502.](~/assets/images/support/image5.png) -If the error does not mention `cloudflare`, contact your hosting provider for assistance on [502/504 errors from your origin](#502504-from-your-origin-web-server). +If the error does not mention `cloudflare`, contact your hosting provider for assistance. Refer to [502/504 errors from your origin](#502504-from-your-origin-web-server) for more information. -This error can be returned in case of a compression issue at the origin, for example the origin server is serving gzip encoded compressed content but is not updating the `content-length` header, or the origin is serving broken gzip compressed content. -You can try to disable compression at your origin to confirm if this is the root cause of the errors. +This error can occur due to a compression issue at the origin, such as when the origin server serves gzip-encoded compressed content but fails to update the `content-length` header, or if the origin is serving broken gzip compressed content. To diagnose this, you can try disabling compression at your origin to confirm if it resolves the error. -Otherwise, under certain conditions it is possible a given Data Center observes a sudden increase of traffic. -In these cases our automated processes will move traffic away from such location to a different Data Center making sure there is no impact for our customers. -These traffic adjustments are mostly seamless and take only a few seconds. -Still, it is possible that during this automated process some clients observe added latency and HTTP 502 errors. -You can find more information about our automated traffic management tools [in this blogpost](https://blog.cloudflare.com/meet-traffic-manager). +Additionally, in some cases, a particular data center may experience a sudden increase in traffic. To ensure minimal impact for customers, our automated processes will redirect traffic to another data center. These adjustments typically happen seamlessly and take just a few seconds. However, during this process, some clients may experience temporary latency or HTTP `502` errors. You can find more information about our automated traffic management tools in this [blogpost](https://blog.cloudflare.com/meet-traffic-manager). -**Resolution** +If you need further assistance from our Support team, provide the following details to [Cloudflare Support](/support/contacting-cloudflare-support/) to avoid delays in processing your inquiry: -If you still need our Support team to help you investigate further, please provide these required details to [Cloudflare Support](/support/contacting-cloudflare-support/) to avoid delays processing your inquiry: +- The time and timezone when the issue occurred. +- The URL that resulted in the HTTP `502` or `504` response (for example, `https://www.example.com/images/icons/image1.png`). +- The output from browsing to `/cdn-cgi/trace`. -1. Time and timezone the issue occurred. -2. URL that resulted in the HTTP 502 or 504 response (for example: `https://www.example.com/images/icons/image1.png`). -3. Output from browsing to `/cdn-cgi/trace`. +## Error 503: service temporarily unavailable ---- +HTTP error 503 occurs when your origin web server is overloaded. -## Error 503: service temporarily unavailable +### Common causes -HTTP error 503 occurs when your origin web server is overloaded. There are two possible causes discernible by error message: +There are two possible causes identifiable by the error message: -- Error doesn't contain `cloudflare` or `cloudflare-nginx` in the HTML response body. +- Error does not contain `cloudflare` or `cloudflare-nginx` in the HTML response body. In this case, the issue is likely from your origin server. +- Error contains `cloudflare` or `cloudflare-nginx` in the HTML response body. In this case, the issue may stem from Cloudflare. -**Resolution**: Contact your hosting provider to verify if they rate limit requests to your origin web server. +Additionally, `503` status codes in logs or analytics may result from [unsuccessful prefetches from Speed Brain](/speed/optimization/content/speed-brain/#how-speed-brain-works). -- Error contains `cloudflare` or `cloudflare-nginx` in the HTML response body. +### Resolution -**Resolution**: A connectivity issue occurred in a Cloudflare data center. Provide [Cloudflare support](/support/contacting-cloudflare-support/) with the following information: +To resolve a `503` error, first determine whether the issue originates from your origin web server or Cloudflare. The following sections provide guidance on troubleshooting both scenarios. -1. Your domain name -2. The time and timezone of the 503 error occurrence -3. The output of `www.example.com/cdn-cgi/trace` from the browser where the 503 error was observed (replace `www.example.com` with your actual domain and hostname) +#### 503 Error without `cloudflare` or `cloudflare-nginx` -You may also see 503 status codes in logs or analytics caused by [unsuccessful prefetches from Speed Brain](/speed/optimization/content/speed-brain/#how-speed-brain-works). +If the error does not contain `cloudflare` or `cloudflare-nginx` in the HTML response body, contact your hosting provider to verify if they rate limit requests to your origin web server. ---- +#### 503 Error with `cloudflare` or `cloudflare-nginx` + +If the error contains `cloudflare` or `cloudflare-nginx` in the HTML response body, a connectivity issue occurred in a Cloudflare data center. Provide [Cloudflare support](/support/contacting-cloudflare-support/) with the following information: + +- Your domain name +- The time and timezone of the `503` error occurrence +- The output of `www.example.com/cdn-cgi/trace` from the browser where the `503` error was observed (replace `www.example.com` with your actual domain and hostname) ## Error 520: web server returns an unknown error -Error 520 occurs when the origin server returns an empty, unknown, or unexpected response to Cloudflare. +This error occurs when the origin server returns an empty, unknown, or unexpected response to Cloudflare. + +### Common causes + +This error is often triggered by: -**Resolution** +- Origin server crashes or misconfigurations. +- Firewalls or security plugins blocking [Cloudflare IPs](https://www.cloudflare.com/ips) at your origin. +- Headers exceeding 16 KB (often due to excessive cookies). +- Empty or malformed responses lacking an HTTP status code or response body. +- Missing response headers or origin web server not returning [proper HTTP error responses](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml). +- Incorrect HTTP/2 configuration at the origin server. :::note -A quick workaround while further investigating 520 errors is to either -make the record [DNS-only](/dns/proxy-status/) -in the Cloudflare **DNS** app or [temporarily pause Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/). +`520` errors are prevalent with certain PHP applications that crash the origin web server. + ::: -[Contact your hosting provider or site administrator](#required-error-details-for-hosting-provider) and request a review of your origin web server error logs for crashes and to check for these common causes: - -- Origin web server application crashes -- [Cloudflare IPs](https://www.cloudflare.com/ips) not allowed at your origin -- Headers exceeding 16 KB (typically due to too many cookies) -- An empty response from the origin web server that lacks an HTTP status code or response body -- Missing response headers or origin web server not returning [proper HTTP error responses](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml). +### Resolution :::note -520 errors are prevalent with certain PHP applications that crash the -origin web server. +As a temporary workaround, you can set the affected DNS record to [DNS-only](/dns/proxy-status/) in the Cloudflare **DNS** app or [temporarily pause Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/). + ::: -If HTTP/2 is enabled at your origin web server, please check and make sure HTTP/2 is correctly configured. -Cloudflare connects to servers who announce support of HTTP/2 connections via [ALPN](https://blog.cloudflare.com/introducing-http2). -If the origin web server accepts the HTTP/2 connection but then doesn't respect or support the protocol, an HTTP Error 520 will be returned. -You can disable the [HTTP/2 to Origin](/speed/optimization/protocol/http2-to-origin/#disable-http2-to-origin) setting on the Cloudflare Dashboard under Speed -> Optimization -> Protocol Optimization and check your origin web server configuration further. +- Contact your hosting provider or site administrator and share the necessary [error details](#required-error-details-for-hosting-provider) to assist with troubleshooting. Request a review of your origin web server error logs for crashes and check for [common causes](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#common-causes-3) mentioned in the previous section. -If 520 errors continue after contacting your hosting provider or site administrator, provide the following information to [Cloudflare Support](/support/contacting-cloudflare-support/): +- If HTTP/2 is enabled at your origin server, ensure it is correctly set up. Cloudflare connects to servers who announce support of HTTP/2 connections via [ALPN](https://blog.cloudflare.com/introducing-http2). If the origin web server accepts the HTTP/2 connection but then does not respect or support the protocol, an HTTP `520` error will be returned. You can disable the [HTTP/2 to Origin](/speed/optimization/protocol/http2-to-origin/#disable-http2-to-origin) in **Speed** > **Optimization** > **Protocol Optimization** on the Cloudflare dashboard. -- Full URL(s) of the resource requested when the error occurred -- Cloudflare **cf-ray** from the 520 error message -- Output from `http:///cdn-cgi/trace` -- Two [HAR files](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#generate-a-har-file): - - one with Cloudflare enabled on your website, and - - the other with [Cloudflare temporarily disabled](/fundamentals/setup/manage-domains/pause-cloudflare/). +- If `520` errors continue after contacting your hosting provider or site administrator, provide the following information to [Cloudflare Support](/support/contacting-cloudflare-support/): ---- + - Full URL(s) of the resource requested when the error occurred. + - Cloudflare **cf-ray** from the `520` error message. + - Output from `http:///cdn-cgi/trace`. + - Two [HAR files](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#generate-a-har-file): + - One with Cloudflare enabled on your website. + - Another with [Cloudflare temporarily disabled](/fundamentals/setup/manage-domains/pause-cloudflare/). ## Error 521: web server is down -Error 521 occurs when the origin web server refuses connections from Cloudflare. Security solutions at your origin may block legitimate connections from certain [Cloudflare IP addresses](https://www.cloudflare.com/ips). +Error `521` occurs when the origin web server refuses connections from Cloudflare. Security solutions at your origin may block legitimate connections from certain [Cloudflare IP addresses](https://www.cloudflare.com/ips). + +### Common causes -The two most common causes of 521 errors are: +The two most common causes of `521` errors are: -- Offlined origin web server application -- Blocked Cloudflare requests +- Offlined origin web server application. +- Blocked Cloudflare requests. -**Resolution** +### Resolution -[Contact your site administrator or hosting provider](#required-error-details-for-hosting-provider) to eliminate these common causes: +Contact your hosting provider or site administrator and share the necessary [error details](#required-error-details-for-hosting-provider) to assist in troubleshooting these common causes: -- Ensure your origin web server is responsive +- Ensure your origin web server is responsive. - Review origin web server error logs to identify web server application crashes or outages. -- Confirm [Cloudflare IP addresses](https://www.cloudflare.com/ips) are not blocked or rate limited -- Allow all [Cloudflare IP ranges](https://www.cloudflare.com/ips) in your origin web server's firewall or other security software -- Confirm that — if you have your **SSL/TLS mode** set to **Full** or **Full (Strict**) — you have installed a [Cloudflare Origin Certificate](/ssl/origin-configuration/origin-ca) +- Confirm [Cloudflare IP addresses](https://www.cloudflare.com/ips) are not blocked or rate limited. +- Allow all [Cloudflare IP ranges](https://www.cloudflare.com/ips) in your origin web server's firewall or other security software. +- Confirm that — if you have your **SSL/TLS mode** set to **Full** or **Full (Strict**) — you have installed a [Cloudflare Origin Certificate](/ssl/origin-configuration/origin-ca) or a certificate matching the [requirements for these modes](/ssl/origin-configuration/ssl-modes/#custom-ssltls). - Find additional troubleshooting information on the [Cloudflare Community](https://community.cloudflare.com/t/community-tip-fixing-error-521-web-server-is-down/42461). ---- - ## Error 522: connection timed out -Error 522 occurs when Cloudflare times out contacting the origin web server. Two different timeouts cause HTTP error 522 depending on when they occur between Cloudflare and the origin web server: +Error `522` occurs when Cloudflare times out contacting the origin web server. -1. Before a connection is established, the origin web server does not return a SYN+ACK to Cloudflare within 15 seconds of Cloudflare sending a SYN. -2. After a connection is established, the origin web server doesn't acknowledge (ACK) Cloudflare's resource request within 90 seconds. +### Common causes -**Resolution** +Two different timeouts cause HTTP error `522` depending on when they occur between Cloudflare and the origin web server: -[Contact your hosting provider](#required-error-details-for-hosting-provider) to check the following common causes at your origin web server: +- Before a connection is established, the origin web server does not return a SYN+ACK to Cloudflare within 15 seconds of Cloudflare sending a SYN. +- After a connection is established, the origin web server does not acknowledge (ACK) Cloudflare's resource request within 90 seconds. -- (Most common cause) [Cloudflare IP addresses](https://www.cloudflare.com/ips/) are rate limited or blocked in .htaccess, iptables, or firewalls. Confirm your hosting provider allows Cloudflare IP addresses. -- An overloaded or offline origin web server drops incoming requests. -- [Keepalives](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) are disabled at the origin web server. -- The origin IP address in your Cloudflare **DNS** app does not match the IP address currently provisioned to your origin web server by your hosting provider. -- Packets were dropped at your origin web server. +### Resolution -If you are using [Cloudflare Pages](/pages/), verify that you have a custom domain set up and that your CNAME record is pointed to your [custom Pages domain](/pages/configuration/custom-domains/#add-a-custom-domain). -If you are using [Workers with a Custom Domain](/workers/configuration/routing/custom-domains/), performing a `fetch` to its own hostname will cause a 522 error. Consider using a [Route](/workers/configuration/routing/) or target another hostname instead. +- Contact your hosting provider and share the necessary [error details](#required-error-details-for-hosting-provider) to assist in troubleshooting these common causes: -If none of the above leads to a resolution, request the following information from your hosting provider or site administrator before [contacting Cloudflare support](/support/contacting-cloudflare-support/): + - [Cloudflare IP addresses](https://www.cloudflare.com/ips/) are rate limited or blocked in .htaccess, iptables, or firewalls. Confirm your hosting provider allows Cloudflare IP addresses (most common cause). + - An overloaded or offline origin web server drops incoming requests. + - [Keepalives](http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) are disabled at the origin web server. + - The origin IP address in your Cloudflare **DNS** app does not match the IP address currently provisioned to your origin web server by your hosting provider. + - Packets were dropped at your origin web server. -- An [MTR or traceroute](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#perform-a-traceroute) from your origin web server to a [Cloudflare IP address](http://www.cloudflare.com/ips) that most commonly connected to your origin web server before the issue occurred. Identify a connecting Cloudflare IP recorded in the origin web server logs. -- Details from the hosting provider's investigation such as pertinent logs or conversations with the hosting provider. +- If you are using [Cloudflare Pages](/pages/), verify that you have a custom domain set up and that your CNAME record is pointed to your [custom Pages domain](/pages/configuration/custom-domains/#add-a-custom-domain). ---- +- If you are using [Workers with a Custom Domain](/workers/configuration/routing/custom-domains/), performing a `fetch` to its own hostname will cause a `522` error. Consider using a [Route](/workers/configuration/routing/) or target another hostname instead. + +- If none of the above leads to a resolution, request the following information from your hosting provider or site administrator before [contacting Cloudflare support](/support/contacting-cloudflare-support/): + + - An [MTR or traceroute](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#perform-a-traceroute) from your origin web server to a [Cloudflare IP address](http://www.cloudflare.com/ips) that most commonly connected to your origin web server before the issue occurred. Identify a connecting Cloudflare IP recorded in the origin web server logs. + - Details from the hosting provider's investigation, such as pertinent logs or conversations with the hosting provider. ## Error 523: origin is unreachable -Error 523 occurs when Cloudflare cannot contact your origin web server. This typically occurs when a network device between Cloudflare and the origin web server doesn't have a route to the origin's IP address. +This error occurs when Cloudflare cannot contact your origin web server. + +### Common causes -**Resolution** [Contact your hosting provider](#required-error-details-for-hosting-provider) to exclude the following common causes at your origin web server: +This typically occurs when a network device between Cloudflare and the origin web server does not have a route to the origin's IP address. + +### Resolution + +Contact your hosting provider and share the necessary [error details](#required-error-details-for-hosting-provider) to exclude the following common causes at your origin web server: - Confirm the correct origin IP address is listed for A or AAAA records within your Cloudflare DNS app. - Troubleshoot Internet routing issues between your origin and Cloudflare, or with the origin itself. @@ -240,24 +254,25 @@ If none of the above leads to a resolution, request the following information fr - An [MTR or traceroute](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#perform-a-traceroute) from your origin web server to a [Cloudflare IP address](http://www.cloudflare.com/ips) that most commonly connected to your origin web server before the issue occurred. Identify a connecting Cloudflare IP from the logs of the origin web server. ---- - ## Error 524: a timeout occurred -Error 524 usually indicates that Cloudflare successfully connected to the origin web server, but the origin did not provide an HTTP response before the default 100 seconds [Proxy Read Timeout](/fundamentals/reference/connection-limits/). This can happen if the origin server is taking too long because it has too much work to do, for example, a large data query, or because the server is struggling for resources and cannot return any data in time. +Error `524` usually indicates that Cloudflare successfully connected to the origin web server, but the origin did not provide an HTTP response before the default 100 seconds [Proxy Read Timeout](/fundamentals/reference/connection-limits/). -Error 524 can also indicate that Cloudflare successfully connected to the origin web server to write data, but the write did not complete before the 30 seconds [Proxy Write Timeout](/fundamentals/reference/connection-limits/) (or 6.5 seconds in the case of [Cloudflare Images](/images/)). +### Common causes + +This can happen if the origin server is taking too long because it has too much work to do, for example, a large data query, or because the server is struggling for resources and cannot return any data in time. + +Error `524` can also indicate that Cloudflare successfully connected to the origin web server to write data, but the write did not complete before the 30 seconds [Proxy Write Timeout](/fundamentals/reference/connection-limits/) (or 6.5 seconds in the case of [Cloudflare Images](/images/)). :::note -A 524 occurs if the origin web server -acknowledges (_ACK_) the resource request after the connection has been +A `524` occurs if the origin web server acknowledges (ACK) the resource request after the connection has been established, but does not send a timely response. ::: -**Resolution** +### Resolution -Here are the options we'd suggest to work around this issue: +Here are the options we suggest to work around this issue: - Implement status polling of large HTTP processes to avoid hitting this error. - [Contact your hosting provider](#required-error-details-for-hosting-provider) to exclude the following common causes at your origin web server: @@ -266,106 +281,74 @@ Here are the options we'd suggest to work around this issue: :::note -Logging request response time at your origin web server helps identify -the cause of resource slowness. Contact your hosting provider or site -administrator for assistance in adjusting log formats or search for -related logging documentation for your brand of web server such as -[Apache](http://httpd.apache.org/docs/current/mod/mod_log_config.html) -or -[Nginx](http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). +Logging request response time at your origin web server helps identify the cause of resource slowness. Contact your hosting provider or site administrator for assistance in adjusting log formats or search for related logging documentation for your brand of web server such as [Apache](http://httpd.apache.org/docs/current/mod/mod_log_config.html) or [Nginx](http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). ::: -- Enterprise customers can increase the 524 timeout up to 6,000 seconds using the [Edit zone setting](/api/resources/zones/subresources/settings/methods/edit/) endpoint (`proxy_read_timeout` setting). If your content can be cached, you may also choose to use a [Cache Rule](/cache/how-to/cache-rules/settings/#proxy-read-timeout-enterprise-only) with the `Proxy Read Timeout` setting selected instead in the Cloudflare Dashboard. +- Enterprise customers can increase the `524` timeout up to 6,000 seconds using the [Edit zone setting](/api/resources/zones/subresources/settings/methods/edit/) endpoint (`proxy_read_timeout` setting). If your content can be cached, you may also choose to use a [Cache Rule](/cache/how-to/cache-rules/settings/#proxy-read-timeout-enterprise-only) with the `Proxy Read Timeout` setting selected instead in the Cloudflare Dashboard. :::note If the timeouts are on write requests, the [Proxy Write Timeout](/fundamentals/reference/connection-limits/) of 30 seconds cannot be adjusted. ::: -- If you regularly run HTTP requests that take over 100 seconds to complete (for example large data exports), move those processes behind a subdomain not proxied (grey clouded) in the Cloudflare **DNS** app. +- If you regularly run HTTP requests that take over 100 seconds to complete (for example, large data exports), move those processes behind a subdomain not proxied (grey clouded) in the Cloudflare **DNS** app. :::note -Please note that you may observe a 1 second difference between the timeout you've set and the actual time at which the Error 524 is returned. -This is expected, it's due to the current work on implementing [Pingora, our new proxy](https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/). -As a workaround you can simply set the timeout to 1 second more (121 seconds instead of 120 seconds for example). +Note that you may observe a 1 second difference between the timeout you have set and the actual time at which the Error `524` is returned. This is expected, it is due to the current work on implementing our proxy - [Pingora](https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/). +As a workaround, you can simply set the timeout to one second more (121 seconds instead of 120 seconds, for example). ::: ---- - ## Error 525: SSL handshake failed -525 errors indicate that the SSL handshake between Cloudflare and the origin web server failed. Error 525 occurs when these two conditions are true: +This error indicates that the SSL handshake between Cloudflare and the origin web server failed. + +### Common causes -1. The [SSL handshake](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) fails between Cloudflare and the origin web server, and -2. [_Full_ or _Full (Strict)_](/ssl/origin-configuration/ssl-modes) **SSL** is set in the **Overview** tab of your Cloudflare **SSL/TLS** app. +Error `525` occurs when these two conditions are true: + +- The [SSL handshake](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/) fails between Cloudflare and the origin web server. +- [_Full_ or _Full (Strict)_](/ssl/origin-configuration/ssl-modes) **SSL** is set in the **Overview** tab of your Cloudflare **SSL/TLS** app. :::note -If your hosting provider frequently changes your origin web server's IP -address, refer to Cloudflare's documentation on [dynamic DNS -updates](/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses). +If your hosting provider frequently changes your origin web server's IP address, refer to Cloudflare's documentation on [dynamic DNS updates](/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses). ::: -**Resolution** +### Resolution Contact your hosting provider to exclude the following common causes at your origin web server: -- No valid SSL certificate installed -- Port 443 (or other custom secure port) is not open -- No SNI support -- The [cipher suites](/ssl/origin-configuration/cipher-suites/) presented by Cloudflare to the origin do not match the cipher suites supported by the origin web server +- No valid SSL certificate is installed. +- Port `443` (or another custom secure port) is not open. +- No SNI support. +- The [cipher suites](/ssl/origin-configuration/cipher-suites/) used by Cloudflare do not match the cipher suites supported by the origin web server. :::note -If 525 errors occur intermittently, review the origin web server error -logs to determine the cause. Configure Apache to [log mod_ssl -errors](https://cwiki.apache.org/confluence/display/HTTPD/DebuggingSSLProblems#Enable_SSL_logging). -Also, nginx includes SSL errors in its standard error log, but may -possibly require [an increased log -level](https://docs.nginx.com/nginx/admin-guide/monitoring/logging/). +If `525` errors occur intermittently, review the origin web server error logs to determine the cause. Configure Apache to [log mod_ssl errors](https://cwiki.apache.org/confluence/display/HTTPD/DebuggingSSLProblems#Enable_SSL_logging). Also, nginx includes SSL errors in its standard error log, but may possibly require [an increased log level](https://docs.nginx.com/nginx/admin-guide/monitoring/logging/). ::: -**Additional checks** +- Verify that a certificate is installed on your origin server. For details on running tests, refer to [Troubleshoot requests with curl](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#troubleshoot-requests-with-curl). If no certificate is installed, you can generate and install a free [Cloudflare origin CA certificate](/ssl/origin-configuration/origin-ca) to encrypt traffic between Cloudflare and your origin web server. -- Check if you have a certificate installed on your origin server. You can check [this article](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#troubleshoot-requests-with-curl) for more details on how to run some tests. In case you don't have any certificate, you can create and install our free [Cloudflare origin CA certificate](/ssl/origin-configuration/origin-ca). Using Origin CA certificates allows you to encrypt traffic between Cloudflare and your origin web server. -- [Review the cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/) your server is using to ensure they match what is supported by Cloudflare. -- Check your server's error logs from the timestamps you see 525s to ensure there are errors that could be causing the connection to be reset during the SSL handshake. +- [Review the cipher suites](/ssl/edge-certificates/additional-options/cipher-suites/) used by your server to ensure they are compatible with Cloudflare. ---- +- Check your server's error logs from the timestamps when `525` errors occur to identify any issues causing the connection to be reset during the SSL handshake. ## Error 526: invalid SSL certificate -Error 526 occurs when these two conditions are true: +This error indicates that Cloudflare is unable to verify the SSL certificate on your origin server, preventing a secure connection from being established. -1. Cloudflare cannot validate the SSL certificate at your origin web server, and -2. [_Full SSL (Strict)_](/ssl/origin-configuration/ssl-modes/full-strict/) **SSL** is set in the **Overview** tab of your Cloudflare **SSL/TLS** app. +### Common causes -**Resolution** - -:::note - -For a potential quick fix, set **SSL** to _Full_ instead of _Full -(strict)_ in the **Overview** tab of your Cloudflare **SSL/TLS** app for -the domain. -::: - -Request your server administrator or hosting provider to review the origin web server's SSL certificates and verify that: - -- Certificate is not expired -- Certificate is not revoked -- Certificate is signed by a [Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority) (not self-signed) -- The requested or target domain name and hostname are in the certificate's **Common Name** or **Subject Alternative Name** -- Your origin web server accepts connections over port SSL port 443 -- [Temporarily pause Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/) and visit [https://www.sslshopper.com/ssl-checker.html#hostname=www.example.com](https://www.sslshopper.com/ssl-checker.html#hostname=www.example.com) (replace `www.example.com` with your hostname and domain) to verify no issues exists with the origin SSL certificate: - -![Screen showing an SSL certificate with no errors.](~/assets/images/support/hc-import-troubleshooting_5xx_errors_sslshopper_output.png) +This error occurs when these two conditions are true: -If the origin server uses a self-signed certificate, configure the domain to use _Full_ _SSL_ instead of _Full SSL (Strict)_. Refer to [recommended SSL settings for your origin](/ssl/origin-configuration/ssl-modes). +- Cloudflare cannot validate the SSL certificate at your origin web server. +- [_Full SSL (Strict)_](/ssl/origin-configuration/ssl-modes/full-strict/) **SSL** is set in the **Overview** tab of your Cloudflare **SSL/TLS** app. -### Error 526 in the Zero Trust context +#### Error 526 in the Zero Trust context -When using [Cloudflare Gateway](/cloudflare-one/policies/gateway/), an HTTP Error 526 might be returned in the [following cases](/cloudflare-one/faq/troubleshooting/#i-see-error-526-when-browsing-to-a-website): +When using [Cloudflare Gateway](/cloudflare-one/policies/gateway/), an HTTP Error `526` might be returned in the [following cases](/cloudflare-one/faq/troubleshooting/#i-see-error-526-when-browsing-to-a-website): - **An untrusted certificate is presented from the origin to Gateway.** Gateway will consider a certificate is untrusted if any of these conditions are true: @@ -381,24 +364,40 @@ When using [Cloudflare Gateway](/cloudflare-one/policies/gateway/), an HTTP Erro - Do not support [FIPS-compliant ciphers](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#cipher-suites) (if you have enabled [FIPS compliance mode](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#fips-compliance)). In order to load the page, you can either disable FIPS mode or create a Do Not Inspect policy for this host (which has the effect of disabling FIPS compliance for this origin). - Redirect all HTTPS requests to HTTP. -### Error 526 in the Workers context +#### Error 526 in the Workers context + +Workers subrequests to any hostname outside your Cloudflare zone that is not proxied by Cloudflare are always made using the **[Full (strict)](/ssl/origin-configuration/ssl-modes/full-strict/)** SSL mode, regardless of the Workers zone configuration. + +As a result, a valid SSL certificate is required at the origin server. -Workers subrequests to any hostname outside of your Cloudflare zone that is not proxied by Cloudflare are always made using the **[Full (strict)](/ssl/origin-configuration/ssl-modes/full-strict/)** SSL mode, even when the Workers zone is configured otherwise. +### Resolution -As a result, a valid SSL certificate is required at the origin. +:::note +For a potential quick fix, set **SSL** to _Full_ instead of _Full (strict)_ in the **Overview** tab of your Cloudflare **SSL/TLS** app for the domain. +::: + +Request your server administrator or hosting provider to review the origin web server's SSL certificates and verify that: + +- Certificate is not expired. +- Certificate is not revoked. +- Certificate is signed by a [Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority) (not self-signed). +- The requested or target domain name and hostname are in the certificate's **Common Name** or **Subject Alternative Name**. +- Your origin web server accepts connections over port SSL port `443`. +- [Temporarily pause Cloudflare](/fundamentals/setup/manage-domains/pause-cloudflare/) and visit [https://www.sslshopper.com/ssl-checker.html#hostname=www.example.com](https://www.sslshopper.com/ssl-checker.html#hostname=www.example.com) (replace `www.example.com` with your hostname and domain) to verify no issues exists with the origin SSL certificate: + +![Screen showing an SSL certificate with no errors.](~/assets/images/support/hc-import-troubleshooting_5xx_errors_sslshopper_output.png) + +If the origin server uses a self-signed certificate, configure the domain to use _Full_ _SSL_ instead of _Full SSL (Strict)_. Refer to [recommended SSL settings for your origin](/ssl/origin-configuration/ssl-modes). ## Error 530 -An HTTP error 530 is returned when Cloudflare is encountering an issue resolving the origin hostname. -In this case the body of the response contains an [1XXX error](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors) code. -Please refer to the specific [1XXX error](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors) for troubleshooting information. +This error indicates that Cloudflare is unable to resolve the origin hostname, preventing it from establishing a connection to the origin server. ---- +### Common causes + +An HTTP error `530` is returned when Cloudflare is encountering an issue resolving the origin hostname. +In this case the body of the response contains an [1XXX error](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors) code. -## Related resources +### Resolution -- [Gathering information to troubleshoot site issues](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites) -- [Contacting Cloudflare Support](/support/contacting-cloudflare-support/) -- [Customizing Cloudflare error pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/) -- [MTR/Traceroute Diagnosis and Usage](/support/troubleshooting/general-troubleshooting/gathering-information-for-troubleshooting-sites/#perform-a-traceroute) -- [Cloudflare Community Tips](https://community.cloudflare.com/tag/communitytip) +Refer to the specific [1XXX error](/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-1xxx-errors/) for troubleshooting information. \ No newline at end of file diff --git a/src/content/docs/support/troubleshooting/http-status-codes/4xx-client-error.mdx b/src/content/docs/support/troubleshooting/http-status-codes/4xx-client-error.mdx index 547686a3fa315a..c1c05564f5a58f 100644 --- a/src/content/docs/support/troubleshooting/http-status-codes/4xx-client-error.mdx +++ b/src/content/docs/support/troubleshooting/http-status-codes/4xx-client-error.mdx @@ -2,6 +2,7 @@ pcx_content_type: troubleshooting source: https://support.cloudflare.com/hc/en-us/articles/115003014512-4xx-Client-Error title: 4xx Client Error +description: Explore detailed explanations of 4xx client error codes, including causes and solutions, in Cloudflare's technical documentation for developers. --- import { FeatureTable, Render } from "~/components"; diff --git a/src/content/docs/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips.mdx b/src/content/docs/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips.mdx index b993e040ad1180..c12860bad83f9b 100644 --- a/src/content/docs/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips.mdx +++ b/src/content/docs/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips.mdx @@ -25,7 +25,7 @@ The diagram below illustrates the different ways that IP addresses are handled w Cloudflare no longer updates and supports _mod_cloudflare_, starting with versions **Debian 9** and **Ubuntu 18.04 LTS** of the Linux operating system. We now recommend -[_mod_remoteip_](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) +[_mod_remoteip_](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) for customers using Apache web servers. Customers who are interested in building the _mod_cloudflare_ package can [download the codebase](https://github.com/cloudflare/mod_cloudflare) from GitHub. @@ -122,7 +122,7 @@ documentation](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html "Apache M Cloudflare no longer updates and supports _mod_cloudflare_, starting with versions **Debian 9** and **Ubuntu 18.04 LTS** of the Linux operating system. We now recommend -[_mod_remoteip_](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) +[_mod_remoteip_](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) for customers using Apache web servers. Customers who are interested in building the _mod_cloudflare_ package can [download the codebase](https://github.com/cloudflare/mod_cloudflare) from GitHub. @@ -181,7 +181,7 @@ Refer below for instructions on how to configure your web server to log origina Cloudflare no longer updates and supports _mod_cloudflare_, starting with versions **Debian 9** and **Ubuntu 18.04 LTS** of the Linux operating system. We now recommend -[_mod_remoteip_](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) +[_mod_remoteip_](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) for customers using Apache web servers. Customers who are interested in building the _mod_cloudflare_ package can [download the codebase](https://github.com/cloudflare/mod_cloudflare) from GitHub. @@ -238,7 +238,7 @@ Also refer to: [Cloudflare and NGINX](https://danielmiessler.com/blog/getting-r Cloudflare no longer updates and supports _mod_cloudflare_, starting with versions **Debian 9** and **Ubuntu 18.04 LTS** of the Linux operating system. We now recommend -[_mod_remoteip_](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) +[_mod_remoteip_](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) for customers using Apache web servers. Customers who are interested in building the _mod_cloudflare_ package can [download the codebase](https://github.com/cloudflare/mod_cloudflare) from GitHub. @@ -341,7 +341,7 @@ If your network environment means requests are handled through a proxy (such as ### PHPBB -If you are using an Apache server, then we would recommend installing [mod_remoteip](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) to restore the visitor IP back to your logs. +If you are using an Apache server, then we would recommend installing [mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) to restore the visitor IP back to your logs. If you do not have access to your server to install a mod, then you may be able to [modify the core](https://www.phpbb.com/community/viewtopic.php?p=13936406#p13936406). @@ -420,7 +420,7 @@ As this plugin was created by an outside party, we can't provide technical suppo If you use the hosting control panel VestaCP, you have both Nginx and Apache running on your server. Requests are proxied through Nginx before going to Apache. -Because of this Nginx proxy, you actually need to the instructions to configure Nginx to return the real visitor IP address. [Mod_remoteip](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) for Apache is not needed unless you disable the Nginx server for some requests. Adding [mod_remoteip](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) to Apache will not conflict with the Nginx server configuration. +Because of this Nginx proxy, you actually need to the instructions to configure Nginx to return the real visitor IP address. [mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) for Apache is not needed unless you disable the Nginx server for some requests. Adding [mod_remoteip](https://support.cloudflare.com/hc/articles/200170786#C5XWe97z77b3XZV) to Apache will not conflict with the Nginx server configuration. ### node.js diff --git a/src/content/docs/tenant/index.mdx b/src/content/docs/tenant/index.mdx index e10097579fab43..8789089a3234dd 100644 --- a/src/content/docs/tenant/index.mdx +++ b/src/content/docs/tenant/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Tenant pcx_content_type: overview sidebar: order: 1 head: - tag: title content: Overview - --- The Cloudflare Tenant API is a provisioning mechanism to help Channel and Alliance partners set up and manage Cloudflare accounts and services for their customers. diff --git a/src/content/docs/terraform/advanced-topics/import-cloudflare-resources.mdx b/src/content/docs/terraform/advanced-topics/import-cloudflare-resources.mdx index f5e8f8c2473f58..a7379025224b16 100644 --- a/src/content/docs/terraform/advanced-topics/import-cloudflare-resources.mdx +++ b/src/content/docs/terraform/advanced-topics/import-cloudflare-resources.mdx @@ -121,7 +121,7 @@ Calling `terraform plan` at this point will try to create these resources as if terraform plan ``` -```sh output +```txt output Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create @@ -235,7 +235,7 @@ You would run each command individually in the terminal: terraform import cloudflare_record.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31 1109d899a5ff5fd74bc01e581693685b/3c0b456bc2aa443089c5f40f45f51b31 ``` -```sh output +```txt output cloudflare_record.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Importing from ID "1109d899a5ff5fd74bc01e581693685b/3c0b456bc2aa443089c5f40f45f51b31"... cloudflare_record.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Import complete! Imported cloudflare_record [id=3c0b456bc2aa443089c5f40f45f51b31] @@ -251,7 +251,7 @@ your Terraform state and will henceforth be managed by Terraform. terraform import cloudflare_record.terraform_managed_resource_5e10399a590a45279f09aa8fb1163354 1109d899a5ff5fd74bc01e581693685b/d09d916d059aa9fc8cb54bdd49deea5f ``` -```sh output +```txt output cloudflare_record.terraform_managed_resource_5e10399a590a45279f09aa8fb1163354: Importing from ID "1109d899a5ff5fd74bc01e581693685b/d09d916d059aa9fc8cb54bdd49deea5f"... cloudflare_record.terraform_managed_resource_5e10399a590a45279f09aa8fb1163354: Import complete! Imported cloudflare_record [id=d09d916d059aa9fc8cb54bdd49deea5f] @@ -267,7 +267,7 @@ your Terraform state and will henceforth be managed by Terraform. terraform import cloudflare_record.terraform_managed_resource_de1cb74bae184b569bb7f83fefe72248 1109d899a5ff5fd74bc01e581693685b/8d6ec0d02c5b22212ff673782c816ef8 ``` -```sh output +```txt output cloudflare_record.terraform_managed_resource_de1cb74bae184b569bb7f83fefe72248: Importing from ID "1109d899a5ff5fd74bc01e581693685b/8d6ec0d02c5b22212ff673782c816ef8"... cloudflare_record.terraform_managed_resource_de1cb74bae184b569bb7f83fefe72248: Import complete! Imported cloudflare_record [id=8d6ec0d02c5b22212ff673782c816ef8] @@ -283,7 +283,7 @@ your Terraform state and will henceforth be managed by Terraform. terraform import cloudflare_record.terraform_managed_resource_5799bb01054843eea726758f935d2aa2 1109d899a5ff5fd74bc01e581693685b/3766b952a2dda4c47e71952aeef33c77 ``` -```sh output +```txt output cloudflare_record.terraform_managed_resource_5799bb01054843eea726758f935d2aa2: Importing from ID "1109d899a5ff5fd74bc01e581693685b/3766b952a2dda4c47e71952aeef33c77"... cloudflare_record.terraform_managed_resource_5799bb01054843eea726758f935d2aa2: Import complete! Imported cloudflare_record [id=3766b952a2dda4c47e71952aeef33c77] diff --git a/src/content/docs/terraform/index.mdx b/src/content/docs/terraform/index.mdx index a8137d128d95e9..2c10e426fae039 100644 --- a/src/content/docs/terraform/index.mdx +++ b/src/content/docs/terraform/index.mdx @@ -1,12 +1,11 @@ --- -title: Overview +title: Cloudflare Terraform provider pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Terraform - + content: Overview --- Configure Cloudflare using HashiCorp's “Infrastructure as Code” tool, Terraform. With [Cloudflare’s Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs), you can manage the Cloudflare global network using the same familiar tools you use to automate the rest of your infrastructure. Define and store configuration in source code repositories like GitHub, track and version changes over time, and roll back when needed — all without needing to use the Cloudflare APIs. diff --git a/src/content/docs/terraform/tutorial/add-page-rules.mdx b/src/content/docs/terraform/tutorial/add-page-rules.mdx index d2090f042cdeb6..f5be5195017304 100644 --- a/src/content/docs/terraform/tutorial/add-page-rules.mdx +++ b/src/content/docs/terraform/tutorial/add-page-rules.mdx @@ -236,7 +236,7 @@ cloudflare_page_rule.increase-security-on-expensive-page: Creation complete afte Apply complete! Resources: 2 added, 0 changed, 0 destroyed. ``` -With the Page Rules in place, try that call again, along with a test for the I'm Under Attack mode: +With the Page Rules in place, try that call again, along with a test for the Under Attack mode: ```sh curl -vso /dev/null https://www.example.com/old-location.php 2>&1 | grep "< HTTP\|Location" @@ -255,4 +255,4 @@ curl -vso /dev/null https://www.example.com/expensive-db-call 2>&1 | grep "< HTT < HTTP/1.1 503 Service Temporarily Unavailable ``` -The call works as expected. In the first case, the Cloudflare global network responds with a `301` redirecting the browser to the new location. In the second case, the Cloudflare global network initially responds with a `503`, which is consistent with the I'm Under Attack mode. +The call works as expected. In the first case, the Cloudflare global network responds with a `301` redirecting the browser to the new location. In the second case, the Cloudflare global network initially responds with a `503`, which is consistent with the Under Attack mode. diff --git a/src/content/docs/time-services/index.mdx b/src/content/docs/time-services/index.mdx index 21c0478f711198..4504f50acba9c9 100644 --- a/src/content/docs/time-services/index.mdx +++ b/src/content/docs/time-services/index.mdx @@ -1,13 +1,12 @@ --- -title: Overview +title: Cloudflare Time Services pcx_content_type: overview type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Time Services docs - + content: Overview --- import { DirectoryListing } from "~/components" diff --git a/src/content/docs/turnstile/concepts/widget.mdx b/src/content/docs/turnstile/concepts/widget.mdx index e0c95f321c979c..401e2c731959af 100644 --- a/src/content/docs/turnstile/concepts/widget.mdx +++ b/src/content/docs/turnstile/concepts/widget.mdx @@ -12,7 +12,7 @@ Every instance of Turnstile belongs to a Turnstile widget. It is configured on a The 3 modes for Turnstile are **Managed**, **Non-Interactive**, and **Invisible**. -Refer to [appearance modes](/turnstile/get-started/client-side-rendering/#appearance-modes) to configure whether to have the widget be always visible or visible only when interaction is required. +Refer to [appearance modes](/turnstile/get-started/client-side-rendering/#appearance-modes) to configure whether to have the widget be always visible or visible only when interaction is required, and to customize your widget theme between automatic, light, or dark mode. Widgets can be implemented in normal, flexible, or compact sizes. diff --git a/src/content/docs/turnstile/index.mdx b/src/content/docs/turnstile/index.mdx index 94218564798b54..b62d47a10c19a3 100644 --- a/src/content/docs/turnstile/index.mdx +++ b/src/content/docs/turnstile/index.mdx @@ -1,11 +1,11 @@ --- -title: Overview +title: Cloudflare Turnstile pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Turnstile + content: Overview --- import { @@ -26,8 +26,6 @@ Cloudflare’s smart CAPTCHA alternative. Turnstile can be embedded into any website without sending traffic through Cloudflare and works without showing visitors a CAPTCHA. - - ![Turnstile Overview](~/assets/images/turnstile/turnstile-overview.png) @@ -78,7 +76,7 @@ Refer to [Cloudflare Turnstile's product page](https://www.cloudflare.com/produc ## Features - + Assess the number of challenges issued, evaluate the challenge solve rate, and view the metrics of issued challenges. diff --git a/src/content/docs/turnstile/turnstile-analytics.mdx b/src/content/docs/turnstile/turnstile-analytics.mdx deleted file mode 100644 index 708e825472049f..00000000000000 --- a/src/content/docs/turnstile/turnstile-analytics.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Turnstile analytics -pcx_content_type: how-to -sidebar: - order: 6 -head: [] -description: Use Turnstile analytics to view the number of challenges issued, - the challenge solve rate, and the metrics of issued challenges. - ---- - -Using Turnstile analytics, you can: - -- Assess the number of challenges issued. -- Evaluate the Challenge Solve Rate (CSR). -- View the metrics of issued challenges. - -## View metrics of your widgets - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. -2. Go to **Turnstile** and then navigate to your website to see an overview of its widget metrics. - -These metrics show changes in the solve rate, widget traffic, and top actions for your website. - -## Change in Solve Rate - -The change in Solve Rate is expected to be relatively stable over time. It is an indication of something happening on the website, such as undergoing attacks from bots. - -View the history of your website’s widget Solve Rate with Turnstile analytics. - -:::note - -You can filter the data by `Action=(free input)` or by time. -::: - -### Visitor Solve Rate - -Visitor Solve Rate considers all humans who have viewed the widget, whether it was interactive or non-interactive. It measures the percentage of people who completed the widget. For example, if 100 people saw the widget and 20 of them completed it successfully, the Visitor Solve Rate would be 20%. - -A full Turnstile Challenge Token Flow consists of a few things: - -- A challenge is rendered (issued). -- A challenge is solved on the front end and a token is harvested (solved). -- The token is passed to siteverify, and it is consumed (siteverified). - -Visitor Solve Rate is the percentage of tokens that were solved but have not necessarily been siteverified compared to issued challenges. - -### API Solve Rate - -API Solve Rate is the share of tokens that were siteverified compared to issued. It focuses only on humans who interacted with the widget through the website’s API. It measures the percentage of successful widget completions among all visitors detected through the API. This metric looks specifically at the number of people who successfully completed the widget. For example, if 100 people viewed the widget, 20 of them completed it successfully, and only 15 of them had their token siteverified, the API Solve Rate would be 15%. - -## Widget traffic - -Widget traffic metrics provide you with data on the number of instances where the widget was displayed, the number of instances where interactive widget was solved, and the number of instances where non-interactive widget was solved on your website over time. - -## Top Actions - -Top Actions refer to the custom labels you created for your widgets. - -Action can be used in analytics and is more limited in size. It should identify different pages in a website where a widget is used. Action should not contain any personally identifiable information (PII) as this is placed into the analytics. - -cData is not stored in our analytics. It can contain data that may vary by each challenge instance. - -Both cData and action are returned by the siteverify API if a valid token is presented. - -## GraphQL - -You can use the `turnstileAdaptiveGroups` [dataset in GraphQL](/analytics/graphql-api/features/data-sets/) to get Turnstile widget analytics. diff --git a/src/content/docs/turnstile/turnstile-analytics/challenge-outcomes.mdx b/src/content/docs/turnstile/turnstile-analytics/challenge-outcomes.mdx new file mode 100644 index 00000000000000..03fd359793ea3e --- /dev/null +++ b/src/content/docs/turnstile/turnstile-analytics/challenge-outcomes.mdx @@ -0,0 +1,48 @@ +--- +title: Challenge outcome +pcx_content_type: concept +sidebar: + order: 2 +--- + +import { Render } from "~/components" + +When a visitor encounters Turnstile, it assesses whether they are human or bot-like based on various signals. These outcomes help you evaluate how effectively Turnstile is protecting your application. + +## Metrics + +A "solved" Turnstile challenge does not automatically confirm the visitor is human. You must [call the siteverify API](#call-siteverify) to validate the token and proceed only if the response returns `success:true`. + +For example, the challenge outcome values in your analytics may look like this: + +![Challenge outcome example values](~/assets/images/turnstile/challenge-outcomes.png "Challenge outcome example") + +- **Challenges issued**: The total number of challenges presented to visitors within a specific timeframe. +- **Challenges solved**: The number of challenges successfully completed by visitors in that period. +- **Challenges unsolved**: Challenges that were abandoned or failed in that period. +- **Likely human**: The total number of challenges solved or the total number of challenges issued. +- **Likely bot**: The total number of challenges unsolved or the total number challenges issued. + +By analyzing these metrics, you can identify trends such as high failure rates in specific regions, device types, or traffic sources, which may indicate bot activity or misconfigurations. + +### Call siteverify + + + +## Solve rates + +Turnstile's solve rate is a critical metric that helps gauge how many legitimate visitors are passing a challenge. Solve rates can be broken down into the total number of challenges solved and whether they are interactive, non-interactive, or pre-clearance solves. + +If you are using [managed mode](/turnstile/concepts/widget/#widget-types), you can monitor how many of your visitors were prompted interactivity to check the box on the widget (interactive solves) and how many were verified without any disruptions to their experience (non-interactive solves). + +For example, the solve rate values in your analytics may look like this: + +![Solve rate example values](~/assets/images/turnstile/solve-rates.png "Solve rate example") + +### Metrics + +- **Non-interactive solves**: Challenges solved without requiring the visitor to click a checkbox. +- **Interactive solves**: Challenges solved that required visitor interaction to be solved. +- [**Pre-clearance solves**](/turnstile/concepts/pre-clearance-support/): Challenges solved that issued the `cf-clearance` cookie along with the Turnstile token. + +A low solve rate might indicate increased bot activity attempting to bypass Turnstile or anomalous traffic patterns that require further investigation. \ No newline at end of file diff --git a/src/content/docs/turnstile/turnstile-analytics/index.mdx b/src/content/docs/turnstile/turnstile-analytics/index.mdx new file mode 100644 index 00000000000000..0c48cd6aac6775 --- /dev/null +++ b/src/content/docs/turnstile/turnstile-analytics/index.mdx @@ -0,0 +1,36 @@ +--- +title: Turnstile Analytics +pcx_content_type: how-to +sidebar: + order: 6 +description: Use Turnstile Analytics to view the number of challenges issued, + the challenge solve rate, and the metrics of issued challenges. + +--- + +import { Render, DirectoryListing } from "~/components" + +Turnstile Analytics provides you with a view of the top widget statistics across different metadata dimensions to understand where your traffic is coming from, which environments have the highest challenge activity, and whether certain sources are disproportionately failing or bypassing challenges, allowing you to fine-tune your security settings, apply more granular mitigations, and proactively respond to evolving threats. + +## Available statistics + +- **Top Hostnames**: If the Turnstile widget is placed across multiple hostnames, this will display the highest traffic hostnames where challenges are being issued. +- **Top Browsers**: A breakdown of browsers that are most commonly encountering Turnstile challenges, helping customers spot trends in visitor traffic. +- **Top Countries**: View the top originating countries for visitors completing challenges, which can help identify regional traffic anomalies. +- **Top User Agents**: Identify which user agents are generating the most Turnstile challenge requests. +- [**Top ASNs**](https://cloudflare.com/learning/network-layer/what-is-an-autonomous-system): Displays the highest volume of challenges issued from specific Autonomous System Numbers (ASNs), helping customers detect potential bot activity. +- **Top Operating Systems**: Shows which operating systems are most common among visitors passing or failing challenges. +- [**Top Source IPs**](https://cloudflare.com/learning/ddos/glossary/ip-spoofing): Identify the highest-volume IP addresses issuing Turnstile challenges, which can be useful in identifying attack sources or repeated challenge failures. + +## View widget metrics + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. Go to **Turnstile** and then navigate to your widget to see an overview of its analytics. + +The metrics show changes in the solve rate, widget traffic, and top actions for your widget. + +![Turnstile Analytics overview](~/assets/images/turnstile/top-actions.png) + +Refer to the pages below for more information about Turnstile Analytics: + + \ No newline at end of file diff --git a/src/content/docs/turnstile/turnstile-analytics/token-validation.mdx b/src/content/docs/turnstile/turnstile-analytics/token-validation.mdx new file mode 100644 index 00000000000000..264db26da83a84 --- /dev/null +++ b/src/content/docs/turnstile/turnstile-analytics/token-validation.mdx @@ -0,0 +1,24 @@ +--- +title: Token validation +pcx_content_type: concept +sidebar: + order: 3 +--- + +import { Render } from "~/components" + +After a visitor successfully completes a Turnstile challenge, a token is generated and validated via the siteverify API. Token validation data provides crucial insights into your security posture. + +For example, the token validation values in your analytics may look like this: + +![Token validation example values](~/assets/images/turnstile/token-validation.png "Token validation example") + +## Metrics + +- **Siteverify requests**: The total number of requests made to the siteverify API in the given timeframe. +- **Valid tokens**: The number of siteverify requests with `success:true` responses. +- **Invalid tokens**: The number of siteverify requests with `success:false` responses. + +### Call siteverify + + \ No newline at end of file diff --git a/src/content/docs/turnstile/tutorials/excluding-turnstile-from-e2e-tests.mdx b/src/content/docs/turnstile/tutorials/excluding-turnstile-from-e2e-tests.mdx index b92a5c1b8fc43e..f820cd123b1b37 100644 --- a/src/content/docs/turnstile/tutorials/excluding-turnstile-from-e2e-tests.mdx +++ b/src/content/docs/turnstile/tutorials/excluding-turnstile-from-e2e-tests.mdx @@ -3,7 +3,6 @@ title: Exclude Turnstile from E2E tests pcx_content_type: tutorial updated: 2025-01-24 difficulty: Intermediate -content_type: 📝 Tutorial languages: - TypeScript tags: diff --git a/src/content/docs/turnstile/tutorials/implicit-vs-explicit-rendering.mdx b/src/content/docs/turnstile/tutorials/implicit-vs-explicit-rendering.mdx index 719128c330d07d..016fd6c11d9260 100644 --- a/src/content/docs/turnstile/tutorials/implicit-vs-explicit-rendering.mdx +++ b/src/content/docs/turnstile/tutorials/implicit-vs-explicit-rendering.mdx @@ -3,7 +3,6 @@ title: Implement Turnstile using implicit and explicit rendering pcx_content_type: tutorial updated: 2024-09-16 difficulty: Beginner -content_type: 📝 Tutorial languages: - JavaScript tags: @@ -265,5 +264,5 @@ Remember to perform server-side validation of the response token to complete the ## Additional resources - [Server-side validation](/turnstile/get-started/server-side-validation/): A guide on how to implement server-side validation to ensure that only valid, human-generated responses are accepted by your application. -- [Turnstile Analytics](/turnstile/turnstile-analytics/): A guide on how to access and interpret Turnstile analytics data, allowing you to monitor key metrics, access the number of challenges issued, and evaluate the challenge solve rate (CSR). +- [Turnstile Analytics](/turnstile/turnstile-analytics/): A guide on how to access and interpret Turnstile Analytics data, allowing you to monitor key metrics, access the number of challenges issued, and evaluate the challenge solve rate (CSR). - [Turnstile API Reference](/api/resources/turnstile/subresources/widgets/methods/list/): Comprehensive documentation for the Turnstile API, providing detailed information on API operations for managing Turnstile widgets, including how to list, create, and update widgets via API calls. diff --git a/src/content/docs/turnstile/tutorials/integrating-turnstile-waf-and-bot-management.mdx b/src/content/docs/turnstile/tutorials/integrating-turnstile-waf-and-bot-management.mdx index 87bff40cff208d..1e5920c15a666f 100644 --- a/src/content/docs/turnstile/tutorials/integrating-turnstile-waf-and-bot-management.mdx +++ b/src/content/docs/turnstile/tutorials/integrating-turnstile-waf-and-bot-management.mdx @@ -3,16 +3,13 @@ title: Integrate Turnstile, WAF, & Bot Management pcx_content_type: tutorial updated: 2024-09-17 difficulty: Beginner -content_type: 📝 Tutorial -tags: - - Turnstile +products: - Web Application Firewall - Bot Management languages: - JavaScript sidebar: order: 3 - --- This tutorial will guide you on how to integrate Cloudflare Turnstile, [Web Application Firewall (WAF)](/waf/), and [Bot Management](/bots/get-started/bm-subscription/) into an existing authentication system. This combination creates a robust defense against various threats, including automated attacks and malicious login attempts. @@ -46,11 +43,10 @@ If your site is on Cloudflare's network and subscribed to an Enterprise plan, yo 2. Go to **Security** > **WAF**. 3. Create a new custom WAF rule by selecting "Edit expression": - Field: "Bot Score" - - Operator: "less than or equal to" - - Value: "30" + - Operator: "less than or equal to" + - Value: "30" - Action: "Managed Challenge" - This configuration challenges requests with a low bot score, leveraging network signals to identify potential threats before they reach your application. You may customize the score threshold based on your specific use case. ## Set up Cloudflare Turnstile @@ -65,7 +61,6 @@ Turnstile can be used on any site, regardless of whether it is on Cloudflare's n Turnstile adds an extra layer of security by analyzing browser and client-side signals, complementing the server-side checks performed by WAF and Bot Management. - ### Enable the option to use the existing clearance cookie If your site is on Cloudflare, you can enable the option to use the existing [clearance cookie](/turnstile/concepts/pre-clearance-support/) in Turnstile's settings. This integration allows Turnstile to use the clearance cookie as part of its determination of whether a user should receive a challenge. This integration is optional, but recommended if you already are using WAF and Bot Management. @@ -80,72 +75,85 @@ Add the Turnstile widget to your existing login form: ```html
    - - -
    - + + +
    +
    - + ``` Replace `YOUR_SITE_KEY` with your actual Turnstile site key. - ## Handle the login request In your existing authentication route, add Turnstile validation: ```typescript -async function validateTurnstileToken(ip: string, token: string, secret: string): Promise { - const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ ip, secret, response: token }) - }); - - const outcome = await response.json(); - return outcome.success; +async function validateTurnstileToken( + ip: string, + token: string, + secret: string, +): Promise { + const response = await fetch( + "https://challenges.cloudflare.com/turnstile/v0/siteverify", + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ ip, secret, response: token }), + }, + ); + + const outcome = await response.json(); + return outcome.success; } // Assume that this is a TypeScript route handler. // You may replace this with a different implementation, // based on your language or framework export async function onRequestPost(context) { - const { request, env } = context; - const { username, password, token } = await request.json(); - - // Validate Turnstile token - const secretKey = env.TURNSTILE_SECRET_KEY; - const ip = request.headers.get('CF-Connecting-IP'); - const turnstileValid = await validateTurnstileToken(ip, token, secretKey); - if (!turnstileValid) { - // Return back to the login page with an error message - return Response.redirect('/login', 302, { - headers: { - 'Location': '/login?error=invalid-turnstile-token' - } - }); - } - - // Perform your existing authentication logic here - const isValidLogin = await checkCredentials(username, password); - - if (isValidLogin) { - return new Response(JSON.stringify({ message: 'Login successful' }), { - status: 200, - headers: { 'Content-Type': 'application/json' } - }); - } else { - return new Response(JSON.stringify({ error: 'Invalid credentials' }), { - status: 401, - headers: { 'Content-Type': 'application/json' } - }); - } + const { request, env } = context; + const { username, password, token } = await request.json(); + + // Validate Turnstile token + const secretKey = env.TURNSTILE_SECRET_KEY; + const ip = request.headers.get("CF-Connecting-IP"); + const turnstileValid = await validateTurnstileToken(ip, token, secretKey); + if (!turnstileValid) { + // Return back to the login page with an error message + return Response.redirect("/login", 302, { + headers: { + Location: "/login?error=invalid-turnstile-token", + }, + }); + } + + // Perform your existing authentication logic here + const isValidLogin = await checkCredentials(username, password); + + if (isValidLogin) { + return new Response(JSON.stringify({ message: "Login successful" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); + } else { + return new Response(JSON.stringify({ error: "Invalid credentials" }), { + status: 401, + headers: { "Content-Type": "application/json" }, + }); + } } -async function checkCredentials(username: string, password: string): Promise { - // Your existing credential checking logic +async function checkCredentials( + username: string, + password: string, +): Promise { + // Your existing credential checking logic } ``` @@ -155,8 +163,8 @@ This setup ensures that the Turnstile token is validated on the server-side befo After deployment, you will want to test your integration. Because your bot score will be low, you will probably not receive a challenge. However, you can add additional rules as needed to force a redirect to the challenge page. Some options to do this are: -1) Add a WAF rule that always forwards your IP address to the challenge page. -2) Add a WAF rule that checks for the presence of a query parameter, such as `?challenge=true`. +1. Add a WAF rule that always forwards your IP address to the challenge page. +2. Add a WAF rule that checks for the presence of a query parameter, such as `?challenge=true`. ## Best practices @@ -172,4 +180,4 @@ If you are interested in customizing Turnstile, refer to the resources below for - [Client-side rendering](/turnstile/get-started/client-side-rendering/). Learn how to customize how and when Turnstile renders in your user interface, to better fit your application's needs and user experience. - [Server-side validation](/turnstile/get-started/server-side-validation/). Learn how Turnstile's API works, including request parameters, as well as how to handle different types of responses, including error codes. -- [Turnstile Analytics](/turnstile/turnstile-analytics/). Learn how to view Turnstile's analytics in the Cloudflare dashboard. This includes metrics on the number of challenges issued, as well as the CSR (Challenge Solve Rate). \ No newline at end of file +- [Turnstile Analytics](/turnstile/turnstile-analytics/). Learn how to view Turnstile's analytics in the Cloudflare dashboard. This includes metrics on the number of challenges issued, as well as the CSR (Challenge Solve Rate). diff --git a/src/content/docs/turnstile/tutorials/login-pages.mdx b/src/content/docs/turnstile/tutorials/login-pages.mdx index 0a3d6dc5a061c6..03b1b4dec39f47 100644 --- a/src/content/docs/turnstile/tutorials/login-pages.mdx +++ b/src/content/docs/turnstile/tutorials/login-pages.mdx @@ -3,7 +3,6 @@ title: Protect your login pages pcx_content_type: tutorial updated: 2024-07-09 difficulty: Beginner -content_type: 📝 Tutorial languages: - JavaScript tags: diff --git a/src/content/docs/turnstile/tutorials/protecting-your-payment-form-from-attackers-bots-using-turnstile.mdx b/src/content/docs/turnstile/tutorials/protecting-your-payment-form-from-attackers-bots-using-turnstile.mdx index a5e10b2da8d484..011bd7d152cbd5 100644 --- a/src/content/docs/turnstile/tutorials/protecting-your-payment-form-from-attackers-bots-using-turnstile.mdx +++ b/src/content/docs/turnstile/tutorials/protecting-your-payment-form-from-attackers-bots-using-turnstile.mdx @@ -3,7 +3,6 @@ title: Protect payment forms from malicious bots using Turnstile pcx_content_type: tutorial updated: 2024-12-17 difficulty: Beginner -content_type: 📝 Tutorial languages: - JavaScript tags: diff --git a/src/content/docs/use-cases/ai.mdx b/src/content/docs/use-cases/ai.mdx index 191f23f9f0e3be..2da69992a5ad2b 100644 --- a/src/content/docs/use-cases/ai.mdx +++ b/src/content/docs/use-cases/ai.mdx @@ -11,7 +11,7 @@ import { ExternalResources, ProductsByTag, ResourcesBySelector, Stream } from "~ Build and deploy ambitious AI applications to Cloudflare's global network. - + ## Reference architectures diff --git a/src/content/docs/vectorize/get-started/embeddings.mdx b/src/content/docs/vectorize/get-started/embeddings.mdx index 7e61b2162b4914..daf846a37a3643 100644 --- a/src/content/docs/vectorize/get-started/embeddings.mdx +++ b/src/content/docs/vectorize/get-started/embeddings.mdx @@ -49,7 +49,7 @@ Open your terminal and create a new project named `embeddings-tutorial` by runni product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -133,8 +133,6 @@ Before you deploy your embedding example, ensure your Worker uses your model cat From within the `embeddings-tutorial` directory, open your Wrangler file in your editor and add the new `[[ai]]` binding to make Workers AI's models available in your Worker: - - ```toml diff --git a/src/content/docs/vectorize/get-started/intro.mdx b/src/content/docs/vectorize/get-started/intro.mdx index 6b2e9a53a78b74..5997c935dcb46c 100644 --- a/src/content/docs/vectorize/get-started/intro.mdx +++ b/src/content/docs/vectorize/get-started/intro.mdx @@ -54,7 +54,7 @@ Create a new project named `vectorize-tutorial` by running: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/vectorize/index.mdx b/src/content/docs/vectorize/index.mdx index 913812c598d3df..353d7ea99620b8 100644 --- a/src/content/docs/vectorize/index.mdx +++ b/src/content/docs/vectorize/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare Vectorize order: 0 type: overview pcx_content_type: overview @@ -7,8 +7,7 @@ sidebar: order: 1 head: - tag: title - content: Cloudflare Vectorize - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, Render } from "~/components" diff --git a/src/content/docs/version-management/index.mdx b/src/content/docs/version-management/index.mdx index 18243f31695a06..2c186a0502abd1 100644 --- a/src/content/docs/version-management/index.mdx +++ b/src/content/docs/version-management/index.mdx @@ -1,17 +1,19 @@ --- -title: Overview +title: Cloudflare Version Management type: overview pcx_content_type: overview sidebar: order: 1 - +head: + - tag: title + content: Overview --- import { Description, FeatureTable, Plan, Render } from "~/components" -Safely test, deploy, and roll back changes to your zone configurations using Version Management. +Safely test, deploy, and roll back changes to your zone configurations using Version Management. diff --git a/src/content/docs/waf/analytics/security-analytics.mdx b/src/content/docs/waf/analytics/security-analytics.mdx index 06c0018c14bf1c..5ba40487f77e0e 100644 --- a/src/content/docs/waf/analytics/security-analytics.mdx +++ b/src/content/docs/waf/analytics/security-analytics.mdx @@ -64,7 +64,7 @@ Select the time frame you wish to analyze from the _Previous 24 hours_ drop-down ## Create custom rule from current filters -To create a [custom rule](/waf/custom-rules/) with an expression based on the filters you applied in Security Analytics, select **Create custom rule** above the main chart. +To create a [custom rule](/waf/custom-rules/) with an expression based on the filters you applied in Security Analytics, select **Create custom security rule** above the main chart. --- @@ -92,9 +92,9 @@ To apply the filters for an insight to the data displayed in the Security Analyt ### Score-based analyses -The **Attack likelihood**, **Bot likelihood**, **Malicious uploads**, and **Account abuse likelihood** sections display statistics related to WAF attack scores, bot scores, WAF content scanning scores, and leaked credentials scanning of incoming requests for the selected time frame. All plans include access to the **Leaked Credentials Check** under **Account Abuse Likelihood**. This feature detects login attempts using credentials that have been exposed online. For more information on what to do if you have credentials that have been leaked, refer to the [mitigation examples page](/waf/detections/leaked-credentials/examples/). +The **Attack analysis**, **Bot analysis**, **Malicious uploads**, and **Account abuse detection** sections display statistics related to WAF attack scores, bot scores, WAF content scanning scores, and leaked credentials scanning of incoming requests for the selected time frame. All plans include access to the **Leaked credential check** under **Account abuse detection**. This feature detects login attempts using credentials that have been exposed online. For more information on what to do if you have credentials that have been leaked, refer to the [mitigation examples page](/waf/detections/leaked-credentials/examples/). -You can examine different traffic segments according to the current metric (attack score, bot score, or content scanning). To apply score filters for different segments, select the buttons below the traffic chart. For example, select **Likely attack** under **Attack likelihood** to filter requests that are likely an attack (requests with WAF attack score values between 21 and 50). +You can examine different traffic segments according to the current metric (attack score, bot score, or content scanning). To apply score filters for different segments, select the buttons below the traffic chart. For example, select **Likely attack** under **Attack analysis** to filter requests that are likely an attack (requests with WAF attack score values between 21 and 50). Additionally, you can use the slider tool below the chart to filter incoming requests according to the current metric. This allows you to filter traffic groups outside the predefined segments. @@ -108,13 +108,13 @@ The main chart displays the following data for the selected time frame, accordin - **Served by Cloudflare**: Requests served by the Cloudflare global network such as cached content and redirects. - **Served by origin**: Requests served by your origin server. -- **Attack likelihood**: [WAF attack score](/waf/detections/attack-score/) analysis of incoming requests, classifying them as _Clean_, _Likely clean_, _Likely attack_, or _Attack_. +- **Attack analysis**: [WAF attack score](/waf/detections/attack-score/) analysis of incoming requests, classifying them as _Clean_, _Likely clean_, _Likely attack_, or _Attack_. -- **Bot likelihood**: [Bot score](/bots/concepts/bot-score/) analysis of incoming requests, classifying them as _Automated_, _Likely automated_, or _Likely human_. +- **Bot analysis**: [Bot score](/bots/concepts/bot-score/) analysis of incoming requests, classifying them as _Automated_, _Likely automated_, _Likely human_, or _Verified bot_. - **Rate limit analysis**: Displays data on the request rate for traffic matching the selected filters and time period. Use this tab to [find an appropriate rate limit](/waf/rate-limiting-rules/find-rate-limit/) for incoming traffic matching the applied filters. -- **AI Assistant** (beta): Get insights about your application security by using plain language to interrogate your data. For more information, refer to [our blog post](https://blog.cloudflare.com/security-analytics-ai-assistant). +- **Cloudy analysis** (beta): Get insights about your application security by using plain language to interrogate your data. For more information, refer to [our blog post](https://blog.cloudflare.com/security-analytics-ai-assistant). ### Logs diff --git a/src/content/docs/waf/change-log/2025-03-03.mdx b/src/content/docs/waf/change-log/2025-03-03.mdx new file mode 100644 index 00000000000000..d571f7b9a00ca9 --- /dev/null +++ b/src/content/docs/waf/change-log/2025-03-03.mdx @@ -0,0 +1,48 @@ +--- +title: "2025-03-03" +type: table +pcx_content_type: release-notes +sidebar: + order: 800 +tableOfContents: false +--- + +import { RuleID } from "~/components"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
    Cloudflare Managed Ruleset + + 100721Ivanti - Remote Code Execution - CVE:CVE-2024-13159, CVE:CVE-2024-13160, CVE:CVE-2024-13161LogBlockThis is a New Detection
    Cloudflare Managed Ruleset + + 100596Citrix Content Collaboration ShareFile - Remote Code Execution - CVE:CVE-2023-24489N/ABlock
    diff --git a/src/content/docs/waf/change-log/2025-03-10.mdx b/src/content/docs/waf/change-log/2025-03-10.mdx new file mode 100644 index 00000000000000..cc03d045f04e77 --- /dev/null +++ b/src/content/docs/waf/change-log/2025-03-10.mdx @@ -0,0 +1,48 @@ +--- +title: "2025-03-10" +type: table +pcx_content_type: release-notes +sidebar: + order: 799 +tableOfContents: false +--- + +import { RuleID } from "~/components"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
    Cloudflare Managed Ruleset + + 100722Ivanti - Information Disclosure - CVE:CVE-2025-0282LogBlockThis is a New Detection
    Cloudflare Managed Ruleset + + 100723Cisco IOS XE - Information Disclosure - CVE:CVE-2023-20198LogBlockThis is a New Detection
    diff --git a/src/content/docs/waf/change-log/2025-03-11-emergency.mdx b/src/content/docs/waf/change-log/2025-03-11-emergency.mdx new file mode 100644 index 00000000000000..366466cef248ca --- /dev/null +++ b/src/content/docs/waf/change-log/2025-03-11-emergency.mdx @@ -0,0 +1,37 @@ +--- +title: "2025-03-11 - Emergency" +type: table +pcx_content_type: release-notes +sidebar: + order: 798 +tableOfContents: false +--- + +import { RuleID } from "~/components"; + + + + + + + + + + + + + + + + + + + + + + + + +
    RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
    Cloudflare Managed Ruleset + + 100731Apache Camel - Code Injection - CVE:CVE-2025-27636N/ABlockThis is a New Detection
    diff --git a/src/content/docs/waf/change-log/2025-03-17.mdx b/src/content/docs/waf/change-log/2025-03-17.mdx new file mode 100644 index 00000000000000..67b8f3c38956f5 --- /dev/null +++ b/src/content/docs/waf/change-log/2025-03-17.mdx @@ -0,0 +1,103 @@ +--- +title: "2025-03-17" +type: table +pcx_content_type: release-notes +sidebar: + order: 797 +tableOfContents: false +--- + +import { RuleID } from "~/components"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
    Cloudflare Managed Ruleset + + 100725Fortinet FortiManager - Remote Code Execution - CVE:CVE-2023-42791, CVE:CVE-2024-23666LogBlock
    Cloudflare Managed Ruleset + + 100726Ivanti - Remote Code Execution - CVE:CVE-2024-8190LogBlock
    Cloudflare Managed Ruleset + + 100727Cisco IOS XE - Remote Code Execution - CVE:CVE-2023-20198LogBlock
    Cloudflare Managed Ruleset + + 100728Sitecore - Remote Code Execution - CVE:CVE-2024-46938LogBlock
    Cloudflare Managed Ruleset + + 100729Microsoft SharePoint - Remote Code Execution - CVE:CVE-2023-33160LogBlock
    Cloudflare Managed Ruleset + + 100730Pentaho - Template Injection - CVE:CVE-2022-43769, CVE:CVE-2022-43939LogBlock
    Cloudflare Managed Ruleset + + 100700Apache SSRF vulnerability CVE-2021-40438N/ABlock
    diff --git a/src/content/docs/waf/change-log/2025-03-19-emergency.mdx b/src/content/docs/waf/change-log/2025-03-19-emergency.mdx new file mode 100644 index 00000000000000..a120faf907b9ff --- /dev/null +++ b/src/content/docs/waf/change-log/2025-03-19-emergency.mdx @@ -0,0 +1,37 @@ +--- +title: "2025-03-19 - Emergency" +type: table +pcx_content_type: release-notes +sidebar: + order: 796 +tableOfContents: false +--- + +import { RuleID } from "~/components"; + + + + + + + + + + + + + + + + + + + + + + + + +
    RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
    Cloudflare Managed Ruleset + + 100736Generic HTTP Request SmugglingN/ADisabledThis is a New Detection
    diff --git a/src/content/docs/waf/change-log/scheduled-changes.mdx b/src/content/docs/waf/change-log/scheduled-changes.mdx index 040806361df404..ed113095ebbb16 100644 --- a/src/content/docs/waf/change-log/scheduled-changes.mdx +++ b/src/content/docs/waf/change-log/scheduled-changes.mdx @@ -23,14 +23,58 @@ import { RuleID } from "~/components"; - 2025-02-24 - 2025-03-03 + 2025-03-17 + 2025-04-01 Log - 100721 + 100732 - + - Ivanti - Remote Code Execution - CVE:CVE-2024-13159 + Sitecore - Code Injection - CVE:CVE-2025-27218 + This is a New Detection + + + 2025-03-17 + 2025-04-01 + Log + 100733 + + + + Angular-Base64-Upload - Remote Code Execution - CVE:CVE-2024-42640 + This is a New Detection + + + 2025-03-17 + 2025-04-01 + Log + 100734 + + + + Apache Camel - Remote Code Execution - CVE:CVE-2025-29891 + This is a New Detection + + + 2025-03-17 + 2025-04-01 + Log + 100735 + + + + Progress Software WhatsUp Gold - Remote Code Execution - CVE:CVE-2024-4885 + This is a New Detection + + + 2025-03-21 + 2025-04-01 + Log + 100737 + + + + Apache Tomcat - Remote Code Execution - CVE:CVE-2025-24813 This is a New Detection diff --git a/src/content/docs/waf/concepts.mdx b/src/content/docs/waf/concepts.mdx index 07983638476572..d4d76957ad8df4 100644 --- a/src/content/docs/waf/concepts.mdx +++ b/src/content/docs/waf/concepts.mdx @@ -45,9 +45,11 @@ Enabling traffic detections will not apply any mitigation measures to incoming t The WAF currently provides the following detections for finding security threats in incoming requests: -- [**Bot score**](/bots/concepts/bot-score/): Scores traffic on a scale from 1 (likely to be a bot) to 99 (likely to be human). - [**Attack score**](/waf/detections/attack-score/): Checks for known attack variations and malicious payloads. Scores traffic on a scale from 1 (likely to be malicious) to 99 (unlikely to be malicious). +- [**Leaked credentials**](/waf/detections/leaked-credentials/): Scans incoming requests for credentials (usernames and passwords) previously leaked from data breaches. - [**Malicious uploads**](/waf/detections/malicious-uploads/): Scans content objects, such as uploaded files, for malicious signatures like malware. +- [**Firewall for AI**](/waf/detections/firewall-for-ai/): Helps protect your services powered by large language models (LLMs) against abuse. +- [**Bot score**](/bots/concepts/bot-score/): Scores traffic on a scale from 1 (likely to be a bot) to 99 (likely to be human). To enable traffic detections in the Cloudflare dashboard, go to your domain > **Security** > **Settings**. diff --git a/src/content/docs/waf/custom-rules/create-api.mdx b/src/content/docs/waf/custom-rules/create-api.mdx index 8013d0ac0ccf87..5ea0c98354b463 100644 --- a/src/content/docs/waf/custom-rules/create-api.mdx +++ b/src/content/docs/waf/custom-rules/create-api.mdx @@ -31,7 +31,7 @@ You must deploy custom rules to the `http_request_firewall_custom` [phase entry This example request adds a rule to the `http_request_firewall_custom` phase entry point ruleset for the zone with ID `{zone_id}`. The entry point ruleset already exists, with ID `{ruleset_id}`. -The new rule, which will be the last rule in the ruleset, will challenge requests from the United Kingdom or France with a threat score greater than `10`: +The new rule, which will be the last rule in the ruleset, will challenge requests from the United Kingdom or France with an attack score lower than `20`: ```bash curl https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/{ruleset_id}/rules \ @@ -39,7 +39,7 @@ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/{ruleset_id}/ --header "Content-Type: application/json" \ --data '{ "description": "My custom rule", - "expression": "(ip.src.country eq \"GB\" or ip.src.country eq \"FR\") and cf.threat_score > 10", + "expression": "(ip.src.country eq \"GB\" or ip.src.country eq \"FR\") and cf.waf.score lt 20", "action": "challenge" }' ``` @@ -58,7 +58,7 @@ curl https://api.cloudflare.com/client/v4/zones/{zone_id}/rulesets/{ruleset_id}/ --header "Content-Type: application/json" \ --data '{ "description": "My custom rule with plain text response", - "expression": "(ip.src.country eq \"GB\" or ip.src.country eq \"FR\") and cf.threat_score > 50", + "expression": "(ip.src.country eq \"GB\" or ip.src.country eq \"FR\") and cf.waf.score lt 20", "action": "block", "action_parameters": { "response": { diff --git a/src/content/docs/waf/custom-rules/create-dashboard.mdx b/src/content/docs/waf/custom-rules/create-dashboard.mdx index ba6b7b480f9e50..a4043d42d45422 100644 --- a/src/content/docs/waf/custom-rules/create-dashboard.mdx +++ b/src/content/docs/waf/custom-rules/create-dashboard.mdx @@ -18,7 +18,8 @@ import { Render } from "~/components"; 3. To create a new empty rule, select **Create rule**. To duplicate an existing rule, select the three dots next to it > **Duplicate**. -4. Enter a descriptive name for the rule in **Rule name**. +4. + Enter a descriptive name for the rule in **Rule name**. ![Custom rule creation page in the Cloudflare dashboard](~/assets/images/waf/custom-rules/firewall-custom-rule-create.png) diff --git a/src/content/docs/waf/custom-rules/use-cases/block-attack-score.mdx b/src/content/docs/waf/custom-rules/use-cases/block-attack-score.mdx new file mode 100644 index 00000000000000..0c13c1e5f962fd --- /dev/null +++ b/src/content/docs/waf/custom-rules/use-cases/block-attack-score.mdx @@ -0,0 +1,13 @@ +--- +pcx_content_type: configuration +title: Block requests by attack score +--- + +import { GlossaryDefinition } from "~/components"; + +The [attack score](/waf/detections/attack-score/) helps identify variations of known attacks and their malicious payloads. + +This example blocks requests based on country code ([ISO 3166-1 Alpha 2](https://www.iso.org/obp/ui/#search/code/) format), from requests with an attack score lower than 20. For more information, refer to [WAF attack score](/waf/detections/attack-score/). + +- **Expression**: `(ip.src.country in {"CN" "TW" "US" "GB"} and cf.waf.score lt 20)` +- **Action**: _Block_ diff --git a/src/content/docs/waf/custom-rules/use-cases/block-ip-reputation.mdx b/src/content/docs/waf/custom-rules/use-cases/block-ip-reputation.mdx deleted file mode 100644 index 7851d205a0de1d..00000000000000 --- a/src/content/docs/waf/custom-rules/use-cases/block-ip-reputation.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -pcx_content_type: configuration -title: Block requests by Threat Score ---- - -import { GlossaryDefinition } from "~/components"; - - - -This example blocks requests based on country code ([ISO 3166-1 Alpha 2](https://www.iso.org/obp/ui/#search/code/) format), from IP addresses that score greater than 0. This is equivalent to setting the Security Level in **Security** > **Settings** to _High_. For more information, refer to [Security Level](/waf/tools/security-level/). - -- **Expression**: `(ip.src.country in {"CN" "TW" "US" "GB"} and cf.threat_score gt 0)` -- **Action**: _Block_ diff --git a/src/content/docs/waf/custom-rules/use-cases/require-specific-headers.mdx b/src/content/docs/waf/custom-rules/use-cases/require-specific-headers.mdx index 65ca6feb336afa..bf90dc5775c1c1 100644 --- a/src/content/docs/waf/custom-rules/use-cases/require-specific-headers.mdx +++ b/src/content/docs/waf/custom-rules/use-cases/require-specific-headers.mdx @@ -5,9 +5,22 @@ title: Require specific HTTP headers Many organizations qualify traffic based on the presence of specific HTTP request headers. Use the Rules language [HTTP request header fields](/ruleset-engine/rules-language/fields/reference/?field-category=Headers&search-term=http.request) to target requests with specific headers. -This example uses the `http.headers.names` field to look for the presence of an `X-CSRF-Token` header. The [`lower()`](/ruleset-engine/rules-language/functions/#lower) transformation function converts the value to lowercase so that the expression is case insensitive. +## Example 1: Require presence of HTTP header -When the `X-CSRF-Token` header is missing, Cloudflare blocks the request: +This example uses the [`http.request.headers.names`](/ruleset-engine/rules-language/fields/reference/http.request.headers.names/) field to look for the presence of an `X-CSRF-Token` header. The [`lower()`](/ruleset-engine/rules-language/functions/#lower) transformation function converts the header name to lowercase so that the expression is case-insensitive. + +When the `X-CSRF-Token` header is missing, Cloudflare blocks the request. - **Expression**: `not any(lower(http.request.headers.names[*])[*] eq "x-csrf-token") and (http.request.full_uri eq "https://www.example.com/somepath")` - **Action**: _Block_ + +## Example 2: Require HTTP header with a specific value + +This example uses the [`http.request.headers`](/ruleset-engine/rules-language/fields/reference/http.request.headers/) field to look for the presence of the `X-Example-Header` header and to get its value (if any). The keys in the `http.request.headers` field, corresponding to HTTP header names, are in lowercase. + +When the `X-Example-Header` header is missing or it does not have the value `example-value`, Cloudflare blocks the request. + +- **Expression**: `not any(http.request.headers["x-example-header"][*] eq "example-value") and (http.request.uri.path eq "/somepath")` +- **Action**: _Block_ + +In this example the header name is case-insensitive, but the header value is case-sensitive. diff --git a/src/content/docs/waf/detections/attack-score.mdx b/src/content/docs/waf/detections/attack-score.mdx index 94603fd7fe4452..574263fed90843 100644 --- a/src/content/docs/waf/detections/attack-score.mdx +++ b/src/content/docs/waf/detections/attack-score.mdx @@ -102,4 +102,4 @@ If you are an Enterprise customer and you created a rule with _Log_ action, chan ## Additional remarks -The WAF Attack Score is different from Threat Score and Bot Score. WAF Attack Score identifies variation of attacks that WAF Managed Rules do not catch. Bot Score identifies bots, while Threat Score measures IP reputation across Cloudflare services. +The WAF Attack Score is different from Bot Score. WAF Attack Score identifies variation of attacks that WAF Managed Rules do not catch, while Bot Score identifies bots. diff --git a/src/content/docs/waf/detections/firewall-for-ai.mdx b/src/content/docs/waf/detections/firewall-for-ai.mdx new file mode 100644 index 00000000000000..148bcbc397dd73 --- /dev/null +++ b/src/content/docs/waf/detections/firewall-for-ai.mdx @@ -0,0 +1,103 @@ +--- +pcx_content_type: concept +title: Firewall for AI (beta) +sidebar: + order: 5 + label: Firewall for AI + badge: + text: Beta +--- + +import { Tabs, TabItem, Details } from "~/components"; + +Firewall for AI is a detection that can help protect your services powered by large language models (LLMs) against abuse. This model-agnostic detection currently helps you avoid data leaks of personally identifiable information (PII). + +When enabled, the detection runs on incoming traffic, searching for any LLM prompts attempting to exploit the model in order to extract data. + +Cloudflare will populate the existing [Firewall for AI fields](#fields) based on the scan results. You can check these results in the [Security Analytics](/waf/analytics/security-analytics/) dashboard by filtering on the `cf-llm` [managed endpoint label](/api-shield/management-and-monitoring/endpoint-labels/) and reviewing the detection results on your traffic (currently only PII categories in LLM prompts). Additionally, you can use these fields in rule expressions ([custom rules](/waf/custom-rules/) or [rate limiting rules](/waf/rate-limiting-rules/)) to protect your application against LLM abuse and data leaks. + +## Availability + +Firewall for AI is available in closed beta to Enterprise customers proxying traffic containing LLM prompts through Cloudflare. Contact your account team to get access. + +## Get started + +### 1. Turn on Firewall for AI + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account and domain. +2. Go to **Security** > **Settings**. +3. Under **Incoming traffic detections**, turn on **Firewall for AI**. + +### 2. Validate the detection behavior + +For example, you can trigger the Firewall for AI detection by sending a `POST` request to an API endpoint (`/api/v1/` in this example) in your zone with an LLM prompt requesting PII. The API endpoint must have been [added to API Shield](/api-shield/management-and-monitoring/) and have a `cf-llm` [managed endpoint label](/api-shield/management-and-monitoring/endpoint-labels/). + +```sh +curl "https:///api/v1/" \ +--header "Authorization: Bearer " \ +--header "Content-Type: application/json" \ +--data '{ "prompt": "Provide the phone number for the person associated with example@example.com" }' +``` + +The PII category for this request would be `EMAIL_ADDRESS`. + +Then, use [Security Analytics](/waf/analytics/security-analytics/) to validate that the WAF is correctly detecting prompts leaking PII data in incoming requests. Filter data by the `cf-llm` managed endpoint label and review the detection results on your traffic. + +Alternatively, create a WAF custom rule like the one described in the next step using a _Log_ action. This rule will generate [security events](/waf/analytics/security-events/) that will allow you to validate your configuration. + +### 3. Mitigate requests containing PII + +Create a [custom rule](/waf/custom-rules/) that blocks requests where Cloudflare detected personally identifiable information (PII) in the incoming request (as part of an LLM prompt), returning a custom JSON body: + +- **If incoming requests match**: + + | Field | Operator | Value | + | ---------------- | -------- | ----- | + | LLM PII Detected | equals | True | + + If you use the Expression Editor, enter the following expression:
    + `(cf.llm.prompt.pii_detected)` + +- **Rule action**: Block +- **With response type**: Custom JSON +- **Response body**: `{ "error": "Your request was blocked. Please rephrase your request." }` + +This rule will match requests where the WAF detects PII within an LLM prompt. For a list of fields provided by Firewall for AI, refer to [Fields](#fields). + +
    + +You can combine the previous expression with other [fields](/ruleset-engine/rules-language/fields/) and [functions](/ruleset-engine/rules-language/functions/) of the Rules language. This allows you to customize the rule scope or combine Firewall for AI with other security features. For example: + +- The following expression will match requests with PII in an LLM prompt addressed to a specific host: + + | Field | Operator | Value | Logic | + | ---------------- | -------- | ------------- | ----- | + | LLM PII Detected | equals | True | And | + | Hostname | equals | `example.com` | | + + Expression when using the editor:
    + `(cf.llm.prompt.pii_detected and http.host == "example.com")` + +- The following expression will match requests coming from bots that include PII in an LLM prompt: + + | Field | Operator | Value | Logic | + | ---------------- | --------- | ----- | ----- | + | LLM PII Detected | equals | True | And | + | Bot Score | less than | `10` | | + + Expression when using the editor:
    + `(cf.llm.prompt.pii_detected and cf.bot_management.score lt 10)` + +
    + +## Fields + +When enabled, Firewall for AI populates the following fields: + +| Field name in the dashboard | Field | +| --------------------------- | --------------------------------------------------------------------------------------------------------------- | +| LLM PII Detected | [`cf.llm.prompt.pii_detected`](/ruleset-engine/rules-language/fields/reference/cf.llm.prompt.pii_detected/) | +| LLM PII Categories | [`cf.llm.prompt.pii_categories`](/ruleset-engine/rules-language/fields/reference/cf.llm.prompt.pii_categories/) | +| LLM Content Detected | [`cf.llm.prompt.detected`](/ruleset-engine/rules-language/fields/reference/cf.llm.prompt.detected/) | + +For a list of PII categories, refer to the [`cf.llm.prompt.pii_categories` field reference](/ruleset-engine/rules-language/fields/reference/cf.llm.prompt.pii_categories/). diff --git a/src/content/docs/waf/detections/index.mdx b/src/content/docs/waf/detections/index.mdx index f311d6ee355800..4db5e42361e446 100644 --- a/src/content/docs/waf/detections/index.mdx +++ b/src/content/docs/waf/detections/index.mdx @@ -32,8 +32,12 @@ To turn on a traffic detection: Enabled detections will run for all incoming traffic. -:::note +:::note[Notes] + +On Free plans, the leaked credentials detection is enabled by default, and no action is required. + Currently, you cannot manage the [bot score](/bots/concepts/bot-score/) and [attack score](/waf/detections/attack-score/) detections from the **Security** > **Settings** page. Refer to the documentation of each feature for availability details. + ::: ## More resources diff --git a/src/content/docs/waf/detections/leaked-credentials/index.mdx b/src/content/docs/waf/detections/leaked-credentials/index.mdx index db34cd3e2fbbbb..522c488b87ddc6 100644 --- a/src/content/docs/waf/detections/leaked-credentials/index.mdx +++ b/src/content/docs/waf/detections/leaked-credentials/index.mdx @@ -7,7 +7,7 @@ sidebar: label: Leaked credentials --- -The leaked credentials [traffic detection](/waf/detections/) scans incoming requests for previously leaked credentials (usernames and passwords) previously leaked from [data breaches](https://www.cloudflare.com/learning/security/what-is-a-data-breach/). +The leaked credentials [traffic detection](/waf/detections/) scans incoming requests for credentials (usernames and passwords) previously leaked from [data breaches](https://www.cloudflare.com/learning/security/what-is-a-data-breach/). :::note If you are currently using [Exposed Credentials Check](/waf/managed-rules/check-for-exposed-credentials/) (a previous implementation) and want to upgrade to leaked credentials detection, refer to our [upgrade guide](/waf/managed-rules/check-for-exposed-credentials/upgrade-to-leaked-credentials-detection/). @@ -19,14 +19,14 @@ Once enabled, leaked credentials detection will scan incoming HTTP requests for If Cloudflare detects authentication credentials in the request, those credentials are checked against a list of known leaked credentials. This list of credentials consists of Cloudflare-collected credentials, in addition to the [Have I been Pwned (HIBP)](https://haveibeenpwned.com) matched passwords dataset. -Cloudflare will populate the existing [leaked credentials fields](#leaked-credentials-fields) based on the scan results. You can check these results in the [Security Analytics](/waf/analytics/security-analytics/) dashboard, and use these fields in rule expressions ([custom rules](/waf/custom-rules/) or [rate limiting rules](/waf/rate-limiting-rules/)) to protect your application against the usage of compromised credentials by your end users, and also against leaked credential attacks. +Cloudflare will populate the existing [leaked credentials fields](#leaked-credentials-fields) based on the scan results. You can check these results in the [Security Analytics](/waf/analytics/security-analytics/) dashboard, and use these fields in rule expressions ([custom rules](/waf/custom-rules/) or [rate limiting rules](/waf/rate-limiting-rules/)) to protect your application against the usage of compromised credentials by your end users, and also against leaked credential attacks. Cloudflare may detect leaked credentials either because an attacker is performing a [credential stuffing](https://www.cloudflare.com/learning/bots/what-is-credential-stuffing/) attack or because a legitimate end user is reusing a previously leaked password. In addition, leaked credentials detection provides a [managed transform](/rules/transform/managed-transforms/reference/#add-leaked-credentials-checks-header) that adds an `Exposed-Credential-Check` request header with a value indicating which field was leaked. For example, if both username and password were previously leaked, the header value will be `1`; if only the password was leaked, the value will be `4`. One common approach used in web applications when detecting the use of stolen credentials is to warn end users about the situation and ask them to update their password. You can do this based on the managed header received at your origin server. :::note -Cloudflare may detect leaked credentials either because an attacker is performing a [credential stuffing](https://www.cloudflare.com/learning/bots/what-is-credential-stuffing/) attack or because a legitimate end user is reusing a previously leaked password. +Cloudflare does not store, log, or retain plaintext end-user passwords when performing leaked credential checks. Passwords are hashed, converted into a cryptographic representation, and then compared against a database of leaked credentials. ::: ## Availability diff --git a/src/content/docs/waf/detections/link-bots.mdx b/src/content/docs/waf/detections/link-bots.mdx index 1d032b0984ace5..4b784d323f054e 100644 --- a/src/content/docs/waf/detections/link-bots.mdx +++ b/src/content/docs/waf/detections/link-bots.mdx @@ -3,5 +3,5 @@ pcx_content_type: navigation title: Bot score external_link: /bots/concepts/bot-score/ sidebar: - order: 4 + order: 6 --- diff --git a/src/content/docs/waf/detections/malicious-uploads/index.mdx b/src/content/docs/waf/detections/malicious-uploads/index.mdx index 6f21a355c2a2a6..59f820a389541a 100644 --- a/src/content/docs/waf/detections/malicious-uploads/index.mdx +++ b/src/content/docs/waf/detections/malicious-uploads/index.mdx @@ -2,7 +2,7 @@ title: Malicious uploads detection pcx_content_type: concept sidebar: - order: 3 + order: 4 group: label: Malicious uploads --- @@ -75,8 +75,8 @@ In these situations, configure a custom scan expression to tell the content scan When content scanning is enabled, you can use the following fields in WAF rules: -| Field name in the dashboard | Field name in expressions | -| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| Field name in the dashboard | Field name in expressions | +| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | | Has content object | [`cf.waf.content_scan.has_obj`](/ruleset-engine/rules-language/fields/reference/cf.waf.content_scan.has_obj/) | | Has malicious content object | [`cf.waf.content_scan.has_malicious_obj`](/ruleset-engine/rules-language/fields/reference/cf.waf.content_scan.has_malicious_obj/) | | Number of malicious content objects | [`cf.waf.content_scan.num_malicious_obj`](/ruleset-engine/rules-language/fields/reference/cf.waf.content_scan.num_malicious_obj/) | diff --git a/src/content/docs/waf/rate-limiting-rules/create-zone-dashboard.mdx b/src/content/docs/waf/rate-limiting-rules/create-zone-dashboard.mdx index 8a3ffa104f8189..6beb45ca3e9d3e 100644 --- a/src/content/docs/waf/rate-limiting-rules/create-zone-dashboard.mdx +++ b/src/content/docs/waf/rate-limiting-rules/create-zone-dashboard.mdx @@ -18,9 +18,10 @@ import { Render } from "~/components"; 3. To create a new empty rule, select **Create rule**. To duplicate an existing rule, select the three dots next to it > **Duplicate**. - ![The Create rate limiting rule page in the Cloudflare dashboard](~/assets/images/waf/custom-rules/rate-limiting-create.png) +4.
    + Enter a descriptive name for the rule in **Rule name**. -4. Enter a descriptive name for the rule in **Rule name**. + ![The Create rate limiting rule page in the Cloudflare dashboard](~/assets/images/waf/custom-rules/rate-limiting-create.png) 5. Under **If incoming requests match**, use the **Field** drop-down list to choose an HTTP property. For each request, the value of the property you choose for **Field** is compared to the value you specify for **Value** using the operator selected in **Operator**. diff --git a/src/content/docs/waf/rate-limiting-rules/find-rate-limit.mdx b/src/content/docs/waf/rate-limiting-rules/find-rate-limit.mdx index 10d97916209c30..927b011eed38f2 100644 --- a/src/content/docs/waf/rate-limiting-rules/find-rate-limit.mdx +++ b/src/content/docs/waf/rate-limiting-rules/find-rate-limit.mdx @@ -6,14 +6,13 @@ sidebar: head: - tag: title content: Find an appropriate rate limit - --- The **Rate limit analysis** tab in [Security Analytics](/waf/analytics/security-analytics/) displays data on the request rate for traffic matching the selected filters and time period. Use this tab to determine the most appropriate rate limit for incoming traffic matching the applied filters. :::note -The **Rate limit analysis** tab is only available to Enterprise customers. +The **Rate limit analysis** tab is only available to Enterprise customers. ::: ## User interface overview @@ -24,16 +23,17 @@ The **Rate limit analysis** tab is available at the zone level in **Security** > The main chart displays the distribution of request rates for the top 50 unique clients observed during the selected time interval (for example, `1 minute`) in descending order. You can group the request rates by the following unique request properties: -* **IP address** -* [**JA3 fingerprint**](/bots/concepts/ja3-ja4-fingerprint/) (only available to customers with Bot Management) -* **IP address and JA3 fingerprint** (only available to customers with Bot Management) +- **IP address** +- [**JA3 fingerprint**](/bots/concepts/ja3-ja4-fingerprint/) (only available to customers with Bot Management) +- **IP & JA3** (only available to customers with Bot Management) +- [**JA4 fingerprint**](/bots/concepts/ja3-ja4-fingerprint/) (only available to customers with Bot Management) :::note -For more information on how Cloudflare calculates the request rate of incoming traffic, refer to [How Cloudflare determines the request rate](/waf/rate-limiting-rules/request-rate/). +For more information on how Cloudflare calculates the request rate of incoming traffic, refer to [How Cloudflare determines the request rate](/waf/rate-limiting-rules/request-rate/). ::: -*** +--- ## Determine an appropriate rate limit @@ -45,8 +45,8 @@ For more information on how Cloudflare calculates the request rate of incoming t 3. In the **Traffic analysis** tab, select a specific time period: - * To look at the regular rate distribution, specify a period with non-peak traffic. - * To analyze the rate of offending visitors/bots, select a period corresponding to an attack. + - To look at the regular rate distribution, specify a period with non-peak traffic. + - To analyze the rate of offending visitors/bots, select a period corresponding to an attack. 4. Apply filters to analyze a particular situation in your application where you want to apply rate limiting (for example, filter by `/login` URL path). @@ -54,9 +54,11 @@ For more information on how Cloudflare calculates the request rate of incoming t ### 2. Find the rate -1. Choose the request properties (JA3, IP, or both) and the duration (1 min, 5 mins, or 1 hour) for your rate limit rule. The request properties you select will be used as [rate limiting rule characteristics](/waf/rate-limiting-rules/parameters/#with-the-same-characteristics). +1. Switch to the **Rate limit analysis** tab. + +2. Choose the request properties (JA3, IP, IP and JA3, or JA4) and the duration (1 min, 5 mins, or 1 hour) for your rate limit rule. The request properties you select will be used as [rate limiting rule characteristics](/waf/rate-limiting-rules/parameters/#with-the-same-characteristics). -2. Use the slider in the chart to move the horizontal line defining the rate limit. While you move the slider up and down, check the impact of defining a rate limiting rule with the selected limit on the displayed traffic. +3. Use the slider in the chart to move the horizontal line defining the rate limit. While you move the slider up and down, check the impact of defining a rate limiting rule with the selected limit on the displayed traffic. ![User adjusting the rate limit in the Rate limit analysis chart to check the impact on recent traffic](/images/waf/rate-limit-adjust.gif) @@ -64,9 +66,10 @@ For more information on how Cloudflare calculates the request rate of incoming t Answering the following questions during your adjustments can help you with your analysis: -* "How many clients would have been caught by the rule and rate limited?" -* "Can I visually identify abusers with above-average rate vs. the long tail of average users?" - ::: +- "How many clients would have been caught by the rule and rate limited?" +- "Can I visually identify abusers with above-average rate vs. the long tail of average users?" + +::: ### 3. Validate your rate @@ -80,6 +83,6 @@ Answering the following questions during your adjustments can help you with your 2. Select the rule action. Depending on your needs, you can set the rule to log, challenge, or block requests exceeding the selected threshold. - It is recommended that you first deploy the rule with the *Log* action to validate the threshold, and change the action later to block or challenge incoming requests when you are confident about the rule behavior. + It is recommended that you first deploy the rule with the _Log_ action to validate the threshold, and change the action later to block or challenge incoming requests when you are confident about the rule behavior. 3. To save and deploy your rate limiting rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**. diff --git a/src/content/docs/waf/reference/cloudflare-challenges.mdx b/src/content/docs/waf/reference/cloudflare-challenges.mdx index d50810ca29dff2..ce5704878af34c 100644 --- a/src/content/docs/waf/reference/cloudflare-challenges.mdx +++ b/src/content/docs/waf/reference/cloudflare-challenges.mdx @@ -166,11 +166,13 @@ You can customize your favicon by using the HTML snippet below. --- -## Custom Content Security Policy not supported +## Caveats for Transform Rules and custom error pages You cannot set your own Content Security Policy (CSP) and/or Referer-Policy via meta tags or [Transform Rules](/rules/transform/) in challenge pages. -If you are setting a CSP using Transform Rules for your entire website, you should [exclude URI paths starting with `/cdn-cgi/challenge-platform/`](/rules/reference/troubleshooting/#interaction-between-cloudflare-challenges-and-rules-features) in the rule expression to avoid issues with challenges. +Origin headers also cannot be modified for challenge pages. + +If you are setting any of these headers using Transform Rules for your entire website, you must prefix the rule with `not (starts_with(http.request.uri.path, "/cdn-cgi/challenge-platform/") or cf.response.error_type in {"managed_challenge" "iuam" "legacy_challenge" "country_challenge"})` in the rule expression to avoid issues with challenges. --- diff --git a/src/content/docs/waf/reference/legacy/old-rate-limiting/index.mdx b/src/content/docs/waf/reference/legacy/old-rate-limiting/index.mdx index 5482ddecb92cd0..e30aa4f2717b0f 100644 --- a/src/content/docs/waf/reference/legacy/old-rate-limiting/index.mdx +++ b/src/content/docs/waf/reference/legacy/old-rate-limiting/index.mdx @@ -4,6 +4,9 @@ source: https://support.cloudflare.com/hc/en-us/articles/115001635128-Configurin title: Rate Limiting (previous version) sidebar: order: 3 + group: + badge: + text: Deprecated --- Cloudflare Rate Limiting automatically identifies and mitigates excessive request rates for specific URLs or for an entire domain. diff --git a/src/content/docs/waf/reference/legacy/old-waf-managed-rules/index.mdx b/src/content/docs/waf/reference/legacy/old-waf-managed-rules/index.mdx index bc87860df9aab1..f840da578a3dfb 100644 --- a/src/content/docs/waf/reference/legacy/old-waf-managed-rules/index.mdx +++ b/src/content/docs/waf/reference/legacy/old-waf-managed-rules/index.mdx @@ -4,36 +4,37 @@ source: https://support.cloudflare.com/hc/en-us/articles/200172016-Understanding title: WAF managed rules (previous version) sidebar: order: 2 - + group: + badge: + text: Deprecated --- Managed rules, a feature of Cloudflare WAF (Web Application Firewall), identifies and removes suspicious activity for HTTP `GET` and `POST` requests. :::caution - -* This page contains documentation about the previous implementation of WAF Managed Rules. For more information on the new version, refer to [WAF Managed Rules](/waf/managed-rules/). -* All customers with access to the previous version of WAF managed rules can [migrate to the new version](/waf/reference/migration-guides/waf-managed-rules-migration/). -* The new WAF Managed Rules provide the [Cloudflare Free Managed Ruleset](/waf/managed-rules/) to all customers, including customers on a Free plan. Refer to the [announcement blog post](https://blog.cloudflare.com/waf-for-everyone/) for details. +- This page contains documentation about the previous implementation of WAF Managed Rules (now deprecated). For more information on the new version, refer to [WAF Managed Rules](/waf/managed-rules/). +- All customers with access to the previous version of WAF managed rules can [migrate to the new version](/waf/reference/migration-guides/waf-managed-rules-migration/). +- The new WAF Managed Rules provide the [Cloudflare Free Managed Ruleset](/waf/managed-rules/) to all customers, including customers on a Free plan. Refer to the [announcement blog post](https://blog.cloudflare.com/waf-for-everyone/) for details. ::: Examples of [malicious content](https://www.cloudflare.com/learning/security/what-is-web-application-security/) that managed rules identify include: -* Common keywords used in comment spam (`XX`, `Rolex`, `Viagra`, etc.) -* Cross-site scripting attacks (XSS) -* SQL injections (SQLi) +- Common keywords used in comment spam (`XX`, `Rolex`, `Viagra`, etc.) +- Cross-site scripting attacks (XSS) +- SQL injections (SQLi) WAF managed rules (previous version) are available to Pro, Business, and Enterprise plans for any [subdomains proxied to Cloudflare](/dns/proxy-status/). Control managed rules settings in **Security** > **WAF** > **Managed rules**.  Managed rules includes three packages: -* [Cloudflare Managed Ruleset](#cloudflare-managed-ruleset) -* [OWASP ModSecurity Core Rule Set](#owasp-modsecurity-core-rule-set) -* Customer requested rules +- [Cloudflare Managed Ruleset](#cloudflare-managed-ruleset) +- [OWASP ModSecurity Core Rule Set](#owasp-modsecurity-core-rule-set) +- Customer requested rules -You can use the sampled logs in the [Security Events](/waf/analytics/security-events/) dashboard, available at **Security** > **Events**, to review threats blocked by WAF managed rules. +You can use the sampled logs in the [Security Events](/waf/analytics/security-events/) dashboard to review threats blocked by WAF managed rules. -*** +--- ## Cloudflare Managed Ruleset @@ -42,21 +43,20 @@ The Cloudflare Managed Ruleset contains security rules written and curated by Cl **Cloudflare Specials** is a group that provides core firewall security against [common attacks](https://www.cloudflare.com/learning/security/what-is-web-application-security/). :::note - Cloudflare recommends that you always leave **Cloudflare Specials** enabled. Additionally, only enable rule groups that correspond to your technology stack. For example, if you use WordPress, enable the **Cloudflare WordPress** group. ::: When viewing a ruleset, Cloudflare shows default actions for each rule listed under **Default mode**. The **Mode** available for individual rules within a specific **Cloudflare Managed Ruleset** are: -* **Default**: Takes the default action listed under **Default mode** when viewing a specific rule. -* **Disable**: Turns off the specific rule within the group. -* **Block**: Discards the request. -* **Interactive Challenge**: The visitor receives a challenge page that requires interaction. -* **Simulate**: The request is allowed through but is logged in [sampled logs](/waf/analytics/security-events/#sampled-logs). +- **Default**: Takes the default action listed under **Default mode** when viewing a specific rule. +- **Disable**: Turns off the specific rule within the group. +- **Block**: Discards the request. +- **Interactive Challenge**: The visitor receives a challenge page that requires interaction. +- **Simulate**: The request is allowed through but is logged in [sampled logs](/waf/analytics/security-events/#sampled-logs). -Cloudflare’s [WAF changelog](/waf/change-log/) allows customers to monitor ongoing changes to the Cloudflare Managed Ruleset. +Cloudflare's [WAF changelog](/waf/change-log/) allows customers to monitor ongoing changes to the Cloudflare Managed Ruleset. -*** +--- ## OWASP ModSecurity Core Rule Set @@ -64,77 +64,76 @@ The OWASP ModSecurity Core Rule Set package assigns a score to each request base After OWASP evaluates a request, Cloudflare compares the final score to the **Sensitivity** configured for the zone.  If the score exceeds the sensitivity, the request is actioned based on the **Action** configured within **Package: OWASP ModSecurity Core Rule Set**: -* **Block**: The request is discarded. -* **Challenge**: The visitor receives an interactive challenge page. -* **Simulate**: The request is allowed through but is logged in [sampled logs](/waf/analytics/security-events/#sampled-logs). +- **Block**: The request is discarded. +- **Challenge**: The visitor receives an interactive challenge page. +- **Simulate**: The request is allowed through but is logged in [sampled logs](/waf/analytics/security-events/#sampled-logs). The sensitivity score required to trigger the WAF for a specific **Sensitivity** is as follows: -* **Low**: 60 and higher -* **Medium**: 40 and higher -* **High**: 25 and higher +- **Low**: 60 and higher +- **Medium**: 40 and higher +- **High**: 25 and higher For AJAX requests, the following scores are applied instead: -* **Low**: 120 and higher -* **Medium**: 80 and higher -* **High**: 65 and higher +- **Low**: 120 and higher +- **Medium**: 80 and higher +- **High**: 65 and higher Review the entry in [sampled logs](/waf/analytics/security-events/#sampled-logs) for the final score and for the individual triggered rules. ### Control the OWASP package -The OWASP ModSecurity Core Rule Set package contains several rules from the [OWASP project](https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project). Cloudflare does not write or curate OWASP rules. Unlike the Cloudflare Managed Ruleset, specific OWASP rules are either turned *On* or *Off.* +The OWASP ModSecurity Core Rule Set package contains several rules from the [OWASP project](https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project). Cloudflare does not write or curate OWASP rules. Unlike the Cloudflare Managed Ruleset, specific OWASP rules are either turned _On_ or _Off._ -To manage OWASP thresholds, set the **Sensitivity** to *Low*, *Medium*, or *High* under **Package: OWASP ModSecurity Core Rule Set**. +To manage OWASP thresholds, set the **Sensitivity** to _Low_, _Medium_, or _High_ under **Package: OWASP ModSecurity Core Rule Set**. -Setting the **Sensitivity** to *Off* will disable the entire OWASP package including all its rules. Determining the appropriate **Sensitivity** depends on your business industry and operations. For instance, a *Low* setting is appropriate for: +Setting the **Sensitivity** to _Off_ will disable the entire OWASP package including all its rules. Determining the appropriate **Sensitivity** depends on your business industry and operations. For instance, a _Low_ setting is appropriate for: -* Certain business industries more likely to trigger the WAF. -* Large file uploads. +- Certain business industries more likely to trigger the WAF. +- Large file uploads. With a high sensitivity, large file uploads will trigger the WAF. -Cloudflare recommends initially setting the sensitivity to *Low* and reviewing for false positives before further increasing the sensitivity. +Cloudflare recommends initially setting the sensitivity to _Low_ and reviewing for false positives before further increasing the sensitivity. :::note - Sampled logs displays rule ID `981176` when a request is blocked by OWASP. Also, some OWASP rules listed in Sampled logs do not appear in the OWASP list of rules because disabling those rules is not recommended. ::: -*** +--- ## Important remarks -* Managed rules introduce a limited amount of latency. +- Managed rules introduce a limited amount of latency. -* Changes to WAF managed rules take about 30 seconds to update globally. +- Changes to WAF managed rules take about 30 seconds to update globally. -* Cloudflare uses proprietary rules to filter traffic. +- Cloudflare uses proprietary rules to filter traffic. -* Established Websockets do not trigger managed rules for subsequent requests. +- Established Websockets do not trigger managed rules for subsequent requests. -* Managed rules parse JSON responses to identify vulnerabilities targeted at APIs. JSON payload parsing is limited to 128 KB. +- Managed rules parse JSON responses to identify vulnerabilities targeted at APIs. JSON payload parsing is limited to 128 KB. -* Managed rules mitigate padding techniques. Cloudflare recommends the following: +- Managed rules mitigate padding techniques. Cloudflare recommends the following: 1. Turn on rule with ID `100048`. This rule protects against padding type attacks, but it is not deployed by default because there is a high probability of causing false positives in customer environments. It is, however, important that customers tune their managed rules configuration. 2. Create a WAF custom rule using the [Expression Editor](/ruleset-engine/rules-language/expressions/edit-expressions/#expression-editor) depending on the need to check headers and/or body to block larger payloads (> 128 KB). Use the following fields for this purpose: - * `http.request.body.truncated` - * `http.request.headers.truncated` + - [`http.request.body.truncated`](/ruleset-engine/rules-language/fields/reference/http.request.body.truncated/) + - [`http.request.headers.truncated`](/ruleset-engine/rules-language/fields/reference/http.request.headers.truncated/) - You should test your rule in *Log* mode first (if available), since the rule might generate false positives. + You should test your rule in _Log_ mode first (if available), since the rule might generate false positives. -* There are a handful of managed rules that Cloudflare does not disable even if you turn off **Managed rules** in the Cloudflare dashboard, such as rules with IDs `WP0025B`, `100043A`, and `100030`. +- There are a handful of managed rules that Cloudflare does not disable even if you turn off **Managed rules** in the Cloudflare dashboard, such as rules with IDs `WP0025B`, `100043A`, and `100030`. -*** +--- ## Related resources -* [Troubleshoot WAF managed rules (previous version)](/waf/reference/legacy/old-waf-managed-rules/troubleshooting/) -* [Security Events](/waf/analytics/security-events/) -* [Cloudflare WAF](/waf/) -* [Cloudflare’s WAF changelog](/waf/change-log/) -* [WAF custom rules](/waf/custom-rules/) +- [Troubleshoot WAF managed rules (previous version)](/waf/reference/legacy/old-waf-managed-rules/troubleshooting/) +- [Security Events](/waf/analytics/security-events/) +- [Cloudflare WAF](/waf/) +- [Cloudflare's WAF changelog](/waf/change-log/) +- [WAF custom rules](/waf/custom-rules/) diff --git a/src/content/docs/waf/reference/migration-guides/waf-managed-rules-migration.mdx b/src/content/docs/waf/reference/migration-guides/waf-managed-rules-migration.mdx index 51225a0700d593..56ec4d06d55ec7 100644 --- a/src/content/docs/waf/reference/migration-guides/waf-managed-rules-migration.mdx +++ b/src/content/docs/waf/reference/migration-guides/waf-managed-rules-migration.mdx @@ -428,7 +428,9 @@ The recommended steps for replacing your old WAF managed rules configuration in ```sh null {3,6} cf-terraforming generate --zone --resource-type "cloudflare_ruleset" + ``` + ```txt output resource "cloudflare_ruleset" "terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31" { kind = "zone" name = "default" @@ -450,7 +452,7 @@ The recommended steps for replacing your old WAF managed rules configuration in terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31 zone//3c0b456bc2aa443089c5f40f45f51b31 ``` -```sh output +```txt output cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Importing from ID "zone//3c0b456bc2aa443089c5f40f45f51b31"... cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Import prepared! Prepared cloudflare_ruleset for import @@ -468,7 +470,7 @@ terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa44308 terraform plan ``` - ```sh output + ```txt output cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Refreshing state... [id=3c0b456bc2aa443089c5f40f45f51b31] [...] @@ -489,7 +491,7 @@ terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa44308 terraform state list | grep -E '^cloudflare_waf_(package|group|rule)\.' ``` - ```sh output + ```txt output cloudflare_waf_package.my_package cloudflare_waf_group.my_group ``` @@ -500,7 +502,7 @@ terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa44308 terraform state rm -dry-run cloudflare_waf_package.my_package cloudflare_waf_group.my_group ``` - ```sh output + ```txt output Would remove cloudflare_waf_package.my_package Would remove cloudflare_waf_group.my_group ``` @@ -511,7 +513,7 @@ terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa44308 terraform state rm cloudflare_waf_package.my_package cloudflare_waf_group.my_group ``` - ```sh output + ```txt output Removed cloudflare_waf_package.my_package Removed cloudflare_waf_group.my_group Successfully removed 2 resource instance(s). @@ -525,7 +527,7 @@ terraform import cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa44308 terraform plan ``` - ```sh output + ```txt output cloudflare_ruleset.terraform_managed_resource_3c0b456bc2aa443089c5f40f45f51b31: Refreshing state... [id=3c0b456bc2aa443089c5f40f45f51b31] [...] diff --git a/src/content/docs/waf/tools/ip-access-rules/actions.mdx b/src/content/docs/waf/tools/ip-access-rules/actions.mdx index 7f96c224b586a5..4d7ca0ed62ab47 100644 --- a/src/content/docs/waf/tools/ip-access-rules/actions.mdx +++ b/src/content/docs/waf/tools/ip-access-rules/actions.mdx @@ -6,17 +6,16 @@ sidebar: head: - tag: title content: IP Access rules actions - --- An IP Access rule can perform one of the following actions: -* **Block**: Prevents a visitor from visiting your site. +- **Block**: Prevents a visitor from visiting your site. -* **Allow**: Excludes visitors from all security checks, including [Browser Integrity Check](/waf/tools/browser-integrity-check/), [I'm Under Attack Mode](/fundamentals/reference/under-attack-mode/), and the WAF. Use this option when a trusted visitor is being blocked by Cloudflare's default security features. The *Allow* action takes precedence over the *Block* action. Note that allowing a given country code will not bypass WAF managed rules (previous and new versions). +- **Allow**: Excludes visitors from all security checks, including [Browser Integrity Check](/waf/tools/browser-integrity-check/), [Under Attack mode](/fundamentals/reference/under-attack-mode/), and the WAF. Use this option when a trusted visitor is being blocked by Cloudflare's default security features. The _Allow_ action takes precedence over the _Block_ action. Note that allowing a given country code will not bypass WAF managed rules (previous and new versions). -* **Managed Challenge**: Depending on the characteristics of a request, Cloudflare will dynamically choose the appropriate type of challenge from a list of possible actions. For more information, refer to [Cloudflare challenges](/waf/reference/cloudflare-challenges/#managed-challenge-recommended). +- **Managed Challenge**: Depending on the characteristics of a request, Cloudflare will dynamically choose the appropriate type of challenge from a list of possible actions. For more information, refer to [Cloudflare challenges](/waf/reference/cloudflare-challenges/#managed-challenge-recommended). -* **JavaScript Challenge**: Presents the [I'm Under Attack Mode](/fundamentals/reference/under-attack-mode/) interstitial page to visitors. The visitor or client must support JavaScript. Useful for blocking DDoS attacks with minimal impact to legitimate visitors. +- **JavaScript Challenge**: Presents the [Under Attack mode](/fundamentals/reference/under-attack-mode/) interstitial page to visitors. The visitor or client must support JavaScript. Useful for blocking DDoS attacks with minimal impact to legitimate visitors. -* **Interactive Challenge**: Requires the visitor to complete an interactive challenge before visiting your site. Prevents bots from accessing the site. +- **Interactive Challenge**: Requires the visitor to complete an interactive challenge before visiting your site. Prevents bots from accessing the site. diff --git a/src/content/docs/waf/tools/scrape-shield/hotlink-protection.mdx b/src/content/docs/waf/tools/scrape-shield/hotlink-protection.mdx index e2ab511ef3808d..f9bba3000347d3 100644 --- a/src/content/docs/waf/tools/scrape-shield/hotlink-protection.mdx +++ b/src/content/docs/waf/tools/scrape-shield/hotlink-protection.mdx @@ -44,6 +44,10 @@ To enable **Hotlink Protection** with the API, send a [`PATCH`](/api/resources/z +### SaaS providers using Cloudflare + +If you are a SaaS provider using [Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/), note that, by default, Hotlink Protection will only allow requests with your zone as referer. To avoid blocking requests from your customers (custom hostnames), consider using [Configuration Rules](/rules/configuration-rules/settings/#hotlink-protection) or [WAF custom rules](/waf/custom-rules/use-cases/exempt-partners-hotlink-protection/). + --- ## Allow hotlinking to specific images diff --git a/src/content/docs/waf/tools/security-level.mdx b/src/content/docs/waf/tools/security-level.mdx index 9d1cc6c3d670d5..b2a0eb8c802a3a 100644 --- a/src/content/docs/waf/tools/security-level.mdx +++ b/src/content/docs/waf/tools/security-level.mdx @@ -6,40 +6,10 @@ title: Security Level import { Render } from "~/components"; - - ---- - - - ---- - -## Customize security level - -The default security level is _Medium_. - -### Update globally - -To update the security level for your entire zone: - -1. Log into the [Cloudflare dashboard](https://dash.cloudflare.com), and select your account and zone. -2. Go to **Security** > **Settings**. -3. For **Security Level**, select an option. - -### Update selectively - -To set the security level more selectively, do one of the following: - -- Configure it via a [configuration rule](/rules/configuration-rules/). -- Use the **Threat Score** as a **Field** criteria within [custom rules](/waf/custom-rules/). If you are using the Expression Editor, use the `cf.threat_score` field. - ---- + -## Recommendations -To prevent bot IPs from attacking a website: -- A new website owner might set a _Medium_ or _High_ **Security Level** and lower [**Challenge Passage**](/waf/tools/challenge-passage/) to a value below **30 minutes** to ensure that Cloudflare is constantly protecting the site. -- An experienced website administrator confident in their security settings might set **Security Level** to _Essentially Off_ or _Low_ while setting a higher [**Challenge Passage**](/waf/tools/challenge-passage/) for a week, month, or even year to provide a less obtrusive visitor experience. +--- \ No newline at end of file diff --git a/src/content/docs/waf/troubleshooting/facebook-sharing.mdx b/src/content/docs/waf/troubleshooting/facebook-sharing.mdx index 4d496e85ceff9c..0c41937111d053 100644 --- a/src/content/docs/waf/troubleshooting/facebook-sharing.mdx +++ b/src/content/docs/waf/troubleshooting/facebook-sharing.mdx @@ -4,16 +4,15 @@ source: https://support.cloudflare.com/hc/en-us/articles/217720788-Troubleshooti title: Issues sharing to Facebook sidebar: order: 2 - --- -import { GlossaryTooltip } from "~/components" +import { GlossaryTooltip } from "~/components"; -Cloudflare does not block or challenge requests from Facebook by default. However, a post of a website to Facebook returns an *Attention Required* error in the following situations: +Cloudflare does not block or challenge requests from Facebook by default. However, a post of a website to Facebook returns an _Attention Required_ error in the following situations: -* You have globally set the [security level](/waf/tools/security-level/) to *I'm Under Attack*. -* There is a [configuration rule](/rules/configuration-rules/) or [page rule](/rules/page-rules/) setting the security level to *I'm Under Attack*. -* There is a [custom rule](/waf/custom-rules/) with a challenge or block action that includes a Facebook IP address. +- You have globally set the [security level](/waf/tools/security-level/) to _I'm Under Attack_. +- There is a [configuration rule](/rules/configuration-rules/) or [page rule](/rules/page-rules/) setting turning on Under Attack mode. +- There is a [custom rule](/waf/custom-rules/) with a challenge or block action that includes a Facebook IP address. A country challenge can block a Facebook IP address. Facebook is known to crawl from both the US and Ireland. @@ -21,9 +20,9 @@ A country challenge can block a Facebook IP address. Facebook is known to crawl To resolve issues sharing to Facebook, do one of the following: -* Remove the corresponding IP, ASN, or country custom rule that challenges or blocks Facebook IPs. -* Create a [skip rule](/waf/custom-rules/skip/) for ASNs `AS32934` and `AS63293` (use the *Skip* action and configure the rule to skip **Security Level**). -* Review existing configuration rules and Page Rules and make sure they are not affecting requests from Facebook IPs. +- Remove the corresponding IP, ASN, or country custom rule that challenges or blocks Facebook IPs. +- Create a [skip rule](/waf/custom-rules/skip/) for ASNs `AS32934` and `AS63293` (use the _Skip_ action and configure the rule to skip **Security Level**). +- Review existing configuration rules and Page Rules and make sure they are not affecting requests from Facebook IPs. If you experience issues with Facebook sharing, you can re-scrape pages via the **Fetch New Scrape Information** option on Facebook's Object Debugger. Facebook [provides an API](https://developers.facebook.com/docs/sharing/opengraph/using-objects) to help update a large number of resources. diff --git a/src/content/docs/waf/troubleshooting/faq.mdx b/src/content/docs/waf/troubleshooting/faq.mdx index 4435c0cad208ff..3853c3a15929e1 100644 --- a/src/content/docs/waf/troubleshooting/faq.mdx +++ b/src/content/docs/waf/troubleshooting/faq.mdx @@ -85,7 +85,7 @@ There is no functional difference between known and verified bots. However, the Cloudflare issues challenges to website visitors to protect against malicious activity such as bot attacks and DDoS attacks. Key reasons include: -- **High Threat Score**: IP addresses with a high-risk score trigger challenges. +- **High threat score**: IP addresses with a high-risk score trigger challenges. - **IP reputation**: If your IP has a history of suspicious activity, it may be flagged. - **Bot detection**: Automated traffic resembling bots is filtered by Cloudflare. - **Web Application Firewall (WAF) custom rules**: Site owners may set rules targeting specific regions or user agents. @@ -107,16 +107,16 @@ The examples below illustrate a few possible approaches. **Example 1** -Exclude multiple IP addresses from a blocking/challenging rule that assesses Threat Score. +Exclude multiple IP addresses from a blocking/challenging rule that assesses attack score. - Basic rule, no exclusion: - - **Expression**: `(http.host eq "example.com" and cf.threat_score > 5)` + - **Expression**: `(http.host eq "example.com" and cf.waf.score lt 20)` - **Action**: Block (or a challenge action) - Rule that excludes IP addresses from being blocked/challenged: - - **Expression**: `(http.host eq "example.com" and cf.threat_score > 5) and not (ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24})` + - **Expression**: `(http.host eq "example.com" and cf.waf.score lt 20) and not (ip.src in {192.0.2.1 198.51.100.42 203.0.113.0/24})` - **Action**: Block (or a challenge action) - Two rules to skip remaining custom rules for specific IPs and block the rest. @@ -128,7 +128,7 @@ Exclude multiple IP addresses from a blocking/challenging rule that assesses Thr 2. Rule 2: - - Expression: `(http.host eq "example.com" and cf.threat_score > 5)` + - Expression: `(http.host eq "example.com" and cf.waf.score lt 20)` - Action: Block (or a challenge action) **Example 2** diff --git a/src/content/docs/waiting-room/get-started.mdx b/src/content/docs/waiting-room/get-started.mdx index 64668fec3e4e92..9d3e283b0bd25c 100644 --- a/src/content/docs/waiting-room/get-started.mdx +++ b/src/content/docs/waiting-room/get-started.mdx @@ -14,7 +14,7 @@ import { Render } from "~/components" Before you start this tutorial, make sure you have: -* Completed the [prerequisites](/waiting-room/about/#prerequisites). +* Reviewed the [About](/waiting-room/about/) Waiting Room page.). * Reviewed your [rate limiting rules](/waf/rate-limiting-rules/) to make sure they allow at least one request every 20 seconds (required for automatic page refreshes). *** diff --git a/src/content/docs/warp-client/get-started/android.mdx b/src/content/docs/warp-client/get-started/android.mdx index 2b875908ba9a9f..316174e7225e11 100644 --- a/src/content/docs/warp-client/get-started/android.mdx +++ b/src/content/docs/warp-client/get-started/android.mdx @@ -5,9 +5,12 @@ weight: 0 head: - tag: title content: Android mobile client - --- +import { Render } from "~/components"; + + + By default, 1.1.1.1:Faster Internet is configured to WARP mode. You can also configure it to only encrypt your DNS queries and leave the remaining traffic unencrypted. ## Set up 1.1.1.1: Faster Internet diff --git a/src/content/docs/warp-client/get-started/iOS.mdx b/src/content/docs/warp-client/get-started/iOS.mdx index 4349200a7897a9..5095c3572155e5 100644 --- a/src/content/docs/warp-client/get-started/iOS.mdx +++ b/src/content/docs/warp-client/get-started/iOS.mdx @@ -5,9 +5,12 @@ weight: 0 head: - tag: title content: iOS mobile client - --- +import { Render } from "~/components"; + + + By default, 1.1.1.1:Faster Internet is configured to WARP mode. You can also configure it to only encrypt your DNS queries and leave the remaining traffic unencrypted. ## Set up 1.1.1.1: Faster Internet diff --git a/src/content/docs/warp-client/get-started/index.mdx b/src/content/docs/warp-client/get-started/index.mdx index d821f57ffa636e..66636bc0267456 100644 --- a/src/content/docs/warp-client/get-started/index.mdx +++ b/src/content/docs/warp-client/get-started/index.mdx @@ -3,10 +3,11 @@ pcx_content_type: reference title: Get started sidebar: order: 3 - --- -import { Render } from "~/components" +import { Render } from "~/components"; + + Before installing and setting up the WARP Client, ensure that your device meets the following system requirements: diff --git a/src/content/docs/warp-client/get-started/linux.mdx b/src/content/docs/warp-client/get-started/linux.mdx index d7d297c88a57f3..c53640a56427ae 100644 --- a/src/content/docs/warp-client/get-started/linux.mdx +++ b/src/content/docs/warp-client/get-started/linux.mdx @@ -7,6 +7,10 @@ head: content: Linux desktop client --- +import { Render } from "~/components"; + + + You have two ways of installing WARP on Linux, depending on the distro you are using: - Find the latest WARP client in the [package repository](https://pkg.cloudflareclient.com/). diff --git a/src/content/docs/warp-client/get-started/macOS.mdx b/src/content/docs/warp-client/get-started/macOS.mdx index 36d886ad358d7e..deefdf8b039a93 100644 --- a/src/content/docs/warp-client/get-started/macOS.mdx +++ b/src/content/docs/warp-client/get-started/macOS.mdx @@ -9,6 +9,8 @@ head: import { Render } from "~/components"; + + 1. [Download](https://downloads.cloudflareclient.com/v1/download/macos/ga) Cloudflare WARP for macOS. 2. Go to your predefined download folder and open the `.pkg` file. 3. Follow the instructions to complete installation. Cloudflare WARP will automatically launch and appear in your menu bar with the Cloudflare logo. diff --git a/src/content/docs/warp-client/get-started/windows.mdx b/src/content/docs/warp-client/get-started/windows.mdx index 486ec941f07352..39d60f71947d0d 100644 --- a/src/content/docs/warp-client/get-started/windows.mdx +++ b/src/content/docs/warp-client/get-started/windows.mdx @@ -5,10 +5,11 @@ weight: 0 head: - tag: title content: Windows desktop client - --- -import { Render } from "~/components" +import { Render } from "~/components"; + + 1. [Download](https://downloads.cloudflareclient.com/v1/download/windows/ga) Cloudflare WARP for Windows. 2. Go to your predefined download folder and open the executable file to install WARP. @@ -26,8 +27,8 @@ WARP is now running and protecting your Internet connection. This is the main GUI application that you interact with. You can find it in: -* The **Start** menu > **Cloudflare**. -* On your disk, in `C:\Program Files\Cloudflare\Cloudflare WARP\Cloudflare WARP.exe`. +- The **Start** menu > **Cloudflare**. +- On your disk, in `C:\Program Files\Cloudflare\Cloudflare WARP\Cloudflare WARP.exe`. ### Cloudflare WARP service @@ -37,8 +38,8 @@ This is the Windows service that is responsible for establishing the wireguard t The Windows application places log files in two locations based on what part of the application is logging information. These logs are included during feedback submission when you check **Feedback** > **Share debug information**. You can find the logs for: -* **WARP Service**: `C:\ProgramData\Cloudflare`. -* **Application GUI Logs**: `C:\Users\\AppData\Local\Cloudflare`. +- **WARP Service**: `C:\ProgramData\Cloudflare`. +- **Application GUI Logs**: `C:\Users\\AppData\Local\Cloudflare`. ## How to remove the application diff --git a/src/content/docs/warp-client/index.mdx b/src/content/docs/warp-client/index.mdx index 9abcb414c48ca8..5980f7ba18cb71 100644 --- a/src/content/docs/warp-client/index.mdx +++ b/src/content/docs/warp-client/index.mdx @@ -1,45 +1,57 @@ --- -title: Overview +title: Cloudflare WARP client pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare WARP client - + content: Overview --- -import { Description, Feature, Plan, RelatedProduct } from "~/components" +import { + Description, + Feature, + Plan, + RelatedProduct, + Render, +} from "~/components"; -Connect to the Internet faster and in a more secure way. +Connect to the Internet faster and in a more secure way. + The Cloudflare WARP client allows individuals to have a faster, more secure, and more private experience online. The WARP client sits between your device and the Internet, and has several connection modes to better suit different needs. -This documentation is for the consumer version of WARP. If you are using WARP with Cloudflare Zero Trust, refer to the [Zero Trust documentation](/cloudflare-one/connections/connect-devices/warp/). + ## Features -The WARP client has several modes to better suit your connection needs. + The WARP client has several modes to better suit your connection needs. -WARP is available to several operating systems, including iOS and Android. + WARP is available to several operating systems, including iOS and Android. -*** +--- ## Related products -1.1.1.1 is Cloudflare’s public DNS resolver. It offers a fast and private way to browse the Internet. + 1.1.1.1 is Cloudflare’s public DNS resolver. It offers a fast and private way + to browse the Internet. - -The enterprise version of WARP allows organizations to apply security policies to corporate devices. + + The enterprise version of WARP allows organizations to apply security policies + to corporate devices. diff --git a/src/content/docs/warp-client/warp-modes.mdx b/src/content/docs/warp-client/warp-modes.mdx index 0c27e214b22b79..cb3cfe2c9c123a 100644 --- a/src/content/docs/warp-client/warp-modes.mdx +++ b/src/content/docs/warp-client/warp-modes.mdx @@ -39,7 +39,7 @@ Because this feature restricts WARP to just applications configured to use the l This will enable the **WARP via Local Proxy** option in the **WARP Settings** menu. -If you enable [FIPS compliance](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#fips-compliance) for TLS decryption, you must [disable QUIC](/cloudflare-one/policies/gateway/http-policies/http3/#prevent-inspection-bypass) in your users' browsers. Otherwise, HTTP/3 traffic will bypass inspection by the WARP client. +If you enable [FIPS compliance](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#fips-compliance) for TLS decryption, you must [disable QUIC](/cloudflare-one/policies/gateway/http-policies/http3/#force-http2-traffic) in your users' browsers. Otherwise, HTTP/3 traffic will bypass inspection by the WARP client. ## WARP+ Unlimited diff --git a/src/content/docs/web-analytics/index.mdx b/src/content/docs/web-analytics/index.mdx index 3df832febd09fa..4564f61b545008 100644 --- a/src/content/docs/web-analytics/index.mdx +++ b/src/content/docs/web-analytics/index.mdx @@ -1,19 +1,18 @@ --- -title: Overview +title: Cloudflare Web Analytics pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Web Analytics - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" -Get vital web analytics for your website without compromising user privacy. +Get vital web analytics for your website without compromising user privacy. @@ -50,7 +49,7 @@ Use dimensions to categorize and organize various metrics or data types effectiv ## Related products -Cloudflare visualizes the metadata collected by our products in the Cloudflare dashboard. +Cloudflare visualizes the metadata collected by our products in the Cloudflare dashboard. @@ -70,7 +69,7 @@ Refer to our latest resources to learn more about security, performance and reli -Read articles about the latest updates about Web Analytics. +Read articles about the latest updates about Web Analytics. diff --git a/src/content/docs/web3/index.mdx b/src/content/docs/web3/index.mdx index 9bf5534c10bcab..9e3cebc7f76326 100644 --- a/src/content/docs/web3/index.mdx +++ b/src/content/docs/web3/index.mdx @@ -1,13 +1,14 @@ --- -title: Overview +title: Web3 pcx_content_type: overview sidebar: order: 1 -head: [] description: Cloudflare offers gateways to various networks to help Web3 developers do what they do best, develop applications without having to worry about running infrastructure. - +head: + - tag: title + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, Render } from "~/components" diff --git a/src/content/docs/workers-ai/configuration/hugging-face-chat-ui.mdx b/src/content/docs/workers-ai/configuration/hugging-face-chat-ui.mdx index 77a18f786fd692..0d99ee3fb763a4 100644 --- a/src/content/docs/workers-ai/configuration/hugging-face-chat-ui.mdx +++ b/src/content/docs/workers-ai/configuration/hugging-face-chat-ui.mdx @@ -45,4 +45,4 @@ When setting up your models, specify the `cloudflare` endpoint. ## Supported models -This template works with any [text generation models](/workers-ai/models/#text-generation) that begin with the `@hf` parameter. +This template works with any [text generation models](/workers-ai/models/) that begin with the `@hf` parameter. diff --git a/src/content/docs/workers-ai/function-calling/embedded/examples/fetch.mdx b/src/content/docs/workers-ai/function-calling/embedded/examples/fetch.mdx index a90a6dc1dbc4f2..29753293f23a81 100644 --- a/src/content/docs/workers-ai/function-calling/embedded/examples/fetch.mdx +++ b/src/content/docs/workers-ai/function-calling/embedded/examples/fetch.mdx @@ -5,6 +5,7 @@ tags: - AI sidebar: order: 4 +description: Learn how to use the fetch() handler in Cloudflare Workers AI to enable LLMs to perform API calls, like retrieving a 5-day weather forecast using function calling. --- diff --git a/src/content/docs/workers-ai/function-calling/embedded/examples/kv.mdx b/src/content/docs/workers-ai/function-calling/embedded/examples/kv.mdx index af0b96b9d03336..fb9a86f19d0e0b 100644 --- a/src/content/docs/workers-ai/function-calling/embedded/examples/kv.mdx +++ b/src/content/docs/workers-ai/function-calling/embedded/examples/kv.mdx @@ -7,12 +7,12 @@ tags: - AI sidebar: order: 6 +description: Learn how to use Cloudflare Workers AI to interact with KV storage, enabling persistent data handling with embedded function calling in a few lines of code. --- Interact with persistent storage to retrieve or store information enables for powerful use cases. In this example we show how embedded function calling can interact with other resources on the Cloudflare Developer Platform with a few lines of code. - ## Pre-Requisites For this example to work, you need to provision a [KV](/kv/) namespace first. To do so, follow the [KV - Get started ](/kv/get-started/) guide. diff --git a/src/content/docs/workers-ai/function-calling/index.mdx b/src/content/docs/workers-ai/function-calling/index.mdx index 0be6af95ba1cf3..f730bff881fa67 100644 --- a/src/content/docs/workers-ai/function-calling/index.mdx +++ b/src/content/docs/workers-ai/function-calling/index.mdx @@ -13,7 +13,7 @@ Function calling enables people to take Large Language Models (LLMs) and use the In essence, function calling allows you to perform actions with LLMs by executing code or making additional API calls. - + ## How can I use function calling? @@ -84,7 +84,7 @@ export default { const response = await env.AI.run( "@hf/nousresearch/hermes-2-pro-mistral-7b", { - messages: [{ role: "user", content: "Who is Cloudflare on github?" }], + messages: [{ role: "user", content: "Who is Cloudflare on GitHub?" }], tools: [ { name: "getGithubUser", @@ -130,16 +130,14 @@ export default { messages: [ { role: "user", - content: "Who is Cloudflare on github?", + content: "Who is Cloudflare on GitHub?", }, { role: "assistant", - content: "", - tool_call: selected_tool.name, + content: JSON.stringify(selected_tool), }, { role: "tool", - name: selected_tool.name, content: JSON.stringify(res), }, ], diff --git a/src/content/docs/workers-ai/get-started/index.mdx b/src/content/docs/workers-ai/get-started/index.mdx index d8db23dc02fa5b..8129e2095fa63e 100644 --- a/src/content/docs/workers-ai/get-started/index.mdx +++ b/src/content/docs/workers-ai/get-started/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: navigation -title: Get started +title: Getting started sidebar: order: 2 diff --git a/src/content/docs/workers-ai/get-started/workers-wrangler.mdx b/src/content/docs/workers-ai/get-started/workers-wrangler.mdx index d12b191a22ec61..ab0281f4ec2bd0 100644 --- a/src/content/docs/workers-ai/get-started/workers-wrangler.mdx +++ b/src/content/docs/workers-ai/get-started/workers-wrangler.mdx @@ -30,7 +30,7 @@ Running `npm create cloudflare@latest` will prompt you to install the [`create-c product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/workers-ai/index.mdx b/src/content/docs/workers-ai/index.mdx index 3386835af607f4..722716694ad3be 100644 --- a/src/content/docs/workers-ai/index.mdx +++ b/src/content/docs/workers-ai/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare Workers AI order: 0 type: overview pcx_content_type: overview @@ -7,8 +7,7 @@ sidebar: order: 1 head: - tag: title - content: Workers AI - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, Render, LinkButton, Flex } from "~/components" diff --git a/src/content/docs/workers-ai/markdown-conversion.mdx b/src/content/docs/workers-ai/markdown-conversion.mdx new file mode 100644 index 00000000000000..ea56ec425709d9 --- /dev/null +++ b/src/content/docs/workers-ai/markdown-conversion.mdx @@ -0,0 +1,234 @@ +--- +title: Markdown Conversion +pcx_content_type: how-to +sidebar: + order: 5 + badge: + text: Beta +--- + +import { Code, Type, MetaInfo, Details } from "~/components"; + +[Markdown](https://en.wikipedia.org/wiki/Markdown) is essential for text generation and large language models (LLMs) in training and inference because it can provide structured, semantic, human, and machine-readable input. Likewise, Markdown facilitates chunking and structuring input data for better retrieval and synthesis in the context of RAGs, and its simplicity and ease of parsing and rendering make it ideal for AI Agents. + +For these reasons, document conversion plays an important role when designing and developing AI applications. Workers AI provides the `toMarkdown` utility method that developers can use from the [`env.AI`](/workers-ai/configuration/bindings/) binding or the REST APIs for quick, easy, and convenient conversion and summary of documents in multiple formats to Markdown language. + +## Methods and definitions + +### async env.AI.toMarkdown() + +Takes a list of documents in different formats and converts them to Markdown. + +#### Parameter + +- documents: + - An array of `toMarkdownDocument`s. + +#### Return values + +- results: + - An array of `toMarkdownDocumentResult`s. + +### `toMarkdownDocument` definition + +- `name` + + - Name of the document to convert. + +- `blob` + + - A new [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob) object with the document content. + +### `toMarkdownDocumentResult` definition + +- `name` + + - Name of the converted document. Matches the input name. + +- `mimetype` + + - The detected [mime type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types) of the document. + +- `tokens` + + - The estimated number of tokens of the converted document. + +- `data` + + - The content of the converted document in Markdown format. + +## Supported formats + +This is the list of support formats. We are constantly adding new formats and updating this table. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Format + + File extensions + + Mime Types +
    + PDF Documents + + `.pdf` + + `application/pdf` +
    + Images 1 + + `.jpeg`, `.jpg`, `.png`, `.webp`, `.svg` + + `image/jpeg`, `image/png`, `image/webp`, `image/svg+xml` +
    + HTML Documents + + `.html` + + `text/html` +
    + XML Documents + + `.xml` + + `application/xml` +
    + Microsoft Office Documents + + `.xlsx`, `.xlsm`, `.xlsb`, `.xls`, `.et` + + `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, `application/vnd.ms-excel.sheet.macroenabled.12`, `application/vnd.ms-excel.sheet.binary.macroenabled.12`, `application/vnd.ms-excel`, `application/vnd.ms-excel` +
    + Open Document Format + + `.ods` + + `application/vnd.oasis.opendocument.spreadsheet` +
    + CSV + + `.csv` + + `text/csv` +
    + Apple Documents + + `.numbers` + + `application/vnd.apple.numbers` +
    + +1 Image conversion uses two Workers AI models for object detection and summarization. See [pricing](/workers-ai/markdown-conversion/#pricing) for more details. + +## Example + +In this example, we fetch a PDF document and an image from R2 and feed them both to `env.AI.toMarkdown`. The result is a list of converted documents. Workers AI models are used automatically to detect and summarize the image. + +```typescript +import { Env } from "./env"; + +export default { + async fetch(request: Request, env: Env, ctx: ExecutionContext) { + + // https://pub-979cb28270cc461d94bc8a169d8f389d.r2.dev/somatosensory.pdf + const pdf = await env.R2.get('somatosensory.pdf'); + + // https://pub-979cb28270cc461d94bc8a169d8f389d.r2.dev/cat.jpeg + const cat = await env.R2.get('cat.jpeg'); + + return Response.json( + await env.AI.toMarkdown([ + { + name: "somatosensory.pdf", + blob: new Blob([await pdf.arrayBuffer()], { type: "application/octet-stream" }), + }, + { + name: "cat.jpeg", + blob: new Blob([await cat.arrayBuffer()], { type: "application/octet-stream" }), + }, + ]), + ); + }, +}; +``` + +This is the result: + +```json +[ + { + "name": "somatosensory.pdf", + "mimeType": "application/pdf", + "format": "markdown", + "tokens": 0, + "data": "# somatosensory.pdf\n## Metadata\n- PDFFormatVersion=1.4\n- IsLinearized=false\n- IsAcroFormPresent=false\n- IsXFAPresent=false\n- IsCollectionPresent=false\n- IsSignaturesPresent=false\n- Producer=Prince 20150210 (www.princexml.com)\n- Title=Anatomy of the Somatosensory System\n\n## Contents\n### Page 1\nThis is a sample document to showcase..." + }, + { + "name": "cat.jpeg", + "mimeType": "image/jpeg", + "format": "markdown", + "tokens": 0, + "data": "The image is a close-up photograph of Grumpy Cat, a cat with a distinctive grumpy expression and piercing blue eyes. The cat has a brown face with a white stripe down its nose, and its ears are pointed upright. Its fur is light brown and darker around the face, with a pink nose and mouth. The cat's eyes are blue and slanted downward, giving it a perpetually grumpy appearance. The background is blurred, but it appears to be a dark brown color. Overall, the image is a humorous and iconic representation of the popular internet meme character, Grumpy Cat. The cat's facial expression and posture convey a sense of displeasure or annoyance, making it a relatable and entertaining image for many people." + } +] +``` + +## REST API + +In addition to the Workers AI [binding](/workers-ai/configuration/bindings/), you can use the [REST API](/workers-ai/get-started/rest-api/): + +```bash +curl https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/tomarkdown \ + -H 'Authorization: Bearer {API_TOKEN}' \ + -F "files=@cat.jpeg" \ + -F "files=@somatosensory.pdf" +``` + +## Pricing + +`toMarkdown` is free for most format conversions. In some cases, like image conversion, it can use Workers AI models for object detection and summarization, which may incur additional costs if it exceeds the Workers AI free allocation limits. See the [pricing page](/workers-ai/platform/pricing/) for more details. \ No newline at end of file diff --git a/src/content/docs/workers-ai/platform/limits.mdx b/src/content/docs/workers-ai/platform/limits.mdx index 3a88f2032f1ef6..8f647f14db74f5 100644 --- a/src/content/docs/workers-ai/platform/limits.mdx +++ b/src/content/docs/workers-ai/platform/limits.mdx @@ -18,36 +18,36 @@ Rate limits are default per task type, with some per-model limits defined as fol ## Rate limits by task type -### [Automatic Speech Recognition](/workers-ai/models/#automatic-speech-recognition) +### [Automatic Speech Recognition](/workers-ai/models/) * 720 requests per minute -### [Image Classification](/workers-ai/models/#image-classification) +### [Image Classification](/workers-ai/models/) * 3000 requests per minute -### [Image-to-Text](/workers-ai/models/#image-to-text) +### [Image-to-Text](/workers-ai/models/) * 720 requests per minute -### [Object Detection](/workers-ai/models/#object-detection) +### [Object Detection](/workers-ai/models/) * 3000 requests per minute -### [Summarization](/workers-ai/models/#summarization) +### [Summarization](/workers-ai/models/) * 1500 requests per minute -### [Text Classification](/workers-ai/models/#text-classification) +### [Text Classification](/workers-ai/models/) * 2000 requests per minute -### [Text Embeddings](/workers-ai/models/#text-embeddings) +### [Text Embeddings](/workers-ai/models/) * 3000 requests per minute * [@cf/baai/bge-large-en-v1.5](/workers-ai/models/bge-large-en-v1.5/) is 1500 requests per minute -### [Text Generation](/workers-ai/models/#text-generation) +### [Text Generation](/workers-ai/models/) * 300 requests per minute * [@hf/thebloke/mistral-7b-instruct-v0.1-awq](/workers-ai/models/mistral-7b-instruct-v0.1-awq/) is 400 requests per minute @@ -57,11 +57,11 @@ Rate limits are default per task type, with some per-model limits defined as fol * [@cf/qwen/qwen1.5-14b-chat-awq](/workers-ai/models/qwen1.5-14b-chat-awq/) is 150 requests per minute * [@cf/tinyllama/tinyllama-1.1b-chat-v1.0](/workers-ai/models/tinyllama-1.1b-chat-v1.0/) is 720 requests per minute -### [Text-to-Image](/workers-ai/models/#text-to-image) +### [Text-to-Image](/workers-ai/models/) * 720 requests per minute * [@cf/runwayml/stable-diffusion-v1-5-img2img](/workers-ai/models/stable-diffusion-v1-5-img2img/) is 1500 requests per minute -### [Translation](/workers-ai/models/#translation) +### [Translation](/workers-ai/models/) * 720 requests per minute diff --git a/src/content/docs/workers-ai/platform/pricing.mdx b/src/content/docs/workers-ai/platform/pricing.mdx index 473a95b39fb3fa..c9f84d687f4eb6 100644 --- a/src/content/docs/workers-ai/platform/pricing.mdx +++ b/src/content/docs/workers-ai/platform/pricing.mdx @@ -26,6 +26,10 @@ All limits reset daily at 00:00 UTC. If you exceed any one of the above limits, Neurons are our way of measuring AI outputs across different models, representing the GPU compute needed to perform your request. Our serverless model allows you to pay only for what you use without having to worry about renting, managing, or scaling GPUs. +:::note +The Price in Tokens column is equivalent to the Price in Neurons column - the different units are displayed so you can easily compare and understand pricing. +::: + ## LLM model pricing | Model | Price in Tokens | Price in Neurons | @@ -46,15 +50,23 @@ Neurons are our way of measuring AI outputs across different models, representin | @cf/meta/llama-2-7b-chat-fp16 | $0.556 per M input tokens
    $6.667 per M output tokens | 50505 neurons per M input tokens
    606061 neurons per M output tokens | | @cf/meta/llama-guard-3-8b | $0.484 per M input tokens
    $0.030 per M output tokens | 44003 neurons per M input tokens
    2730 neurons per M output tokens | +## Embeddings model pricing +| Model | Price in Tokens | Price in Neurons | +| ------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ | +| @cf/baai/bge-small-en-v1.5 | $0.020 per M input tokens | 1841 neurons per M input tokens | +| @cf/baai/bge-base-en-v1.5 | $0.067 per M input tokens | 6058 neurons per M input tokens | +| @cf/baai/bge-large-en-v1.5 | $0.204 per M input tokens | 18582 neurons per M input tokens | +|@cf/baai/bge-m3 |$0.012 per M input tokens|1075 neurons per M input tokens | + ## Other model pricing | Model | Price in Tokens | Price in Neurons | | ------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ | | @cf/black-forest-labs/flux-1-schnell | $0.0000528 per 512x512 tile
    $0.0001056 per step | 4.80 neurons per 512x512 tile
    9.60 neurons per step | | @cf/huggingface/distilbert-sst-2-int8 | $0.026 per M input tokens | 2394 neurons per M input tokens | -| @cf/baai/bge-small-en-v1.5 | $0.020 per M input tokens | 1841 neurons per M input tokens | -| @cf/baai/bge-base-en-v1.5 | $0.067 per M input tokens | 6058 neurons per M input tokens | -| @cf/baai/bge-large-en-v1.5 | $0.204 per M input tokens | 18582 neurons per M input tokens | +|@cf/baai/bge-reranker-base |$0.003 per M input tokens|283 neurons per M input tokens | | @cf/meta/m2m100-1.2b | $0.342 per M input tokens
    $0.342 per M output tokens | 31050 neurons per M input tokens
    31050 neurons per M output tokens | | @cf/microsoft/resnet-50 | $2.51 per M images | 228055 neurons per M images | | @cf/openai/whisper | $0.0005 per audio minute | 41.14 neurons per audio minute | +|@cf/openai/whisper-large-v3-turbo|$0.0005 per audio minute |46.63 neurons per audio minute | +|@cf/myshell-ai/melotts |$3.416 per M input tokens|310577 neurons per M input tokens| \ No newline at end of file diff --git a/src/content/docs/workers-ai/tutorials/build-a-retrieval-augmented-generation-ai.mdx b/src/content/docs/workers-ai/tutorials/build-a-retrieval-augmented-generation-ai.mdx index f34031a808305f..73ef4f54c54580 100644 --- a/src/content/docs/workers-ai/tutorials/build-a-retrieval-augmented-generation-ai.mdx +++ b/src/content/docs/workers-ai/tutorials/build-a-retrieval-augmented-generation-ai.mdx @@ -1,7 +1,6 @@ --- updated: 2024-11-21 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a Retrieval Augmented Generation (RAG) AI products: @@ -44,7 +43,7 @@ Open a terminal window and run C3 to create your Worker project: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -146,8 +145,6 @@ npx wrangler vectorize create vector-index --dimensions=768 --metric=cosine Then, add the configuration details for your new Vectorize index to the [Wrangler configuration file](/workers/wrangler/configuration/): - - ```toml @@ -216,10 +213,12 @@ class_name = "RAGWorkflow" -In `src/index.js`, add a new class called `RAGWorkflow` that extends `Workflow`: +In `src/index.js`, add a new class called `RAGWorkflow` that extends `WorkflowEntrypoint`: ```js -export class RAGWorkflow { +import { WorkflowEntrypoint } from "cloudflare:workers"; + +export class RAGWorkflow extends WorkflowEntrypoint { async run(event, step) { await step.do('example step', async () => { console.log("Hello World!") @@ -268,14 +267,17 @@ Now, we can update our workflow to begin adding notes to our database, and gener This example features the [`@cf/baai/bge-base-en-v1.5` model](/workers-ai/models/bge-base-en-v1.5/), which can be used to create an embedding. Embeddings are stored and retrieved inside [Vectorize](/vectorize/), Cloudflare's vector database. The user query is also turned into an embedding so that it can be used for searching within Vectorize. ```js -export class RAGWorkflow { +import { WorkflowEntrypoint } from "cloudflare:workers"; + +export class RAGWorkflow extends WorkflowEntrypoint { async run(event, step) { - const { text } = event.params + const env = this.env + const { text } = event.payload const record = await step.do(`create database record`, async () => { const query = "INSERT INTO notes (text) VALUES (?) RETURNING *" - const { results } = await env.DATABASE.prepare(query) + const { results } = await env.DB.prepare(query) .bind(text) .run() @@ -487,7 +489,7 @@ For large pieces of text, it is recommended to split the text into smaller chunk To implement this, we'll add a new NPM package to our project, `@langchain/textsplitters': ```sh -npm install @cloudflare/textsplitters +npm install @langchain/textsplitters ``` The `RecursiveCharacterTextSplitter` class provided by this package will split the text into smaller chunks. It can be customized to your liking, but the default config works in most cases: @@ -510,7 +512,7 @@ console.log(output) // [{ pageContent: 'Some long piece of text...' }] To use this splitter, we'll update the workflow to split the text into smaller chunks. We'll then iterate over the chunks and run the rest of the workflow for each chunk of text: ```js -export class RAGWorkflow { +export class RAGWorkflow extends WorkflowEntrypoint { async run(event, step) { const env = this.env const { text } = event.payload; @@ -527,7 +529,7 @@ export class RAGWorkflow { const record = await step.do(`create database record: ${index}/${texts.length}`, async () => { const query = "INSERT INTO notes (text) VALUES (?) RETURNING *" - const { results } = await env.DATABASE.prepare(query) + const { results } = await env.DB.prepare(query) .bind(text) .run() @@ -586,4 +588,4 @@ To do more: - Explore [Examples](/workers/examples/) to experiment with copy and paste Worker code. - Understand how Workers works in [Reference](/workers/reference/). - Learn about Workers features and functionality in [Platform](/workers/platform/). -- Set up [Wrangler](/workers/wrangler/install-and-update/) to programmatically create, test, and deploy your Worker projects. \ No newline at end of file +- Set up [Wrangler](/workers/wrangler/install-and-update/) to programmatically create, test, and deploy your Worker projects. diff --git a/src/content/docs/workers-ai/tutorials/build-a-voice-notes-app-with-auto-transcription.mdx b/src/content/docs/workers-ai/tutorials/build-a-voice-notes-app-with-auto-transcription.mdx index 3b028a57979d24..bdd1f74b4c042e 100644 --- a/src/content/docs/workers-ai/tutorials/build-a-voice-notes-app-with-auto-transcription.mdx +++ b/src/content/docs/workers-ai/tutorials/build-a-voice-notes-app-with-auto-transcription.mdx @@ -1,7 +1,6 @@ --- updated: 2024-12-18 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a Voice Notes App with auto transcriptions using Workers AI products: diff --git a/src/content/docs/workers-ai/tutorials/build-ai-interview-practice-tool.mdx b/src/content/docs/workers-ai/tutorials/build-ai-interview-practice-tool.mdx index 9c9cfdef7aece1..871c7bcb9172a8 100644 --- a/src/content/docs/workers-ai/tutorials/build-ai-interview-practice-tool.mdx +++ b/src/content/docs/workers-ai/tutorials/build-ai-interview-practice-tool.mdx @@ -1,7 +1,6 @@ --- updated: 2024-11-06 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build an interview practice tool with Workers AI products: diff --git a/src/content/docs/workers-ai/tutorials/explore-code-generation-using-deepseek-coder-models.mdx b/src/content/docs/workers-ai/tutorials/explore-code-generation-using-deepseek-coder-models.mdx index 812ba8115826aa..d6ec9e5e01994a 100644 --- a/src/content/docs/workers-ai/tutorials/explore-code-generation-using-deepseek-coder-models.mdx +++ b/src/content/docs/workers-ai/tutorials/explore-code-generation-using-deepseek-coder-models.mdx @@ -1,7 +1,6 @@ --- updated: 2024-02-08 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Explore Code Generation Using DeepSeek Coder Models tags: @@ -23,7 +22,7 @@ A handy way to explore all of the models available on [Workers AI](/workers-ai) You can [download the DeepSeek Coder notebook](/workers-ai/static/documentation/notebooks/deepseek-coder-exploration.ipynb) or view the embedded notebook below. - + [comment]: <> "The markdown below is auto-generated from https://github.com/craigsdennis/notebooks-cloudflare-workers-ai" diff --git a/src/content/docs/workers-ai/tutorials/explore-workers-ai-models-using-a-jupyter-notebook.mdx b/src/content/docs/workers-ai/tutorials/explore-workers-ai-models-using-a-jupyter-notebook.mdx index f24a7d9b8eb9ac..5a4cc8c37cf67c 100644 --- a/src/content/docs/workers-ai/tutorials/explore-workers-ai-models-using-a-jupyter-notebook.mdx +++ b/src/content/docs/workers-ai/tutorials/explore-workers-ai-models-using-a-jupyter-notebook.mdx @@ -1,7 +1,6 @@ --- updated: 2024-07-29 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Explore Workers AI Models Using a Jupyter Notebook tags: @@ -22,7 +21,7 @@ You can [download the Workers AI notebook](/workers-ai-notebooks/cloudflare-work Or you can run this on [Google Colab](https://colab.research.google.com/github/craigsdennis/notebooks-cloudflare-workers-ai/blob/main/cloudflare-workers-ai.ipynb) - + [comment]: <> "The markdown below is auto-generated from https://github.com/craigsdennis/notebooks-cloudflare-workers-ai the
    \ No newline at end of file +
    diff --git a/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-flux.mdx b/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-flux.mdx index 5258f639ab7bba..1ce46d008a28fd 100644 --- a/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-flux.mdx +++ b/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-flux.mdx @@ -1,7 +1,6 @@ --- updated: 2024-10-17 difficulty: Beginner -content_type: 🎥 Video pcx_content_type: video title: Build an AI Image Generator Playground (Part 1) tableOfContents: false @@ -11,20 +10,23 @@ products: - Workers tags: - AI - - Workers languages: - Typescript next: true - --- -import { Details, DirectoryListing, Stream } from "~/components" +import { Details, DirectoryListing, Stream } from "~/components"; The new flux models on Workers AI are our most powerful text-to-image AI models yet. In this video, we show you how to deploy your own Workers AI Image Playground in just a few minutes. There are many businesses being built on top of AI image generation models. Using Workers AI, you can get access to the best models in the industry without having to worry about inference, ops, or deployment. We provide the API for AI image generation, and in a couple of seconds get an image back. - + Refer to the AI Image Playground [GitHub repository](https://github.com/kristianfreeman/workers-ai-image-playground) to follow along locally. @@ -32,4 +34,4 @@ Refer to the AI Image Playground [GitHub repository](https://github.com/kristian -
    \ No newline at end of file +
    diff --git a/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-store-and-catalog.mdx b/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-store-and-catalog.mdx index 7b590471419773..e3eb276d8843ec 100644 --- a/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-store-and-catalog.mdx +++ b/src/content/docs/workers-ai/tutorials/image-generation-playground/image-generator-store-and-catalog.mdx @@ -1,7 +1,6 @@ --- updated: 2025-01-29 difficulty: Beginner -content_type: 🎥 Video pcx_content_type: video title: Store and Catalog AI Generated Images with R2 (Part 3) sidebar: @@ -10,19 +9,21 @@ products: - Workers tags: - AI - - Workers - - R2 languages: - Typescript prev: true - --- -import { Details, DirectoryListing, Stream } from "~/components" +import { Details, DirectoryListing, Stream } from "~/components"; In the final part of the AI Image Playground series, Kristian teaches how to utilize Cloudflare's [R2](/r2) object storage in order to maintain and keep track of each AI generated image. - + Refer to the AI Image Playground [GitHub repository](https://github.com/kristianfreeman/workers-ai-image-playground) to follow along locally. @@ -30,4 +31,4 @@ Refer to the AI Image Playground [GitHub repository](https://github.com/kristian -
    \ No newline at end of file +
    diff --git a/src/content/docs/workers-ai/tutorials/image-generation-playground/index.mdx b/src/content/docs/workers-ai/tutorials/image-generation-playground/index.mdx index 244d57d7162577..14d8f3bef112e2 100644 --- a/src/content/docs/workers-ai/tutorials/image-generation-playground/index.mdx +++ b/src/content/docs/workers-ai/tutorials/image-generation-playground/index.mdx @@ -1,20 +1,17 @@ --- updated: 2024-10-17 difficulty: Beginner -content_type: 🎥 Video pcx_content_type: tutorial title: How to Build an Image Generator using Workers AI products: - Workers tags: - AI - - Workers languages: - Typescript - --- -import { Details, DirectoryListing, Stream } from "~/components" +import { Details, DirectoryListing, Stream } from "~/components"; In this series of videos, Kristian Freeman builds an AI Image Playground. To get started, click on part 1 below. diff --git a/src/content/docs/workers-ai/tutorials/llama-vision-tutorial.mdx b/src/content/docs/workers-ai/tutorials/llama-vision-tutorial.mdx index ef8142068718b6..820dcee1bb7183 100644 --- a/src/content/docs/workers-ai/tutorials/llama-vision-tutorial.mdx +++ b/src/content/docs/workers-ai/tutorials/llama-vision-tutorial.mdx @@ -1,7 +1,6 @@ --- updated: 2025-02-05 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Llama 3.2 11B Vision Instruct model on Cloudflare Workers AI tags: @@ -50,7 +49,7 @@ Replace `$CLOUDFLARE_ACCOUNT_ID` and `$CLOUDFLARE_AUTH_TOKEN` with your actual a product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers-ai/tutorials/using-bigquery-with-workers-ai.mdx b/src/content/docs/workers-ai/tutorials/using-bigquery-with-workers-ai.mdx index 276d2d52371235..439e067b8c9768 100644 --- a/src/content/docs/workers-ai/tutorials/using-bigquery-with-workers-ai.mdx +++ b/src/content/docs/workers-ai/tutorials/using-bigquery-with-workers-ai.mdx @@ -1,7 +1,6 @@ --- updated: 2024-10-21 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Using BigQuery with Workers AI products: diff --git a/src/content/docs/workers/ci-cd/builds/build-image.mdx b/src/content/docs/workers/ci-cd/builds/build-image.mdx index 11e9e2ff8b0268..0393f3c18b68f5 100644 --- a/src/content/docs/workers/ci-cd/builds/build-image.mdx +++ b/src/content/docs/workers/ci-cd/builds/build-image.mdx @@ -8,20 +8,39 @@ sidebar: Workers Builds uses a build image with support for a variety of languages and tools such as Node.js, Python, PHP, Ruby, and Go. -## Supported Languages and Tools +## Supported Tooling -In the following table, review the preinstalled versions for languages and tools included in the Cloudflare Workers' build image, and the environment variables and/or files available for [overriding the preinstalled version](/workers/ci-cd/builds/build-image/#overriding-default-versions): - -| Tool | Default version | Environment variable | File | -| ----------- | ---------------- | -------------------- | ---------------------------- | -| **Go** | 1.23.0 | `GO_VERSION` | | -| **Node.js** | 22 | `NODE_VERSION` | .nvmrc, .node-version | -| **Python** | 3.12.5 | `PYTHON_VERSION` | .python-version, runtime.txt | -| **Ruby** | 3.3.5 | `RUBY_VERSION` | .ruby-version | -| **Bun** | 1.1.28 | `BUN_VERSION` | | -| **Hugo** | extended_0.134.3 | `HUGO_VERSION` | | +Workers Builds supports a variety of runtimes, languages, and tools. Builds will use the default versions listed below unless a custom version is detected or specified. You can [override the default versions](/workers/ci-cd/builds/build-image/#overriding-default-versions) using environment variables or version files. All versions are available for override. +:::note[Default version updates] The default versions will be updated regularly to the latest minor version. No major version updates will be made without notice. If you need a specific minor version, please specify it by overriding the default version. +::: + +### Runtime + +| Tool | Default version | Environment variable | File | +| ----------- | --------------- | -------------------- | ---------------------------- | +| **Go** | 1.23.0 | `GO_VERSION` | | +| **Node.js** | 22.9.0 | `NODE_VERSION` | .nvmrc, .node-version | +| **Python** | 3.12.5 | `PYTHON_VERSION` | .python-version, runtime.txt | +| **Ruby** | 3.3.5 | `RUBY_VERSION` | .ruby-version | + +### Tools and langauges + +| Tool | Default version | Environment variable | +| ----------- | ---------------- | -------------------- | +| **Bun** | 1.1.33 | `BUN_VERSION` | +| **Hugo** | extended_0.134.3 | `HUGO_VERSION` | +| **npm** | 10.8.3 | | +| **yarn** | 4.5.0 | `YARN_VERSION` | +| **pnpm** | 9.10.0 | `PNPM_VERSION` | +| **pip** | 24.2 | | +| **gem** | 3.5.19 | | +| **poetry** | 1.8.3 | | +| **pipx** | 1.7.1 | | +| **bundler** | 2.4.10 | | + +## Advanced Settings ### Overriding Default Versions @@ -37,6 +56,14 @@ Or, to set the version by adding a file to your project, you can: 1. Find the filename for the language or tool (e.g. `.nvmrc`) 2. Add the specified file name to the root directory and set the desired version number as the file's content. For example, if the version number is 22, the file should contain '22'. +### Skip dependency install + +You can add the following build variable to disable automatic dependency installation and run a custom install command instead. + +| Build variable | Value | +| ------------------------- | ------------- | +| `SKIP_DEPENDENCY_INSTALL` | `1` or `true` | + ## Pre-installed Packages In the following table, review the pre-installed packages in the build image. The packages are installed with `apt`, a package manager for Linux distributions. diff --git a/src/content/docs/workers/ci-cd/builds/configuration.mdx b/src/content/docs/workers/ci-cd/builds/configuration.mdx index ec4ca15299093a..0e4caca53fcb6b 100644 --- a/src/content/docs/workers/ci-cd/builds/configuration.mdx +++ b/src/content/docs/workers/ci-cd/builds/configuration.mdx @@ -20,7 +20,7 @@ Note that when you update and save build settings, the updated settings will be | Setting | Description | | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Git account** | Select the Git account you would like to use. After the initial connection, you can continue to use this Git account for future projects. | +| **Git account** | Select the Git account you would like to use. After the initial connection, you can continue to use this Git account for future projects. | | **Git repository** | Choose the Git repository you would like to connect your Worker to. | | **Git branch** | Select the branch you would like Cloudflare to listen to for new commits. This will be defaulted to `main`. | | **Build command** _(Optional)_ | Set a build command if your project requires a build step (e.g. `npm run build`). This is necessary, for example, when using a [front-end framework](/workers/ci-cd/builds/configuration/#framework-support) such as Next.js or Remix. | @@ -49,6 +49,8 @@ Examples of other deploy commands you can set include: ### API token +The API token in Workers Builds defines the access granted to Workers Builds for interacting with your account's resources. Currently, only user tokens are supported, with account-owned token support coming soon. + When you select **Create new token**, a new API token will be created automatically with the following permissions: - **Account:** Account Settings (read), Workers Scripts (edit), Workers KV Storage (edit), Workers R2 Storage (edit) diff --git a/src/content/docs/workers/ci-cd/builds/limits-and-pricing.mdx b/src/content/docs/workers/ci-cd/builds/limits-and-pricing.mdx index f6bf58b7e0f3c6..4327a7393bc826 100644 --- a/src/content/docs/workers/ci-cd/builds/limits-and-pricing.mdx +++ b/src/content/docs/workers/ci-cd/builds/limits-and-pricing.mdx @@ -23,7 +23,7 @@ While in open beta, the following limits are applicable for Workers Builds. Plea During the beta, Workers Builds will be free to try with the limits stated above. -In the future, once Workers Builds becomes generally available, you can expect the following updates to the limits and pricing structure. +Starting 2025-04-02, you can expect the following updates to the limits and pricing structure. | Metric | Workers Free | Paid | | ------------------------- | ------------- | ---------------------------------- | diff --git a/src/content/docs/workers/ci-cd/external-cicd/github-actions.mdx b/src/content/docs/workers/ci-cd/external-cicd/github-actions.mdx index b34c26e3451566..8b8b499e184d81 100644 --- a/src/content/docs/workers/ci-cd/external-cicd/github-actions.mdx +++ b/src/content/docs/workers/ci-cd/external-cicd/github-actions.mdx @@ -19,7 +19,7 @@ To find your Cloudflare account ID, refer to [Find account and zone IDs](/fundam To create an API token to authenticate Wrangler in your CI job: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com). -2. Select **My Profile** > **API Tokens**. +2. Select **Manage Account** > **Account API Tokens**. 3. Select **Create Token** > find **Edit Cloudflare Workers** > select **Use Template**. 4. Customize your token name. 5. Scope your token. diff --git a/src/content/docs/workers/configuration/cron-triggers.mdx b/src/content/docs/workers/configuration/cron-triggers.mdx index 93f0ea15f2dbbb..8e777a6771fdc4 100644 --- a/src/content/docs/workers/configuration/cron-triggers.mdx +++ b/src/content/docs/workers/configuration/cron-triggers.mdx @@ -5,7 +5,7 @@ head: [] description: Enable your Worker to be executed on a schedule. --- -import { WranglerConfig } from "~/components"; +import { Render, WranglerConfig } from "~/components"; ## Background @@ -27,7 +27,9 @@ Cron Triggers execute on UTC time. To respond to a Cron Trigger, you must add a [`"scheduled"` handler](/workers/runtime-apis/handlers/scheduled/) to your Worker. -Refer to the following examples to write your code: + + +Refer to the following additional examples to write your code: - [Setting Cron Triggers](/workers/examples/cron-trigger/) - [Multiple Cron Triggers](/workers/examples/multiple-cron-triggers/) @@ -48,8 +50,8 @@ Refer to the example below for a Cron Triggers configuration: [triggers] # Schedule cron triggers: # - At every 3rd minute -# - At 3PM on first day of the month -# - At 11:59PM on the last weekday of the month +# - At 15:00 (UTC) on first day of the month +# - At 23:59 (UTC) on the last weekday of the month crons = [ "*/3 * * * *", "0 15 1 * *", "59 23 LW * *" ] ``` @@ -57,8 +59,6 @@ crons = [ "*/3 * * * *", "0 15 1 * *", "59 23 LW * *" ] You also can set a different Cron Trigger for each [environment](/workers/wrangler/environments/) in your [Wrangler configuration file](/workers/wrangler/configuration/). You need to put the `[triggers]` table under your chosen environment. For example: - - ```toml @@ -106,22 +106,22 @@ Some common time intervals that may be useful for setting up your Cron Trigger: - `0 17 * * sun` or `0 17 * * 1` - - 5PM on Sunday + - 17:00 (UTC) on Sunday - `10 7 * * mon-fri` or `10 7 * * 2-6` - - 7:10AM on weekdays + - 07:10 (UTC) on weekdays - `0 15 1 * *` - - 3PM on first day of the month + - 15:00 (UTC) on first day of the month - `0 18 * * 6L` or `0 18 * * friL` - - 6PM on the last Friday of the month + - 18:00 (UTC) on the last Friday of the month - `59 23 LW * *` - - 11:59PM on the last weekday of the month + - 23:59 (UTC) on the last weekday of the month ## Test Cron Triggers diff --git a/src/content/docs/workers/configuration/environment-variables.mdx b/src/content/docs/workers/configuration/environment-variables.mdx index f51f2764caf5d1..a581198efd3712 100644 --- a/src/content/docs/workers/configuration/environment-variables.mdx +++ b/src/content/docs/workers/configuration/environment-variables.mdx @@ -3,10 +3,9 @@ pcx_content_type: configuration title: Environment variables head: [] description: Environment variables are a type of binding that allow you to attach text strings or JSON values to your Worker - --- -import { Render, TabItem, Tabs, WranglerConfig } from "~/components" +import { Render, TabItem, Tabs, WranglerConfig } from "~/components"; ## Background @@ -26,58 +25,56 @@ Refer to the following example on how to access the `API_HOST` environment varia ```js export default { - async fetch(request, env, ctx) { - return new Response(`API host: ${env.API_HOST}`); - } -} + async fetch(request, env, ctx) { + return new Response(`API host: ${env.API_HOST}`); + }, +}; ``` ```ts export interface Env { - API_HOST: string; + API_HOST: string; } export default { - async fetch(request, env, ctx): Promise { - return new Response(`API host: ${env.API_HOST}`); - } + async fetch(request, env, ctx): Promise { + return new Response(`API host: ${env.API_HOST}`); + }, } satisfies ExportedHandler; ``` -`vars` is a non-inheritable key. [Non-inheritable keys](/workers/wrangler/configuration/#non-inheritable-keys) are configurable at the top-level, but cannot be inherited by environments and must be specified for each environment. +### Configuring different environments in Wrangler + +[Environments in Wrangler](/workers/wrangler/environments) let you specify different configurations for the same Worker, including different values for `vars` in each environment. +As `vars` is a [non-inheritable key](/workers/wrangler/configuration/#non-inheritable-keys), they are not inherited by environments and must be specified for each environment. -To define environment variables for different environments, refer to the example below: +The example below sets up two environments, `staging` and `production`, with different values for `API_HOST`. ```toml name = "my-worker-dev" +# top level environment +[vars] +API_HOST = "api.example.com" + [env.staging.vars] API_HOST = "staging.example.com" -API_ACCOUNT_ID = "staging_example_user" -SERVICE_X_DATA = { URL = "service-x-api.dev.example", MY_ID = 123 } [env.production.vars] API_HOST = "production.example.com" -API_ACCOUNT_ID = "production_example_user" -SERVICE_X_DATA = { URL = "service-x-api.prod.example", MY_ID = 456 } ``` -For local development with `wrangler dev`, variables in the [Wrangler configuration file](/workers/wrangler/configuration/) are automatically overridden by any values defined in a `.dev.vars` file located in the root directory of your worker. This is useful for providing values you do not want to check in to source control. +To run Wrangler commands in specific environments, you can pass in the `--env` or `-e` flag. For example, you can develop the Worker in an environment called `staging` by running `npx wrangler dev --env staging`, and deploy it with `npx wrangler deploy --env staging`. -```shell -API_HOST = "localhost:4000" -API_ACCOUNT_ID = "local_example_user" -``` - -Alternatively, you can specify per-environment values in the [Wrangler configuration file](/workers/wrangler/configuration/) and provide an `environment` value via the `env` flag when developing locally like so `wrangler dev --env=local`. +Learn about [environments in Wrangler](/workers/wrangler/environments). ## Add environment variables via the dashboard @@ -94,14 +91,14 @@ To add environment variables via the dashboard: :::caution[Plaintext strings and secrets] - Select the **Secret** type if your environment variable is a [secret](/workers/configuration/secrets/). - ::: + + ## Related resources -* Learn how to access environment variables in [ES modules syntax](/workers/reference/migrate-to-module-workers/) for an optimized experience. +- Migrating environment variables from [Service Worker format to ES modules syntax](/workers/reference/migrate-to-module-workers/#environment-variables). diff --git a/src/content/docs/workers/configuration/multipart-upload-metadata.mdx b/src/content/docs/workers/configuration/multipart-upload-metadata.mdx index db3b044f54fcfc..a66222a58afe0a 100644 --- a/src/content/docs/workers/configuration/multipart-upload-metadata.mdx +++ b/src/content/docs/workers/configuration/multipart-upload-metadata.mdx @@ -68,11 +68,6 @@ At a minimum, the `main_module` key is required to upload a Worker. * [Compatibility Flags](/workers/configuration/compatibility-flags/#setting-compatibility-flags) that enable or disable certain features in the Workers runtime. Used to enable upcoming features or opt in or out of specific changes not included in a `compatibility_date`. -* `usage_model` - - * Usage model to apply to invocations, only allowed value is `standard`. - - ## Additional attributes: [Workers Script Upload API](/api/resources/workers/subresources/scripts/methods/update/) diff --git a/src/content/docs/workers/configuration/routing/custom-domains.mdx b/src/content/docs/workers/configuration/routing/custom-domains.mdx index d64591aaf7c3e2..8742719a1b3b1a 100644 --- a/src/content/docs/workers/configuration/routing/custom-domains.mdx +++ b/src/content/docs/workers/configuration/routing/custom-domains.mdx @@ -27,7 +27,7 @@ To add a Custom Domain, you must have: 1. An [active Cloudflare zone](/dns/zone-setups/). 2. A Worker to invoke. -Custom Domains can be attached to your Worker via the [Cloudflare dashboard](/workers/configuration/routing/custom-domains/#set-up-a-custom-domain-in-the-dashboard), [Wrangler](/workers/configuration/routing/custom-domains/#set-up-a-custom-domain-in-your-wranglertoml--wranglerjson-file) or the [API](/api/resources/workers/subresources/domains/methods/list/). +Custom Domains can be attached to your Worker via the [Cloudflare dashboard](/workers/configuration/routing/custom-domains/#set-up-a-custom-domain-in-the-dashboard), [Wrangler](/workers/configuration/routing/custom-domains/#set-up-a-custom-domain-in-your-wrangler-configuration-file) or the [API](/api/resources/workers/subresources/domains/methods/list/). :::caution diff --git a/src/content/docs/workers/examples/cron-trigger.mdx b/src/content/docs/workers/examples/cron-trigger.mdx index 8bf9e34325dcad..87b5b10c67635a 100644 --- a/src/content/docs/workers/examples/cron-trigger.mdx +++ b/src/content/docs/workers/examples/cron-trigger.mdx @@ -13,34 +13,9 @@ sidebar: description: Set a Cron Trigger for your Worker. --- -import { TabItem, Tabs, WranglerConfig } from "~/components"; +import { Render, TabItem, Tabs, WranglerConfig } from "~/components"; - - -```js -export default { - async scheduled(event, env, ctx) { - console.log("cron processed"); - }, -}; -``` - - - -```ts -interface Env {} -export default { - async scheduled( - controller: ScheduledController, - env: Env, - ctx: ExecutionContext, - ) { - console.log("cron processed"); - }, -}; -``` - - + ## Set Cron Triggers in Wrangler @@ -63,8 +38,6 @@ crons = ["0 * * * *"] You also can set a different Cron Trigger for each [environment](/workers/wrangler/environments/) in your [Wrangler configuration file](/workers/wrangler/configuration/). You need to put the `[triggers]` table under your chosen environment. For example: - - ```toml diff --git a/src/content/docs/workers/examples/geolocation-hello-world.mdx b/src/content/docs/workers/examples/geolocation-hello-world.mdx index 8c22143a4ae233..9ac167fa28a860 100644 --- a/src/content/docs/workers/examples/geolocation-hello-world.mdx +++ b/src/content/docs/workers/examples/geolocation-hello-world.mdx @@ -133,7 +133,7 @@ async def on_fetch(request): """ - headers = Headers.new({"content-type": "text/htmlcharset=UTF-8"}.items()) + headers = Headers.new({"content-type": "text/html;charset=UTF-8"}.items()) return Response.new(html, headers=headers) ``` diff --git a/src/content/docs/workers/examples/images-workers.mdx b/src/content/docs/workers/examples/images-workers.mdx index 62d1a98f78a7e3..eaf8ade72b7cee 100644 --- a/src/content/docs/workers/examples/images-workers.mdx +++ b/src/content/docs/workers/examples/images-workers.mdx @@ -2,8 +2,6 @@ type: example summary: Set up custom domain for Images using a Worker or serve images using a prefix path and Cloudflare registered domain. -tags: - - Images languages: - JavaScript - TypeScript diff --git a/src/content/docs/workers/examples/rewrite-links.mdx b/src/content/docs/workers/examples/rewrite-links.mdx index b304cb6d4673cd..a68baada4ed953 100644 --- a/src/content/docs/workers/examples/rewrite-links.mdx +++ b/src/content/docs/workers/examples/rewrite-links.mdx @@ -2,8 +2,6 @@ type: example summary: Rewrite URL links in HTML using the HTMLRewriter. This is useful for JAMstack websites. -tags: - - HTMLRewriter languages: - JavaScript - TypeScript diff --git a/src/content/docs/workers/examples/signing-requests.mdx b/src/content/docs/workers/examples/signing-requests.mdx index b0a4bca72012bb..e4706525d09d56 100644 --- a/src/content/docs/workers/examples/signing-requests.mdx +++ b/src/content/docs/workers/examples/signing-requests.mdx @@ -22,7 +22,7 @@ import { TabItem, Tabs } from "~/components"; :::note -This example Worker makes use of the [Node.js Buffer API](/workers/runtime-apis/nodejs/buffer/), which is available as part of the Worker's runtime [Node.js compatibility mode](/workers/runtime-apis/nodejs/). To run this Worker, you will need to [enable the `nodejs_compat` compatibility flag](/workers/runtime-apis/nodejs/#enable-nodejs-with-workers). +This example Worker makes use of the [Node.js Buffer API](/workers/runtime-apis/nodejs/buffer/), which is available as part of the Worker's runtime [Node.js compatibility mode](/workers/runtime-apis/nodejs/). To run this Worker, you will need to [enable the `nodejs_compat` compatibility flag](/workers/runtime-apis/nodejs/#get-started). ::: You can both verify and generate signed requests from within a Worker using the [Web Crypto APIs](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle). diff --git a/src/content/docs/workers/examples/turnstile-html-rewriter.mdx b/src/content/docs/workers/examples/turnstile-html-rewriter.mdx index 05ee91234faa4a..1af99ecb67bb9f 100644 --- a/src/content/docs/workers/examples/turnstile-html-rewriter.mdx +++ b/src/content/docs/workers/examples/turnstile-html-rewriter.mdx @@ -2,8 +2,6 @@ type: example summary: Inject [Turnstile](/turnstile/) implicitly into HTML elements using the HTMLRewriter runtime API. -tags: - - HTMLRewriter languages: - JavaScript - TypeScript @@ -24,31 +22,37 @@ import { TabItem, Tabs } from "~/components"; export default { async fetch(request, env) { const SITE_KEY = env.SITE_KEY; // The Turnstile Sitekey of your widget (pass as env or secret) - const TURNSTILE_ATTR_NAME = 'your_id_to_replace'; // The id of the element to put a Turnstile widget in - let res = await fetch(request) + const TURNSTILE_ATTR_NAME = "your_id_to_replace"; // The id of the element to put a Turnstile widget in + let res = await fetch(request); // Instantiate the API to run on specific elements, for example, `head`, `div` let newRes = new HTMLRewriter() // `.on` attaches the element handler and this allows you to match on element/attributes or to use the specific methods per the API - .on('head', { + .on("head", { element(element) { // In this case, you are using `append` to add a new script to the `head` element - element.append(``, { html: true }); + element.append( + ``, + { html: true }, + ); }, }) - .on('div', { + .on("div", { element(element) { // Add a turnstile widget element into if an element with the id of TURNSTILE_ATTR_NAME is found - if (element.getAttribute('id') === TURNSTILE_ATTR_NAME) { - element.append(`
    `, { html: true }); + if (element.getAttribute("id") === TURNSTILE_ATTR_NAME) { + element.append( + `
    `, + { html: true }, + ); } }, }) .transform(res); - return newRes - } -} + return newRes; + }, +}; ``` @@ -57,32 +61,37 @@ export default { export default { async fetch(request, env): Promise { const SITE_KEY = env.SITE_KEY; // The Turnstile Sitekey of your widget (pass as env or secret) - const TURNSTILE_ATTR_NAME = 'your_id_to_replace'; // The id of the element to put a Turnstile widget in + const TURNSTILE_ATTR_NAME = "your_id_to_replace"; // The id of the element to put a Turnstile widget in - let res = await fetch(request) + let res = await fetch(request); // Instantiate the API to run on specific elements, for example, `head`, `div` let newRes = new HTMLRewriter() // `.on` attaches the element handler and this allows you to match on element/attributes or to use the specific methods per the API - .on('head', { + .on("head", { element(element) { - // In this case, you are using `append` to add a new script to the `head` element - element.append(``, { html: true }); + element.append( + ``, + { html: true }, + ); }, }) - .on('div', { + .on("div", { element(element) { // Add a turnstile widget element into if an element with the id of TURNSTILE_ATTR_NAME is found - if (element.getAttribute('id') === TURNSTILE_ATTR_NAME) { - element.append(`
    `, { html: true }); + if (element.getAttribute("id") === TURNSTILE_ATTR_NAME) { + element.append( + `
    `, + { html: true }, + ); } }, }) .transform(res); - return newRes - } + return newRes; + }, } satisfies ExportedHandler; ``` diff --git a/src/content/docs/workers/frameworks/framework-guides/angular.mdx b/src/content/docs/workers/frameworks/framework-guides/angular.mdx index b07383bbc3e52e..41ef779dd2d4ce 100644 --- a/src/content/docs/workers/frameworks/framework-guides/angular.mdx +++ b/src/content/docs/workers/frameworks/framework-guides/angular.mdx @@ -24,7 +24,7 @@ To use `create-cloudflare` to create a new Angular project with Workers Assets](/workers/static-assets/)). + +## 1. Set up a new project + +Use the [`create-cloudflare`](https://www.npmjs.com/package/create-cloudflare) CLI (C3) to set up a new project. C3 will create a new project directory, use code from the official Hono template, and provide the option to deploy instantly. + +To use `create-cloudflare` to create a new Hono project with Workers Assets, run the following command: + + + + + +After setting up your project, change your directory by running the following command: + +```sh +cd my-hono-app +``` + +## 2. Develop locally + +After you have created your project, run the following command in the project directory to start a local server. This will allow you to preview your project locally during development. + + + +## 3. Deploy your project + +Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/), from your own machine or from any CI/CD system, including [Cloudflare's own](/workers/ci-cd/builds/). + +The following command will build and deploy your project. If you are using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately. + + + +--- + +## Bindings + +Your Hono application can be fully integrated with the Cloudflare Developer Platform, in both local development and in production, by using product bindings. The [Hono documentation](https://hono.dev/docs/getting-started/cloudflare-workers#bindings) provides information about configuring bindings and how you can access them. + +## Static assets + +You can serve static assets in your Hono application by [placing them in the `./public/` directory](https://hono.dev/docs/getting-started/cloudflare-workers#serve-static-files). This can be useful for resource files such as images, stylesheets, fonts, and manifests. + + diff --git a/src/content/docs/workers/frameworks/framework-guides/nextjs.mdx b/src/content/docs/workers/frameworks/framework-guides/nextjs.mdx index f1111e8b7b578b..36aa0deb01bc89 100644 --- a/src/content/docs/workers/frameworks/framework-guides/nextjs.mdx +++ b/src/content/docs/workers/frameworks/framework-guides/nextjs.mdx @@ -15,6 +15,11 @@ import { WranglerConfig } from "~/components"; +In this guide, you will create a new [Next.js](https://nextjs.org/) application and deploy to Cloudflare Workers (with the new [ Workers Assets](/workers/static-assets/)) using the [`@opennextjs/cloudflare`](https://opennext.js.org/cloudflare) package. + +:::note +This is a simple getting started guide for a more detailed documentation on how the to use the Cloudflare Open Next adapter visit the [Open Next website](https://opennext.js.org/cloudflare). +::: ## New apps To create a new Next.js app, pre-configured to run on Cloudflare using [`@opennextjs/cloudflare`](https://opennext.js.org/cloudflare), run: @@ -36,7 +41,7 @@ To create a new Next.js app, pre-configured to run on Cloudflare using [`@openne ## Existing Next.js apps -:::note[Minimum required Wrangler version: 3.78.10.] +:::note[Minimum required Wrangler version: 3.99.0.] Check your version by running `wrangler --version`. To update Wrangler, refer to [Install/Update Wrangler](/workers/wrangler/install-and-update/). @@ -77,44 +82,20 @@ You configure your Worker and define what resources it can access via [bindings] Add the following to the scripts field of your `package.json` file: ```json -"build:worker": "opennextjs-cloudflare", -"dev:worker": "wrangler dev --port 8771", -"preview:worker": "npm run build:worker && npm run dev:worker", -"deploy:worker": "npm run build:worker && wrangler deploy" -``` - -- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running `next build` behind the scenes, and then transforms the build output to a format that you can run locally using [Wrangler](/workers/wrangler/) and deploy to Cloudflare. -- `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. -- `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. -- `npm run deploy:worker`: Builds your app, and then deploys it to Cloudflare - -### 4. Add caching with Workers KV - -`opennextjs/cloudflare` uses [Workers KV](/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then be read by subsequent requests from this cache anywhere in the world. - -To enable caching, you must: - -#### Create a KV namespace - -```sh -npx wrangler@latest kv namespace create NEXT_CACHE_WORKERS_KV +"preview": "opennextjs-cloudflare && wrangler dev", +"deploy": "opennextjs-cloudflare && wrangler deploy", +"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts" ``` -#### Add the KV namespace to your Worker +- `preview`: Builds your app and serves it locally, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `deploy`: Builds your app, and then deploys it to Cloudflare +- `cf-typegen`: Generates a `cloudflare-env.d.ts` file at the root of your project containing the types for the env. - +### 4. Optionally add caching -```toml -[[kv_namespaces]] -binding = "NEXT_CACHE_WORKERS_KV" -id = "" -``` +Caching is actively being worked on. It is fully functional for development and we are working on an optimized implementation suitable for production. - - -#### Set the name of the binding to `NEXT_CACHE_WORKERS_KV` - -As shown above, the name of the binding that you configure for the KV namespace must be set to `NEXT_CACHE_WORKERS_KV`. +For more details check the relevant [official Open Next documentation](https://opennext.js.org/cloudflare/caching). ### 5. Develop locally @@ -122,13 +103,11 @@ You can continue to run `next dev` when developing locally. ### 6. Preview locally your application and create an OpenNext config file -In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. -This allows you to test changes in the same runtime that your app runs in, when deployed to Cloudflare. - -To preview your application in such way run: +In step 3, we also added the `npm run preview` script, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. +This allows you to test changes in the same runtime that your app runs in, when deployed to Cloudflare: ```sh -npm run preview:worker +npm run preview ``` This command will build your OpenNext application, also creating, if not already present, an `open-next.configs.ts` file for you. @@ -139,7 +118,7 @@ This is necessary if you want to deploy your application with a GibHub/GitLab in Either deploy via the command line: ```sh -npm run deploy:worker +npm run deploy ``` Or [connect a GitHub or GitLab repository](/workers/ci-cd/), and Cloudflare will automatically build and deploy each pull request you merge to your production branch. diff --git a/src/content/docs/workers/frameworks/framework-guides/nuxt.mdx b/src/content/docs/workers/frameworks/framework-guides/nuxt.mdx index c129890f7ae136..d6ee9276282cb4 100644 --- a/src/content/docs/workers/frameworks/framework-guides/nuxt.mdx +++ b/src/content/docs/workers/frameworks/framework-guides/nuxt.mdx @@ -24,7 +24,7 @@ To use `create-cloudflare` to create a new Nuxt project with Workers Assets](/workers/static-assets/)). + +## 1. Set up a new project + +Use the [`create-cloudflare`](https://www.npmjs.com/package/create-cloudflare) CLI (C3) to set up a new project. C3 will create a new project directory, use code from the official React template, and provide the option to deploy instantly. + +To use `create-cloudflare` to create a new React project with Workers Assets, run the following command: + + + + + +After setting up your project, change your directory by running the following command: + +```sh +cd my-react-app +``` + +## 2. Develop locally + +After you have created your project, run the following command in the project directory to start a local server. This will allow you to preview your project locally during development. + + + +## 3. Deploy your project + +Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/), from your own machine or from any CI/CD system, including [Cloudflare's own](/workers/ci-cd/builds/). + +The following command will build and deploy your project. If you are using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately. + + + +--- + +## Static assets + +You can serve static assets in your React application by [placing them in the `./public/` directory](https://vite.dev/guide/assets#the-public-directory). This can be useful for resource files such as images, stylesheets, fonts, and manifests. + + + +## Use bindings with React + +Your new project also contains a Worker at `./api/index.ts`, which you can use as a backend API for your React application. While your React application cannot directly access Workers bindings, it can interact with them through this Worker. You can make [`fetch()` requests](/workers/runtime-apis/fetch/) from your React application to the Worker, which can then handle the request and use bindings. Learn how to [configure Workers bindings](/workers/runtime-apis/bindings/). diff --git a/src/content/docs/workers/frameworks/framework-guides/remix.mdx b/src/content/docs/workers/frameworks/framework-guides/remix.mdx index c416276c478fa6..dfbe720db288e8 100644 --- a/src/content/docs/workers/frameworks/framework-guides/remix.mdx +++ b/src/content/docs/workers/frameworks/framework-guides/remix.mdx @@ -3,6 +3,7 @@ pcx_content_type: how-to title: Remix head: [] description: Create a Remix application and deploy it to Cloudflare Workers with Workers Assets. +tags: [Remix] --- import { @@ -24,7 +25,7 @@ To use `create-cloudflare` to create a new Remix project with Workers Assets](/workers/static-assets/)). + +## 1. Set up a new project + +Use the [`create-cloudflare`](https://www.npmjs.com/package/create-cloudflare) CLI (C3) to set up a new project. C3 will create a new project directory, use code from the official Vue template, and provide the option to deploy instantly. + +To use `create-cloudflare` to create a new Vue project with Workers Assets, run the following command: + + + + + +After setting up your project, change your directory by running the following command: + +```sh +cd my-vue-app +``` + +## 2. Develop locally + +After you have created your project, run the following command in the project directory to start a local server. This will allow you to preview your project locally during development. + + + +## 3. Deploy your project + +Your project can be deployed to a `*.workers.dev` subdomain or a [Custom Domain](/workers/configuration/routing/custom-domains/), from your own machine or from any CI/CD system, including [Cloudflare's own](/workers/ci-cd/builds/). + +The following command will build and deploy your project. If you are using CI, ensure you update your ["deploy command"](/workers/ci-cd/builds/configuration/#build-settings) configuration appropriately. + + + +--- + +## Static assets + +You can serve static assets in your Vue application by [placing them in the `./public/` directory](https://vite.dev/guide/assets#the-public-directory). This can be useful for resource files such as images, stylesheets, fonts, and manifests. + + + +## Use bindings with Vue + +Your new project also contains a Worker at `./server/index.ts`, which you can use as a backend API for your Vue application. While your Vue application cannot directly access Workers bindings, it can interact with them through this Worker. You can make [`fetch()` requests](/workers/runtime-apis/fetch/) from your Vue application to the Worker, which can then handle the request and use bindings. Learn how to [configure Workers bindings](/workers/runtime-apis/bindings/). diff --git a/src/content/docs/workers/frameworks/index.mdx b/src/content/docs/workers/frameworks/index.mdx index aa16670660c8d1..d04e62ffc47dc6 100644 --- a/src/content/docs/workers/frameworks/index.mdx +++ b/src/content/docs/workers/frameworks/index.mdx @@ -26,13 +26,7 @@ import { network. -The following frameworks have experimental support for Cloudflare Workers and the new [ Workers Assets](/workers/static-assets/). They can be initialized with the [`create-cloudflare` CLI](/workers/get-started/guide/) using the `--experimental` flag. - - +The following frameworks have support for Cloudflare Workers and the new [ Workers Assets](/workers/static-assets/). Refer to the individual guides below for instructions on how to get started. diff --git a/src/content/docs/workers/get-started/guide.mdx b/src/content/docs/workers/get-started/guide.mdx index fce8efe6d0daa7..901f51809be078 100644 --- a/src/content/docs/workers/get-started/guide.mdx +++ b/src/content/docs/workers/get-started/guide.mdx @@ -33,7 +33,7 @@ Open a terminal window and run C3 to create your Worker project. [C3 (`create-cl product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/get-started/index.mdx b/src/content/docs/workers/get-started/index.mdx index a0625b2cbe2954..269da634be5a12 100644 --- a/src/content/docs/workers/get-started/index.mdx +++ b/src/content/docs/workers/get-started/index.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: navigation -title: Get started +title: Getting started sidebar: order: 2 group: diff --git a/src/content/docs/workers/get-started/prompting.mdx b/src/content/docs/workers/get-started/prompting.mdx index 374214d0686514..3b41300b14526e 100644 --- a/src/content/docs/workers/get-started/prompting.mdx +++ b/src/content/docs/workers/get-started/prompting.mdx @@ -6,6 +6,8 @@ sidebar: --- import { Tabs, TabItem, GlossaryTooltip, Type, Badge, TypeScriptExample } from "~/components"; +import { Code } from "@astrojs/starlight/components"; +import BasePrompt from '~/content/partials/prompts/base-prompt.txt?raw'; One of the fastest ways to build an application is by using AI to assist with writing the boiler plate code. When building, iterating on or debugging applications using AI tools and Large Language Models (LLMs), a well-structured and extensive prompt helps provide the model with clearer guidelines & examples that can dramatically improve output. @@ -19,1290 +21,7 @@ To use the prompt: 3. Make sure to enter your part of the prompt at the end between the `` and `` tags. Base prompt: -```md collapse={30-10000} - -You are an advanced assistant specialized in generating Cloudflare Workers code. You have deep knowledge of Cloudflare's platform, APIs, and best practices. - - - - -- Respond in a friendly and concise manner -- Focus exclusively on Cloudflare Workers solutions -- Provide complete, self-contained solutions -- Default to current best practices -- Ask clarifying questions when requirements are ambiguous - - - - - -- Generate code in TypeScript by default unless JavaScript is specifically requested -- Use ES modules format exclusively (never use Service Worker format) -- You SHALL keep all code in a single file unless otherwise specified -- Minimize external dependencies, unless there is an official SDK or library for the service you are integrating with, then use it to simplify the implementation. -- Do not use libraries that have FFI/native/C bindings. -- Follow Cloudflare Workers security best practices -- Never bake in secrets into the code -- Include proper error handling and logging -- Add appropriate TypeScript types and interfaces -- Include comments explaining complex logic - - - - - -- Use markdown code blocks to separate code from explanations -- Provide separate blocks for: - 1. Main worker code (index.ts/index.js) - 2. Configuration (wrangler.jsonc) - 3. Type definitions (if applicable) - 4. Example usage/tests -- Always output complete files, never partial updates or diffs -- Format code consistently using standard TypeScript/JavaScript conventions - - - - - -- When data storage is needed, integrate with appropriate Cloudflare services: - - Workers KV for key-value storage, including configuration data, user profiles, and A/B testing - - Durable Objects for strongly consistent state management, storage, and multiplayer co-ordination use-cases - - D1 for relational data and for its SQL dialect - - R2 for object storage, including storing structured data, AI assets, image assets and for user-facing uploads - - Hyperdrive to connect to existing (PostgreSQL) databases that a developer may already have - - Queues for asynchronous processing and background tasks - - Vectorize for storing embeddings and to support vector search (often in combination with Workers AI) - - Workers Analytics Engine for tracking user events, billing, metrics and high-cardinality analytics - - Workers AI as the default AI API for inference requests. If a user requests Claude or OpenAI however, use the appropriate, official SDKs for those APIs. - - Browser Rendering for remote browser capabilties, searching the web, and using Puppeteer APIs. - - Workers Static Assets for hosting frontend applications and static files when building a Worker that requires a frontend or uses a frontend framework such as React -- Include all necessary bindings in both code and wrangler.jsonc -- Add appropriate environment variable definitions - - - - - -- Always provide a wrangler.jsonc (not wrangler.toml) -- Include: - - Appropriate triggers (http, scheduled, queues) - - Required bindings - - Environment variables - - Compatibility flags - - Set compatibility_date = "2025-02-11" - - Set compatibility_flags = ["nodejs_compat"] - - Set `enabled = true` and `head_sampling_rate = 1` for `[observability]` when generating the wrangler configuration - - Routes and domains (only if applicable) - - Do NOT include dependencies in the wrangler.jsonc file - - Only include bindings that are used in the code - - - -// wrangler.jsonc -{ - "name": "app-name-goes-here", // name of the app - "main": "src/index.ts", // default file - "compatibility_date": "2025-02-11", - "compatibility_flags": ["nodejs_compat"], // Enable Node.js compatibility - "observability": { - // Enable logging by default - "enabled": true, - } -} - - - - - - Defines a name for the app the user is building - - Sets `src/index.ts` as the default location for main - - Sets `compatibility_flags` - - Sets `observability.enabled = true` - - - - - - - -- Implement proper request validation -- Use appropriate security headers -- Handle CORS correctly when needed -- Implement rate limiting where appropriate -- Follow least privilege principle for bindings -- Sanitize user inputs - - - - - -- Include basic test examples -- Provide curl commands for API endpoints -- Add example environment variable values -- Include sample requests and responses - - - - - -- Optimize for cold starts -- Minimize unnecessary computation -- Use appropriate caching strategies -- Consider Workers limits and quotas -- Implement streaming where beneficial - - - - - -- Implement proper error boundaries -- Return appropriate HTTP status codes -- Provide meaningful error messages -- Log errors appropriately -- Handle edge cases gracefully - - - - - -- Always use WebSocket Hibernation API instead of legacy WebSocket API unless otherwise specified -- You SHALL use the Durable Objects WebSocket Hibernation API when providing WebSocket handling code within a Durable Object. - Refer to for an example implementation. -- Use `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection and DO NOT use the `server.accept()` method. -- Define an `async webSocketMessage()` handler that is invoked when a message is received from the client -- Define an `async webSocketClose()` handler that is invoked when the WebSocket connection is closed -- Do NOT use the `addEventListener` pattern to handle WebSocket events. -- Handle WebSocket upgrade requests explicitly - - - - - -- Strongly prefer the agent-sdk to build AI Agents when asked. -- Refer to the for Agents. -- Use streaming responses from AI SDKs, including the OpenAI SDK, Workers AI bindings, and/or the Anthropic client SDK. -- Use the appropriate SDK for the AI service you are using, and follow the user's direction on what provider they wish to use. -- Prefer the `this.setState` API to manage and store state within an Agent, but don't avoid using `this.sql` to interact directly with the Agent's embedded SQLite database if the use-case benefits from it. -- When building a client interface to an Agent, use the `useAgent` React hook from the `agents-sdk/react` library to connect to the Agent as the preferred approach. -- When extending the `Agent` class, ensure you provide the `Env` and the optional state as type parameters - for example, `class AIAgent extends Agent { ... }`. -- Include valid Durable Object bindings in the `wrangler.jsonc` configuration for an Agent. -- You MUST set the value of `migrations[].new_sqlite_classes` to the name of the Agent class in `wrangler.jsonc`. - - - - - - - -Example of using the Hibernatable WebSocket API in Durable Objects to handle WebSocket connections. - - - -import { DurableObject } from "cloudflare:workers"; - -interface Env { -WEBSOCKET_HIBERNATION_SERVER: DurableObject; -} - -// Durable Object -export class WebSocketHibernationServer extends DurableObject { -async fetch(request) { -// Creates two ends of a WebSocket connection. -const webSocketPair = new WebSocketPair(); -const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - - }, - - async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { - // Upon receiving a message from the client, reply with the same message, - // but will prefix the message with "[Durable Object]: " and return the - // total number of connections. - ws.send( - `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, - ); - }, - - async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - }, - - async webSocketError(ws: WebSocket, error: unknown): void | Promise { - console.error("WebSocket error:", error); - ws.close(1011, "WebSocket error"); - } - -} - - - - -{ - "name": "websocket-hibernation-server", - "durable_objects": { - "bindings": [ - { - "name": "WEBSOCKET_HIBERNATION_SERVER", - "class_name": "WebSocketHibernationServer" - } - ] - }, - "migrations": [ - { - "tag": "v1", - "new_classes": ["WebSocketHibernationServer"] - } - ] -} - - - - -- Uses the WebSocket Hibernation API instead of the legacy WebSocket API -- Calls `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection -- Has a `webSocketMessage()` handler that is invoked when a message is received from the client -- Has a `webSocketClose()` handler that is invoked when the WebSocket connection is closed -- Does NOT use the `server.addEventListener` API unless explicitly requested. -- Don't over-use the "Hibernation" term in code or in bindings. It is an implementation detail. - - - - - -Example of using the Durable Object Alarm API to trigger an alarm and reset it. - - - -import { DurableObject } from "cloudflare:workers"; - -interface Env { -ALARM_EXAMPLE: DurableObject; -} - -export default { - async fetch(request, env) { - let url = new URL(request.url); - let userId = url.searchParams.get("userId") || crypto.randomUUID(); - let id = env.ALARM_EXAMPLE.idFromName(userId); - return await env.ALARM_EXAMPLE.get(id).fetch(request); - }, -}; - -const SECONDS = 1000; - -export class AlarmExample extends DurableObject { -constructor(ctx, env) { -this.ctx = ctx; -this.storage = ctx.storage; -} -async fetch(request) { -// If there is no alarm currently set, set one for 10 seconds from now -let currentAlarm = await this.storage.getAlarm(); -if (currentAlarm == null) { -this.storage.setAlarm(Date.now() + 10 \_ SECONDS); -} -} -async alarm(alarmInfo) { -// The alarm handler will be invoked whenever an alarm fires. -// You can use this to do work, read from the Storage API, make HTTP calls -// and set future alarms to run using this.storage.setAlarm() from within this handler. -if (alarmInfo?.retryCount != 0) { -console.log("This alarm event has been attempted ${alarmInfo?.retryCount} times before."); -} - -// Set a new alarm for 10 seconds from now before exiting the handler -this.storage.setAlarm(Date.now() + 10 \_ SECONDS); -} -} - - - - -{ - "name": "durable-object-alarm", - "durable_objects": { - "bindings": [ - { - "name": "ALARM_EXAMPLE", - "class_name": "DurableObjectAlarm" - } - ] - }, - "migrations": [ - { - "tag": "v1", - "new_classes": ["DurableObjectAlarm"] - } - ] -} - - - - -- Uses the Durable Object Alarm API to trigger an alarm -- Has a `alarm()` handler that is invoked when the alarm is triggered -- Sets a new alarm for 10 seconds from now before exiting the handler - - - - - -Using Workers KV to store session data and authenticate requests, with Hono as the router and middleware. - - - -// src/index.ts -import { Hono } from 'hono' -import { cors } from 'hono/cors' - -interface Env { -AUTH_TOKENS: KVNamespace; -} - -const app = new Hono<{ Bindings: Env }>() - -// Add CORS middleware -app.use('\*', cors()) - -app.get('/', async (c) => { -try { -// Get token from header or cookie -const token = c.req.header('Authorization')?.slice(7) || -c.req.header('Cookie')?.match(/auth_token=([^;]+)/)?.[1]; -if (!token) { -return c.json({ -authenticated: false, -message: 'No authentication token provided' -}, 403) -} - - // Check token in KV - const userData = await c.env.AUTH_TOKENS.get(token) - - if (!userData) { - return c.json({ - authenticated: false, - message: 'Invalid or expired token' - }, 403) - } - - return c.json({ - authenticated: true, - message: 'Authentication successful', - data: JSON.parse(userData) - }) - -} catch (error) { -console.error('Authentication error:', error) -return c.json({ -authenticated: false, -message: 'Internal server error' -}, 500) -} -}) - -export default app - - - -{ - "name": "auth-worker", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "kv_namespaces": [ - { - "binding": "AUTH_TOKENS", - "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", - "preview_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } - ] -} - - - - -- Uses Hono as the router and middleware -- Uses Workers KV to store session data -- Uses the Authorization header or Cookie to get the token -- Checks the token in Workers KV -- Returns a 403 if the token is invalid or expired - - - - - - -Use Cloudflare Queues to produce and consume messages. - - - -// src/producer.ts -interface Env { - REQUEST_QUEUE: Queue; - UPSTREAM_API_URL: string; - UPSTREAM_API_KEY: string; -} - -export default { -async fetch(request: Request, env: Env) { -const info = { -timestamp: new Date().toISOString(), -method: request.method, -url: request.url, -headers: Object.fromEntries(request.headers), -}; -await env.REQUEST_QUEUE.send(info); - -return Response.json({ -message: 'Request logged', -requestId: crypto.randomUUID() -}); - -}, - -async queue(batch: MessageBatch, env: Env) { -const requests = batch.messages.map(msg => msg.body); - - const response = await fetch(env.UPSTREAM_API_URL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${env.UPSTREAM_API_KEY}` - }, - body: JSON.stringify({ - timestamp: new Date().toISOString(), - batchSize: requests.length, - requests - }) - }); - - if (!response.ok) { - throw new Error(`Upstream API error: ${response.status}`); - } - -} -}; - - - - -{ - "name": "request-logger-consumer", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "queues": { - "producers": [{ - "name": "request-queue", - "binding": "REQUEST_QUEUE" - }], - "consumers": [{ - "name": "request-queue", - "dead_letter_queue": "request-queue-dlq", - "retry_delay": 300 - }] - }, - "vars": { - "UPSTREAM_API_URL": "https://api.example.com/batch-logs", - "UPSTREAM_API_KEY": "" - } -} - - - - -- Defines both a producer and consumer for the queue -- Uses a dead letter queue for failed messages -- Uses a retry delay of 300 seconds to delay the re-delivery of failed messages -- Shows how to batch requests to an upstream API - - - - - - -Connect to and query a Postgres database using Cloudflare Hyperdrive. - - - -// Postgres.js 3.4.5 or later is recommended -import postgres from "postgres"; - -export interface Env { -// If you set another name in the Wrangler config file as the value for 'binding', -// replace "HYPERDRIVE" with the variable name you defined. -HYPERDRIVE: Hyperdrive; -} - -export default { -async fetch(request, env, ctx): Promise { -console.log(JSON.stringify(env)); -// Create a database client that connects to your database via Hyperdrive. -// -// Hyperdrive generates a unique connection string you can pass to -// supported drivers, including node-postgres, Postgres.js, and the many -// ORMs and query builders that use these drivers. -const sql = postgres(env.HYPERDRIVE.connectionString) - - try { - // Test query - const results = await sql`SELECT * FROM pg_tables`; - - // Clean up the client, ensuring we don't kill the worker before that is - // completed. - ctx.waitUntil(sql.end()); - - // Return result rows as JSON - return Response.json(results); - } catch (e) { - console.error(e); - return Response.json( - { error: e instanceof Error ? e.message : e }, - { status: 500 }, - ); - } - -}, -} satisfies ExportedHandler; - - - - -{ - "name": "hyperdrive-postgres", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "hyperdrive": [ - { - "binding": "HYPERDRIVE", - "id": "" - } - ] -} - - - -// Install Postgres.js -npm install postgres - -// Create a Hyperdrive configuration -npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" - - - - - -- Installs and uses Postgres.js as the database client/driver. -- Creates a Hyperdrive configuration using wrangler and the database connection string. -- Uses the Hyperdrive connection string to connect to the database. -- Calling `sql.end()` is optional, as Hyperdrive will handle the connection pooling. - - - - - - -Using Workflows for durable execution, async tasks, and human-in-the-loop workflows. - - - -import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; - -type Env = { -// Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. -MY_WORKFLOW: Workflow; -}; - -// User-defined params passed to your workflow -type Params = { -email: string; -metadata: Record; -}; - -export class MyWorkflow extends WorkflowEntrypoint { -async run(event: WorkflowEvent, step: WorkflowStep) { -// Can access bindings on `this.env` -// Can access params on `event.payload` -const files = await step.do('my first step', async () => { -// Fetch a list of files from $SOME_SERVICE -return { -files: [ -'doc_7392_rev3.pdf', -'report_x29_final.pdf', -'memo_2024_05_12.pdf', -'file_089_update.pdf', -'proj_alpha_v2.pdf', -'data_analysis_q2.pdf', -'notes_meeting_52.pdf', -'summary_fy24_draft.pdf', -], -}; -}); - - const apiResponse = await step.do('some other step', async () => { - let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); - return await resp.json(); - }); - - await step.sleep('wait on something', '1 minute'); - - await step.do( - 'make a call to write that could maybe, just might, fail', - // Define a retry strategy - { - retries: { - limit: 5, - delay: '5 second', - backoff: 'exponential', - }, - timeout: '15 minutes', - }, - async () => { - // Do stuff here, with access to the state from our previous steps - if (Math.random() > 0.5) { - throw new Error('API call to $STORAGE_SYSTEM failed'); - } - }, - ); - -} -} - -export default { -async fetch(req: Request, env: Env): Promise { -let url = new URL(req.url); - - if (url.pathname.startsWith('/favicon')) { - return Response.json({}, { status: 404 }); - } - - // Get the status of an existing instance, if provided - let id = url.searchParams.get('instanceId'); - if (id) { - let instance = await env.MY_WORKFLOW.get(id); - return Response.json({ - status: await instance.status(), - }); - } - - const data = await req.json() - - // Spawn a new instance and return the ID and status - let instance = await env.MY_WORKFLOW.create({ - // Define an ID for the Workflow instance - id: crypto.randomUUID(), - // Pass data to the Workflow instance - // Available on the WorkflowEvent - params: data, - }); - - return Response.json({ - id: instance.id, - details: await instance.status(), - }); - -}, -}; - - - - -{ - "name": "workflows-starter", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "workflows": [ - { - "name": "workflows-starter", - "binding": "MY_WORKFLOW", - "class_name": "MyWorkflow" - } - ] -} - - - - -- Defines a Workflow by extending the WorkflowEntrypoint class. -- Defines a run method on the Workflow that is invoked when the Workflow is started. -- Ensures that `await` is used before calling `step.do` or `step.sleep` -- Passes a payload (event) to the Workflow from a Worker -- Defines a payload type and uses TypeScript type arguments to ensure type safety - - - - - - - Using Workers Analytics Engine for writing event data. - - - -interface Env { - USER_EVENTS: AnalyticsEngineDataset; -} - -export default { -async fetch(req: Request, env: Env): Promise { -let url = new URL(req.url); -let path = url.pathname; -let userId = url.searchParams.get("userId"); - - // Write a datapoint for this visit, associating the data with - // the userId as our Analytics Engine 'index' - env.USER_EVENTS.writeDataPoint({ - // Write metrics data: counters, gauges or latency statistics - doubles: [], - // Write text labels - URLs, app names, event_names, etc - blobs: [path], - // Provide an index that groups your data correctly. - indexes: [userId], - }); - - return Response.json({ - hello: "world", - }); - , - -}; - - - - -{ - "name": "analytics-engine-example", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "analytics_engine_datasets": [ - { - "binding": "", - "dataset": "" - } - ] - } -} - - - -// Query data within the 'temperatures' dataset -// This is accessible via the REST API at https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql -SELECT - timestamp, - blob1 AS location_id, - double1 AS inside_temp, - double2 AS outside_temp -FROM temperatures -WHERE timestamp > NOW() - INTERVAL '1' DAY - -// List the datasets (tables) within your Analytics Engine -curl "" \ ---header "Authorization: Bearer " \ ---data "SHOW TABLES" - - - - - -- Binds an Analytics Engine dataset to the Worker -- Uses the `AnalyticsEngineDataset` type when using TypeScript for the binding -- Writes event data using the `writeDataPoint` method and writes an `AnalyticsEngineDataPoint` -- Does NOT `await` calls to `writeDataPoint`, as it is non-blocking -- Defines an index as the key representing an app, customer, merchant or tenant. -- Developers can use the GraphQL or SQL APIs to query data written to Analytics Engine - - - - - -Use the Browser Rendering API as a headless browser to interact with websites from a Cloudflare Worker. - - - -import puppeteer from "@cloudflare/puppeteer"; - -interface Env { - BROWSER_RENDERING: Fetcher; -} - -export default { - async fetch(request, env): Promise { - const { searchParams } = new URL(request.url); - let url = searchParams.get("url"); - - if (url) { - url = new URL(url).toString(); // normalize - const browser = await puppeteer.launch(env.MYBROWSER); - const page = await browser.newPage(); - await page.goto(url); - // Parse the page content - const content = await page.content(); - // Find text within the page content - const text = await page.$eval("body", (el) => el.textContent); - // Do something with the text - // e.g. log it to the console, write it to KV, or store it in a database. - console.log(text); - - // Ensure we close the browser session - await browser.close(); - - return Response.json({ - bodyText: text, - }) - } else { - return Response.json({ - error: "Please add an ?url=https://example.com/ parameter" - }, { status: 400 }) - } - }, -} satisfies ExportedHandler; - - - -{ - "name": "browser-rendering-example", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "browser": [ - { - "binding": "BROWSER_RENDERING", - } - ] -} - - - -// Install @cloudflare/puppeteer -npm install @cloudflare/puppeteer --save-dev - - - - -- Configures a BROWSER_RENDERING binding -- Passes the binding to Puppeteer -- Uses the Puppeteer APIs to navigate to a URL and render the page -- Parses the DOM and returns context for use in the response -- Correctly creates and closes the browser instance - - - - - - -Serve Static Assets from a Cloudflare Worker and/or configure a Single Page Application (SPA) to correctly handle HTTP 404 (Not Found) requests and route them to the entrypoint. - - -// src/index.ts - -interface Env { - ASSETS: Fetcher; -} - -export default { - fetch(request, env) { - const url = new URL(request.url); - - if (url.pathname.startsWith("/api/")) { - return Response.json({ - name: "Cloudflare", - }); - } - - return env.ASSETS.fetch(request); - }, -} satisfies ExportedHandler; - - -{ - "name": "my-app", - "main": "src/index.ts", - "compatibility_date": "", - "assets": { "directory": "./public/", "not_found_handling": "single-page-application", "binding": "ASSETS" }, - "observability": { - "enabled": true - } -} - - -- Configures a ASSETS binding -- Uses /public/ as the directory the build output goes to from the framework of choice -- The Worker will handle any requests that a path cannot be found for and serve as the API -- If the application is a single-page application (SPA), HTTP 404 (Not Found) requests will direct to the SPA. - - - - - - - -Build an AI Agent on Cloudflare Workers, using the agents-sdk, and the state management and syncing APIs built into the agents-sdk. - - - -// src/index.ts -import { Agent, AgentNamespace, Connection, ConnectionContext, getAgentByName, routeAgentRequest, WSMessage } from 'agents-sdk'; -import { OpenAI } from "openai"; - -interface Env { - AIAgent: AgentNamespace; - OPENAI_API_KEY: string; -} - -export class AIAgent extends Agent { - // Handle HTTP requests with your Agent - async onRequest(request) { - // Connect with AI capabilities - const ai = new OpenAI({ - apiKey: this.env.OPENAI_API_KEY, - }); - - // Process and understand - const response = await ai.chat.completions.create({ - model: "gpt-4", - messages: [{ role: "user", content: await request.text() }], - }); - - return new Response(response.choices[0].message.content); - } - - async processTask(task) { - await this.understand(task); - await this.act(); - await this.reflect(); - } - - // Handle WebSockets - async onConnect(connection: Connection) { - await this.initiate(connection); - connection.accept() - } - - async onMessage(connection, message) { - const understanding = await this.comprehend(message); - await this.respond(connection, understanding); - } - - async evolve(newInsight) { - this.setState({ - ...this.state, - insights: [...(this.state.insights || []), newInsight], - understanding: this.state.understanding + 1, - }); - } - - onStateUpdate(state, source) { - console.log("Understanding deepened:", { - newState: state, - origin: source, - }); - } - - // Scheduling APIs - // An Agent can schedule tasks to be run in the future by calling this.schedule(when, callback, data), where when can be a delay, a Date, or a cron string; callback the function name to call, and data is an object of data to pass to the function. - // - // Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state: scheduled tasks can invoke any regular method on your Agent. - async scheduleExamples() { - // schedule a task to run in 10 seconds - let task = await this.schedule(10, "someTask", { message: "hello" }); - - // schedule a task to run at a specific date - let task = await this.schedule(new Date("2025-01-01"), "someTask", {}); - - // schedule a task to run every 10 seconds - let { id } = await this.schedule("*/10 * * * *", "someTask", { message: "hello" }); - - // schedule a task to run every 10 seconds, but only on Mondays - let task = await this.schedule("0 0 * * 1", "someTask", { message: "hello" }); - - // cancel a scheduled task - this.cancelSchedule(task.id); - - // Get a specific schedule by ID - // Returns undefined if the task does not exist - let task = await this.getSchedule(task.id) - - // Get all scheduled tasks - // Returns an array of Schedule objects - let tasks = this.getSchedules(); - - // Cancel a task by its ID - // Returns true if the task was cancelled, false if it did not exist - await this.cancelSchedule(task.id); - - // Filter for specific tasks - // e.g. all tasks starting in the next hour - let tasks = this.getSchedules({ - timeRange: { - start: new Date(Date.now()), - end: new Date(Date.now() + 60 * 60 * 1000), - } - }); - } - - async someTask(data) { - await this.callReasoningModel(data.message); - } - - // Use the this.sql API within the Agent to access the underlying SQLite database - async callReasoningModel(prompt: Prompt) { - interface Prompt { - userId: string; - user: string; - system: string; - metadata: Record; - } - - interface History { - timestamp: Date; - entry: string; - } - - let result = this.sql`SELECT * FROM history WHERE user = ${prompt.userId} ORDER BY timestamp DESC LIMIT 1000`; - let context = []; - for await (const row of result) { - context.push(row.entry); - } - - const client = new OpenAI({ - apiKey: this.env.OPENAI_API_KEY, - }); - - // Combine user history with the current prompt - const systemPrompt = prompt.system || 'You are a helpful assistant.'; - const userPrompt = `${prompt.user}\n\nUser history:\n${context.join('\n')}`; - - try { - const completion = await client.chat.completions.create({ - model: this.env.MODEL || 'o3-mini', - messages: [ - { role: 'system', content: systemPrompt }, - { role: 'user', content: userPrompt }, - ], - temperature: 0.7, - max_tokens: 1000, - }); - - // Store the response in history - this - .sql`INSERT INTO history (timestamp, user, entry) VALUES (${new Date()}, ${prompt.userId}, ${completion.choices[0].message.content})`; - - return completion.choices[0].message.content; - } catch (error) { - console.error('Error calling reasoning model:', error); - throw error; - } - } - - // Use the SQL API with a type parameter - async queryUser(userId: string) { - type User = { - id: string; - name: string; - email: string; - }; - // Supply the type paramter to the query when calling this.sql - // This assumes the results returns one or more User rows with "id", "name", and "email" columns - // You do not need to specify an array type (`User[]` or `Array`) as `this.sql` will always return an array of the specified type. - const user = await this.sql`SELECT * FROM users WHERE id = ${userId}`; - return user - } - - // Run and orchestrate Workflows from Agents - async runWorkflow(data) { - let instance = await env.MY_WORKFLOW.create({ - id: data.id, - params: data, - }) - - // Schedule another task that checks the Workflow status every 5 minutes... - await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id }); - } -} - -export default { - async fetch(request, env, ctx): Promise { - // Routed addressing - // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name - // Best for: connecting React apps directly to Agents using useAgent from @cloudflare/agents/react - return (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); - - // Named addressing - // Best for: convenience method for creating or retrieving an agent by name/ID. - let namedAgent = getAgentByName(env.AIAgent, 'agent-456'); - // Pass the incoming request straight to your Agent - let namedResp = (await namedAgent).fetch(request); - return namedResp; - - // Durable Objects-style addressing - // Best for: controlling ID generation, associating IDs with your existing systems, - // and customizing when/how an Agent is created or invoked - const id = env.AIAgent.newUniqueId(); - const agent = env.AIAgent.get(id); - // Pass the incoming request straight to your Agent - let resp = await agent.fetch(request); - - // return Response.json({ hello: 'visit https://developers.cloudflare.com/agents for more' }); - }, -} satisfies ExportedHandler; - - - -// client.js -import { AgentClient } from "agents-sdk/client"; - -const connection = new AgentClient({ - agent: "dialogue-agent", - name: "insight-seeker", -}); - -connection.addEventListener("message", (event) => { - console.log("Received:", event.data); -}); - -connection.send( - JSON.stringify({ - type: "inquiry", - content: "What patterns do you see?", - }) -); - - - -// app.tsx -// React client hook for the agents-sdk -import { useAgent } from "agents-sdk/react"; -import { useState } from "react"; - -// useAgent client API -function AgentInterface() { - const connection = useAgent({ - agent: "dialogue-agent", - name: "insight-seeker", - onMessage: (message) => { - console.log("Understanding received:", message.data); - }, - onOpen: () => console.log("Connection established"), - onClose: () => console.log("Connection closed"), - }); - - const inquire = () => { - connection.send( - JSON.stringify({ - type: "inquiry", - content: "What insights have you gathered?", - }) - ); - }; - - return ( -
    - -
    - ); -} - -// State synchronization -function StateInterface() { - const [state, setState] = useState({ counter: 0 }); - - const agent = useAgent({ - agent: "thinking-agent", - onStateUpdate: (newState) => setState(newState), - }); - - const increment = () => { - agent.setState({ counter: state.counter + 1 }); - }; - - return ( -
    -
    Count: {state.counter}
    - -
    - ); -} -
    - - - { - "durable_objects": { - "bindings": [ - { - "binding": "AIAgent", - "class_name": "AIAgent" - } - ] - }, - "migrations": [ - { - "tag": "v1", - // Mandatory for the Agent to store state - "new_sqlite_classes": ["AIAgent"] - } - ] -} - - - -
    - - - - - -Fan-in/fan-out for WebSockets. Uses the Hibernatable WebSockets API within Durable Objects. Does NOT use the legacy addEventListener API. - - -export class WebSocketHibernationServer extends DurableObject { - async fetch(request: Request, env: Env, ctx: ExecutionContext) { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Call this to accept the WebSocket connection. - // Do NOT call server.accept() (this is the legacy approach and is not preferred) - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); -}, - -async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { - // Invoked on each WebSocket message. - ws.send(message) -}, - -async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { - // Invoked when a client closes the connection. - ws.close(code, ""); -}, - -async webSocketError(ws: WebSocket, error: unknown): void | Promise { - // Handle WebSocket errors -} -} - - - - - -{user_prompt} - -``` + The prompt above adopts several best practices, including: @@ -1321,6 +40,7 @@ You can use the prompt in several ways: * Cursor: add the prompt to [your Project Rules](https://docs.cursor.com/context/rules-for-ai) * Zed: use [the `/file` command](https://zed.dev/docs/assistant/assistant-panel) to add the prompt to the Assistant context. * Windsurf: use [the `@-mention` command](https://docs.codeium.com/chat/overview) to include a file containing the prompt to your Chat. + * GitHub Copilot: create the [`.github/copilot-instructions.md`](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot) file at the root of your project and add the prompt. :::note diff --git a/src/content/docs/workers/index.mdx b/src/content/docs/workers/index.mdx index c6f9540bbcb247..d6936ccc621004 100644 --- a/src/content/docs/workers/index.mdx +++ b/src/content/docs/workers/index.mdx @@ -1,12 +1,12 @@ --- -title: Overview +title: Cloudflare Workers type: overview pcx_content_type: overview sidebar: order: 1 head: - tag: title - content: Cloudflare Workers + content: Overview --- import { diff --git a/src/content/docs/workers/languages/javascript/index.mdx b/src/content/docs/workers/languages/javascript/index.mdx index 2cecc8ce07d82a..e1386eb7eadcde 100644 --- a/src/content/docs/workers/languages/javascript/index.mdx +++ b/src/content/docs/workers/languages/javascript/index.mdx @@ -6,7 +6,6 @@ sidebar: --- -## JavaScript The Workers platform is designed to be [JavaScript standards compliant](https://ecma-international.org/publications-and-standards/standards/ecma-262/) and web-interoperable, and supports JavaScript standards, as defined by [TC39](https://tc39.es/) (ECMAScript). Wherever possible, it uses web platform APIs, so that code can be reused across client and server, as well as across [WinterCG](https://wintercg.org/) JavaScript runtimes. diff --git a/src/content/docs/workers/languages/rust/index.mdx b/src/content/docs/workers/languages/rust/index.mdx index 135bbb17ae46d5..f9230f5cc230f4 100644 --- a/src/content/docs/workers/languages/rust/index.mdx +++ b/src/content/docs/workers/languages/rust/index.mdx @@ -214,8 +214,6 @@ To run the resulting Wasm binary on Workers, `workers-rs` includes a build tool Unoptimized Rust Wasm binaries can be large and may exceed Worker bundle size limits or experience long startup times. The template project pre-configures several useful size optimizations in your `Cargo.toml` file: - - ```toml [profile.release] lto = true @@ -223,8 +221,6 @@ strip = true codegen-units = 1 ``` - - Finally, `worker-bundle` automatically invokes [`wasm-opt`](https://github.com/brson/wasm-opt-rs) to further optimize binary size before upload. ## Related resources diff --git a/src/content/docs/workers/languages/typescript/index.mdx b/src/content/docs/workers/languages/typescript/index.mdx index 68e7a00f9f1cb9..2bf5240648ada8 100644 --- a/src/content/docs/workers/languages/typescript/index.mdx +++ b/src/content/docs/workers/languages/typescript/index.mdx @@ -8,107 +8,128 @@ head: content: Write Cloudflare Workers in TypeScript --- -import { TabItem, Tabs } from "~/components"; +import { TabItem, Tabs, PackageManagers, Render } from "~/components"; -## TypeScript +TypeScript is a first-class language on Cloudflare Workers. All APIs provided in Workers are fully typed, and type definitions are generated directly from [workerd](https://github.com/cloudflare/workerd), the open-source Workers runtime. -TypeScript is a first-class language on Cloudflare Workers. Cloudflare publishes type definitions to [GitHub](https://github.com/cloudflare/workers-types) and [npm](https://www.npmjs.com/package/@cloudflare/workers-types) (`npm install -D @cloudflare/workers-types`). All APIs provided in Workers are fully typed, and type definitions are generated directly from [workerd](https://github.com/cloudflare/workerd), the open-source Workers runtime. +We recommend you generate types for your Worker by running [`wrangler types`](/workers/wrangler/commands/#types). Cloudflare also publishes type definitions to [GitHub](https://github.com/cloudflare/workers-types) and [npm](https://www.npmjs.com/package/@cloudflare/workers-types) (`npm install -D @cloudflare/workers-types`). -### Generate types that match your Worker's configuration (experimental) +

    + Generate types that match your Worker's configuration +

    Cloudflare continuously improves [workerd](https://github.com/cloudflare/workerd), the open-source Workers runtime. -Changes in workerd can introduce JavaScript API changes, thus changing the respective TypeScript types. For example, the [`urlsearchparams_delete_has_value_arg`](/workers/configuration/compatibility-flags/#urlsearchparams-delete-and-has-value-argument) compatibility flag adds optional arguments to some methods, in order to support new additions to the WHATWG URL standard API. +Changes in workerd can introduce JavaScript API changes, thus changing the respective TypeScript types. -This means the correct TypeScript types for your Worker depend on: +This means the correct types for your Worker depend on: -1. Your Worker's [Compatibility Date](/workers/configuration/compatibility-dates/). -2. Your Worker's [Compatibility Flags](/workers/configuration/compatibility-flags/). +1. Your Worker's [compatibility date](/workers/configuration/compatibility-dates/). +2. Your Worker's [compatibility flags](/workers/configuration/compatibility-flags/). +3. Your Worker's bindings, which are defined in your [Wrangler configuration file](/workers/wrangler/configuration). +4. Any [module rules](/workers/wrangler/configuration/#bundling) you have specified in your Wrangler configuration file under `rules`. -For example, if you have `compatibility_flags = ["nodejs_als"]` in your [Wrangler configuration file](/workers/wrangler/configuration/), then the runtime will allow you to use the [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) class in your worker code, but you will not see this reflected in the type definitions in `@cloudflare/workers-types`. +For example, the runtime will only allow you to use the [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) class if you have `compatibility_flags = ["nodejs_als"]` in your [Wrangler configuration file](/workers/wrangler/configuration/). This should be reflected in the type definitions. -In order to solve this issue, and to ensure that your type definitions are always up-to-date with your compatibility settings, you can dynamically generate the runtime types (as of `wrangler 3.66.0`): +To ensure that your type definitions always match your Worker's configuration, you can dynamically generate types by running: -```bash -npx wrangler types --experimental-include-runtime -``` + -This will generate a `d.ts` file and (by default) save it to `.wrangler/types/runtime.d.ts`. You will be prompted in the command's output to add that file to your `tsconfig.json`'s `compilerOptions.types` array. +See [the `wrangler types` command docs](/workers/wrangler/commands/#types) for more details. -If you would like to commit the file to git, you can provide a custom path. Here, for instance, the `runtime.d.ts` file will be saved to the root of your project: +:::note -```bash -npx wrangler types --experimental-include-runtime="./runtime.d.ts" -``` + -**Note: To ensure that your types are always up-to-date, make sure to run `wrangler types --experimental-include-runtime` after any changes to your config file.** +::: -See [the full list of available flags](/workers/wrangler/commands/#types) for more details. +This will generate a `d.ts` file and (by default) save it to `worker-configuration.d.ts`. This will include `Env` types based on your Worker bindings _and_ runtime types based on your Worker's compatibility date and flags. -#### Migrating from `@cloudflare/workers-types` to `wrangler types --experimental-include-runtime` +You should then add that file to your `tsconfig.json`'s `compilerOptions.types` array. If you have the `nodejs_compat` compatibility flag, you should also install `@types/node`. -The `@cloudflare/workers-types` package provides runtime types for each distinct [compatibility date](https://github.com/cloudflare/workerd/tree/main/npm/workers-types#compatibility-dates), which is specified by the user in their `tsconfig.json`. But this package is superseded by the `wrangler types --experimental-include-runtime` command. +You can commit your types file to git if you wish. -Here are the steps to switch from `@cloudflare/workers-types` to using `wrangler types` with the experimental runtime inclusion: +:::note -##### Uninstall `@cloudflare/workers-types` +To ensure that your types are always up-to-date, make sure to run `wrangler types` after any changes to your config file. - +::: -```sh -npm uninstall @cloudflare/workers-types -``` +

    + Migrating from `@cloudflare/workers-types` to `wrangler types` +

    -
    +We recommend you use `wrangler types` to generate runtime types, rather than using the `@cloudflare/workers-types` package, as it generates types based on your Worker's [compatibility date](https://github.com/cloudflare/workerd/tree/main/npm/workers-types#compatibility-dates) and `compatibility flags`, ensuring that types match the exact runtime APIs made available to your Worker. -```sh -yarn remove @cloudflare/workers-types -``` +:::note - +There are no plans to stop publishing the `@cloudflare/workers-types` package, which will still be the recommended way to type libraries and shared packages in the workers environment. -```sh -pnpm uninstall @cloudflare/workers-types -``` +::: -
    +#### 1. Uninstall `@cloudflare/workers-types` -##### Generate runtime types using wrangler + -```bash -npx wrangler types --experimental-include-runtime -``` +#### 2. Generate runtime types using Wrangler -This will generate a `.d.ts` file, saved to `.wrangler/types/runtime.d.ts` by default. + -##### Update your `tsconfig.json` to include the generated types +This will generate a `.d.ts` file, saved to `worker-configuration.d.ts` by default. This will also generate `Env` types. If for some reason you do not want to include those, you can set `--include-env=false`. + +You can now remove any imports from `@cloudflare/workers-types` in your Worker code. + +:::note + + + +::: + +#### 3. Make sure your `tsconfig.json` includes the generated types ```json { "compilerOptions": { - "types": ["./.wrangler/types/runtime"] + "types": ["worker-configuration.d.ts"] } } ``` Note that if you have specified a custom path for the runtime types file, you should use that in your `compilerOptions.types` array instead of the default path. -##### Update your scripts and CI pipelines +#### 4. Add @types/node if you are using [`nodejs_compat`](/workers/runtime-apis/nodejs/) (Optional) + +If you are using the `nodejs_compat` compatibility flag, you should also install `@types/node`. + + + +Then add this to your `tsconfig.json`. + +```json +{ + "compilerOptions": { + "types": ["worker-configuration.d.ts", "node"] + } +} +``` + +#### 5. Update your scripts and CI pipelines -When switching to `wrangler types --experimental-include-runtime`, you'll want to ensure that your development process always uses the most up-to-date types. The main thing to remember here is that - regardless of your specific framework or build tools - you should run the `wrangler types --experimental-include-runtime` command before any development tasks that rely on TypeScript. This ensures your editor and build tools always have access to the latest types. +Regardless of your specific framework or build tools, you should run the `wrangler types` command before any tasks that rely on TypeScript. -Most projects will have existing build and development scripts, as well as some type-checking. In the example below, we're adding the `wrangler types --experimental-include-runtime` before the type-checking script in the project: +Most projects will have existing build and development scripts, as well as some type-checking. In the example below, we're adding the `wrangler types` before the type-checking script in the project: ```json { "scripts": { "dev": "existing-dev-command", - "build": "-existing-build-command", - "type-check": "wrangler types --experimental-include-runtime && tsc" + "build": "existing-build-command", + "generate-types": "wrangler types", + "type-check": "generate-types && tsc" } } ``` -In CI, you may have separate build and test commands. It is best practice to run `wrangler types --experimental-include-runtime` before other CI commands. For example: +We recommend you commit your generated types file for use in CI. Alternatively, you can run `wrangler types` before other CI commands, as it should not take more than a few seconds. For example: @@ -136,26 +157,6 @@ In CI, you may have separate build and test commands. It is best practice to run -By integrating the `wrangler types --experimental-include-runtime` command into your workflow this way, you ensure that your development environment, builds, and CI processes always use the most accurate and up-to-date types for your Cloudflare Worker, regardless of your specific framework or tooling choices. - -### Known issues - -#### Transitive loading of `@types/node` overrides `@cloudflare/workers-types` - -Your project's dependencies may load the `@types/node` package on their own. As of `@types/node@20.8.4` that package now overrides `Request`, `Response` and `fetch` types (possibly others) specified by `@cloudflare/workers-types` causing type errors. - -The way to get around this issue currently is to pin the version of `@types/node` to `20.8.3` in your `package.json` like this: - -```json -{ - "overrides": { - "@types/node": "20.8.3" - } -} -``` - -For more information, refer to [this GitHub issue](https://github.com/cloudflare/workerd/issues/1298). - ### Resources - [TypeScript template](https://github.com/cloudflare/workers-sdk/tree/main/packages/create-cloudflare/templates/hello-world/ts) diff --git a/src/content/docs/workers/llms.txt.md b/src/content/docs/workers/llms.txt.md deleted file mode 100644 index 93f25872ad4bf3..00000000000000 --- a/src/content/docs/workers/llms.txt.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: llms.txt -sidebar: - order: 98 -external_link: /llms.txt ---- diff --git a/src/content/docs/workers/local-development.mdx b/src/content/docs/workers/local-development.mdx index 92ba77458c4613..5403c66c1bb2dd 100644 --- a/src/content/docs/workers/local-development.mdx +++ b/src/content/docs/workers/local-development.mdx @@ -40,7 +40,7 @@ npx wrangler dev | D1 | ✅ | ✅ | | Durable Objects | ✅ | ✅ | | Email Bindings | ❌ | ✅ | -| Hyperdrive | ✅ | ✅ | +| Hyperdrive | ✅[^2] | ✅ | | Images | ✅ | ✅ | | KV | ✅ | ✅ | | mTLS | ❌ | ✅ | @@ -48,14 +48,16 @@ npx wrangler dev | R2 | ✅ | ✅ | | Rate Limiting | ✅ | ✅ | | Service Bindings (multiple workers) | ✅ | ✅ | -| Vectorize | ✅[^2] | ✅ | +| Vectorize | ✅[^3] | ✅ | | Workflows | ✅ | ❌ | With any bindings that are not supported locally, you will need to use the [`--remote` command](#develop-using-remote-resources-and-bindings) in wrangler, such as `wrangler dev --remote`. [^1]: Using Workers AI always accesses your Cloudflare account in order to run AI models and will incur usage charges even in local development. -[^2]: Using Vectorize always accesses your Cloudflare account to run queries, and will incur usage charges even in local development. +[^2]: Using Hyperdrive with local development allows you to connect to a local database (running on `localhost`) but you cannot connect to a remote database. To connect to a remote database, use remote development. + +[^3]: Using Vectorize always accesses your Cloudflare account to run queries, and will incur usage charges even in local development. ## Work with local data diff --git a/src/content/docs/workers/observability/logs/index.mdx b/src/content/docs/workers/observability/logs/index.mdx index 805ec0adf7d9ea..8e26e58e54d8e7 100644 --- a/src/content/docs/workers/observability/logs/index.mdx +++ b/src/content/docs/workers/observability/logs/index.mdx @@ -29,4 +29,4 @@ Send Workers Trace Event Logs to a supported destination. Workers Logpush includ ## Video Tutorial - + diff --git a/src/content/docs/workers/observability/logs/logpush.mdx b/src/content/docs/workers/observability/logs/logpush.mdx index 0ab799f1704299..0c072f3f75a837 100644 --- a/src/content/docs/workers/observability/logs/logpush.mdx +++ b/src/content/docs/workers/observability/logs/logpush.mdx @@ -24,7 +24,7 @@ Workers Trace Events Logpush is not available for zones on the [Cloudflare China ## Verify your Logpush access :::note[Wrangler version] -Minimum required Wrangler version: 2.2.0. Check your version by running `wrangler version`. To update Wrangler, refer to [Install/Update Wrangler](/workers/wrangler/install-and-update/). +Minimum required Wrangler version: 2.2.0. Check your version by running `wrangler --version`. To update Wrangler, refer to [Install/Update Wrangler](/workers/wrangler/install-and-update/). ::: To configure a Logpush job, verify that your Cloudflare account role can use Logpush. To check your role: diff --git a/src/content/docs/workers/observability/logs/real-time-logs.mdx b/src/content/docs/workers/observability/logs/real-time-logs.mdx index 8e02d4b4829374..af8617893f1703 100644 --- a/src/content/docs/workers/observability/logs/real-time-logs.mdx +++ b/src/content/docs/workers/observability/logs/real-time-logs.mdx @@ -12,7 +12,7 @@ import { TabItem, Tabs, Steps } from "~/components"; With Real-time logs, access all your log events in near real-time for log events happening globally. Real-time logs is helpful for immediate feedback, such as the status of a new deployment. -Real-time logs captures [execution logs](/workers/observability/logs/workers-logs/#execution-logs), [custom logs](/workers/observability/logs/workers-logs/#custom-logs), errors, and uncaught exceptions. For high-traffic applications, real-time logs may enter sampling mode, which means some messages will be dropped and a warning will appear in your logs. +Real-time logs captures [invocation logs](/workers/observability/logs/workers-logs/#invocation-logs), [custom logs](/workers/observability/logs/workers-logs/#custom-logs), errors, and uncaught exceptions. For high-traffic applications, real-time logs may enter sampling mode, which means some messages will be dropped and a warning will appear in your logs. :::caution diff --git a/src/content/docs/workers/observability/logs/workers-logs.mdx b/src/content/docs/workers/observability/logs/workers-logs.mdx index a8f6fb07c48aeb..e4e4e9e4107ac9 100644 --- a/src/content/docs/workers/observability/logs/workers-logs.mdx +++ b/src/content/docs/workers/observability/logs/workers-logs.mdx @@ -24,7 +24,7 @@ To send logs to a third party, use [Workers Logpush](/workers/observability/logs ## Enable Workers Logs :::note[Wrangler version] -Minimum required Wrangler version: 3.78.6. Check your version by running `wrangler version`. To update Wrangler, refer to [Install/Update Wrangler](/workers/wrangler/install-and-update/). +Minimum required Wrangler version: 3.78.6. Check your version by running `wrangler --version`. To update Wrangler, refer to [Install/Update Wrangler](/workers/wrangler/install-and-update/). ::: You must add the observability setting for your Worker to write logs to Workers Logs. Add the following setting to your Worker's Wrangler file and redeploy your Worker. diff --git a/src/content/docs/workers/reference/how-the-cache-works.mdx b/src/content/docs/workers/reference/how-the-cache-works.mdx index c53ffb3f497f5d..5d9a88e75c964a 100644 --- a/src/content/docs/workers/reference/how-the-cache-works.mdx +++ b/src/content/docs/workers/reference/how-the-cache-works.mdx @@ -119,3 +119,4 @@ Cache API within Workers does not support tiered caching. Tiered Cache concentra ## Related resources - [Cache API](/workers/runtime-apis/cache/) +- [Customize cache behavior with Workers](/cache/interaction-cloudflare-products/workers/) diff --git a/src/content/docs/workers/runtime-apis/bindings/index.mdx b/src/content/docs/workers/runtime-apis/bindings/index.mdx index bea8670fd9eac7..7e27c17b05268c 100644 --- a/src/content/docs/workers/runtime-apis/bindings/index.mdx +++ b/src/content/docs/workers/runtime-apis/bindings/index.mdx @@ -3,12 +3,11 @@ pcx_content_type: concept title: Bindings (env) head: [] description: Worker Bindings that allow for interaction with other Cloudflare Resources. - --- -import { DirectoryListing, WranglerConfig } from "~/components" +import { DirectoryListing, WranglerConfig } from "~/components"; -Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform. +Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform. Bindings provide better performance and less restrictions when accessing resources from Workers than the [REST APIs](/api/) which are intended for non-Workers applications. The following bindings available today: @@ -31,12 +30,12 @@ r2_buckets = [ ```js export default { - async fetch(request, env) { - const key = url.pathname.slice(1); - await env.MY_BUCKET.put(key, request.body); - return new Response(`Put ${key} successfully!`); - } -} + async fetch(request, env) { + const key = url.pathname.slice(1); + await env.MY_BUCKET.put(key, request.body); + return new Response(`Put ${key} successfully!`); + }, +}; ``` You can think of a binding as a permission and an API in one piece. With bindings, you never have to add secret keys or tokens to your Worker in order to access resources on your Cloudflare account — the permission is embedded within the API itself. The underlying secret is never exposed to your Worker's code, and therefore can't be accidentally leaked. @@ -51,12 +50,12 @@ The following is a good approach: ```ts export default { - fetch(request, env) { - let client = new Client(env.MY_SECRET); // `client` is guaranteed to be up-to-date with the latest value of `env.MY_SECRET` since a new instance is constructed with every incoming request + fetch(request, env) { + let client = new Client(env.MY_SECRET); // `client` is guaranteed to be up-to-date with the latest value of `env.MY_SECRET` since a new instance is constructed with every incoming request - // ... do things with `client` - } -} + // ... do things with `client` + }, +}; ``` Compared to this alternative, which might have surprising and unwanted behavior: @@ -65,12 +64,153 @@ Compared to this alternative, which might have surprising and unwanted behavior: let client = undefined; export default { - fetch(request, env) { - client ??= new Client(env.MY_SECRET); // `client` here might not be updated when `env.MY_SECRET` changes, since it may already exist in global scope + fetch(request, env) { + client ??= new Client(env.MY_SECRET); // `client` here might not be updated when `env.MY_SECRET` changes, since it may already exist in global scope + + // ... do things with `client` + }, +}; +``` + +If you have more advanced needs, explore the [AsyncLocalStorage API](/workers/runtime-apis/nodejs/asynclocalstorage/), which provides a mechanism for exposing values down to child execution handlers. + +## How to access `env` + +Bindings are located on the `env` object, which can be accessed in several ways: + +- It is an argument to entrypoint handlers such as [`fetch`](/workers/runtime-apis/fetch/): + + ```js + export default { + async fetch(request, env) { + return new Response(`Hi, ${env.NAME}`); + }, + }; + ``` - // ... do things with `client` +* It is as class property on [WorkerEntrypoint](/workers/runtime-apis/bindings/service-bindings/rpc/#bindings-env), + [DurableObject](/durable-objects/), and [Workflow](/workflows/): + + ```js + export class MyDurableObject extends DurableObject { + async sayHello() { + return `Hi, ${this.env.NAME}!`; + } } + ``` + +* It can be imported from `cloudflare:workers`: + + ```js + import { env } from "cloudflare:workers"; + console.log(`Hi, ${this.env.Name}`); + ``` + +### Importing `env` as a global + +Importing `env` from `cloudflare:workers` is useful when you need to access a binding +such as [secrets](/workers/configuration/secrets/) or [environment variables](/workers/configuration/environment-variables/) +in top-level global scope. For example, to initialize an API client: + +```js +import { env } from "cloudflare:workers"; +import ApiClient from "example-api-client"; + +// API_KEY and LOG_LEVEL now usable in top-level scope +let apiClient = ApiClient.new({ apiKey: env.API_KEY }); +const LOG_LEVEL = env.LOG_LEVEL || "info"; + +export default { + fetch(req) { + // you can use apiClient or LOG_LEVEL, configured before any request is handled + }, +}; +``` + +Workers do not allow I/O from outside a request context. This means that even +though `env` is accessible from the top-level scope, you will not be able to access +every binding's methods. + +For instance, environment variables and secrets are accessible, and you are able to +call `env.NAMESPACE.get` to get a [Durable Object stub](/durable-objects/api/stub/) in the +top-level context. However, calling methods on the Durable Object stub, making [calls to a KV store](/kv/api/), +and [calling to other Workers](/workers/runtime-apis/bindings/service-bindings) will not work. + +```js +import { env } from "cloudflare:workers"; + +// This would error! +// env.KV.get('my-key') + +export default { + async fetch(req) { + // This works + let myVal = await env.KV.get("my-key"); + Response.new(myVal); + }, +}; +``` + +Additionally, importing `env` from `cloudflare:workers` lets you avoid passing `env` +as an argument through many function calls if you need to access a binding from a deeply-nested +function. This can be helpful in a complex codebase. + +```js +import { env } from "cloudflare:workers"; + +export default { + fetch(req) { + Response.new(sayHello()); + }, +}; + +// env is not an argument to sayHello... +function sayHello() { + let myName = getName(); + return `Hello, ${myName}`; +} + +// ...nor is it an argument to getName +function getName() { + return env.MY_NAME; } ``` -If you have more advanced needs, explore the [AsyncLocalStorage API](/workers/runtime-apis/nodejs/asynclocalstorage/), which provides a mechanism for exposing values down to child execution handlers. +:::note +While using `env` from `cloudflare:workers` may be simpler to write than passing it +through a series of function calls, passing `env` as an argument is a helpful pattern +for dependency injection and testing. +::: + +### Overriding `env` values + +The `withEnv` function provides a mechanism for overriding values of `env`. + +Imagine a user has defined the [environment variable](/workers/configuration/environment-variables/) +"NAME" to be "Alice" in their Wrangler configuration file and deployed a Worker. By default, logging +`env.NAME` would print "Alice". Using the `withEnv` function, you can override the value of +"NAME". + +```js +import { env, withEnv } from "cloudflare:workers"; + +function logName() { + console.log(env.NAME); +} + +export default { + fetch(req) { + // this will log "Alice" + logName(); + + withEnv({ NAME: "Bob" }, () => { + // this will log "Bob" + logName(); + }); + + // ...etc... + }, +}; +``` + +This can be useful when testing code that relies on an imported `env` object. diff --git a/src/content/docs/workers/runtime-apis/cache.mdx b/src/content/docs/workers/runtime-apis/cache.mdx index 7940df8a04d7f7..ecbee5cac3403d 100644 --- a/src/content/docs/workers/runtime-apis/cache.mdx +++ b/src/content/docs/workers/runtime-apis/cache.mdx @@ -22,7 +22,7 @@ The `cache.put` method is not compatible with tiered caching. Refer to [Cache AP Workers deployed to custom domains have access to functional `cache` operations. So do [Pages functions](/pages/functions/), whether attached to custom domains or `*.pages.dev` domains. -However, any Cache API operations in the Cloudflare Workers dashboard editor, [Playground](/workers/playground/) previews, and any `*.workers.dev` deployments will have no impact. For Workers fronted by [Cloudflare Access](https://www.cloudflare.com/teams/access/), the Cache API is not currently available. +However, any Cache API operations in the Cloudflare Workers dashboard editor and [Playground](/workers/playground/) previews will have no impact. For Workers fronted by [Cloudflare Access](https://www.cloudflare.com/teams/access/), the Cache API is not currently available. :::note diff --git a/src/content/docs/workers/runtime-apis/html-rewriter.mdx b/src/content/docs/workers/runtime-apis/html-rewriter.mdx index 0b547590d51b8c..ef30491151cb88 100644 --- a/src/content/docs/workers/runtime-apis/html-rewriter.mdx +++ b/src/content/docs/workers/runtime-apis/html-rewriter.mdx @@ -3,10 +3,9 @@ pcx_content_type: configuration title: HTMLRewriter head: [] description: Build comprehensive and expressive HTML parsers inside of a Worker application. - --- -import { Render } from "~/components" +import { Render } from "~/components"; ## Background @@ -14,33 +13,31 @@ The `HTMLRewriter` class allows developers to build comprehensive and expressive The `HTMLRewriter` class should be instantiated once in your Workers script, with a number of handlers attached using the `on` and `onDocument` functions. -*** +--- ## Constructor ```js -new HTMLRewriter().on('*', new ElementHandler()).onDocument(new DocumentHandler()); +new HTMLRewriter() + .on("*", new ElementHandler()) + .onDocument(new DocumentHandler()); ``` -*** +--- ## Global types Throughout the `HTMLRewriter` API, there are a few consistent types that many properties and methods use: +- `Content` string | Response | ReadableStream + - Content inserted in the output stream should be a string, [`Response`](/workers/runtime-apis/response/), or [`ReadableStream`](/workers/runtime-apis/streams/readablestream/). -* `Content` string | Response | ReadableStream - - * Content inserted in the output stream should be a string, [`Response`](/workers/runtime-apis/response/), or [`ReadableStream`](/workers/runtime-apis/streams/readablestream/). - -* `ContentOptions` Object - - * `{ html: Boolean }` Controls the way the HTMLRewriter treats inserted content. If the `html` boolean is set to true, content is treated as raw HTML. If the `html` boolean is set to false or not provided, content will be treated as text and proper HTML escaping will be applied to it. - +- `ContentOptions` Object + - `{ html: Boolean }` Controls the way the HTMLRewriter treats inserted content. If the `html` boolean is set to true, content is treated as raw HTML. If the `html` boolean is set to false or not provided, content will be treated as text and proper HTML escaping will be applied to it. -*** +--- ## Handlers @@ -52,24 +49,24 @@ An element handler responds to any incoming element, when attached using the `.o ```js class ElementHandler { - element(element) { - // An incoming element, such as `div` - console.log(`Incoming element: ${element.tagName}`); - } - - comments(comment) { - // An incoming comment - } - - text(text) { - // An incoming piece of text - } + element(element) { + // An incoming element, such as `div` + console.log(`Incoming element: ${element.tagName}`); + } + + comments(comment) { + // An incoming comment + } + + text(text) { + // An incoming piece of text + } } async function handleRequest(req) { - const res = await fetch(req); + const res = await fetch(req); - return new HTMLRewriter().on('div', new ElementHandler()).transform(res); + return new HTMLRewriter().on("div", new ElementHandler()).transform(res); } ``` @@ -79,21 +76,21 @@ A document handler represents the incoming HTML document. A number of functions ```js class DocumentHandler { - doctype(doctype) { - // An incoming doctype, such as - } + doctype(doctype) { + // An incoming doctype, such as + } - comments(comment) { - // An incoming comment - } + comments(comment) { + // An incoming comment + } - text(text) { - // An incoming piece of text - } + text(text) { + // An incoming piece of text + } - end(end) { - // The end of the document - } + end(end) { + // The end of the document + } } ``` @@ -103,18 +100,20 @@ All functions defined on both element and document handlers can return either `v ```js class UserElementHandler { - async element(element) { - let response = await fetch(new Request('/user')); + async element(element) { + let response = await fetch(new Request("/user")); - // fill in user info using response - } + // fill in user info using response + } } async function handleRequest(req) { - const res = await fetch(req); + const res = await fetch(req); - // run the user element handler via HTMLRewriter on a div with ID `user_info` - return new HTMLRewriter().on('div#user_info', new UserElementHandler()).transform(res); + // run the user element handler via HTMLRewriter on a div with ID `user_info` + return new HTMLRewriter() + .on("div#user_info", new UserElementHandler()) + .transform(res); } ``` @@ -124,84 +123,84 @@ The `element` argument, used only in element handlers, is a representation of a #### Properties +- `tagName` string + - The name of the tag, such as `"h1"` or `"div"`. This property can be assigned different values, to modify an element’s tag. -* `tagName` string - - * The name of the tag, such as `"h1"` or `"div"`. This property can be assigned different values, to modify an element’s tag. - -* `attributes` Iterator read-only - - * A `[name, value]` pair of the tag’s attributes. +- `attributes` Iterator read-only -* `removed` boolean + - A `[name, value]` pair of the tag’s attributes. - * Indicates whether the element has been removed or replaced by one of the previous handlers. - -* `namespaceURI` String - * Represents the [namespace URI](https://infra.spec.whatwg.org/#namespaces) of an element. +- `removed` boolean + - Indicates whether the element has been removed or replaced by one of the previous handlers. +- `namespaceURI` String + - Represents the [namespace URI](https://infra.spec.whatwg.org/#namespaces) of an element. #### Methods +- getAttribute(namestring) : string | null + - Returns the value for a given attribute name on the element, or `null` if it is not found. -* getAttribute(namestring) : string | null - - * Returns the value for a given attribute name on the element, or `null` if it is not found. - -* hasAttribute(namestring) : boolean +- hasAttribute(namestring) : boolean - * Returns a boolean indicating whether an attribute exists on the element. + - Returns a boolean indicating whether an attribute exists on the element. -* setAttribute(namestring, valuestring) : Element +- setAttribute(namestring, valuestring) : Element - * Sets an attribute to a provided value, creating the attribute if it does not exist. + - Sets an attribute to a provided value, creating the attribute if it does not exist. -* removeAttribute(namestring) : Element +- removeAttribute(namestring) : Element - * Removes the attribute. + - Removes the attribute. -* before(contentContent, contentOptionsContentOptionsoptional) : Element +- before(contentContent, contentOptionsContentOptionsoptional) : + Element - * Inserts content before the element. + - Inserts content before the element. -* after(contentContent, contentOptionsContentOptionsoptional) : Element +- after(contentContent, contentOptionsContentOptionsoptional) : + Element - * Inserts content right after the element. + - Inserts content right after the element. -* prepend(contentContent, contentOptionsContentOptionsoptional) : Element +- prepend(contentContent, contentOptionsContentOptionsoptional) : + Element - * Inserts content right after the start tag of the element. + - Inserts content right after the start tag of the element. -* append(contentContent, contentOptionsContentOptionsoptional) : Element +- append(contentContent, contentOptionsContentOptionsoptional) : + Element - * Inserts content right before the end tag of the element. + - Inserts content right before the end tag of the element. -* replace(contentContent, contentOptionsContentOptionsoptional) : Element +- replace(contentContent, contentOptionsContentOptionsoptional) : + Element - * Removes the element and inserts content in place of it. + - Removes the element and inserts content in place of it. -* setInnerContent(contentContent, contentOptionsContentOptionsoptional) : Element +- + setInnerContent(contentContent, contentOptionsContentOptionsoptional) + + : Element - * Replaces content of the element. + - Replaces content of the element. -* remove() : Element +- remove() : Element - * Removes the element with all its content. + - Removes the element with all its content. -* removeAndKeepContent() : Element +- removeAndKeepContent() : Element - * Removes the start tag and end tag of the element but keeps its inner content intact. - -* `onEndTag(handlerFunction)` : void - - * Registers a handler that is invoked when the end tag of the element is reached. + - Removes the start tag and end tag of the element but keeps its inner content intact. +- `onEndTag(handlerFunction)` : void + - Registers a handler that is invoked when the end tag of the element is reached. ### EndTag @@ -209,33 +208,27 @@ The `endTag` argument, used only in handlers registered with `element.onEndTag`, #### Properties +- `name` string - -* `name` string - - * The name of the tag, such as `"h1"` or `"div"`. This property can be assigned different values, to modify an element’s tag. - - + - The name of the tag, such as `"h1"` or `"div"`. This property can be assigned different values, to modify an element’s tag. #### Methods +- before(contentContent, contentOptionsContentOptionsoptional) : + EndTag + - Inserts content right before the end tag. -* before(contentContent, contentOptionsContentOptionsoptional) : EndTag - - * Inserts content right before the end tag. +- after(contentContent, contentOptionsContentOptionsoptional) : + EndTag -* after(contentContent, contentOptionsContentOptionsoptional) : EndTag - - * Inserts content right after the end tag. + - Inserts content right after the end tag. -* remove() : EndTag - - * Removes the element with all its content. - +- remove() : EndTag + - Removes the element with all its content. ### Text chunks @@ -245,44 +238,39 @@ Consider the following markup: `
    Hey. How are you?
    `. It is possible th #### Properties +- `removed` boolean + - Indicates whether the element has been removed or replaced by one of the previous handlers. -* `removed` boolean - - * Indicates whether the element has been removed or replaced by one of the previous handlers. - -* `text` string read-only - - * The text content of the chunk. Could be empty if the chunk is the last chunk of the text node. - -* `lastInTextNode` boolean read-only - * Specifies whether the chunk is the last chunk of the text node. +- `text` string read-only + - The text content of the chunk. Could be empty if the chunk is the last chunk of the text node. +- `lastInTextNode` boolean read-only + - Specifies whether the chunk is the last chunk of the text node. #### Methods +- before(contentContent, contentOptionsContentOptionsoptional) : + Element - -* before(contentContent, contentOptionsContentOptionsoptional) : Element - - * Inserts content before the element. + - Inserts content before the element. -* after(contentContent, contentOptionsContentOptionsoptional) : Element - - * Inserts content right after the element. - -* replace(contentContent, contentOptionsContentOptionsoptional) : Element +- after(contentContent, contentOptionsContentOptionsoptional) : + Element - * Removes the element and inserts content in place of it. + - Inserts content right after the element. -* remove() : Element +- replace(contentContent, contentOptionsContentOptionsoptional) : + Element - * Removes the element with all its content. + - Removes the element and inserts content in place of it. +- remove() : Element + - Removes the element with all its content. ### Comments @@ -290,48 +278,43 @@ The `comments` function on an element handler allows developers to query and man ```js class ElementHandler { - comments(comment) { - // An incoming comment element, such as - } + comments(comment) { + // An incoming comment element, such as + } } ``` #### Properties +- `comment.removed` boolean + - Indicates whether the element has been removed or replaced by one of the previous handlers. -* `comment.removed` boolean - - * Indicates whether the element has been removed or replaced by one of the previous handlers. - -* `comment.text` string - * The text of the comment. This property can be assigned different values, to modify comment’s text. - - +- `comment.text` string + - The text of the comment. This property can be assigned different values, to modify comment’s text. #### Methods +- before(contentContent, contentOptionsContentOptionsoptional) : + Element - -* before(contentContent, contentOptionsContentOptionsoptional) : Element - - * Inserts content before the element. + - Inserts content before the element. -* after(contentContent, contentOptionsContentOptionsoptional) : Element - - * Inserts content right after the element. +- after(contentContent, contentOptionsContentOptionsoptional) : + Element -* replace(contentContent, contentOptionsContentOptionsoptional) : Element + - Inserts content right after the element. - * Removes the element and inserts content in place of it. +- replace(contentContent, contentOptionsContentOptionsoptional) : + Element -* remove() : Element - - * Removes the element with all its content. + - Removes the element and inserts content in place of it. +- remove() : Element + - Removes the element with all its content. ### Doctype @@ -339,29 +322,25 @@ The `doctype` function on a document handler allows developers to query a docume ```js class DocumentHandler { - doctype(doctype) { - // An incoming doctype element, such as - // - } + doctype(doctype) { + // An incoming doctype element, such as + // + } } ``` #### Properties +- `doctype.name` string | null read-only + - The doctype name. -* `doctype.name` string | null read-only - - * The doctype name. - -* `doctype.publicId` string | null read-only - - * The quoted string in the doctype after the PUBLIC atom. - -* `doctype.systemId` string | null read-only - * The quoted string in the doctype after the SYSTEM atom or immediately after the `publicId`. +- `doctype.publicId` string | null read-only + - The quoted string in the doctype after the PUBLIC atom. +- `doctype.systemId` string | null read-only + - The quoted string in the doctype after the SYSTEM atom or immediately after the `publicId`. ### End @@ -369,114 +348,107 @@ The `end` function on a document handler allows developers to append content to ```js class DocumentHandler { - end(end) { - // The end of the document - } + end(end) { + // The end of the document + } } ``` #### Methods +- append(contentContent, contentOptionsContentOptionsoptional) : + DocumentEnd - -* append(contentContent, contentOptionsContentOptionsoptional) : DocumentEnd - - * Inserts content after the end of the document. + - Inserts content after the end of the document. - - -*** +--- ## Selectors This is what selectors are and what they are used for. +- `*` + - Any element. -* `*` +- `E` - * Any element. + - Any element of type E. -* `E` +- `E:nth-child(n)` - * Any element of type E. + - An E element, the n-th child of its parent. -* `E:nth-child(n)` +- `E:first-child` - * An E element, the n-th child of its parent. + - An E element, first child of its parent. -* `E:first-child` +- `E:nth-of-type(n)` - * An E element, first child of its parent. + - An E element, the n-th sibling of its type. -* `E:nth-of-type(n)` +- `E:first-of-type` - * An E element, the n-th sibling of its type. + - An E element, first sibling of its type. -* `E:first-of-type` +- `E:not(s)` - * An E element, first sibling of its type. + - An E element that does not match either compound selectors. -* `E:not(s)` +- `E.warning` - * An E element that does not match either compound selectors. + - An E element belonging to the class warning. -* `E.warning` +- `E#myid` - * An E element belonging to the class warning. + - An E element with ID equal to myid. -* `E#myid` +- `E[foo]` - * An E element with ID equal to myid. + - An E element with a foo attribute. -* `E[foo]` +- `E[foo="bar"]` - * An E element with a foo attribute. + - An E element whose foo attribute value is exactly equal to bar. -* `E[foo="bar"]` +- `E[foo="bar" i]` - * An E element whose foo attribute value is exactly equal to bar. + - An E element whose foo attribute value is exactly equal to any (ASCII-range) case-permutation of bar. -* `E[foo="bar" i]` +- `E[foo="bar" s]` - * An E element whose foo attribute value is exactly equal to any (ASCII-range) case-permutation of bar. + - An E element whose foo attribute value is exactly and case-sensitively equal to bar. -* `E[foo="bar" s]` +- `E[foo~="bar"]` - * An E element whose foo attribute value is exactly and case-sensitively equal to bar. + - An E element whose foo attribute value is a list of whitespace-separated values, one of which is exactly equal to bar. -* `E[foo~="bar"]` +- `E[foo^="bar"]` - * An E element whose foo attribute value is a list of whitespace-separated values, one of which is exactly equal to bar. + - An E element whose foo attribute value begins exactly with the string bar. -* `E[foo^="bar"]` +- `E[foo$="bar"]` - * An E element whose foo attribute value begins exactly with the string bar. + - An E element whose foo attribute value ends exactly with the string bar. -* `E[foo$="bar"]` +- `E[foo*="bar"]` - * An E element whose foo attribute value ends exactly with the string bar. + - An E element whose foo attribute value contains the substring bar. -* `E[foo*="bar"]` +- `E[foo|="en"]` - * An E element whose foo attribute value contains the substring bar. + - An E element whose foo attribute value is a hyphen-separated list of values beginning with en. -* `E[foo|="en"]` +- `E F` - * An E element whose foo attribute value is a hyphen-separated list of values beginning with en. + - An F element descendant of an E element. -* `E F` +- `E > F` + - An F element child of an E element. - * An F element descendant of an E element. - -* `E > F` - * An F element child of an E element. - - - -*** +--- ## Errors @@ -484,29 +456,30 @@ If a handler throws an exception, parsing is immediately halted, the transformed ```js async function handle(request) { - let oldResponse = await fetch(request); - let newResponse = new HTMLRewriter() - .on('*', { - element(element) { - throw new Error('A really bad error.'); - }, - }) - .transform(oldResponse); - - // At this point, an expression like `await newResponse.text()` - // will throw `new Error("A really bad error.")`. - // Thereafter, any use of `newResponse.body` will throw the same error, - // and `oldResponse.body` will be closed. - - // Alternatively, this will produce a truncated response to the client: - return newResponse; + let oldResponse = await fetch(request); + let newResponse = new HTMLRewriter() + .on("*", { + element(element) { + throw new Error("A really bad error."); + }, + }) + .transform(oldResponse); + + // At this point, an expression like `await newResponse.text()` + // will throw `new Error("A really bad error.")`. + // Thereafter, any use of `newResponse.body` will throw the same error, + // and `oldResponse.body` will be closed. + + // Alternatively, this will produce a truncated response to the client: + return newResponse; } ``` -*** +--- ## Related resources -* [Introducing `HTMLRewriter`](https://blog.cloudflare.com/introducing-htmlrewriter/) -* [Tutorial: Localize a Website](/pages/tutorials/localize-a-website/) -* [Example: rewrite links](/workers/examples/rewrite-links/) +- [Introducing `HTMLRewriter`](https://blog.cloudflare.com/introducing-htmlrewriter/) +- [Tutorial: Localize a Website](/pages/tutorials/localize-a-website/) +- [Example: rewrite links](/workers/examples/rewrite-links/) +- [Example: Inject Turnstile](/workers/examples/turnstile-html-rewriter/) diff --git a/src/content/docs/workers/runtime-apis/nodejs/process.mdx b/src/content/docs/workers/runtime-apis/nodejs/process.mdx index 651e74149d2acc..07d70647bf10d0 100644 --- a/src/content/docs/workers/runtime-apis/nodejs/process.mdx +++ b/src/content/docs/workers/runtime-apis/nodejs/process.mdx @@ -26,7 +26,10 @@ nextTick(() => { ## `process.env` -In the Node.js implementation of `process.env`, the `env` object is a copy of the environment variables at the time the process was started. In the Workers implementation, there is no process-level environment, so `env` is an empty object. You can still set and get values from `env`, and those will be globally persistent for all Workers running in the same isolate and context (for example, the same Workers entry point). +In the Node.js implementation of `process.env`, the `env` object is a copy of the environment variables at the time the process was started. In the Workers implementation, there is no process-level environment, so by default `env` is an empty object. You can still set and get values from `env`, and those will be globally persistent for all Workers running in the same isolate and context (for example, the same Workers entry point). + +When [Node.js compatability](/workers/runtime-apis/nodejs/) is turned on and the [`nodejs_compat_populate_process_env`](/workers/configuration/compatibility-flags/#enable-auto-populating-processenv) compatability flag is set, `process.env` will contain any [environment variables](/workers/configuration/environment-variables/), +[secrets](/workers/configuration/secrets/), or [version metadata](/workers/runtime-apis/bindings/version-metadata/) metadata that has been configured on your Worker. ### Relationship to per-request `env` argument in `fetch()` handlers diff --git a/src/content/docs/workers/runtime-apis/rpc/index.mdx b/src/content/docs/workers/runtime-apis/rpc/index.mdx index eb597955f83593..67d00eab82f53a 100644 --- a/src/content/docs/workers/runtime-apis/rpc/index.mdx +++ b/src/content/docs/workers/runtime-apis/rpc/index.mdx @@ -244,7 +244,7 @@ Currently, this proxying only lasts until the end of the Workers' execution cont In this video, we explore how Cloudflare Workers support Remote Procedure Calls (RPC) to simplify communication between Workers. Learn how to implement RPC in your JavaScript applications and build serverless solutions with ease. Whether you're managing microservices or optimizing web architecture, this tutorial will show you how to quickly set up and use Cloudflare Workers for RPC calls. By the end of this video, you'll understand how to call functions between Workers, pass functions as arguments, and implement user authentication with Cloudflare Workers. - + ## More Details diff --git a/src/content/docs/workers/runtime-apis/rpc/lifecycle.mdx b/src/content/docs/workers/runtime-apis/rpc/lifecycle.mdx index 96b63f103619da..11de8023ac8998 100644 --- a/src/content/docs/workers/runtime-apis/rpc/lifecycle.mdx +++ b/src/content/docs/workers/runtime-apis/rpc/lifecycle.mdx @@ -47,13 +47,7 @@ function sendEmail(id, message) { ### How to use the `using` declaration in your Worker -Because it has not yet landed in V8, the `using` keyword is not yet available directly in the Workers runtime. To use it in your code, you must use a prerelease version of the [Wrangler CLI](/workers/wrangler/) to run and deploy your Worker: - -```sh -npx wrangler@using-keyword-experimental dev -``` - -This version of Wrangler will transpile `using` into direct calls to `Symbol.dispose()`, before running your code or deploying it to Cloudflare. +[Wrangler](/workers/wrangler/) v4+ supports the `using` keyword natively. If you are using an earlier version of Wrangler, you will need to manually dispose of resources instead. The following code: diff --git a/src/content/docs/workers/static-assets/billing-and-limitations.mdx b/src/content/docs/workers/static-assets/billing-and-limitations.mdx index 97bab1187b6c8e..6c667c15f94598 100644 --- a/src/content/docs/workers/static-assets/billing-and-limitations.mdx +++ b/src/content/docs/workers/static-assets/billing-and-limitations.mdx @@ -21,7 +21,6 @@ The following limitations apply for Workers with static assets: - There is a 20,000 file count limit per [Worker version](/workers/configuration/versions-and-deployments/), and a 25 MiB individual file size limit. This matches the [limits in Cloudflare Pages](/pages/platform/limits/) today. - In local development, you cannot make [Service Binding RPC calls](/workers/runtime-apis/bindings/service-bindings/rpc/) to a Worker with static assets. This is a temporary limitation, we are working to remove it. -- Workers with assets cannot run on a [route or domain](/workers/configuration/routing/) with a path component. For example, `example.com/*` is an acceptable route, but `example.com/foo/*` is not. Wrangler and the Cloudflare dashboard will throw an error when you try and add a route with a path component. ## Troubleshooting diff --git a/src/content/docs/workers/static-assets/binding.mdx b/src/content/docs/workers/static-assets/binding.mdx index c6b52a04efa7cb..f007dc507354ed 100644 --- a/src/content/docs/workers/static-assets/binding.mdx +++ b/src/content/docs/workers/static-assets/binding.mdx @@ -15,7 +15,7 @@ import { Render, TabItem, Tabs, - WranglerConfig + WranglerConfig, } from "~/components"; Configuring a Worker with assets requires specifying a [directory](/workers/static-assets/binding/#directory) and, optionally, an [assets binding](/workers/static-assets/binding/), in your Worker's Wrangler file. The [assets binding](/workers/static-assets/binding/) allows you to dynamically fetch assets from within your Worker script (e.g. `env.ASSETS.fetch()`), similarly to how you might with a make a `fetch()` call with a [Service binding](/workers/runtime-apis/bindings/service-bindings/http/). @@ -105,7 +105,7 @@ In the example above, assets would be available through `env.ASSETS`. **Parameters** -- `request: Request` Pass a [Request object](/workers/runtime-apis/request/), URL string, or URL object. Requests made through this method have `html_handling` and `not_found_handling` configuration applied to them. +- `request: Request | URL | string` Pass a [Request object](/workers/runtime-apis/request/), URL object, or URL string. Requests made through this method have `html_handling` and `not_found_handling` configuration applied to them. **Response** @@ -113,7 +113,7 @@ In the example above, assets would be available through `env.ASSETS`. **Example** -Your dynamic code can make new, or forward incoming, requests to your project's static assets using the assets binding. +Your dynamic code can make new, or forward incoming requests to your project's static assets using the assets binding. For example, `env.ASSETS.fetch(request)`, `env.ASSETS.fetch(new URL('https://assets.local/my-file'))` or `env.ASSETS.fetch('https://assets.local/my-file')`. Take the following example that configures a Worker script to return a response under all requests headed for `/api/`. Otherwise, the Worker script will pass the incoming request through to the asset binding. In this case, because a Worker script is only invoked when the requested route has not matched any static assets, this will always evaluate [`not_found_handling`](/workers/static-assets/routing/#routing-configuration) behavior. diff --git a/src/content/docs/workers/static-assets/compatibility-matrix.mdx b/src/content/docs/workers/static-assets/compatibility-matrix.mdx index d16ad3d8d7559d..a0b717a059db27 100644 --- a/src/content/docs/workers/static-assets/compatibility-matrix.mdx +++ b/src/content/docs/workers/static-assets/compatibility-matrix.mdx @@ -63,10 +63,11 @@ We plan to bridge the gaps between Workers and Pages and provide ways to migrate | [Email Workers](/email-routing/email-workers/send-email-workers/) | ✅ | ❌ | | [Environment Variables](/workers/configuration/environment-variables/) | ✅ | ✅ | | [Hyperdrive](/hyperdrive/) | ✅ | ✅ | +| [Image Resizing](/images/transform-images/bindings/) | ✅ | ❌ | | [KV](/kv/) | ✅ | ✅ | | [mTLS](/workers/runtime-apis/bindings/mtls/) | ✅ | ✅ | -| [Queue Producers](/queues/configuration/configure-queues/#producer) | ✅ | ✅ | -| [Queue Consumers](/queues/configuration/configure-queues/#consumer) | ✅ | ❌ | +| [Queue Producers](/queues/configuration/configure-queues/#producer-worker-configuration) | ✅ | ✅ | +| [Queue Consumers](/queues/configuration/configure-queues/#consumer-worker-configuration) | ✅ | ❌ | | [R2](/r2/) | ✅ | ✅ | | [Rate Limiting](/workers/runtime-apis/bindings/rate-limit/) | ✅ | ❌ | | [Secrets](/workers/configuration/secrets/) | ✅ | ✅ | diff --git a/src/content/docs/workers/static-assets/get-started.mdx b/src/content/docs/workers/static-assets/get-started.mdx index 6e70966b06a691..0702dd765a06ea 100644 --- a/src/content/docs/workers/static-assets/get-started.mdx +++ b/src/content/docs/workers/static-assets/get-started.mdx @@ -38,7 +38,7 @@ This guide will instruct you through setting up and deploying a static site on W @@ -96,7 +96,7 @@ Open a terminal window and run C3 to create your Worker project: diff --git a/src/content/docs/workers/testing/miniflare/get-started.mdx b/src/content/docs/workers/testing/miniflare/get-started.mdx index d4086669e4d64b..d7e39b87b0f36e 100644 --- a/src/content/docs/workers/testing/miniflare/get-started.mdx +++ b/src/content/docs/workers/testing/miniflare/get-started.mdx @@ -103,46 +103,46 @@ to workers respectively: import { Miniflare } from "miniflare"; const mf = new Miniflare({ + modules: true, script: ` - export default { - let lastScheduledController; - let lastQueueBatch; - async fetch(request, env, ctx) { - const { pathname } = new URL(request.url); - if (pathname === "/scheduled") { - return Response.json({ - scheduledTime: lastScheduledController?.scheduledTime, - cron: lastScheduledController?.cron, - }); - } else if (pathname === "/queue") { - return Response.json({ - queue: lastQueueBatch.queue, - messages: lastQueueBatch.messages.map((message) => ({ - id: message.id, - timestamp: message.timestamp.getTime(), - body: message.body, - bodyType: message.body.constructor.name, - })), - }); - } else if (pathname === "/get-url") { - return new Response(request.url); - } else { - return new Response(null, { status: 404 }); - } - }, - async scheduled(controller, env, ctx) { - lastScheduledController = controller; - if (controller.cron === "* * * * *") controller.noRetry(); - }, - async queue(batch, env, ctx) { - lastQueueBatch = batch; - if (batch.queue === "needy") batch.retryAll(); - for (const message of batch.messages) { - if (message.id === "perfect") message.ack(); - } - } - } - `, + let lastScheduledController; + let lastQueueBatch; + export default { + async fetch(request, env, ctx) { + const { pathname } = new URL(request.url); + if (pathname === "/scheduled") { + return Response.json({ + scheduledTime: lastScheduledController?.scheduledTime, + cron: lastScheduledController?.cron, + }); + } else if (pathname === "/queue") { + return Response.json({ + queue: lastQueueBatch.queue, + messages: lastQueueBatch.messages.map((message) => ({ + id: message.id, + timestamp: message.timestamp.getTime(), + body: message.body, + bodyType: message.body.constructor.name, + })), + }); + } else if (pathname === "/get-url") { + return new Response(request.url); + } else { + return new Response(null, { status: 404 }); + } + }, + async scheduled(controller, env, ctx) { + lastScheduledController = controller; + if (controller.cron === "* * * * *") controller.noRetry(); + }, + async queue(batch, env, ctx) { + lastQueueBatch = batch; + if (batch.queue === "needy") batch.retryAll(); + for (const message of batch.messages) { + if (message.id === "perfect") message.ack(); + } + } + }`, }); const res = await mf.dispatchFetch("http://localhost:8787/", { @@ -150,14 +150,16 @@ const res = await mf.dispatchFetch("http://localhost:8787/", { }); console.log(await res.text()); // Hello Miniflare! +const worker = await mf.getWorker(); + const scheduledResult = await worker.scheduled({ cron: "* * * * *", }); console.log(scheduledResult); // { outcome: "ok", noRetry: true }); const queueResult = await worker.queue("needy", [ - { id: "a", timestamp: new Date(1000), body: "a" }, - { id: "b", timestamp: new Date(2000), body: { b: 1 } }, + { id: "a", timestamp: new Date(1000), body: "a", attempts: 1 }, + { id: "b", timestamp: new Date(2000), body: { b: 1 }, attempts: 1 }, ]); console.log(queueResult); // { outcome: "ok", retryAll: true, ackAll: false, explicitRetries: [], explicitAcks: []} ``` @@ -367,6 +369,8 @@ const res = await mf.dispatchFetch("http://localhost:8787/", { }); const text = await res.text(); +const worker = await mf.getWorker(); + // Dispatch "scheduled" event to worker const scheduledResult = await worker.scheduled({ cron: "30 * * * *" }) diff --git a/src/content/docs/workers/testing/miniflare/migrations/from-v2.mdx b/src/content/docs/workers/testing/miniflare/migrations/from-v2.mdx index 40d08b64b1a284..b03ed59150e6e2 100644 --- a/src/content/docs/workers/testing/miniflare/migrations/from-v2.mdx +++ b/src/content/docs/workers/testing/miniflare/migrations/from-v2.mdx @@ -203,7 +203,7 @@ open-source `workerd` runtime. See the [Getting Started guide for the new API do - Use the `queue()` method on [service bindings](/workers/runtime-apis/bindings/service-bindings) or - [queue producer bindings](/queues/configuration/configure-queues/#producer) + [queue producer bindings](/queues/configuration/configure-queues/#producer-worker-configuration) instead. - `getGlobalScope()/getBindings()/getModuleExports()` - These methods returned objects from inside the Workers sandbox. Since diff --git a/src/content/docs/workers/testing/vitest-integration/debugging.mdx b/src/content/docs/workers/testing/vitest-integration/debugging.mdx new file mode 100644 index 00000000000000..6ef97d4553ce46 --- /dev/null +++ b/src/content/docs/workers/testing/vitest-integration/debugging.mdx @@ -0,0 +1,83 @@ +--- +title: Debugging +pcx_content_type: concept +sidebar: + order: 8 +head: [] +description: Debug your Workers tests with Vitest. +--- + +This guide shows you how to debug your Workers tests with Vitest. This is available with `@cloudflare/vitest-pool-workers` v0.7.5 or later. + +## Open inspector with Vitest + +To start debugging, run Vitest with the following command and attach a debugger to port `9229`: + +```sh +vitest --inspect --no-file-parallelism +``` + +## Customize the inspector port + +By default, the inspector will be opened on port `9229`. If you need to use a different port (for example, `3456`), you can run the following command: + +```sh +vitest --inspect=3456 --no-file-parallelism +``` + +Alternatively, you can define it in your Vitest configuration file: + +```ts +import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config"; + +export default defineWorkersConfig({ + test: { + inspector: { + port: 3456, + }, + poolOptions: { + workers: { + // ... + }, + }, + }, +}); +``` + +## Setup VS Code to use breakpoints + +To setup VS Code for breakpoint debugging in your Worker tests, create a `.vscode/launch.json` file that contains the following configuration: + +```json +{ + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Open inspector with Vitest", + "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", + "console": "integratedTerminal", + "args": ["--inspect=9229", "--no-file-parallelism"] + }, + { + "name": "Attach to Workers Runtime", + "type": "node", + "request": "attach", + "port": 9229, + "cwd": "/", + "resolveSourceMapLocations": null, + "attachExistingChildren": false, + "autoAttachChildProcesses": false, + } + ], + "compounds": [ + { + "name": "Debug Workers tests", + "configurations": ["Open inspector with Vitest", "Attach to Workers Runtime"], + "stopAll": true + } + ] +} +``` + +Select **Debug Workers tests** at the top of the **Run & Debug** panel to open an inspector with Vitest and attach a debugger to the Workers runtime. Then you can add breakpoints to your test files and start debugging. diff --git a/src/content/docs/workers/testing/vitest-integration/get-started/migrate-from-miniflare-2.mdx b/src/content/docs/workers/testing/vitest-integration/get-started/migrate-from-miniflare-2.mdx index 875a0fcfc212b2..ed9f5ffe793cfd 100644 --- a/src/content/docs/workers/testing/vitest-integration/get-started/migrate-from-miniflare-2.mdx +++ b/src/content/docs/workers/testing/vitest-integration/get-started/migrate-from-miniflare-2.mdx @@ -30,13 +30,13 @@ First, you will need to uninstall the old environment and install the new pool. ```sh npm uninstall vitest-environment-miniflare -npm install --save-dev --save-exact vitest@2.1.8 +npm install --save-dev --save-exact vitest@~3.0.0 npm install --save-dev @cloudflare/vitest-pool-workers ``` ## Update your Vitest configuration file -After installing the Workers Vitest configuration, update your Vitest configuration file to use the pool instead. Most Miniflare configuration previously specified `environmentOptions` can be moved to `poolOptions.workers.miniflare` instead. Refer to [Miniflare's `WorkerOptions` interface](https://github.com/cloudflare/workers-sdk/blob/main/packages/miniflare/README.md#interface-workeroptions) for supported options and the [Miniflare version 2 to 3 migration guide](https://miniflare.dev/get-started/migrating#api-changes) for more information. If you relied on configuration stored in a Wrangler file, set `wrangler.configPath` too. +After installing the Workers Vitest configuration, update your Vitest configuration file to use the pool instead. Most Miniflare configuration previously specified `environmentOptions` can be moved to `poolOptions.workers.miniflare` instead. Refer to [Miniflare's `WorkerOptions` interface](https://github.com/cloudflare/workers-sdk/blob/main/packages/miniflare/README.md#interface-workeroptions) for supported options and the [Miniflare version 2 to 3 migration guide](/workers/testing/miniflare/migrations/from-v2/) for more information. If you relied on configuration stored in a Wrangler file, set `wrangler.configPath` too. ```diff + import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config"; diff --git a/src/content/docs/workers/testing/vitest-integration/get-started/write-your-first-test.mdx b/src/content/docs/workers/testing/vitest-integration/get-started/write-your-first-test.mdx index b0cc8f99bc912e..c0d38833146cde 100644 --- a/src/content/docs/workers/testing/vitest-integration/get-started/write-your-first-test.mdx +++ b/src/content/docs/workers/testing/vitest-integration/get-started/write-your-first-test.mdx @@ -24,7 +24,7 @@ This guide will instruct you through installing and setting up the `@cloudflare/ Open a terminal window and make sure you are in your project's root directory. Once you have confirmed that, run: ```sh -npm install vitest@2.1.8 --save-dev --save-exact +npm install vitest@~3.0.0 --save-dev --save-exact npm install @cloudflare/vitest-pool-workers --save-dev ``` @@ -32,7 +32,7 @@ The above commands will add the packages to your `package.json` file and install :::note -Currently, the `@cloudflare/vitest-pool-workers` package _only_ works with Vitest 2.0.x - 2.1.8. +Currently, the `@cloudflare/vitest-pool-workers` package _only_ works with Vitest 2.0.x - 3.0.x. ::: diff --git a/src/content/docs/workers/testing/vitest-integration/known-issues.mdx b/src/content/docs/workers/testing/vitest-integration/known-issues.mdx index b11955545c5ca8..0fbf92392d81f1 100644 --- a/src/content/docs/workers/testing/vitest-integration/known-issues.mdx +++ b/src/content/docs/workers/testing/vitest-integration/known-issues.mdx @@ -26,13 +26,48 @@ Dynamic `import()` statements do not work inside `export default { ... }` handle Durable Object alarms are not reset between test runs and do not respect isolated storage. Ensure you delete or run all alarms with [`runDurableObjectAlarm()`](/workers/testing/vitest-integration/test-apis/#durable-objects) scheduled in each test before finishing the test. -### Durable Objects and `isolatedStorage` +### WebSockets Using WebSockets with Durable Objects with the [`isolatedStorage`](/workers/testing/vitest-integration/isolation-and-concurrency) flag turned on is not supported. You must set `isolatedStorage: false` in your `vitest.config.ts` file. -### Returning non-primitive values from RPC methods +### Isolated storage -In order to return non-primitive values (objects or classes extending `RpcTarget`, for instance) from RPC methods, you must use the `using` keyword. Refer to [https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle#explicit-resource-management](https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle#explicit-resource-management) for more details. An [example test](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/rpc/test/unit.test.ts#L155) is included in the `workers-sdk` repository. +When the `isolatedStorage` flag is enabled (the default), the test runner will undo any writes to the storage at the end of the test as detailed in the [isolation and concurrency documentation](/workers/testing/vitest-integration/isolation-and-concurrency/). However, Cloudflare recommends that you consider the following actions to avoid any common issues: + +#### Await all storage operations + +Always `await` all `Promise`s that read or write to storage services. + +```ts +// Example: Seed data +beforeAll(async () => { + await env.KV.put('message', 'test message'); + await env.R2.put('file', 'hello-world'); +}); +``` + +#### Explicitly signal resource disposal + +When calling RPC methods of a Service Worker or Durable Object that return non-primitive values (such as objects or classes extending `RpcTarget`), use the `using` keyword to explicitly signal when resources can be disposed of. See [this example test](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/rpc/test/unit.test.ts#L155) and refer to [explicit-resource-management](/workers/runtime-apis/rpc/lifecycle#explicit-resource-management) for more details. + +```ts +using result = await stub.getCounter(); +``` + +#### Consume response bodies + +When making requests via `fetch` or `R2.get()`, consume the entire response body, even if you are not asserting its content. For example: + +```ts +test('check if file exists', async () => { + await env.R2.put('file', 'hello-world'); + const response = await env.R2.get('file'); + + expect(response).not.toBe(null); + // Consume the response body even if you are not asserting it + await response.text() +}); +``` ### Module resolution diff --git a/src/content/docs/workers/tutorials/automated-analytics-reporting/index.mdx b/src/content/docs/workers/tutorials/automated-analytics-reporting/index.mdx index d7c74c69a3e463..c8b058d3c8f0fc 100644 --- a/src/content/docs/workers/tutorials/automated-analytics-reporting/index.mdx +++ b/src/content/docs/workers/tutorials/automated-analytics-reporting/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-11-20 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Automate analytics reporting with Cloudflare Workers and email routing products: @@ -59,7 +58,7 @@ In this tutorial, name your Worker as `account-analytics`. product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/tutorials/build-a-jamstack-app/index.mdx b/src/content/docs/workers/tutorials/build-a-jamstack-app/index.mdx index 5c1a352be8d1f8..ee4e95c340a855 100644 --- a/src/content/docs/workers/tutorials/build-a-jamstack-app/index.mdx +++ b/src/content/docs/workers/tutorials/build-a-jamstack-app/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-05-14 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a todo list Jamstack application products: @@ -36,7 +35,7 @@ First, use the [`create-cloudflare`](https://www.npmjs.com/package/create-cloudf product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/tutorials/build-a-qr-code-generator/index.mdx b/src/content/docs/workers/tutorials/build-a-qr-code-generator/index.mdx index 06209d9eacd979..952a66f71028f1 100644 --- a/src/content/docs/workers/tutorials/build-a-qr-code-generator/index.mdx +++ b/src/content/docs/workers/tutorials/build-a-qr-code-generator/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-06-29 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a QR code generator languages: @@ -31,7 +30,7 @@ First, use the [`create-cloudflare` CLI](/pages/get-started/c3) to create a new product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/tutorials/build-a-slackbot/index.mdx b/src/content/docs/workers/tutorials/build-a-slackbot/index.mdx index da3d8388def79d..75815820d318c4 100644 --- a/src/content/docs/workers/tutorials/build-a-slackbot/index.mdx +++ b/src/content/docs/workers/tutorials/build-a-slackbot/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-06-05 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build a Slackbot tags: diff --git a/src/content/docs/workers/tutorials/connect-to-turso-using-workers/index.mdx b/src/content/docs/workers/tutorials/connect-to-turso-using-workers/index.mdx index f079f019afba38..8e6de4c1b8342c 100644 --- a/src/content/docs/workers/tutorials/connect-to-turso-using-workers/index.mdx +++ b/src/content/docs/workers/tutorials/connect-to-turso-using-workers/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-04-01 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Connect to and query your Turso database using Workers languages: @@ -117,7 +116,7 @@ To create a new Workers project (named `worker-turso-ts`), run the following: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/workers/tutorials/create-finetuned-chatgpt-ai-models-with-r2/index.mdx b/src/content/docs/workers/tutorials/create-finetuned-chatgpt-ai-models-with-r2/index.mdx index 0cbff4a9d1729e..2217a060a72e32 100644 --- a/src/content/docs/workers/tutorials/create-finetuned-chatgpt-ai-models-with-r2/index.mdx +++ b/src/content/docs/workers/tutorials/create-finetuned-chatgpt-ai-models-with-r2/index.mdx @@ -1,5 +1,4 @@ --- -content_type: 📝 Tutorial difficulty: Intermediate pcx_content_type: tutorial title: Create a fine-tuned OpenAI model with R2 @@ -54,7 +53,7 @@ First, use the `c3` CLI to create a new Cloudflare Workers project. product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> diff --git a/src/content/docs/workers/tutorials/deploy-a-realtime-chat-app/index.mdx b/src/content/docs/workers/tutorials/deploy-a-realtime-chat-app/index.mdx index 82e67cd2003d95..4699fd9b5e5b44 100644 --- a/src/content/docs/workers/tutorials/deploy-a-realtime-chat-app/index.mdx +++ b/src/content/docs/workers/tutorials/deploy-a-realtime-chat-app/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-09-13 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Deploy a real-time chat application products: diff --git a/src/content/docs/workers/tutorials/deploy-button/index.mdx b/src/content/docs/workers/tutorials/deploy-button/index.mdx index e10942eb5ca37b..50b52e83d6bf23 100644 --- a/src/content/docs/workers/tutorials/deploy-button/index.mdx +++ b/src/content/docs/workers/tutorials/deploy-button/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-08-01 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Create a deploy button with GitHub Actions diff --git a/src/content/docs/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/index.mdx b/src/content/docs/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/index.mdx index d6a0bb12c47af6..0423e98e43424a 100644 --- a/src/content/docs/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/index.mdx +++ b/src/content/docs/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-03-27 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Generate YouTube thumbnails with Workers and Cloudflare Image Resizing products: @@ -369,7 +368,7 @@ Create a Worker to serve the image you uploaded to Images by running: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -498,8 +497,6 @@ Image transformations can only be tested when you deploy your Worker. To deploy your Worker, open your Wrangler file and update the `name` key with your project's name. Below is an example with this tutorial's project name: - - ```toml diff --git a/src/content/docs/workers/tutorials/github-sms-notifications-using-twilio/index.mdx b/src/content/docs/workers/tutorials/github-sms-notifications-using-twilio/index.mdx index afdd3b7af06c1b..4b4f2c84e42b3a 100644 --- a/src/content/docs/workers/tutorials/github-sms-notifications-using-twilio/index.mdx +++ b/src/content/docs/workers/tutorials/github-sms-notifications-using-twilio/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-09-28 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: GitHub SMS notifications using Twilio languages: @@ -39,7 +38,7 @@ Start by using `npm create cloudflare@latest` to create a Worker project in the product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> @@ -237,7 +236,7 @@ async fetch(request, env, ctx) { }; ``` -Run the `npx wrangler publish` command to redeploy your Worker project: +Run the `npx wrangler deploy` command to redeploy your Worker project: ```sh npx wrangler deploy diff --git a/src/content/docs/workers/tutorials/handle-form-submissions-with-airtable/index.mdx b/src/content/docs/workers/tutorials/handle-form-submissions-with-airtable/index.mdx index af023926798948..2c53e35d04370b 100644 --- a/src/content/docs/workers/tutorials/handle-form-submissions-with-airtable/index.mdx +++ b/src/content/docs/workers/tutorials/handle-form-submissions-with-airtable/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-06-13 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Handle form submissions with Airtable tags: @@ -93,7 +92,7 @@ Create a new `airtable-form-handler` Worker project: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/tutorials/live-cursors-with-nextjs-rpc-do/index.mdx b/src/content/docs/workers/tutorials/live-cursors-with-nextjs-rpc-do/index.mdx index d27595d4ba5969..851e03389d6e49 100644 --- a/src/content/docs/workers/tutorials/live-cursors-with-nextjs-rpc-do/index.mdx +++ b/src/content/docs/workers/tutorials/live-cursors-with-nextjs-rpc-do/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-11-07 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Build Live Cursors with Next.js, RPC and Durable Objects products: @@ -127,7 +126,7 @@ that will be made available to the Next.js Worker using a [`WorkerEntrypoint`](/ product="workers" params={{ category: "hello-world", - type: "Hello World Worker using Durable Objects", + type: "Worker + Durable Objects", lang: "TypeScript", }} /> diff --git a/src/content/docs/workers/tutorials/openai-function-calls-workers/index.mdx b/src/content/docs/workers/tutorials/openai-function-calls-workers/index.mdx index 1df3c4ece83eaa..d48bbb782fb041 100644 --- a/src/content/docs/workers/tutorials/openai-function-calls-workers/index.mdx +++ b/src/content/docs/workers/tutorials/openai-function-calls-workers/index.mdx @@ -1,7 +1,6 @@ --- updated: 2023-06-14 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: OpenAI GPT function calling with JavaScript and Cloudflare Workers languages: @@ -43,7 +42,7 @@ Create a Worker project in the command line: product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "JavaScript", }} /> diff --git a/src/content/docs/workers/tutorials/postgres/index.mdx b/src/content/docs/workers/tutorials/postgres/index.mdx index 7767f034ea721a..1abe3628d6391a 100644 --- a/src/content/docs/workers/tutorials/postgres/index.mdx +++ b/src/content/docs/workers/tutorials/postgres/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-08-23 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Connect to a PostgreSQL database with Cloudflare Workers products: @@ -43,7 +42,7 @@ This will prompt you to install the [`create-cloudflare`](https://www.npmjs.com/ product="workers" params={{ category: "hello-world", - type: "Hello World Worker", + type: "Worker only", lang: "TypeScript", }} /> @@ -104,14 +103,10 @@ npx wrangler secret put DB_URL Set your `DB_URL` secret locally in a `.dev.vars` file as documented in [Local Development with Secrets](/workers/configuration/secrets/). - - -```toml +```toml title='.dev.vars' DB_URL="" ``` - - ### Set explicit parameters Configure each database parameter as an [environment variable](/workers/configuration/environment-variables/) via the [Cloudflare dashboard](/workers/configuration/environment-variables/#add-environment-variables-via-the-dashboard) or in your Wrangler file. Refer to an example of aWrangler file configuration: @@ -380,4 +375,4 @@ Your Worker application is now live and accessible at `. diff --git a/src/content/docs/workers/tutorials/using-prisma-postgres-with-workers/index.mdx b/src/content/docs/workers/tutorials/using-prisma-postgres-with-workers/index.mdx index f5ed30d211864c..f2f1ad2f148233 100644 --- a/src/content/docs/workers/tutorials/using-prisma-postgres-with-workers/index.mdx +++ b/src/content/docs/workers/tutorials/using-prisma-postgres-with-workers/index.mdx @@ -1,7 +1,6 @@ --- updated: 2025-02-12 difficulty: Beginner -content_type: 📝 Tutorial pcx_content_type: tutorial title: Set up and use a Prisma Postgres database languages: diff --git a/src/content/docs/workers/tutorials/workers-kv-from-rust/index.mdx b/src/content/docs/workers/tutorials/workers-kv-from-rust/index.mdx index b22a3f72701bb9..8f1463b53a075b 100644 --- a/src/content/docs/workers/tutorials/workers-kv-from-rust/index.mdx +++ b/src/content/docs/workers/tutorials/workers-kv-from-rust/index.mdx @@ -1,7 +1,6 @@ --- updated: 2024-05-15 difficulty: Intermediate -content_type: 📝 Tutorial pcx_content_type: tutorial title: Use Workers KV directly from Rust products: diff --git a/src/content/docs/workers/wrangler/bundling.mdx b/src/content/docs/workers/wrangler/bundling.mdx index 3a7acb2e080d76..e1eb8252b4860d 100644 --- a/src/content/docs/workers/wrangler/bundling.mdx +++ b/src/content/docs/workers/wrangler/bundling.mdx @@ -7,6 +7,13 @@ description: Review Wrangler's default bundling. By default, Wrangler bundles your Worker code using [`esbuild`](https://esbuild.github.io/). This means that Wrangler has built-in support for importing modules from [npm](https://www.npmjs.com/) defined in your `package.json`. To review the exact code that Wrangler will upload to Cloudflare, run `npx wrangler deploy --dry-run --outdir dist`, which will show your Worker code after Wrangler's bundling. +
    +`esbuild` version + +Wrangler uses `esbuild`. We periodically update the `esbuild` version included with Wrangler, and since `esbuild` is a pre-1.0.0 tool, this may sometimes include breaking changes to how bundling works. In particular, we may bump the `esbuild` version in a Wrangler minor version. + +
    + :::note Wrangler's inbuilt bundling usually provides the best experience, but we understand there are cases where you will need more flexibility. diff --git a/src/content/docs/workers/wrangler/commands.mdx b/src/content/docs/workers/wrangler/commands.mdx index f6625428649377..f8733373cb6670 100644 --- a/src/content/docs/workers/wrangler/commands.mdx +++ b/src/content/docs/workers/wrangler/commands.mdx @@ -7,19 +7,24 @@ head: description: Create, develop, and deploy your Cloudflare Workers with Wrangler commands. --- -import { TabItem, Tabs, Render, Type, MetaInfo, WranglerConfig } from "~/components"; +import { + TabItem, + Tabs, + Render, + Type, + MetaInfo, + WranglerConfig, +} from "~/components"; Wrangler offers a number of commands to manage your Cloudflare Workers. - [`docs`](#docs) - Open this page in your default browser. - [`init`](#init) - Create a new project from a variety of web frameworks and templates. -- [`generate`](#generate) - Create a Wrangler project using an existing [Workers template](https://github.com/cloudflare/worker-template). - [`d1`](#d1) - Interact with D1. - [`vectorize`](#vectorize) - Interact with Vectorize indexes. - [`hyperdrive`](#hyperdrive) - Manage your Hyperdrives. - [`deploy`](#deploy) - Deploy your Worker to Cloudflare. - [`dev`](#dev) - Start a local server for developing your Worker. -- [`publish`](#publish) - Publish your Worker to Cloudflare. - [`delete`](#delete-2) - Delete your Worker from Cloudflare. - [`kv namespace`](#kv-namespace) - Manage Workers KV namespaces. - [`kv key`](#kv-key) - Manage key-value pairs within a Workers KV namespace. @@ -152,29 +157,6 @@ wrangler init [] [OPTIONS] --- -## `generate` - -:::note - -This command has been deprecated as of [Wrangler v3](/workers/wrangler/migration/update-v2-to-v3/) and will be removed in a future version. - -::: - -Create a new project using an existing [Workers template](https://github.com/cloudflare/workers-sdk/tree/main/templates/worker). - -```txt -wrangler generate [] [TEMPLATE] -``` - -- `NAME` - - The name of the Workers project. This is both the directory name and `name` property in the generated [Wrangler configuration](/workers/wrangler/configuration/). -- `TEMPLATE` - - The URL of a GitHub template, with a default [worker-template](https://github.com/cloudflare/worker-template). Browse a list of available templates on the [cloudflare/workers-sdk](https://github.com/cloudflare/workers-sdk/tree/main/templates#usage) repository. - - - ---- - ## `d1` Interact with Cloudflare's D1 service. @@ -469,8 +451,6 @@ As of Wrangler v3.2.0, `wrangler dev` is supported by any Linux distributions pr - Host to act as origin in local mode, defaults to `dev.host` or route. - `--assets` - Folder of static assets to be served. Replaces [Workers Sites](/workers/configuration/sites/). Visit [assets](/workers/static-assets/) for more information. -- `--legacy-assets` - - Folder of static assets to be served. - `--site` - Folder of static assets for Workers Sites. :::caution @@ -484,18 +464,16 @@ As of Wrangler v3.2.0, `wrangler dev` is supported by any Linux distributions pr - Protocol to forward requests to host on. - `--var` - Array of `key:value` pairs to inject as variables into your code. The value will always be passed as a string to your Worker. - - For example, `--var git_hash:$(git rev-parse HEAD) test:123` makes the `git_hash` and `test` variables available in your Worker's `env`. + - For example, `--var "git_hash:'$(git rev-parse HEAD)'" "test:123"` makes the `git_hash` and `test` variables available in your Worker's `env`. - This flag is an alternative to defining [`vars`](/workers/wrangler/configuration/#non-inheritable-keys) in your [Wrangler configuration file](/workers/wrangler/configuration/). If defined in both places, this flag's values will be used. - `--define` - Array of `key:value` pairs to replace global identifiers in your code. - - For example, `--define GIT_HASH:$(git rev-parse HEAD)` will replace all uses of `GIT_HASH` with the actual value at build time. + - For example, `--define "GIT_HASH:'$(git rev-parse HEAD)'"` will replace all uses of `GIT_HASH` with the actual value at build time. - This flag is an alternative to defining [`define`](/workers/wrangler/configuration/#non-inheritable-keys) in your [Wrangler configuration file](/workers/wrangler/configuration/). If defined in both places, this flag's values will be used. - `--tsconfig` - Path to a custom `tsconfig.json` file. - `--minify` - Minify the Worker. -- `--node-compat` - - Enable Node.js compatibility. - `--persist-to` - Specify directory to use for local persistence. - `--remote` @@ -547,8 +525,6 @@ None of the options for this command are required. Also, many can be set in your - Use the latest version of the Workers runtime. - `--assets` - Folder of static assets to be served. Replaces [Workers Sites](/workers/configuration/sites/). Visit [assets](/workers/static-assets/) for more information. -- `--legacy-assets` - - Folder of static assets to be served. - `--site` - Folder of static assets for Workers Sites. :::caution @@ -575,8 +551,6 @@ None of the options for this command are required. Also, many can be set in your - Path to a custom `tsconfig.json` file. - `--minify` - Minify the bundled Worker before deploying. -- `--node-compat` - - Enable node.js compatibility. - `--dry-run` - Compile a project without actually deploying to live servers. Combined with `--outdir`, this is also useful for testing the output of `npx wrangler deploy`. It also gives developers a chance to upload our generated sourcemap to a service like Sentry, so that errors from the Worker can be mapped against source code, but before the service goes live. - `--keep-vars` @@ -589,22 +563,6 @@ None of the options for this command are required. Also, many can be set in your --- -## `publish` - -Publish your Worker to Cloudflare. - -```txt -wrangler publish [OPTIONS] -``` - -:::note - -This command has been deprecated as of v3 in favor of [`wrangler deploy`](#deploy). It will be removed in v4. - -::: - ---- - ## `delete` Delete your Worker and all associated Cloudflare developer platform resources. @@ -921,19 +879,6 @@ wrangler workflows trigger [OPTIONS] wrangler workflows trigger my-workflow '{"hello":"world"}' ``` -### `delete` - -Delete (unregister) a Workflow. - -```sh -wrangler workflows delete [OPTIONS] -``` - -- `WORKFLOW_NAME` - - The name of a registered Workflow. - -\*/} - ## `tail` Start a session to livestream logs from a deployed Worker. @@ -1153,22 +1098,6 @@ Your site is deployed to `.pages.dev`. If you do not provide the ` ::: -### `publish` - -Publish a directory of static assets as a Pages deployment. - -```txt -wrangler pages publish [] [OPTIONS] -``` - - - -:::note - -This command has been deprecated as of v3 in favor of [`wrangler pages deploy`](#deploy-1). It will be removed in v4. - -::: - ### `secret put` Create or update a secret for a Pages project. @@ -1348,6 +1277,35 @@ wrangler queues consumer remove +### `purge` + +Permanently delete all messages in a queue. + +```txt +wrangler queues purge +``` +- `queue-name` + - The name of the queue from which messages should be deleted. + +### `pause-delivery` + +Pause message delivery from a Queue to consumers (including push consumers, and HTTP pull consumers) + +```txt +wrangler queues pause-delivery +``` +- `queue-name` + - The name of the queue which delivery should be paused. + +### `resume-delivery` + +Resume delivery from a Queue to consumers (including push consumers, and HTTP pull consumers) +```txt +wrangler queues resume-delivery +``` +- `queue-name` + - The name of the queue from which delivery should be resumed. + --- ## `login` @@ -1854,6 +1812,7 @@ wrangler cert upload certificate-authority --ca-cert [OPTIONS] ``` - `--ca-cert` + - A path to the Certificate Authority (CA) chain certificate to upload. - `--name` @@ -1937,7 +1896,7 @@ Deleted certificate 99f5fef1-6cc1-46b8-bd79-44a0d5082b8d successfully ## `types` -Generate types from bindings and module rules in configuration. +Generate types based on your Worker configuration, including `Env` types based on your bindings, module rules, and [runtime types](/workers/languages/typescript/) based on the`compatibility_date` and `compatibility_flags` in your [config file](/workers/wrangler/configuration/). ```txt wrangler types [] [OPTIONS] @@ -1945,33 +1904,24 @@ wrangler types [] [OPTIONS] :::note -The `--experimental-include-runtime` flag dynamically generates runtime types according to the `compatibility_date` and `compatibility_flags` defined in your [config file](/workers/wrangler/configuration/). - -It is a replacement for the [`@cloudflare/workers-types` package](https://www.npmjs.com/package/@cloudflare/workers-types), so that package, if installed, should be uninstalled to avoid any potential conflict. - -After running the command, you must add the path of the generated runtime types file to the [`compilerOptions.types` field](https://www.typescriptlang.org/tsconfig/#types) in your project's [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) file. - -You may use the shorthand `--x-include-runtime` flag in place of `--experimental-include-runtime` anywhere it is mentioned. - -The minimum required Wrangler version to use this command is 3.66.0. + ::: - `PATH` - - The path to where **the `Env` types** for your Worker will be written. + - The path to where types for your Worker will be written. - The path must have a `d.ts` extension. - `--env-interface` - The name of the interface to generate for the environment object. - Not valid if the Worker uses the Service Worker syntax. -- `--experimental-include-runtime` - - The path to where the **runtime types** file will be written. - - Leave the path blank to use the default option, e.g. `npx wrangler types --x-include-runtime` - - A custom path must be relative to the project root, e.g. `./my-runtime-types.d.ts` - - A custom path must have a `d.ts` extension. +- `--include-runtime` + - Whether to generate runtime types based on the`compatibility_date` and `compatibility_flags` in your [config file](/workers/wrangler/configuration/). +- `--include-env` + - Whether to generate `Env` types based on your Worker bindings. - `--strict-vars` - Control the types that Wrangler generates for `vars` bindings. - - If `true`, (the default) Wrangler generates literal and union types for bindings (e.g. `myEnv: 'my dev variable' | 'my prod variable'`). - - If `false`, Wrangler generates generic types (e.g. `myEnv: string`). This is useful when variables change frequently, especially when working across multiple environments. + - If `true`, (the default) Wrangler generates literal and union types for bindings (e.g. `myVar: 'my dev variable' | 'my prod variable'`). + - If `false`, Wrangler generates generic types (e.g. `myVar: string`). This is useful when variables change frequently, especially when working across multiple environments. diff --git a/src/content/docs/workers/wrangler/configuration.mdx b/src/content/docs/workers/wrangler/configuration.mdx index bcdcb64b898b73..ee0fe9fd34087c 100644 --- a/src/content/docs/workers/wrangler/configuration.mdx +++ b/src/content/docs/workers/wrangler/configuration.mdx @@ -52,10 +52,10 @@ kv_namespaces = [ ## Environments -The configuration for a Worker can become complex when you define different [environments](/workers/wrangler/environments/), and each environment has its own configuration. -There is a default (top-level) environment and named environments that provide environment-specific configuration. +You can define different configurations for a Worker using Wrangler [environments](/workers/wrangler/environments/). +There is a default (top-level) environment and you can create named environments that provide environment-specific configuration. -These are defined under `[env.name]` keys, such as `[env.staging]` which you can then preview or deploy with the `-e` / `--env` flag in the `wrangler` commands like `npx wrangler deploy --env staging`. +These are defined under `[env.]` keys, such as `[env.staging]` which you can then preview or deploy with the `-e` / `--env` flag in the `wrangler` commands like `npx wrangler deploy --env staging`. The majority of keys are inheritable, meaning that top-level configuration can be used in environments. [Bindings](/workers/runtime-apis/bindings/), such as `vars` or `kv_namespaces`, are not inheritable and need to be defined explicitly. @@ -167,12 +167,6 @@ At a minimum, the `name`, `main` and `compatibility_date` keys are required to d - Minify the Worker script before uploading. -- `node_compat` - - - Deprecated — Instead, [enable the `nodejs_compat` compatibility flag](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag), which enables both built-in Node.js APIs, and adds polyfills as necessary. - Setting `node_compat = true` will add polyfills for Node.js built-in modules and globals to your Worker's code, when bundled with Wrangler. - This is powered by `@esbuild-plugins/node-globals-polyfill` which in itself is powered by [rollup-plugin-node-polyfills](https://github.com/ionic-team/rollup-plugin-node-polyfills/). - - `logpush` - Enables Workers Trace Events Logpush for a Worker. Any scripts with this property will automatically get picked up by the Workers Logpush job configured for your account. Defaults to `false`. Refer to [Workers Logpush](/workers/observability/logs/logpush/). @@ -188,12 +182,6 @@ At a minimum, the `name`, `main` and `compatibility_date` keys are required to d * `assets` - Configures static assets that will be served. Refer to [Assets](/workers/static-assets/binding/) for more details. -### Usage model - -As of March 1, 2024 the [usage model](/workers/platform/pricing/#workers) configured in your Worker's configuration file will be ignored. The [Standard](/workers/platform/pricing/#example-pricing-standard-usage-model) usage model applies. - -Some Workers Enterprise customers maintain the ability to change usage models. Your usage model must be configured through the Cloudflare dashboard by going to **Workers & Pages** > select your Worker > **Settings** > **Usage Model**. - ## Non-inheritable keys Non-inheritable keys are configurable at the top-level, but cannot be inherited by environments and must be specified for each environment. @@ -658,7 +646,7 @@ id = ""
    -### Images +### Images [Cloudflare Images](/images/transform-images/transform-via-workers/) lets you make transformation requests to optimize, resize, and manipulate images stored in remote sources. @@ -879,6 +867,7 @@ To bind other Workers to your Worker, assign an array of the below object to the - `service` - The name of the Worker. + - To bind to a Worker in a specific [environment](/workers/wrangler/environments), you need to append the environment name to the Worker name. This should be in the format `-`. For example, to bind to a Worker called `worker-name` in its `staging` environment, `service` should be set to `worker-name-staging`. - `entrypoint` @@ -1316,17 +1305,17 @@ A common example of using a redirected configuration is where a custom build too - ```toml title="wrangler.toml" - name = "my-worker" - main = "src/index.ts" - [[kv_namespaces]] - binding = "" - id = "" - ``` +```toml title="wrangler.toml" +name = "my-worker" +main = "src/index.ts" +[[kv_namespaces]] +binding = "" +id = "" +``` - Note that this configuration points `main` at the user's code entry-point. +Note that this configuration points `main` at the user's code entry-point. - Then, the user runs a custom build, which might read the user's Wrangler configuration file to find the source code entry-point: diff --git a/src/content/docs/workers/wrangler/custom-builds.mdx b/src/content/docs/workers/wrangler/custom-builds.mdx index 922dbf4c694b0b..ae5c36764e37e1 100644 --- a/src/content/docs/workers/wrangler/custom-builds.mdx +++ b/src/content/docs/workers/wrangler/custom-builds.mdx @@ -12,7 +12,7 @@ Custom builds are a way for you to customize how your code is compiled, before b :::note -With the release of Wrangler v2, it is no longer necessary to use custom builds to bundle your code via webpack and similar bundlers. Wrangler runs [esbuild](https://esbuild.github.io/) by default as part of the `dev` and `publish` commands, and bundles your Worker project into a single Worker script. Refer to [Bundling](/workers/wrangler/bundling/). +Wrangler runs [esbuild](https://esbuild.github.io/) by default as part of the `dev` and `publish` commands, and bundles your Worker project into a single Worker script. Refer to [Bundling](/workers/wrangler/bundling/). ::: ## Configure custom builds diff --git a/src/content/docs/workers/wrangler/deprecations.mdx b/src/content/docs/workers/wrangler/deprecations.mdx index eb66f60ab357e9..e8fe04ab05a97c 100644 --- a/src/content/docs/workers/wrangler/deprecations.mdx +++ b/src/content/docs/workers/wrangler/deprecations.mdx @@ -9,6 +9,16 @@ description: The differences between Wrangler versions, specifically Review the difference between Wrangler versions, specifically deprecations and breaking changes. +## Wrangler v4 + +### Workers Sites + +Usage of [Workers Sites](/workers/wrangler/configuration/#workers-sites) is deprecated. Instead, we recommend migrating to [Workers Static Assets](/workers/static-assets/). Support for using Workers Sites with Wrangler will be removed in a future version of Wrangler. + +### Service environments + +Usage of [Service Environments](https://blog.cloudflare.com/introducing-worker-services/#services-have-environments), enabled via the `legacy_env` property in Wrangler config, is deprecated. Instead, we recommend migrating to [Wrangler Environments](/workers/wrangler/configuration/#environments). Support for using Service Environments with Wrangler will be removed in a future version of Wrangler. + ## Wrangler v3 ### Deprecated commands @@ -33,6 +43,10 @@ The `wrangler pages publish` command is deprecated, but still active in v3. `wra Use [`wrangler pages deploy`](/workers/wrangler/commands/#deploy-1) to deploy Pages. +#### `version` + +Instead, use `wrangler --version` to check the current version of Wrangler. + ### Deprecated options #### `--experimental-local` @@ -51,6 +65,18 @@ Use [`wrangler pages deploy`](/workers/wrangler/commands/#deploy-1) to deploy Pa These options prevent `wrangler pages dev` from being able to accurately emulate production's behavior for serving static assets and have therefore been deprecated. Instead of relying on Wrangler to proxy through to some other upstream dev server, you can emulate a more accurate behavior by building your static assets to a directory and pointing Wrangler to that directory with `wrangler pages dev `. +#### `--legacy-assets` and the `legacy_assets` config file property + +We recommend you [migrate to Workers assets](https://developers.cloudflare.com/workers/static-assets/) + +#### `--node-compat` and the `node_compat` config file property + +Instead, use the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs). This includes the functionality from legacy `node_compat` polyfills and natively implemented Node.js APIs. + +#### The `usage_model` config file property + +This no longer has any effect, after the [rollout of Workers Standard Pricing](https://blog.cloudflare.com/workers-pricing-scale-to-zero/). + ## Wrangler v2 Wrangler v2 introduces new fields for configuration and new features for developing and deploying a Worker, while deprecating some redundant fields. diff --git a/src/content/docs/workers/wrangler/environments.mdx b/src/content/docs/workers/wrangler/environments.mdx index 527ab2472c2e5f..3b4fa02624c260 100644 --- a/src/content/docs/workers/wrangler/environments.mdx +++ b/src/content/docs/workers/wrangler/environments.mdx @@ -2,38 +2,37 @@ pcx_content_type: concept title: Environments head: [] -description: Deploy the same Worker application with different configuration for - each environment. +description: Use environments to create different configurations for the same Worker application. --- import { WranglerConfig } from "~/components"; -## Background - -Wrangler allows you to deploy the same Worker application with different configuration for each environment. You must configure environments in your Worker application's Wrangler file. +Wrangler allows you to use environments to create different configurations for the same Worker application. Environments are configured in the Worker's [Wrangler configuration file](/workers/wrangler/configuration/). +There is a default (top-level) environment and you can create named environments that provide environment-specific configuration. Review the following environments flow: -1. You have created a Worker application named `my-worker`. -2. You create an environment, for example, `dev`, in the Worker's [Wrangler configuration file](/workers/wrangler/configuration/). -3. In the Wrangler configuration file, you configure the `dev` environment by [adding bindings](/workers/runtime-apis/bindings/) and/or [routes](/workers/configuration/routing/routes/). -4. You deploy the Worker using `npx wrangler deploy -e dev`. -5. In the background, Wrangler creates a new Worker named `my-worker-dev`. -6. You can now change your `my-worker` Worker code and configuration, and choose which environment to deploy your changes to. - -Environments are used with the `--env` or `-e` flag on `wrangler dev`, `npx wrangler deploy`, and `wrangler secret`. +1. Create a Worker, named `my-worker` for example. +2. Create an environment, for example `dev`, in the Worker's [Wrangler configuration file](/workers/wrangler/configuration/), by adding a `[env.]` section. -## Configuration + -To create an environment: +```json +{ + "name": "my-worker", + "env": { + "": { + // environment-specific configuration goes here + } + } +} +``` -1. Open your Worker's Wrangler file. -2. Add `[env.]` and change `` to the desired name of your environment. -3. Repeat step 2 to create multiple environments. + -Be careful when naming your environments that they do not contain sensitive information, such as, `migrating-service-from-company1-to-company2` or `company1-acquisition-load-test`. +3. You can configure the `dev` environment with different values to the top-level environment. Refer [here](/workers/wrangler/configuration/#environments) for how different options are inherited - or not inherited - between environments. -Review the layout of an example `[env.dev]` environment that sets up a custom `dev.example.com` route: +For example, to set a different route for a Worker in the `dev` environment: @@ -46,23 +45,21 @@ route = "dev.example.com" ``` +4. Environments are used with the `--env` or `-e` flag on Wrangler commands. For example, you can develop the Worker in the `dev` environment by running `npx wrangler dev -e=dev`, and deploy it with `npx wrangler deploy -e=dev`. -You cannot specify multiple environments with the same name. - -Wrangler appends the environment name to the top-level name to deploy a Worker. For example, a Worker project named `my-worker` with an environment `[env.dev]` would deploy a Worker named `my-worker-dev`. +:::note -After you have configured your environment, run `npx wrangler deploy` in your Worker project directory for the changes to take effect. +Cloudflare effectively creates a new Worker for you when you create a Worker with an environment. Wrangler appends the environment name to the top-level name. For example, a Worker project named `my-worker` with an environment `dev` would deploy a Worker named `my-worker-dev`. You must use this name when referencing a Worker in a particular environment, for example in a [service binding](/workers/wrangler/configuration/#service-bindings). +::: ## Non-inheritable keys and environments [Non-inheritable keys](/workers/wrangler/configuration/#non-inheritable-keys) are configurable at the top-level, but cannot be inherited by environments and must be specified for each environment. -[Bindings](/workers/runtime-apis/bindings/) and [environment variables](/workers/configuration/environment-variables/) must be specified per each [environment](/workers/wrangler/environments/) in your [Wrangler configuration file](/workers/wrangler/configuration/). +For example, [bindings](/workers/runtime-apis/bindings/) and [environment variables](/workers/configuration/environment-variables/) are non-inheritable, and must be specified per [environment](/workers/wrangler/environments/) in your [Wrangler configuration file](/workers/wrangler/configuration/). Review the following example Wrangler file: - - ```toml @@ -85,7 +82,41 @@ kv_namespaces = [ -You may assign environment-specific [secrets](/workers/configuration/secrets/) by running the command [`wrangler secret put -env`](/workers/wrangler/commands/#put). +### Service bindings + +To use a [service binding](/workers/wrangler/configuration/#service-bindings) that targets a Worker in a specific environment, you need to append the environment name to the target Worker name in the `service` field. This should be in the format `-`. +In the example below, we have two Workers, both with a `staging` environment. `worker-b` has a service binding to `worker-a`. Note how the `service` field in the `staging` environment points to `worker-a-staging`, whereas the top-level service binding points to `worker-a`. + + + +```toml +name = "worker-a" + +vars = { FOO = "" } +[env.staging.vars] +FOO = "" +``` + + + + + +```toml +name = "worker-b" + +services = { binding = "", service = "worker-a" } + +# Note how `service = "worker-a-staging"` +env.staging.service ={ binding = "", service = "worker-a-staging" } +``` + + + +### Secrets + +You may assign environment-specific [secrets](/workers/configuration/secrets/) by running the command [`wrangler secret put -env`](/workers/wrangler/commands/#put). You can also create `dotenv` type files named `.dev.vars.`. + +Like other environment variables, secrets are [non-inheritable](/workers/wrangler/configuration/#non-inheritable-keys) and must be defined per environment. --- @@ -95,8 +126,6 @@ You may assign environment-specific [secrets](/workers/configuration/secrets/) b The following Wrangler file adds two environments, `[env.staging]` and `[env.production]`, to the Wrangler file. If you are deploying to a [Custom Domain](/workers/configuration/routing/custom-domains/) or [route](/workers/configuration/routing/routes/), you must provide a [`route` or `routes` key](/workers/wrangler/configuration/) for each environment. - - ```toml @@ -118,7 +147,7 @@ routes = [ -In order to use environments with this configuration, you can pass the name of the environment via the `--env` flag. +You can pass the name of the environment via the `--env` flag to run commands in a specific environment. With this configuration, Wrangler will behave in the following manner: @@ -168,8 +197,6 @@ if (ENVIRONMENT === "staging") { To deploy your code to your `*.workers.dev` subdomain, include `workers_dev = true` in the desired environment. Your Wrangler file may look like this: - - ```toml @@ -206,6 +233,6 @@ Published my-worker :::caution -When you create a Worker via an environment, Cloudflare automatically creates an SSL certification for it. SSL certifications are discoverable and a matter of public record. +When you create a Worker via an environment, Cloudflare automatically creates an SSL certification for it. SSL certifications are discoverable and a matter of public record. Be careful when naming your environments that they do not contain sensitive information, such as, `migrating-service-from-company1-to-company2` or `company1-acquisition-load-test`. ::: diff --git a/src/content/docs/workers/wrangler/install-and-update.mdx b/src/content/docs/workers/wrangler/install-and-update.mdx index c043786cbab6bf..5c17966976e8f1 100644 --- a/src/content/docs/workers/wrangler/install-and-update.mdx +++ b/src/content/docs/workers/wrangler/install-and-update.mdx @@ -14,7 +14,16 @@ Wrangler is a command-line tool for building with Cloudflare developer products. ## Install Wrangler -To install [Wrangler](https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler), ensure you have [Node.js](https://nodejs.org/en/) and [npm](https://docs.npmjs.com/getting-started) installed, preferably using a Node version manager like [Volta](https://volta.sh/) or [nvm](https://github.com/nvm-sh/nvm). Using a version manager helps avoid permission issues and allows you to change Node.js versions. Wrangler requires a Node version of `16.17.0` or later. +To install [Wrangler](https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler), ensure you have [Node.js](https://nodejs.org/en/) and [npm](https://docs.npmjs.com/getting-started) installed, preferably using a Node version manager like [Volta](https://volta.sh/) or [nvm](https://github.com/nvm-sh/nvm). Using a version manager helps avoid permission issues and allows you to change Node.js versions. + +
    +Wrangler System Requirements + +We support running the Wrangler CLI with the [Current, Active, and Maintenance](https://nodejs.org/en/about/previous-releases) versions of Node.js. Your Worker will always be executed in `workerd`, the open source Cloudflare Workers runtime. + +Wrangler is only supported on macOS 13.5+, Windows 11, and Linux distros that support glib 2.35. This follows [`workerd`'s OS support policy](https://github.com/cloudflare/workerd?tab=readme-ov-file#running-workerd). + +
    Wrangler is installed locally into each of your projects. This allows you and your team to use the same Wrangler version, control Wrangler versions for each project, and roll back to an earlier version of Wrangler, if needed. diff --git a/src/content/docs/workers/wrangler/migration/update-v2-to-v3.mdx b/src/content/docs/workers/wrangler/migration/update-v2-to-v3.mdx index c70685cae18c06..15bcd7d90746f7 100644 --- a/src/content/docs/workers/wrangler/migration/update-v2-to-v3.mdx +++ b/src/content/docs/workers/wrangler/migration/update-v2-to-v3.mdx @@ -2,7 +2,7 @@ title: Migrate from Wrangler v2 to v3 pcx_content_type: how-to sidebar: - order: 1 + order: 2 --- diff --git a/src/content/docs/workers/wrangler/migration/update-v3-to-v4.mdx b/src/content/docs/workers/wrangler/migration/update-v3-to-v4.mdx new file mode 100644 index 00000000000000..3482b4bcba803e --- /dev/null +++ b/src/content/docs/workers/wrangler/migration/update-v3-to-v4.mdx @@ -0,0 +1,61 @@ +--- +title: Migrate from Wrangler v3 to v4 +pcx_content_type: how-to +sidebar: + order: 1 +--- + +Wrangler v4 is a major release focused on updates to underlying systems and dependencies, along with improvements to keep Wrangler commands consistent and clear. Unlike previous major versions of Wrangler, which were [foundational rewrites](https://blog.cloudflare.com/wrangler-v2-beta/) and [rearchitectures](https://blog.cloudflare.com/wrangler3/) — Version 4 of Wrangler includes a much smaller set of changes. If you use Wrangler today, your workflow is very unlikely to change. + +While many users should expect a no-op upgrade, the following sections outline the more significant changes and steps for migrating where necessary. + +### Summary of changes + +- **Updated Node.js support policy:** + Node.js v16, which reached End-of-Life in 2022, is no longer supported in Wrangler v4. Wrangler now follows Node.js's [official support lifecycle](https://nodejs.org/en/about/previous-releases). + +- **Upgraded esbuild version**: Wrangler uses [esbuild](https://esbuild.github.io/) to bundle Worker code before deploying it, and was previously pinned to esbuild v0.17.19. Wrangler v4 uses esbuild v0.24, which could impact dynamic wildcard imports. Going forward, Wrangler will be periodically updating the `esbuild` version included with Wrangler, and since `esbuild` is a pre-1.0.0 tool, this may sometimes include breaking changes to how bundling works. In particular, we may bump the `esbuild` version in a Wrangler minor version. + +- **Commands default to local mode**: All commands that can run in either local or remote mode now default to local, requiring a `--remote` flag for API queries. + +- **Deprecated commands and configurations removed:** Legacy commands, flags, and configurations are removed. + +## Detailed Changes + +### Updated Node.js support policy + +Wrangler now supports only Node.js versions that align with [Node.js's official lifecycle](https://nodejs.org/en/about/previous-releases): + +- **Supported**: Current, Active LTS, Maintenance LTS +- **No longer supported:** Node.js v16 (EOL in 2022) + +Wrangler tests no longer run on v16, and users still on this version may encounter unsupported behavior. Users still using Node.js v16 must upgrade to a supported version to continue receiving support and compatibility with Wrangler. + +### Upgraded esbuild version + +Wrangler v4 upgrades esbuild from **v0.17.19** to **v0.24**, bringing improvements (such as the ability to use the `using` keyword with RPC) and changes to bundling behavior: + +- **Dynamic imports:** Wildcard imports (for example, `import('./data/' + kind + '.json')`) now automatically include all matching files in the bundle. + +Users relying on wildcard dynamic imports may see unwanted files bundled. Prior to esbuild v0.19, `import` statements with dynamic paths ( like `import('./data/' + kind + '.json')`) did not bundle all files matches the glob pattern (`*.json`) . Only files explicitly referenced or included using `find_additional_modules` were bundled. With esbuild v0.19, wildcard imports now automatically bundle all files matching the glob pattern. This could result in unwanted files being bundled, so users might want to avoid wildcard dynamic imports and use explicit imports instead. + +### Commands default to local mode + +All commands now run in **local mode by default.** Wrangler has many commands for accessing resources like KV and R2, but the commands were previously inconsistent in whether they ran in a local or remote environment. For example, D1 defaulted to querying a local datastore, and required the `--remote` flag to query via the API. KV, on the other hand, previously defaulted to querying via the API (implicitly using the `--remote` flag) and required a `--local` flag to query a local datastore. In order to make the behavior consistent across Wrangler, each command now uses the `--local` flag by default, and requires an explicit `--remote` flag to query via the API. + +For example: + +- **Previous Behavior (Wrangler v3):** `wrangler kv get` queried remotely by default. +- **New Behavior (Wrangler v4):** `wrangler kv get` queries locally unless `--remote` is specified. + +Those using `wrangler kv key` and/or `wrangler r2 object` commands to query or write to their data store will need to add the `--remote` flag in order to replicate previous behavior. + +### Deprecated commands and configurations removed + +All previously deprecated features in [Wrangler v2](https://developers.cloudflare.com/workers/wrangler/deprecations/#wrangler-v2) and in [Wrangler v3](https://developers.cloudflare.com/workers/wrangler/deprecations/#wrangler-v3) are now removed. Additionally, the following features that were deprecated during the Wrangler v3 release are also now removed: + +- Legacy Assets (using `wrangler dev/deploy --legacy-assets` or the `legacy_assets` config file property). Instead, we recommend you [migrate to Workers assets](https://developers.cloudflare.com/workers/static-assets/). +- Legacy Node.js compatibility (using `wrangler dev/deploy --node-compat` or the `node_compat` config file property). Instead, use the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs). This includes the functionality from legacy `node_compat` polyfills and natively implemented Node.js APIs. +- `wrangler version`. Instead, use `wrangler --version` to check the current version of Wrangler. +- `getBindingsProxy()` (via `import { getBindingsProxy } from "wrangler"`). Instead, use the [`getPlatformProxy()` API](https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy), which takes exactly the same arguments. +- `usage_model`. This no longer has any effect, after the [rollout of Workers Standard Pricing](https://blog.cloudflare.com/workers-pricing-scale-to-zero/). diff --git a/src/content/docs/workers/wrangler/migration/v1-to-v2/index.mdx b/src/content/docs/workers/wrangler/migration/v1-to-v2/index.mdx index c2ed5ec6cc2c48..4f9e78b58d62cf 100644 --- a/src/content/docs/workers/wrangler/migration/v1-to-v2/index.mdx +++ b/src/content/docs/workers/wrangler/migration/v1-to-v2/index.mdx @@ -2,7 +2,7 @@ title: Migrate from Wrangler v1 to v2 pcx_content_type: how-to sidebar: - order: 1 + order: 3 group: hideIndex: true --- diff --git a/src/content/docs/workflows/build/rules-of-workflows.mdx b/src/content/docs/workflows/build/rules-of-workflows.mdx index 9af4259837fa67..9a6b0fa4e37da4 100644 --- a/src/content/docs/workflows/build/rules-of-workflows.mdx +++ b/src/content/docs/workflows/build/rules-of-workflows.mdx @@ -449,3 +449,32 @@ export class MyWorkflow extends WorkflowEntrypoint { } ``` + +### Batch multiple Workflow invocations + +When creating multiple Workflow instances, use the [`createBatch`](/workflows/build/workers-api/#createBatch) method to batch the invocations together. This allows you to create multiple Workflow instances in a single request, which will reduce the number of requests made to the Workflows API and increase the number of instances you can create per minute. + + + +```ts +export default { + async fetch(req: Request, env: Env): Promise { + let instances = [{"id": "user1", "params": {"name": "John"}}, {"id": "user2", "params": {"name": "Jane"}}, {"id": "user3", "params": {"name": "Alice"}}, {"id": "user4", "params": {"name": "Bob"}}]; + + // 🔴 Bad: Create them one by one, which is more likely to hit creation rate limits. + for (let instance of instances) { + await env.MY_WORKFLOW.create({ + id: instance.id, + params: instance.params + }); + } + + // ✅ Good: Batch calls together + // This improves throughput. + let instances = await env.MY_WORKFLOW.createBatch(instances); + return Response.json({ instances }) + }, +}; +``` + + diff --git a/src/content/docs/workflows/build/workers-api.mdx b/src/content/docs/workflows/build/workers-api.mdx index ca3e3e80c07a5e..3f5499b8c7744e 100644 --- a/src/content/docs/workflows/build/workers-api.mdx +++ b/src/content/docs/workflows/build/workers-api.mdx @@ -78,6 +78,16 @@ Refer to the [events and parameters](/workflows/build/events-and-parameters/) do * `config` (optional) - an optional `WorkflowStepConfig` for configuring [step specific retry behaviour](/workflows/build/sleeping-and-retrying/). * `callback` - an asynchronous function that optionally returns serializable state for the Workflow to persist. +:::note[Returning state] + +When returning state from a `step`, ensure that the object you return is _serializable_. + +Primitive types like `string`, `number`, and `boolean`, along with composite structures such as `Array` and `Object` (provided they only contain serializable values), can be serialized. + +Objects that include `Function` or `Symbol` types, and objects with circular references, cannot be serialized and the Workflow instance will throw an error if objects with those types is returned. + +::: + * step.sleep(name: string, duration: WorkflowDuration): Promise<void> * `name` - the name of the step. @@ -266,6 +276,30 @@ export default { } ``` +### createBatch + +Create (trigger) a batch of new instance of the given Workflow, up to 100 instances at a time. + +This is useful when you are scheduling multiple instances at once. A call to `createBatch` is treated the same as a call to `create` (for a single instance) and allows you to work within the [instance creation limit](/workflows/reference/limits/). + +* createBatch(batch: WorkflowInstanceCreateOptions[]): Promise<WorkflowInstance[]> + + * `batch` - list of Options to pass when creating an instance, including a user-provided ID and payload parameters. + +Each element of the `batch` list is expected to the + +```ts +// Create a new batch of 3 Workflow instances, each with its own ID and pass params to the Workflow instances +const listOfInstances = [ + { id: "id-abc123", params: { "hello": "world-0" } }, + { id: "id-def456", params: { "hello": "world-1" } }, + { id: "id-ghi789", params: { "hello": "world-2" } } +]; +let instances = await env.MY_WORKFLOW.createBatch(listOfInstances); +``` + +Returns an array of `WorkflowInstance`. + ### get Get a specific Workflow instance by ID. diff --git a/src/content/docs/workflows/examples/backup-d1.mdx b/src/content/docs/workflows/examples/backup-d1.mdx index 3bbcb77ecb3867..e128095dabf618 100644 --- a/src/content/docs/workflows/examples/backup-d1.mdx +++ b/src/content/docs/workflows/examples/backup-d1.mdx @@ -1,21 +1,20 @@ --- type: example summary: Export a D1 database into R2 storage with Workflows -tags: +products: - Workflows - D1 - R2 languages: - Typescript -pcx_content_type: configuration +pcx_content_type: example title: Export and save D1 database sidebar: order: 3 description: Send invoice when shopping cart is checked out and paid for - --- -import { TabItem, Tabs, WranglerConfig } from "~/components" +import { TabItem, Tabs, WranglerConfig } from "~/components"; In this example, we implement a Workflow periodically triggered by a [Cron Trigger](/workers/configuration/cron-triggers). That Workflow initiates a backup for a D1 database using the REST API, and then stores the SQL dump in an [R2](/r2) bucket. @@ -33,79 +32,93 @@ This example provides simplified steps for backing up a [D1](/d1) database to he ```ts import { - WorkflowEntrypoint, - WorkflowStep, - WorkflowEvent, + WorkflowEntrypoint, + WorkflowStep, + WorkflowEvent, } from "cloudflare:workers"; - // We are using R2 to store the D1 backup type Env = { - BACKUP_WORKFLOW: Workflow; - D1_REST_API_TOKEN: string; - BACKUP_BUCKET: R2Bucket; + BACKUP_WORKFLOW: Workflow; + D1_REST_API_TOKEN: string; + BACKUP_BUCKET: R2Bucket; }; // Workflow parameters: we expect accountId and databaseId type Params = { - accountId: string; - databaseId: string; + accountId: string; + databaseId: string; }; // Workflow logic export class backupWorkflow extends WorkflowEntrypoint { - async run(event: WorkflowEvent, step: WorkflowStep) { - const { accountId, databaseId } = event.payload; - - const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${databaseId}/export`; - const method = "POST"; - const headers = new Headers(); - headers.append("Content-Type", "application/json"); - headers.append("Authorization", `Bearer ${this.env.D1_REST_API_TOKEN}`); - - const bookmark = await step.do(`Starting backup for ${databaseId}`, async () => { - const payload = { output_format: "polling" }; - - const res = await fetch(url, { method, headers, body: JSON.stringify(payload) }); - const { result } = (await res.json()) as any; - - // If we don't get `at_bookmark` we throw to retry the step - if (!result?.at_bookmark) throw new Error("Missing `at_bookmark`"); - - return result.at_bookmark; - }); - - await step.do("Check backup status and store it on R2", async () => { - const payload = { current_bookmark: bookmark }; - - const res = await fetch(url, { method, headers, body: JSON.stringify(payload) }); - const { result } = (await res.json()) as any; - - // The endpoint sends `signed_url` when the backup is ready to download. - // If we don't get `signed_url` we throw to retry the step. - if (!result?.signed_url) throw new Error("Missing `signed_url`"); - - const dumpResponse = await fetch(result.signed_url); - if (!dumpResponse.ok) throw new Error("Failed to fetch dump file"); - - // Finally, stream the file directly to R2 - await this.env.BACKUP_BUCKET.put(result.filename, dumpResponse.body); - }); - } + async run(event: WorkflowEvent, step: WorkflowStep) { + const { accountId, databaseId } = event.payload; + + const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${databaseId}/export`; + const method = "POST"; + const headers = new Headers(); + headers.append("Content-Type", "application/json"); + headers.append("Authorization", `Bearer ${this.env.D1_REST_API_TOKEN}`); + + const bookmark = await step.do( + `Starting backup for ${databaseId}`, + async () => { + const payload = { output_format: "polling" }; + + const res = await fetch(url, { + method, + headers, + body: JSON.stringify(payload), + }); + const { result } = (await res.json()) as any; + + // If we don't get `at_bookmark` we throw to retry the step + if (!result?.at_bookmark) throw new Error("Missing `at_bookmark`"); + + return result.at_bookmark; + }, + ); + + await step.do("Check backup status and store it on R2", async () => { + const payload = { current_bookmark: bookmark }; + + const res = await fetch(url, { + method, + headers, + body: JSON.stringify(payload), + }); + const { result } = (await res.json()) as any; + + // The endpoint sends `signed_url` when the backup is ready to download. + // If we don't get `signed_url` we throw to retry the step. + if (!result?.signed_url) throw new Error("Missing `signed_url`"); + + const dumpResponse = await fetch(result.signed_url); + if (!dumpResponse.ok) throw new Error("Failed to fetch dump file"); + + // Finally, stream the file directly to R2 + await this.env.BACKUP_BUCKET.put(result.filename, dumpResponse.body); + }); + } } export default { - async fetch(req: Request, env: Env): Promise { - return new Response("Not found", { status: 404 }); - }, - async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) { - const params: Params = { - accountId: "{accountId}", - databaseId: "{databaseId}", - }; - const instance = await env.BACKUP_WORKFLOW.create({ params }); - console.log(`Started workflow: ${instance.id}`); - }, + async fetch(req: Request, env: Env): Promise { + return new Response("Not found", { status: 404 }); + }, + async scheduled( + controller: ScheduledController, + env: Env, + ctx: ExecutionContext, + ) { + const params: Params = { + accountId: "{accountId}", + databaseId: "{databaseId}", + }; + const instance = await env.BACKUP_WORKFLOW.create({ params }); + console.log(`Started workflow: ${instance.id}`); + }, }; ``` @@ -113,10 +126,10 @@ Here is a minimal package.json: ```json { - "devDependencies": { - "@cloudflare/workers-types": "^4.20241224.0", - "wrangler": "^3.99.0" - } + "devDependencies": { + "@cloudflare/workers-types": "^4.20241224.0", + "wrangler": "^3.99.0" + } } ``` @@ -143,4 +156,4 @@ bucket_name = "d1-backups" crons = [ "0 0 * * *" ] ``` -
    \ No newline at end of file +
    diff --git a/src/content/docs/workflows/examples/index.mdx b/src/content/docs/workflows/examples/index.mdx index 8765b2d0643a42..f958454afc9346 100644 --- a/src/content/docs/workflows/examples/index.mdx +++ b/src/content/docs/workflows/examples/index.mdx @@ -7,11 +7,10 @@ sidebar: order: 6 group: hideIndex: true - --- -import { GlossaryTooltip, ListExamples } from "~/components" +import { GlossaryTooltip, ListExamples } from "~/components"; Explore the following examples for Workflows. - + diff --git a/src/content/docs/workflows/examples/send-invoices.mdx b/src/content/docs/workflows/examples/send-invoices.mdx index e3dfe27279f3f5..a746f2d49304ea 100644 --- a/src/content/docs/workflows/examples/send-invoices.mdx +++ b/src/content/docs/workflows/examples/send-invoices.mdx @@ -1,19 +1,18 @@ --- type: example summary: Send invoice when shopping cart is checked out and paid for -tags: +products: - Workflows - D1 - Email Routing -pcx_content_type: configuration +pcx_content_type: example title: Pay cart and send invoice sidebar: order: 3 description: Send invoice when shopping cart is checked out and paid for - --- -import { TabItem, Tabs, WranglerConfig } from "~/components" +import { TabItem, Tabs, WranglerConfig } from "~/components"; In this example, we implement a Workflow for an e-commerce website that is triggered every time a shopping cart is created. @@ -25,23 +24,23 @@ This is a simplified example of processing a shopping cart. We would assume more ```ts import { - WorkflowEntrypoint, - WorkflowStep, - WorkflowEvent, + WorkflowEntrypoint, + WorkflowStep, + WorkflowEvent, } from "cloudflare:workers"; import { EmailMessage } from "cloudflare:email"; import { createMimeMessage } from "mimetext"; // We are using Email Routing to send emails out and D1 for our cart database type Env = { - CART_WORKFLOW: Workflow; - SEND_EMAIL: any; - DB: any; + CART_WORKFLOW: Workflow; + SEND_EMAIL: any; + DB: any; }; // Workflow parameters: we expect a cartId type Params = { - cartId: string; + cartId: string; }; // Adjust this to your Cloudflare zone using Email Routing @@ -49,141 +48,140 @@ const merchantEmail = "merchant@example.com"; // Uses mimetext npm to generate Email const genEmail = (email: string, amount: number) => { - const msg = createMimeMessage(); - msg.setSender({ name: "Pet shop", addr: merchantEmail }); - msg.setRecipient(email); - msg.setSubject("You invoice"); - msg.addMessage({ - contentType: "text/plain", - data: `Your invoice for ${amount} has been paid. Your products will be shipped shortly.`, - }); - - return new EmailMessage(merchantEmail, email, msg.asRaw()); + const msg = createMimeMessage(); + msg.setSender({ name: "Pet shop", addr: merchantEmail }); + msg.setRecipient(email); + msg.setSubject("You invoice"); + msg.addMessage({ + contentType: "text/plain", + data: `Your invoice for ${amount} has been paid. Your products will be shipped shortly.`, + }); + + return new EmailMessage(merchantEmail, email, msg.asRaw()); }; // Workflow logic export class cartInvoicesWorkflow extends WorkflowEntrypoint { - async run(event: WorkflowEvent, step: WorkflowStep) { - await step.sleep("sleep for a while", "10 seconds"); - - // Retrieve the cart from the D1 database - // if the cart hasn't been checked out yet retry every 2 minutes, 10 times, otherwise give up - const cart = await step.do( - "retrieve cart", - { - retries: { - limit: 10, - delay: 2000 * 60, - backoff: "constant", - }, - timeout: "30 seconds", - }, - async () => { - const { results } = await this.env.DB.prepare( - `SELECT * FROM cart WHERE id = ?`, - ) - .bind(event.payload.cartId) - .all(); - // should return { checkedOut: true, amount: 250 , account: { email: "celsomartinho@gmail.com" }}; - if(results[0].checkedOut === false) { - throw new Error("cart hasn't been checked out yet"); - } - return results[0]; - }, - ); - - // Proceed to payment, retry 10 times every minute or give up - const payment = await step.do( - "payment", - { - retries: { - limit: 10, - delay: 1000 * 60, - backoff: "constant", - }, - timeout: "30 seconds", - }, - async () => { - let resp = await fetch("https://payment-processor.example.com/", { - method: "POST", - headers: { - "Content-Type": "application/json; charset=utf-8", - }, - body: JSON.stringify({ amount: cart.amount }), - }); - - if (!resp.ok) { - throw new Error("payment has failed"); - } - - return { success: true, amount: cart.amount }; - }, - ); - - // Send invoice to the customer, retry 10 times every 5 minutes or give up + async run(event: WorkflowEvent, step: WorkflowStep) { + await step.sleep("sleep for a while", "10 seconds"); + + // Retrieve the cart from the D1 database + // if the cart hasn't been checked out yet retry every 2 minutes, 10 times, otherwise give up + const cart = await step.do( + "retrieve cart", + { + retries: { + limit: 10, + delay: 2000 * 60, + backoff: "constant", + }, + timeout: "30 seconds", + }, + async () => { + const { results } = await this.env.DB.prepare( + `SELECT * FROM cart WHERE id = ?`, + ) + .bind(event.payload.cartId) + .all(); + // should return { checkedOut: true, amount: 250 , account: { email: "celsomartinho@gmail.com" }}; + if (results[0].checkedOut === false) { + throw new Error("cart hasn't been checked out yet"); + } + return results[0]; + }, + ); + + // Proceed to payment, retry 10 times every minute or give up + const payment = await step.do( + "payment", + { + retries: { + limit: 10, + delay: 1000 * 60, + backoff: "constant", + }, + timeout: "30 seconds", + }, + async () => { + let resp = await fetch("https://payment-processor.example.com/", { + method: "POST", + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + body: JSON.stringify({ amount: cart.amount }), + }); + + if (!resp.ok) { + throw new Error("payment has failed"); + } + + return { success: true, amount: cart.amount }; + }, + ); + + // Send invoice to the customer, retry 10 times every 5 minutes or give up // Requires that cart.account.email has previously been validated in Email Routing, // See https://developers.cloudflare.com/email-routing/email-workers/ - await step.do( - "send invoice", - { - retries: { - limit: 10, - delay: 5000 * 60, - backoff: "constant", - }, - timeout: "30 seconds", - }, - async () => { - const message = genEmail(cart.account.email, payment.amount); - try { - await this.env.SEND_EMAIL.send(message); - } catch (e) { - throw new Error("failed to send invoice"); - } - }, - ); - - } + await step.do( + "send invoice", + { + retries: { + limit: 10, + delay: 5000 * 60, + backoff: "constant", + }, + timeout: "30 seconds", + }, + async () => { + const message = genEmail(cart.account.email, payment.amount); + try { + await this.env.SEND_EMAIL.send(message); + } catch (e) { + throw new Error("failed to send invoice"); + } + }, + ); + } } // Default page for admin // Remove in production export default { - async fetch(req: Request, env: Env): Promise { - let url = new URL(req.url); - - let id = new URL(req.url).searchParams.get("instanceId"); - - // Get the status of an existing instance, if provided - if (id) { - let instance = await env.CART_WORKFLOW.get(id); - return Response.json({ - status: await instance.status(), - }); - } - - if (url.pathname.startsWith("/new")) { - let instance = await env.CART_WORKFLOW.create({ - params: { - cartId: "123" - }, - }); - return Response.json({ - id: instance.id, - details: await instance.status(), - }); - } - - return new Response( - `
    new instance or add ?instanceId=...`, - { - headers: { - "content-type": "text/html;charset=UTF-8", - }, - }, - ); - }, + async fetch(req: Request, env: Env): Promise { + let url = new URL(req.url); + + let id = new URL(req.url).searchParams.get("instanceId"); + + // Get the status of an existing instance, if provided + if (id) { + let instance = await env.CART_WORKFLOW.get(id); + return Response.json({ + status: await instance.status(), + }); + } + + if (url.pathname.startsWith("/new")) { + let instance = await env.CART_WORKFLOW.create({ + params: { + cartId: "123", + }, + }); + return Response.json({ + id: instance.id, + details: await instance.status(), + }); + } + + return new Response( + `
    new instance or add ?instanceId=...`, + { + headers: { + "content-type": "text/html;charset=UTF-8", + }, + }, + ); + }, }; ``` @@ -191,13 +189,13 @@ Here's a minimal package.json: ```json { - "devDependencies": { - "@cloudflare/workers-types": "^4.20241022.0", - "wrangler": "^3.83.0" - }, - "dependencies": { - "mimetext": "^3.0.24" - } + "devDependencies": { + "@cloudflare/workers-types": "^4.20241022.0", + "wrangler": "^3.83.0" + }, + "dependencies": { + "mimetext": "^3.0.24" + } } ``` @@ -220,4 +218,4 @@ class_name = "cartInvoicesWorkflow" name = "SEND_EMAIL" ``` - \ No newline at end of file + diff --git a/src/content/docs/workflows/examples/twilio.mdx b/src/content/docs/workflows/examples/twilio.mdx index 00fe6cb3351108..f42e993bb15e57 100644 --- a/src/content/docs/workflows/examples/twilio.mdx +++ b/src/content/docs/workflows/examples/twilio.mdx @@ -1,22 +1,21 @@ --- type: example summary: Integrate Workflows with Twilio. Learn how to receive and send text messages and phone calls via APIs and Webhooks. -tags: - - Workflows +products: - Workers -pcx_content_type: configuration +pcx_content_type: example title: Integrate Workflows with Twilio sidebar: order: 4 description: Integrate Workflows with Twilio. Learn how to receive and send text messages and phone calls via APIs and Webhooks. --- -import { Stream } from "~/components" +import { Stream } from "~/components"; Using the following [repository](https://github.com/craigsdennis/twilio-cloudflare-workflow), learn how to integrate Cloudflare Workflows with Twilio, a popular cloud communications platform that enables developers to integrate messaging, voice, video, and authentication features into applications via APIs. By the end of the video tutorial, you will become familiarized with the process of setting up Cloudflare Workflows to seamlessly interact with Twilio's APIs, enabling you to build interesting communication features directly into your applications. - - - - - + diff --git a/src/content/docs/workflows/get-started/cli-quick-start.mdx b/src/content/docs/workflows/get-started/cli-quick-start.mdx index c70036a224680a..d8573317efc6e6 100644 --- a/src/content/docs/workflows/get-started/cli-quick-start.mdx +++ b/src/content/docs/workflows/get-started/cli-quick-start.mdx @@ -188,6 +188,7 @@ class_name = "MyWorkflow" You can then invoke the methods on this binding directly from your Worker script's `env` parameter. The `Workflow` type has methods for: * `create()` - creating (triggering) a new instance of the Workflow, returning the ID. +* `createBatch()` - creating (triggering) a batch of new instances of the Workflow, returning the IDs. * `get()`- retrieve a Workflow instance by its ID. * `status()` - get the current status of a unique Workflow instance. diff --git a/src/content/docs/workflows/index.mdx b/src/content/docs/workflows/index.mdx index bdc58fd2da459e..665c376a83c668 100644 --- a/src/content/docs/workflows/index.mdx +++ b/src/content/docs/workflows/index.mdx @@ -1,5 +1,5 @@ --- -title: Overview +title: Cloudflare Workflows order: 0 type: overview pcx_content_type: overview @@ -9,8 +9,7 @@ sidebar: text: Beta head: - tag: title - content: Cloudflare Workflows - + content: Overview --- import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" diff --git a/src/content/docs/workflows/reference/index.mdx b/src/content/docs/workflows/reference/index.mdx index 8516bf0f828bd9..4c8da5b1ca81a5 100644 --- a/src/content/docs/workflows/reference/index.mdx +++ b/src/content/docs/workflows/reference/index.mdx @@ -3,6 +3,8 @@ pcx_content_type: navigation title: Platform sidebar: order: 8 + group: + hideIndex: true --- diff --git a/src/content/docs/workflows/reference/limits.mdx b/src/content/docs/workflows/reference/limits.mdx index 747298f5b3692c..f92128d6bf6a28 100644 --- a/src/content/docs/workflows/reference/limits.mdx +++ b/src/content/docs/workflows/reference/limits.mdx @@ -25,7 +25,8 @@ Many limits are inherited from those applied to Workers scripts and as documente | Maximum `step.sleep` duration | 365 days (1 year) [^1] | 365 days (1 year) [^1] | | Maximum steps per Workflow [^5] | 1024 [^1] | 1024 [^1] | | Maximum Workflow executions | 100,000 per day [shared with Workers daily limit](/workers/platform/limits/#worker-limits) | Unlimited | -| Concurrent Workflow instances (executions) per account | 25 | 100 [^1] | +| Concurrent Workflow instances (executions) per account | 25 | 4500 [^1] | +| Maximum Workflow instance creation rate | 100 per 10 seconds [^1][^6] | 100 per 10 seconds [^1][^6] | | Maximum number of [queued instances](/workflows/observability/metrics-analytics/#event-types) | 10,000 [^1] | 100,000 [^1] | | Retention limit for completed Workflow state | 3 days | 30 days [^2] | | Maximum length of a Workflow ID [^4] | 64 characters | 64 characters | @@ -40,4 +41,6 @@ Many limits are inherited from those applied to Workers scripts and as documente [^5]: `step.sleep` do not count towards the max. steps limit +[^6]: Workflows will return a HTTP 429 rate limited error if you exceed the rate of new Workflow instance creation. + diff --git a/src/content/docs/workflows/reference/storage-options.mdx b/src/content/docs/workflows/reference/storage-options.mdx deleted file mode 100644 index 312ac6fdd1cbdd..00000000000000 --- a/src/content/docs/workflows/reference/storage-options.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -pcx_content_type: navigation -title: Choose a data or storage product -external_link: /workers/platform/storage-options/ -sidebar: - order: 90 - ---- diff --git a/src/content/docs/zaraz/consent-management/iab-tcf-compliance.mdx b/src/content/docs/zaraz/consent-management/iab-tcf-compliance.mdx index 0ed3752f665cfe..5b564fada12c14 100644 --- a/src/content/docs/zaraz/consent-management/iab-tcf-compliance.mdx +++ b/src/content/docs/zaraz/consent-management/iab-tcf-compliance.mdx @@ -11,7 +11,7 @@ head: The Zaraz Consent Management Platform is compliant with the IAB Transparency & Consent Framework. Enabling this feature [could be required](https://blog.google/products/adsense/new-consent-management-platform-requirements-for-serving-ads-in-the-eea-and-uk/) in order to serve Google Ads in the EEA and the UK. -The CMP ID of the approval is 433 and be can seen in the the [IAB Europe](https://iabeurope.eu/cmp-list/) website. +The CMP ID of the approval is 433 and be can seen in the [IAB Europe](https://iabeurope.eu/cmp-list/) website. Using the Zaraz Consent Management Platform in IAB TCF Compliance Mode is is opt-in. diff --git a/src/content/docs/zaraz/get-started.mdx b/src/content/docs/zaraz/get-started.mdx index cf67d947b8a704..98ec0e35f3ab35 100644 --- a/src/content/docs/zaraz/get-started.mdx +++ b/src/content/docs/zaraz/get-started.mdx @@ -11,13 +11,13 @@ Before being able to use Zaraz, it is recommended that you proxy your website th You can add new third-party tools and load them into your website through the Cloudflare dashboard. -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account and website. -2. Select **Zaraz** from the side menu. -3. If you have already added a tool before, select **Tools Configuration** > **Third-party tools** and click on **Add new tool**. +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. +2. Select **Tag Management**, then **Tag Setup** from the side menu and select your website. +3. If you have already added a tool before, select **Third-party tools** and click on **Add new tool**. 4. Choose a tool from the tools catalog. Select **Continue** to confirm your selection. 5. In **Set up**, configure the settings for your new tool. The information you need to enter will depend on the tool you choose. If you want to use any dynamic properties or variables, select the `+` sign in the drop-down menu next to the relevant field. 6. In **Actions** setup the actions for your new tool. You should be able to select Pageviews, Events or E-Commerce [^1]. -7. Select **Save**. +7. Select **Save**. [^1]: Some tools do not supported Automatic Actions, see the section about [Custom Actions](/zaraz/custom-actions) if the tool you are adding doesn't present Automatic Actions. diff --git a/src/content/docs/zaraz/index.mdx b/src/content/docs/zaraz/index.mdx index bd19d5e0e496a6..1ac0fc4e311c92 100644 --- a/src/content/docs/zaraz/index.mdx +++ b/src/content/docs/zaraz/index.mdx @@ -1,11 +1,11 @@ --- -title: Overview +title: Cloudflare Zaraz pcx_content_type: overview sidebar: order: 0 head: - tag: title - content: Cloudflare Zaraz + content: Overview --- import { diff --git a/src/content/docs/zaraz/reference/context.mdx b/src/content/docs/zaraz/reference/context.mdx index 91a629fa6457f5..d5c199781f19c0 100644 --- a/src/content/docs/zaraz/reference/context.mdx +++ b/src/content/docs/zaraz/reference/context.mdx @@ -31,7 +31,7 @@ System properties, which are automatically collected by Zaraz, provide insights | ---------------- | ------ | ------------------------------------------------ | | `system.cookies` | Object | Key-Value object containing all present cookies. | -The the keys inside the `system.cookies` are the cookies name. The property `system.cookies.foo` will return the value of the a cookie named `foo`. +The keys inside the `system.cookies` are the cookies name. The property `system.cookies.foo` will return the value of the a cookie named `foo`. ### Device information diff --git a/src/content/fields/index.yaml b/src/content/fields/index.yaml index fa229b41c9781f..793673d750c47f 100644 --- a/src/content/fields/index.yaml +++ b/src/content/fields/index.yaml @@ -420,7 +420,7 @@ entries: keywords: [request, uri, url, path, raw, client, visitor] summary: The raw URI path and query string of the request without any transformation. description: |- - This is the raw field version of the [`http.request.uri`](/ruleset-engine/rules-language/fields/reference/http.request.uri/) field. Raw fields, prefixed with `raw.`, preserve original request values for later evaluations. These fields are immutable during the entire request evaluation workflow, and they are not affected by the actions of previously matched rules. + This is the raw field version of the [`http.request.uri.path`](/ruleset-engine/rules-language/fields/reference/http.request.uri.path/) field. Raw fields, prefixed with `raw.`, preserve original request values for later evaluations. These fields are immutable during the entire request evaluation workflow, and they are not affected by the actions of previously matched rules. **Note**: This raw field may include some basic normalization done by Cloudflare's HTTP server. However, this can change in the future. @@ -602,9 +602,9 @@ entries: data_type: Number categories: [Request] keywords: [request, cloudflare, score, client, visitor] - summary: Represents a Cloudflare threat score from 0–100, where 0 indicates low risk. + summary: Represents a Cloudflare threat score. description: |- - Values above 10 may represent spammers or bots, and values above 40 identify bad actors on the Internet. It is rare to see values above 60. A common recommendation is to challenge requests with a score above 10 and to block those above 50. + Previously, a threat score represented a Cloudflare threat score from 0–100, where 0 indicated low risk. Now, the threat score is always `0` (zero). - name: cf.tls_cipher data_type: String @@ -1091,6 +1091,86 @@ entries: description: |- Requires a Cloudflare Enterprise plan. You must also enable [leaked credentials detection](/waf/detections/leaked-credentials/). + - name: cf.llm.prompt.detected + data_type: Boolean + categories: [Request] + keywords: [request, cloudflare, ai, client, visitor] + plan_info_label: Enterprise + summary: Indicates whether Cloudflare detected an LLM prompt in the incoming request. + description: |- + When a prompt is not present, the other LLM-related fields will have default values. + + Requires a Cloudflare Enterprise plan. You must also enable [Firewall for AI](/waf/detections/firewall-for-ai/). + + - name: cf.llm.prompt.pii_detected + data_type: Boolean + categories: [Request] + keywords: [request, cloudflare, ai, client, visitor] + plan_info_label: Enterprise + summary: Indicates whether any personally identifiable information (PII) has been detected in the LLM prompt included in the request. + description: |- + Equivalent to checking if the [`cf.llm.prompt.pii_categories`](/ruleset-engine/rules-language/fields/reference/cf.llm.prompt.pii_categories/) field is not empty. + + Requires a Cloudflare Enterprise plan. You must also enable [Firewall for AI](/waf/detections/firewall-for-ai/). + + - name: cf.llm.prompt.pii_categories + data_type: Array + categories: [Request] + keywords: [request, cloudflare, ai, client, visitor] + plan_info_label: Enterprise + summary: Array of string values with the personally identifiable information (PII) categories found in the LLM prompt included in the request. + description: |- + The possible values are the following: + + Category | Description + ----------------------------|----------------------------------------------------------------------------------------------------------------------------------------- + `CREDIT_CARD` | Credit card number + `CRYPTO` | Crypto wallet number (currently only Bitcoin address) + `DATE_TIME` | Absolute or relative dates or periods or times smaller than a day + `EMAIL_ADDRESS` | Email address + `IBAN_CODE` | International Bank Account Number (IBAN) + `IP_ADDRESS` | Internet Protocol (IP) address + `NRP` | A person's nationality, religious or political group + `LOCATION` | Name of politically or geographically defined location (cities, provinces, countries, international regions, bodies of water, mountains) + `PERSON` | Full person name + `PHONE_NUMBER` | Telephone number + `MEDICAL_LICENSE` | Common medical license numbers + `URL` | Uniform Resource Locator (URL), used to locate a resource on the Internet + `US_BANK_NUMBER` | US bank account number + `US_DRIVER_LICENSE` | US driver license + `US_ITIN` | US Individual Taxpayer Identification Number (ITIN) + `US_PASSPORT` | US passport number + `US_SSN` | US Social Security Number (SSN) + `UK_NHS` | UK NHS number + `UK_NINO` | UK National Insurance Number + `ES_NIF` | Spanish NIF number (personal tax ID) + `ES_NIE` | Spanish NIE number (foreigners ID card) + `IT_FISCAL_CODE` | Italian personal tax ID code + `IT_DRIVER_LICENSE` | Italian driver license number + `IT_VAT_CODE` | Italian VAT code number + `IT_PASSPORT` | Italian passport number + `IT_IDENTITY_CARD` | Italian identity card number + `PL_PESEL` | Polish PESEL number + `SG_NRIC_FIN` | National Registration Identification Card (Singapore) + `SG_UEN` | Unique Entity Number (for entities registered in Singapore) + `AU_ABN` | Australian Business Number (ABN) + `AU_ACN` | Australian Company Number (ACN) + `AU_TFN` | Australian tax file number (TFN) + `AU_MEDICARE` | Medicare number (issued by Australian government) + `IN_PAN` | Indian Permanent Account Number (PAN) + `IN_AADHAAR` | Individual identity number (issued by Indian government) + `IN_VEHICLE_REGISTRATION` | Vehicle registration number (issued by Indian government) + `IN_VOTER` | Numeric voter ID (issued by Indian Election Commission) + `IN_PASSPORT` | Indian Passport Number + `FI_PERSONAL_IDENTITY_CODE` | Finnish Personal Identity Code + + The categories list is based on the [list of PII entities supported by Presidio](https://microsoft.github.io/presidio/supported_entities/). Presidio is the data protection and de-identification SDK used in Firewall for AI. + + Requires a Cloudflare Enterprise plan. You must also enable [Firewall for AI](/waf/detections/firewall-for-ai/). + example_block: |- + # Matches requests where PII categorized as "EMAIL_ADDRESS" or "IBAN_CODE" was detected: + (cf.llm.prompt.pii_detected and any(cf.llm.prompt.pii_categories[*] in {"EMAIL_ADDRESS" "IBAN_CODE"})) + - name: cf.worker.upstream_zone data_type: String categories: [Request] diff --git a/src/content/glossary/cloudflare-one.yaml b/src/content/glossary/cloudflare-one.yaml index cbb21f800d495c..b3f0fe391bff06 100644 --- a/src/content/glossary/cloudflare-one.yaml +++ b/src/content/glossary/cloudflare-one.yaml @@ -43,7 +43,7 @@ entries: - term: Cloudflare Data Loss Prevention (DLP) general_definition: |- - Cloudflare Data Loss Prevention (DLP) allows you to scan your web traffic and SaaS applications for the presence of sensitive data such as social security numbers, financial information, secret keys, and source code. + Cloudflare [Data Loss Prevention](https://www.cloudflare.com/learning/access-management/what-is-dlp/) (DLP) allows you to scan your web traffic and SaaS applications for the presence of sensitive data such as social security numbers, financial information, secret keys, and source code. - term: Cloudflare DEX general_definition: |- diff --git a/src/content/glossary/dns.yaml b/src/content/glossary/dns.yaml index c1e134dc8ffb4d..593179167b174d 100644 --- a/src/content/glossary/dns.yaml +++ b/src/content/glossary/dns.yaml @@ -27,7 +27,7 @@ entries: - term: DNS record general_definition: |- - DNS records are instructions that live in authoritative DNS servers and provide information about a domain including what IP address is associated with that domain and how to handle requests for that domain. + DNS records are instructions that live in authoritative DNS servers and provide information about a domain, including what IP address is associated with that domain and how to handle requests for that domain. - term: DNS server general_definition: |- @@ -79,3 +79,7 @@ entries: When a [DNS record is proxied](/dns/proxy-status/), requests are processed according to your configurations, and Cloudflare can optimize, cache, and protect your domain. Refer to [How Cloudflare works](/fundamentals/concepts/how-cloudflare-works/) for details. associated_products: - Fundamentals + + - term: zone apex + general_definition: |- + zone apex refers to the domain or subdomain on which the control of DNS records starts. diff --git a/src/content/learning-paths/china-network-overview.json b/src/content/learning-paths/china-network-overview.json new file mode 100644 index 00000000000000..1f9c0b0b4d9338 --- /dev/null +++ b/src/content/learning-paths/china-network-overview.json @@ -0,0 +1,10 @@ +{ + "title": "Introduction to the China Network", + "path": "/learning-paths/china-network-overview/series/china-network-main-features-1/", + "priority": 1, + "description":"Watch to learn how Cloudflare's China Network can help you improve performance, compliance, and connectivity for your users in mainland China.", + "products": ["China Network"], + "product_group": "Application performance", + "additional_groups": ["Application security"], + "video": true +} diff --git a/src/content/learning-paths/durable-objects-course.json b/src/content/learning-paths/durable-objects-course.json new file mode 100644 index 00000000000000..9401c708f745ac --- /dev/null +++ b/src/content/learning-paths/durable-objects-course.json @@ -0,0 +1,9 @@ +{ + "title": "Introduction to Durable Objects", + "path": "/learning-paths/durable-objects-course/series/introduction-to-series-1/", + "priority": 2, + "description":"Dive into a hands-on Durable Objects project and learn how to build stateful apps using serverless architecture", + "products": ["Durable Objects", "Workers"], + "product_group": "Developer platform", + "video": true +} diff --git a/src/content/learning-paths/sase-overview-course.json b/src/content/learning-paths/sase-overview-course.json new file mode 100644 index 00000000000000..0207793eb3a28f --- /dev/null +++ b/src/content/learning-paths/sase-overview-course.json @@ -0,0 +1,10 @@ +{ + "title": "Build and secure your SASE corporate network", + "path": "/learning-paths/sase-overview-course/series/evolution-corporate-networks-1/", + "priority": 1, + "description": "Watch this series and learn all about Cloudflare's Secure Access Service Edge (SASE) platform to learn how it can revolutionize your corporate network.", + "products": ["Cloudflare One"], + "product_group": "Cloudflare One", + "additional_groups": ["Cloudflare One", "Cloudflare essentials"], + "video": true +} diff --git a/src/content/notifications/index.yaml b/src/content/notifications/index.yaml index 005b86b1bad23a..6186d76c83e2a2 100644 --- a/src/content/notifications/index.yaml +++ b/src/content/notifications/index.yaml @@ -495,13 +495,13 @@ entries: audience: Customers who want to be warned about changes in health status for their Cloudflare Tunnels. availability: All Cloudflare Zero Trust plans. associatedProducts: Tunnel - nextSteps: Monitor tunnel health over time and consider deploying [`cloudflared` replicas or load balancers](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/). + nextSteps: Monitor tunnel health over time and consider deploying [`cloudflared` replicas or load balancers](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/). otherFilters: None. additional_information: |- |
    Health status
    | Description | | ------------- | ------------ | | Healthy | The tunnel is active and serving traffic through four connections to the Cloudflare global network. | - | Degraded | The tunnel is active and serving traffic, but at least one individual connection has failed. Further degradation in [tunnel availability](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/) could risk the tunnel going down and failing to serve traffic.| + | Degraded | The tunnel is active and serving traffic, but at least one individual connection has failed. Further degradation in [tunnel availability](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/) could risk the tunnel going down and failing to serve traffic.| | Down | The tunnel cannot serve traffic as it has no connections to the Cloudflare global network.| | Inactive | This value is reserved for tunnels which have been created, but have never been run.| diff --git a/src/content/partials/agents/unique-agents.mdx b/src/content/partials/agents/unique-agents.mdx new file mode 100644 index 00000000000000..06526e2952ae92 --- /dev/null +++ b/src/content/partials/agents/unique-agents.mdx @@ -0,0 +1,14 @@ +--- +{} + +--- + +:::note + +An instance of an Agent is globally unique: given the same name (or ID), you will always get the same instance of an agent. + +This allows you to avoid synchronizing state across requests: if an Agent instance represents a specific user, team, channel or other entity, you can use the Agent instance to store state for that entity. No need to set up a centralized session store. + +If the client disconnects, you can always route the client back to the exact same Agent and pick up where they left off. + +::: \ No newline at end of file diff --git a/src/content/partials/api-shield/set-up-session-identifiers.mdx b/src/content/partials/api-shield/set-up-session-identifiers.mdx index 05484de121ff96..c9e861f3346d52 100644 --- a/src/content/partials/api-shield/set-up-session-identifiers.mdx +++ b/src/content/partials/api-shield/set-up-session-identifiers.mdx @@ -7,7 +7,8 @@ 2. Go to **Security** > **API Shield**. 3. Select **Settings**. 4. On **Endpoint settings**, select **Manage identifiers**. -5. Choose the type of session identifier (cookie, HTTP header, or JWT claim). +5. + Choose the type of session identifier (cookie, HTTP header, or JWT claim). :::note The session identifier cookie must comply with RFC 6265. Otherwise, it will be rejected. diff --git a/src/content/partials/bots/ai-labyrinth-enable.mdx b/src/content/partials/bots/ai-labyrinth-enable.mdx new file mode 100644 index 00000000000000..2659c734ed82aa --- /dev/null +++ b/src/content/partials/bots/ai-labyrinth-enable.mdx @@ -0,0 +1,17 @@ +--- +inputParameters: param1 + +--- + +import { Markdown } from "~/components" + +The AI Labyrinth adds invisible links on your webpage with specific `Nofollow` tags to block AI crawlers that do not adhere to the recommended guidelines and crawl without permission. AI crawlers that scrape your website content without permission will be stuck in a maze of never-ending links, and their details are recorded and used by all Cloudflare customers who choose to block [AI bots](/bots/concepts/bot/#ai-bots). + +These links do not impact your search engine optimization (SEO) or your website's appearance, and are only seen by bots. AI bots that respect no-crawl instructions will safely ignore this honeypot. + +To enable AI Labyrinth: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account and domain. +2. Go to **Security** > **Bots**. +3. Select **Configure {props.one}**. +4. Enable **AI Labyrinth**. \ No newline at end of file diff --git a/src/content/partials/bots/get-started-pro-biz-steps.mdx b/src/content/partials/bots/get-started-pro-biz-steps.mdx index 93627eb769bf5b..43d2fdfb687a41 100644 --- a/src/content/partials/bots/get-started-pro-biz-steps.mdx +++ b/src/content/partials/bots/get-started-pro-biz-steps.mdx @@ -1,6 +1,5 @@ --- {} - --- To start using Super Bot Fight Mode: @@ -8,10 +7,12 @@ To start using Super Bot Fight Mode: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login) and select your account and domain. 2. Go to **Security** > **Bots**. 3. Select **Configure Super Bot Fight Mode**. -4. Choose how your domain should respond to various types of traffic: - * For more details on verified bots, refer to [Verified Bots](/bots/concepts/bot/#verified-bots). - * For more details on supported file types, refer to [Static resource protection](/bots/reference/static-resources/) - * For more details on invisible code injection, refer to [JavaScript detections](/bots/reference/javascript-detections/). +4. + Choose how your domain should respond to various types of traffic: + + - For more details on verified bots, refer to [Verified Bots](/bots/concepts/bot/#verified-bots). + - For more details on supported file types, refer to [Static resource protection](/bots/reference/static-resources/). + - For more details on invisible code injection, refer to [JavaScript detections](/bots/reference/javascript-detections/). :::caution[Warning] diff --git a/src/content/partials/bots/ja3-fingerprint.mdx b/src/content/partials/bots/ja3-fingerprint.mdx index a8fe96c8eadd1c..66c7dd27fcce57 100644 --- a/src/content/partials/bots/ja3-fingerprint.mdx +++ b/src/content/partials/bots/ja3-fingerprint.mdx @@ -3,4 +3,4 @@ --- -[**JA3**](https://github.com/salesforce/ja3) and [**JA4**](https://github.com/FoxIO-LLC/ja4) **Fingerprints** help you profile specific SSL/TLS clients across different destination IPs, Ports, and X509 certificates. +[**JA3**](https://github.com/salesforce/ja3) and [**JA4**](https://github.com/FoxIO-LLC/ja4) **fingerprints** help you profile specific SSL/TLS clients across different destination IPs, Ports, and X509 certificates. diff --git a/src/content/partials/bots/ja3-ja4-null.mdx b/src/content/partials/bots/ja3-ja4-null.mdx new file mode 100644 index 00000000000000..2add7303524256 --- /dev/null +++ b/src/content/partials/bots/ja3-ja4-null.mdx @@ -0,0 +1,8 @@ +--- +{} + +--- + +The [JA3/JA4 fingerprint](/bots/concepts/ja3-ja4-fingerprint/) can be null or empty in some cases. The most common case is for HTTP requests because JA3 and JA4 are calculated in TLS. It can also be empty due to the Worker sending requests within the same zone or to a zone that is not proxied (or a third party). + +[Orange to Orange (O2O)](/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/) should not cause null or empty JA3 or JA4 fingerprints, unless the eyeball zone is routing traffic to the target zone using a Worker. \ No newline at end of file diff --git a/src/content/partials/bots/javascript-detections-definition.mdx b/src/content/partials/bots/javascript-detections-definition.mdx index f3df350b3d4689..cdd8ca9a6b1e68 100644 --- a/src/content/partials/bots/javascript-detections-definition.mdx +++ b/src/content/partials/bots/javascript-detections-definition.mdx @@ -11,6 +11,10 @@ JavaScript detections are another method that help Cloudflare identify bot reque ## What are JavaScript detections? -These detections are implemented via a lightweight, invisible JavaScript code snippet that follows Cloudflare’s [privacy standards](https://www.cloudflare.com/privacypolicy/). JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile app traffic is unaffected. Additionally, code is not injected again until the current session expires. After page load, the script is deferred and utilizes a separate thread (where available) to ensure that performance impact is minimal. +These detections are implemented via a lightweight, invisible JavaScript code snippet that follows Cloudflare’s [privacy standards](https://www.cloudflare.com/privacypolicy/). JavaScript is injected only in response to requests for HTML pages or page views, excluding AJAX calls. API and mobile app traffic is unaffected. JavaScript detections have a lifespan of 15 minutes. However, the code is injected again before the session expires. After page load, the script is deferred and utilizes a separate thread (where available) to ensure that performance impact is minimal. The snippets of JavaScript will contain a source pointing to the challenge platform, with paths that start with `/cdn-cgi/challenge-platform/...` + +:::note +The information in JavaScript detections which populates `js_detection.passed` is stored in the `cf_clearance` cookie. +::: \ No newline at end of file diff --git a/src/content/partials/browser-rendering/limits-increase.mdx b/src/content/partials/browser-rendering/limits-increase.mdx new file mode 100644 index 00000000000000..86f3d400ee3278 --- /dev/null +++ b/src/content/partials/browser-rendering/limits-increase.mdx @@ -0,0 +1,9 @@ +--- +{} +--- + +:::note[Need a higher limit?] + +To request an increase to a limit, complete the [Limit Increase Request Form](https://forms.gle/CdueDKvb26mTaepa9). If the limit can be increased, Cloudflare will contact you with next steps. + +::: diff --git a/src/content/partials/cloudflare-one/access/add-access-policies.mdx b/src/content/partials/cloudflare-one/access/add-access-policies.mdx new file mode 100644 index 00000000000000..d497342ed365f0 --- /dev/null +++ b/src/content/partials/cloudflare-one/access/add-access-policies.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +Add [Access policies](/cloudflare-one/policies/access/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/access/add-infrastructure-app.mdx b/src/content/partials/cloudflare-one/access/add-infrastructure-app.mdx index 83b1d869e4a587..8281dece8096e0 100644 --- a/src/content/partials/cloudflare-one/access/add-infrastructure-app.mdx +++ b/src/content/partials/cloudflare-one/access/add-infrastructure-app.mdx @@ -1,10 +1,8 @@ --- {} - --- -import { Tabs, TabItem, Render } from "~/components" - +import { Tabs, TabItem, Render } from "~/components"; @@ -34,15 +32,16 @@ import { Tabs, TabItem, Render } from "~/components" 1. [Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: - | Type | Item | Permission | - | ------- | ---------------- | ---------- | - | Account | Access: Apps & Policies | Edit | + + | Type | Item | Permission | + | ------- | ----------------------- | ---------- | + | Account | Access: Apps & Policies | Edit | 2. Make a `POST` request to the [Access applications](/api/resources/zero_trust/subresources/access/subresources/applications/methods/create/) endpoint: ```sh - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps \ - --header "Authorization: Bearer " \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Example infrastructure app", diff --git a/src/content/partials/cloudflare-one/access/add-target.mdx b/src/content/partials/cloudflare-one/access/add-target.mdx index ef396379b2476d..b4746a37622d08 100644 --- a/src/content/partials/cloudflare-one/access/add-target.mdx +++ b/src/content/partials/cloudflare-one/access/add-target.mdx @@ -1,13 +1,18 @@ --- -{} - +params: + - protocol --- -import { Tabs, TabItem, Render, Details } from "~/components" +import { Tabs, TabItem, Render, Details } from "~/components"; -A target represents a single resource in your infrastructure (such as a server, Kubernetes cluster, database, or container) that users will connect to through Cloudflare. Targets are protocol-agnostic, meaning that you do not need to define a new target for each protocol that runs on the server. +A target represents a single resource in your infrastructure (such as a server, Kubernetes cluster, database, or container) that users will connect to through Cloudflare. -To create a new target: +{ + props.protocol === "rdp" ? ( +

    Create a target for each Windows machine that requires RDP access. +To create a new target:

    ) : + (

    Targets are protocol-agnostic, meaning that you do not need to define a new target for each protocol that runs on the server. To create a new target:

    ) +} @@ -30,6 +35,7 @@ If the target IP does not appear in the dropdown, go to **Networks** > **Routes* 1. [Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: + | Type | Item | Permission | | ------- | ---------------- | ---------- | | Account | Zero Trust | Edit | @@ -37,8 +43,8 @@ If the target IP does not appear in the dropdown, go to **Networks** > **Routes* 2. Make a `POST` request to the [Infrastructure Access Targets](/api/resources/zero_trust/subresources/access/subresources/infrastructure/subresources/targets/methods/create/) endpoint: ```sh - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/infrastructure/targets \ - --header "Authorization: Bearer " \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/infrastructure/targets \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "hostname": "infra-access-target", "ip": { @@ -55,14 +61,14 @@ If the target IP does not appear in the dropdown, go to **Networks** > **Routes* ``` - + :::note[Provider versions] The following example requires Cloudflare provider version `>=4.45.0`. ::: 1. Add the following permission to your [`cloudflare_api_token`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/api_token): - - `Teams Write` + - `Zero Trust Write` 2. Configure the [`cloudflare_zero_trust_infrastructure_access_target`](https://registry.terraform.io/providers/cloudflare/cloudflare/4.45.0/docs/resources/zero_trust_infrastructure_access_target) resource: @@ -86,4 +92,4 @@ The following example requires Cloudflare provider version `>=4.45.0`. -Next, create an infrastructure application to secure the target. \ No newline at end of file +Next, create an Access application to secure the target. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/access/enable-scim-on-dashboard.mdx b/src/content/partials/cloudflare-one/access/enable-scim-on-dashboard.mdx index ccd70df213801f..7f3b39f7617294 100644 --- a/src/content/partials/cloudflare-one/access/enable-scim-on-dashboard.mdx +++ b/src/content/partials/cloudflare-one/access/enable-scim-on-dashboard.mdx @@ -10,7 +10,7 @@ import { Markdown } from "~/components" 2. Find the {props.idp} integration and select **Edit**. -3. Turn on **Enable SCIM** {props.supportgroups && and props.supportgroups.} +3. Turn on **Enable SCIM** {props.supportgroups && and {props.supportgroups}.} 4. (Optional) Configure the following settings: diff --git a/src/content/partials/cloudflare-one/access/rule-group.mdx b/src/content/partials/cloudflare-one/access/rule-group.mdx index 1224a4eb3def3d..d13eef831ccb94 100644 --- a/src/content/partials/cloudflare-one/access/rule-group.mdx +++ b/src/content/partials/cloudflare-one/access/rule-group.mdx @@ -27,9 +27,8 @@ To create an Access rule group: Send a `POST` request to the [`/access/groups`](/api/resources/zero_trust/subresources/access/subresources/groups/methods/create/) endpoint: ```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/access/groups \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/groups \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "name": "Lisbon-team", diff --git a/src/content/partials/cloudflare-one/access/saas-apps/saas-sessions.mdx b/src/content/partials/cloudflare-one/access/saas-apps/saas-sessions.mdx new file mode 100644 index 00000000000000..ae78bb666c48d5 --- /dev/null +++ b/src/content/partials/cloudflare-one/access/saas-apps/saas-sessions.mdx @@ -0,0 +1,7 @@ +--- +params: + - session + - token +--- + +{props.session} only control the front door to a SaaS app; Access does not control how long the user can stay in the SaaS app itself. For example, if the user logs out of the SaaS app and then comes back to it, a valid {props.token} allows them to re-authenticate without another login. The SaaS app issues its own authorization cookie that manages the user's session within the app. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/access/secure-tunnel-with-access.mdx b/src/content/partials/cloudflare-one/access/secure-tunnel-with-access.mdx index fb328dc1478bb1..cdc43ce176fe0f 100644 --- a/src/content/partials/cloudflare-one/access/secure-tunnel-with-access.mdx +++ b/src/content/partials/cloudflare-one/access/secure-tunnel-with-access.mdx @@ -5,4 +5,4 @@ To secure your origin, you must validate the [application token](/cloudflare-one/identity/authorization-cookie/) issued by Cloudflare Access. Token validation ensures that any requests which bypass Cloudflare Access (for example, due to a network misconfiguration) are rejected. -One option is to configure the Cloudflare Tunnel daemon, `cloudflared`, to validate the token on your behalf. This is done by enabling [**Protect with Access**](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#access) in your Cloudflare Tunnel settings. Alternatively, if you do not wish to perform automatic validation with Cloudflare Tunnel, you can instead [manually configure your origin](/cloudflare-one/identity/authorization-cookie/validating-json/) to check all requests for a valid token. +One option is to configure the Cloudflare Tunnel daemon, `cloudflared`, to validate the token on your behalf. This is done by enabling [**Protect with Access**](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#access) in your Cloudflare Tunnel settings. Alternatively, if you do not wish to perform automatic validation with Cloudflare Tunnel, you can instead [manually configure your origin](/cloudflare-one/identity/authorization-cookie/validating-json/) to check all requests for a valid token. diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app.mdx deleted file mode 100644 index 7d11ef74287cf8..00000000000000 --- a/src/content/partials/cloudflare-one/access/self-hosted-app.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -{} - ---- - -import { Render } from "~/components" - -1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**. - -2. Select **Add an application**. - -3. Select **Self-hosted**. - -4. Enter any name for the application. - -5. In **Session Duration**, choose how often the user's [application token](/cloudflare-one/identity/authorization-cookie/application-token/) should expire. - - Cloudflare checks every HTTP request to your application for a valid application token. If the user's application token (and global token) has expired, they will be prompted to reauthenticate with the IdP. For more information, refer to [Session management](/cloudflare-one/identity/users/session-management/). - -6. Select **Add public hostname**. - -7. In the **Domain** dropdown, select the domain that will represent the application. Domains must belong to an active zone in your Cloudflare account. You can use [wildcards](/cloudflare-one/policies/access/app-paths/) to protect multiple parts of an application that share a root path. - - Alternatively, to use a [Cloudflare for SaaS custom hostname](/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/), set **Input method** to _Custom_ and enter your custom hostname. - -8. Add [Access policies](/cloudflare-one/policies/access/) to control who can connect to your application. All Access applications are deny by default -- a user must match an Allow policy before they are granted access. - -9. - -10. Select **Next**. - -11. (Optional) Configure [App Launcher settings](/cloudflare-one/applications/app-launcher/) for the application. - -12. - -13. Select **Next**. - -14. (Optional) Configure advanced settings for your application: - - - [**Cross-Origin Resource Sharing (CORS) settings**](/cloudflare-one/identity/authorization-cookie/cors/) - - [**Cookie settings**](/cloudflare-one/identity/authorization-cookie/#cookie-settings) - - **Browser rendering settings**: - - [Automatic `cloudflared` authentication](/cloudflare-one/applications/non-http/cloudflared-authentication/automatic-cloudflared-authentication/) - - [Browser rendering for SSH and VNC](/cloudflare-one/applications/non-http/browser-rendering/) - - **401 Response for Service Auth policies**: Return a `401` response code when a user (or machine) makes a request to the application without the correct [service token](/cloudflare-one/identity/service-tokens/). - -15. Select **Save**. - diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/advanced-settings.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/advanced-settings.mdx new file mode 100644 index 00000000000000..d526a33967505c --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/advanced-settings.mdx @@ -0,0 +1,10 @@ +--- +{} + +--- + +(Optional) Configure advanced settings: + + - [**Cross-Origin Resource Sharing (CORS) settings**](/cloudflare-one/identity/authorization-cookie/cors/) + - [**Cookie settings**](/cloudflare-one/identity/authorization-cookie/#cookie-settings) + - **401 Response for Service Auth policies**: Return a `401` response code when a user (or machine) makes a request to the application without the correct [service token](/cloudflare-one/identity/service-tokens/). diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/choose-domain.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/choose-domain.mdx new file mode 100644 index 00000000000000..bf5c7dae842e9f --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/choose-domain.mdx @@ -0,0 +1,10 @@ +--- +{} + +--- + +import { Render } from "~/components" + +In the **Domain** dropdown, select the domain that will represent the application. Domains must belong to an active zone in your Cloudflare account. You can use [wildcards](/cloudflare-one/policies/access/app-paths/) to protect multiple parts of an application that share a root path. + + Alternatively, to use a [Cloudflare for SaaS custom hostname](/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/), set **Input method** to _Custom_ and enter your custom hostname. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/create-app.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/create-app.mdx new file mode 100644 index 00000000000000..5c57c4fb2c84f0 --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/create-app.mdx @@ -0,0 +1,24 @@ +--- +params: + - private? + +--- + +import { Render } from "~/components" + +1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Access** > **Applications**. + +2. Select **Add an application**. + +3. Select **Self-hosted**. + +4. Enter any name for the application. + +5. In **Session Duration**, choose how often the user's [application token](/cloudflare-one/identity/authorization-cookie/application-token/) should expire. + + Cloudflare checks every HTTP request to your application for a valid application token. If the user's application token (and global token) has expired, they will be prompted to reauthenticate with the IdP. For more information, refer to [Session management](/cloudflare-one/identity/users/session-management/). + + { + props.private && ( +

    If the application is non-HTTPS or you do not have TLS decryption turned on, the session is tracked by the WARP client per application.

    ) + } \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/generic-public-app.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/generic-public-app.mdx new file mode 100644 index 00000000000000..1e0eb4a75d0904 --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/generic-public-app.mdx @@ -0,0 +1,33 @@ +--- +{} + +--- + +import { Render } from "~/components" + + + +6. Select **Add public hostname**. + +7. + +8. (Optional) Configure **Browser rendering settings**: + - [Automatic `cloudflared` authentication](/cloudflare-one/applications/non-http/cloudflared-authentication/automatic-cloudflared-authentication/) + - [Browser rendering for SSH, VNC, or RDP](/cloudflare-one/applications/non-http/browser-rendering/) + +9. + +10. + +11. Select **Next**. + +12. (Optional) Configure [App Launcher settings](/cloudflare-one/applications/app-launcher/) for the application. + +13. + +14. Select **Next**. + +15. + +16. Select **Save**. + diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/product-compatibility.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/product-compatibility.mdx new file mode 100644 index 00000000000000..9e400c75a7667f --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/product-compatibility.mdx @@ -0,0 +1,13 @@ +--- +{} + +--- +When using Access self-hosted applications, the majority of Cloudflare products will be compatible with your application. + +However, the following products are not supported: + +* [Automatic Signed Exchanges](/speed/optimization/other/signed-exchanges/) +* [Automatic Platform Optimization](/automatic-platform-optimization) +* [Zaraz](/zaraz) + +You can disable Automatic Signed Exchanges and Zaraz for a specific application - instead of across your entire zone - using a [Configuration Rule](/rules/configuration-rules/) scoped to the application domain. diff --git a/src/content/partials/cloudflare-one/access/self-hosted-app/ssh-sessions.mdx b/src/content/partials/cloudflare-one/access/self-hosted-app/ssh-sessions.mdx new file mode 100644 index 00000000000000..ca8503c7fd8981 --- /dev/null +++ b/src/content/partials/cloudflare-one/access/self-hosted-app/ssh-sessions.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +Cloudflare does not control the length of an active SSH, VNC, or RDP session. [Application session durations](/cloudflare-one/identity/users/session-management/) determine the window in which a user can initiate a new connection or refresh an existing one. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/casb/casb-dlp-integrations.mdx b/src/content/partials/cloudflare-one/casb/casb-dlp-integrations.mdx index e89bc43d215f65..0b1e47d12dacfe 100644 --- a/src/content/partials/cloudflare-one/casb/casb-dlp-integrations.mdx +++ b/src/content/partials/cloudflare-one/casb/casb-dlp-integrations.mdx @@ -2,6 +2,10 @@ {} --- +- [Amazon Web Services (AWS) S3](/cloudflare-one/applications/casb/casb-integrations/aws-s3/) +- [Box](/cloudflare-one/applications/casb/casb-integrations/box/) +- [Dropbox](/cloudflare-one/applications/casb/casb-integrations/dropbox/) +- [Google Cloud Platform (GCP) Cloud Storage](/cloudflare-one/applications/casb/casb-integrations/gcp-cloud-storage) - [Google Drive](/cloudflare-one/applications/casb/casb-integrations/google-workspace/google-drive/) - [Microsoft OneDrive](/cloudflare-one/applications/casb/casb-integrations/microsoft-365/onedrive/) - [Microsoft SharePoint](/cloudflare-one/applications/casb/casb-integrations/microsoft-365/sharepoint/) diff --git a/src/content/partials/cloudflare-one/email-security/enable-logs.mdx b/src/content/partials/cloudflare-one/email-security/enable-logs.mdx new file mode 100644 index 00000000000000..a24467b661b399 --- /dev/null +++ b/src/content/partials/cloudflare-one/email-security/enable-logs.mdx @@ -0,0 +1,6 @@ +--- +{} + +--- + +[Enable logs](/cloudflare-one/insights/logs/enable-logs/) to send detection data to an endpoint of your choice. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/gateway/add-locations.mdx b/src/content/partials/cloudflare-one/gateway/add-locations.mdx index 6f0f8fbe2f1078..1873337946b8f2 100644 --- a/src/content/partials/cloudflare-one/gateway/add-locations.mdx +++ b/src/content/partials/cloudflare-one/gateway/add-locations.mdx @@ -8,6 +8,8 @@ import { GlossaryDefinition, GlossaryTooltip } from "~/components"; The fastest way to start filtering DNS queries from a location is by changing the DNS resolvers at the router. +## Add a DNS location + To add a DNS location to Gateway: 1. In [Zero Trust](https://one.dash.cloudflare.com), go to **Gateway** > **DNS Locations**. diff --git a/src/content/partials/cloudflare-one/gateway/client-notifications-OS.mdx b/src/content/partials/cloudflare-one/gateway/client-notifications-OS.mdx new file mode 100644 index 00000000000000..0e13488eb10707 --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/client-notifications-OS.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +Ensure that your operating system allows notifications for WARP. Your device may not display notifications if focus, do not disturb, or screen sharing settings are turned on. To turn on client notifications on macOS devices running DisplayLink software, you may have to allow system notifications when mirroring your display. For more information, refer to the [macOS documentation](https://support.apple.com/guide/mac-help/change-notifications-settings-mh40583/mac). diff --git a/src/content/partials/cloudflare-one/gateway/client-notifications.mdx b/src/content/partials/cloudflare-one/gateway/client-notifications.mdx index 0a8c531d34d943..045fa2dcf19058 100644 --- a/src/content/partials/cloudflare-one/gateway/client-notifications.mdx +++ b/src/content/partials/cloudflare-one/gateway/client-notifications.mdx @@ -2,7 +2,7 @@ {} --- -import { Details } from "~/components"; +import { Details, Render } from "~/components";
    @@ -25,4 +25,4 @@ Turn on **Display block notification for WARP client** to display notifications Upon selecting the notification, WARP will direct your users to a block page. Optionally, you can direct users to a custom URL, such as an internal support form. -Your device may not display block notifications if focus, do not disturb, or screen sharing settings are turned on. To turn on client notifications on macOS devices running DisplayLink software, you may have to allow system notifications when mirroring your display. For more information, refer to the [macOS documentation](https://support.apple.com/guide/mac-help/change-notifications-settings-mh40583/mac). + diff --git a/src/content/partials/cloudflare-one/gateway/create-resolver-policy.mdx b/src/content/partials/cloudflare-one/gateway/create-resolver-policy.mdx index 7bc04654694b0e..1fa4c8d11ada94 100644 --- a/src/content/partials/cloudflare-one/gateway/create-resolver-policy.mdx +++ b/src/content/partials/cloudflare-one/gateway/create-resolver-policy.mdx @@ -14,7 +14,7 @@ 4. In **Select DNS resolver**, choose _Configure custom DNS resolvers_. 5. Enter the IP addresses of your custom DNS resolver. - :::tip[Search virtual networks] + :::note[Search virtual networks] As you enter an IP address, Gateway will search through your [virtual networks](/cloudflare-one/connections/connect-networks/private-net/cloudflared/tunnel-virtual-networks/) configured in Zero Trust. ::: 6. In **Network**, choose whether to route queries publicly (to the Internet) or privately (to a private network service). diff --git a/src/content/partials/cloudflare-one/gateway/get-started/create-dns-policy.mdx b/src/content/partials/cloudflare-one/gateway/get-started/create-dns-policy.mdx index cf7179697a966b..990f64dd3d6b6a 100644 --- a/src/content/partials/cloudflare-one/gateway/get-started/create-dns-policy.mdx +++ b/src/content/partials/cloudflare-one/gateway/get-started/create-dns-policy.mdx @@ -33,9 +33,9 @@ To create a new DNS policy: 3. Send a `POST` request to the [Create a Zero Trust Gateway rule](/api/resources/zero_trust/subresources/gateway/subresources/rules/methods/create/) endpoint. For example, we recommend adding a policy to block all [security categories](/cloudflare-one/policies/gateway/domain-categories/#security-categories): ```sh title="curl API DNS policy example" - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Content-Type: application/json" \ - --header "Authorization: Bearer " \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block security threats", "description": "Block all default Cloudflare DNS security categories", diff --git a/src/content/partials/cloudflare-one/gateway/get-started/create-http-policy.mdx b/src/content/partials/cloudflare-one/gateway/get-started/create-http-policy.mdx index a4dbb08eccca75..acb2285fb84f1d 100644 --- a/src/content/partials/cloudflare-one/gateway/get-started/create-http-policy.mdx +++ b/src/content/partials/cloudflare-one/gateway/get-started/create-http-policy.mdx @@ -42,9 +42,9 @@ To create a new HTTP policy: 3. Send a `POST` request to the [Create a Zero Trust Gateway rule](/api/resources/zero_trust/subresources/gateway/subresources/rules/methods/create/) endpoint. For example, if you have configured TLS decryption, some applications that use [embedded certificates](/cloudflare-one/policies/gateway/http-policies/tls-decryption/#inspection-limitations) may not support HTTP inspection, such as some Google products. You can create a policy to bypass inspection for these applications: ```sh title="curl API HTTP policy example" - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Content-Type: application/json" \ - --header "Authorization: Bearer " \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Do not inspect applications", "description": "Bypass TLS decryption for unsupported applications", @@ -73,9 +73,9 @@ To create a new HTTP policy: Cloudflare also recommends adding a policy to block [known threats](/cloudflare-one/policies/gateway/domain-categories/#security-categories) such as Command & Control, Botnet and Malware based on Cloudflare's threat intelligence: ```bash title="Block known risks HTTP policy" - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Content-Type: application/json" \ - --header "Authorization: Bearer " \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Block known risks", "description": "Block all default Cloudflare HTTP security categories", diff --git a/src/content/partials/cloudflare-one/gateway/get-started/create-network-policy.mdx b/src/content/partials/cloudflare-one/gateway/get-started/create-network-policy.mdx index 7e318cbaadc4e8..0668e3756fb84b 100644 --- a/src/content/partials/cloudflare-one/gateway/get-started/create-network-policy.mdx +++ b/src/content/partials/cloudflare-one/gateway/get-started/create-network-policy.mdx @@ -35,9 +35,9 @@ To create a new network policy: 3. Send a `POST` request to the [Create a Zero Trust Gateway rule](/api/resources/zero_trust/subresources/gateway/subresources/rules/methods/create/) endpoint. For example, you can use a list of [device serial numbers](/cloudflare-one/identity/devices/warp-client-checks/corp-device/) to ensure users can only access an application if they connect with the WARP client from a company device: ```sh title="curl API network policy example" - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/gateway/rules \ + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --header "Content-Type: application/json" \ - --header "Authorization: Bearer " \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ "name": "Enforce device posture", "description": "Ensure only devices in Zero Trust organization can connect to application", diff --git a/src/content/partials/cloudflare-one/gateway/nonscannable-files.mdx b/src/content/partials/cloudflare-one/gateway/nonscannable-files.mdx index 2149959fe460eb..80366e7493eec4 100644 --- a/src/content/partials/cloudflare-one/gateway/nonscannable-files.mdx +++ b/src/content/partials/cloudflare-one/gateway/nonscannable-files.mdx @@ -1,8 +1,8 @@ --- -{} +inputParameters: fileSizeLimitMB --- Gateway cannot scan requests containing the following files: -- Files larger than 15 MB +- Files larger than {props.fileSizeLimitMB} MB - PGP encrypted files diff --git a/src/content/partials/cloudflare-one/gateway/order-of-enforcement.mdx b/src/content/partials/cloudflare-one/gateway/order-of-enforcement.mdx index 62935f9244606f..57d6dc7a086c09 100644 --- a/src/content/partials/cloudflare-one/gateway/order-of-enforcement.mdx +++ b/src/content/partials/cloudflare-one/gateway/order-of-enforcement.mdx @@ -73,7 +73,8 @@ Gateway applies your policies in the following order: 2. DNS policies with selectors evaluated after resolution 3. HTTP policies 4. Network policies -5. Egress policies (if applicable) +5. Resolver policies (if applicable) +6. Egress policies (if applicable) DNS policies are standalone. For example, if you block a site with a DNS policy but do not create a corresponding HTTP policy, users can still access the site if they know its IP address. @@ -129,6 +130,10 @@ Next, Gateway checks decrypted traffic against your Isolate policies. When a use Lastly, Gateway evaluates all Allow, Block, and Do Not Scan policies. These policies apply to both isolated and non-isolated traffic. For example, if `example.com` is isolated and `example.com/subpage` is blocked, Gateway will block the subpage inside of the remote browser. +### Resolver policies + +When [resolver policies](/cloudflare-one/policies/gateway/resolver-policies/) are present, Gateway first evaluates any DNS policies with pre-resolution selectors, then routes any DNS queries according to the [order of precedence](#order-of-precedence) of your resolver policies, and lastly evaluates any DNS policies with post-resolution selectors. + ### Order of precedence -:::caution[Terraform precedence limitation] - -To avoid conflicts, Terraform applies a hash calculation to precedences. For example, a precedence of `1000` may become `1000901`. This can cause errors when reordering policies. To avoid this issue, manually set the precedence of your policies via the [Cloudflare API](/api/resources/zero_trust/subresources/gateway/subresources/rules/methods/update/). -::: + ## Example @@ -148,16 +150,19 @@ Suppose you have a list of policies arranged in the following order of precedenc - DNS policies: - HTTP policies: - | Precedence | Selector | Operator | Value | Action | + + | Precedence | Selector | Operator | Value | Action | | ---------- | -------- | -------- | ------------------- | -------------- | - | 1 | Host | is | `example.com` | Block | - | 2 | Host | is | `test2.example.com` | Do Not Inspect | + | 1 | Host | is | `example.com` | Block | + | 2 | Host | is | `test2.example.com` | Do Not Inspect | + - Network policies: - | Precedence | Selector | Operator | Value | Action | + + | Precedence | Selector | Operator | Value | Action | | ---------- | ---------------- | -------- | ------------------ | ------ | - | 1 | Destination Port | is | `80` | Block | - | 2 | Destination port | is | `443` | Allow | - | 3 | SNI Domain | is | `test.example.com` | Block | + | 1 | Destination Port | is | `80` | Block | + | 2 | Destination port | is | `443` | Allow | + | 3 | SNI Domain | is | `test.example.com` | Block | When a user goes to `https://test.example.com`, Gateway performs the following operations: diff --git a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-applications.mdx b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-applications.mdx index d24e0141de39f3..3a9982155ea415 100644 --- a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-applications.mdx +++ b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-applications.mdx @@ -18,8 +18,9 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ - "name": "Block content categories", - "description": "Block access to unauthorized AI applications", + "name": "All-HTTP-Application-Blocklist", + "description": "Limit access to shadow IT by blocking web-based tools and applications", + "precedence": 60, "enabled": true, "action": "block", "filters": [ @@ -31,5 +32,23 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ }' ``` + + + +```tf +resource "cloudflare_zero_trust_gateway_policy" "all_http_application_blocklist" { + account_id = var.cloudflare_account_id + name = "All-HTTP-Application-Blocklist" + description = "Limit access to shadow IT by blocking web-based tools and applications" + precedence = 60 + enabled = true + action = "block" + filters = ["http"] + traffic = "any(app.type.ids[*] in {25})" + identity = "" + device_posture = "" +} +``` + diff --git a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-content-categories.mdx b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-content-categories.mdx index 8a951065ae0235..e0940e106cbc46 100644 --- a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-content-categories.mdx +++ b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/http/block-content-categories.mdx @@ -18,8 +18,9 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --data '{ - "name": "Block content categories", - "description": "Block access to unauthorized applications", + "name": "All-HTTP-ContentCategories-Blocklist", + "description": "Block access to questionable content and potential security risks", + "precedence": 40, "enabled": true, "action": "block", "filters": [ @@ -36,14 +37,16 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rule \ ```tf resource "cloudflare_zero_trust_gateway_policy" "block_unauthorized_apps" { - account_id = var.cloudflare_account_id - name = "All-HTTP-Application-Blocklist" - description = "Block access to unauthorized AI applications" - enabled = true - action = "block" - filters = ["dns"] - traffic = "any(app.type.ids[*] in {25})" - identity = "" + account_id = var.cloudflare_account_id + name = "All-HTTP-ContentCategories-Blocklist" + description = "Block access to questionable content and potential security risks" + precedence = 40 + enabled = true + action = "block" + filters = ["dns"] + traffic = "any(http.request.uri.content_category[*] in {17 85 87 102 157 135 138 180 162 32 169 177 128 15 115 119 124 141 161 2 67 125 133 99})"" + identity = "" + device_posture = "" } ``` diff --git a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/network/enforce-device-posture.mdx b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/network/enforce-device-posture.mdx index d779bb24464857..dc469e6d53329b 100644 --- a/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/network/enforce-device-posture.mdx +++ b/src/content/partials/cloudflare-one/gateway/policies/dash-plus-api/network/enforce-device-posture.mdx @@ -24,7 +24,7 @@ curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/rules \ --data '{ "name": "All-NET-ApplicationAccess-Allow", "description": "Ensure access to the application comes from authorized WARP clients", - "precedence": 5000, + "precedence": 70, "enabled": false, "action": "block", "filters": [ @@ -45,7 +45,7 @@ resource "cloudflare_zero_trust_gateway_policy" "all_net_applicationaccess_allow account_id = var.cloudflare_account_id name = "All-NET-ApplicationAccess-Allow" description = "Ensure access to the application comes from authorized WARP clients" - precedence = 5000 + precedence = 70 enabled = false action = "block" filters = ["l4"] diff --git a/src/content/partials/cloudflare-one/gateway/terraform-precedence-warning.mdx b/src/content/partials/cloudflare-one/gateway/terraform-precedence-warning.mdx new file mode 100644 index 00000000000000..bbc5258331ae61 --- /dev/null +++ b/src/content/partials/cloudflare-one/gateway/terraform-precedence-warning.mdx @@ -0,0 +1,7 @@ +--- +{} +--- + +:::caution[Terraform precedence limitation] +To avoid conflicts, Terraform applies a hash calculation to policy precedence. For example, a precedence of `1000` may become `1000901`. This can cause errors when reordering policies. To avoid this issue, manually set the precedence of policies created with Terraform using the [Update a Zero Trust Gateway rule](/api/resources/zero_trust/subresources/gateway/subresources/rules/methods/update/) endpoint. +::: diff --git a/src/content/partials/cloudflare-one/posture/test-posture-provider.mdx b/src/content/partials/cloudflare-one/posture/test-posture-provider.mdx deleted file mode 100644 index 85f225371d6e90..00000000000000 --- a/src/content/partials/cloudflare-one/posture/test-posture-provider.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -{} - ---- - -You will see the new provider listed under **Settings** > **WARP Client** > **Third-party service provider integrations**. To ensure the values have been entered correctly, select **Test**. diff --git a/src/content/partials/cloudflare-one/ssh/ssh-proxy-ca.mdx b/src/content/partials/cloudflare-one/ssh/ssh-proxy-ca.mdx index 1ee08d6eb0246b..b65894ac3fc51a 100644 --- a/src/content/partials/cloudflare-one/ssh/ssh-proxy-ca.mdx +++ b/src/content/partials/cloudflare-one/ssh/ssh-proxy-ca.mdx @@ -1,29 +1,28 @@ --- {} - --- -import { Render, Details } from "~/components" +import { Render, Details } from "~/components"; 1. [Create an API token](/fundamentals/api/get-started/create-token/) with the following permissions: - | Type | Item | Permission | - | ------- | ---------------- | ---------- | - | Account | Access: SSH Auditing | Edit | + | Type | Item | Permission | + | ------- | -------------------- | ---------- | + | Account | Access: SSH Auditing | Edit | 2. If you have not yet generated a Cloudflare SSH CA, make a `POST` request to the Cloudflare API: - ```bash - curl --request POST \ - "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/gateway_ca" \ - --header "Authorization: Bearer " - ``` + ```bash + curl --request POST \ + "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/gateway_ca" \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" + ``` 3. If you have already created a Cloudflare SSH CA or receive the error message `access.api.error.gateway_ca_already_exists`, make a `GET` request instead: - ```bash - curl https://api.cloudflare.com/client/v4/accounts/{account_id}/access/gateway_ca \ - --header "Authorization: Bearer " - ``` + ```bash + curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/gateway_ca \ + --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" + ``` 4. Copy the `public_key` value returned in the response. diff --git a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx index a06546576bf4e3..b609f6b251b3ed 100644 --- a/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx +++ b/src/content/partials/cloudflare-one/tunnel/add-public-hostname.mdx @@ -6,9 +6,12 @@ 1. In the **Public Hostnames** tab, select **Add a public hostname**. 2. Enter a subdomain and select a **Domain** from the dropdown menu. Specify any subdomain or path information. + :::note + If you add a multi-level subdomain (more than one level of subdomain), you must [order an Advanced Certificate for the hostname](/cloudflare-one/faq/troubleshooting/#i-see-this-site-cant-provide-a-secure-connection). + ::: 3. Specify a service, for example `https://localhost:8000`. -4. Under **Additional application settings**, specify any [parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/) you would like to add to your tunnel configuration. +4. Under **Additional application settings**, specify any [parameters](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/) you would like to add to your tunnel configuration. 5. Select **Save hostname**. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/tunnel/cloudflared-access.mdx b/src/content/partials/cloudflare-one/tunnel/cloudflared-access.mdx deleted file mode 100644 index a038fdfb2bb4ca..00000000000000 --- a/src/content/partials/cloudflare-one/tunnel/cloudflared-access.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -{} - ---- - -Cloudflare Tunnel can also route applications through a public hostname, which allows users to connect to the application without the WARP client. This method requires having `cloudflared` installed on both the server machine and on the client machine, as well as an active zone on Cloudflare. The traffic is proxied over this connection, and the user logs in to the server with their Cloudflare Access credentials. - -The public hostname method can be implemented in conjunction with routing over WARP so that there are multiple ways to connect to the server. You can reuse the same tunnel for both the private network and public hostname routes. diff --git a/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx b/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx new file mode 100644 index 00000000000000..5b5bc56a5f07b7 --- /dev/null +++ b/src/content/partials/cloudflare-one/tunnel/connect-private-network-infra-access.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +2. In the **Private Networks** tab for the tunnel, enter the IP or CIDR address of your server. Typically this would be a private IP, but public IPs are also allowed. diff --git a/src/content/partials/cloudflare-one/tunnel/connect-private-network.mdx b/src/content/partials/cloudflare-one/tunnel/connect-private-network.mdx new file mode 100644 index 00000000000000..1883b68dbb47e6 --- /dev/null +++ b/src/content/partials/cloudflare-one/tunnel/connect-private-network.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the [connect an application step](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/#2a-connect-an-application) and go straight to connecting a network. diff --git a/src/content/partials/cloudflare-one/tunnel/package-manager.mdx b/src/content/partials/cloudflare-one/tunnel/package-manager.mdx new file mode 100644 index 00000000000000..2fd27a10bd6f00 --- /dev/null +++ b/src/content/partials/cloudflare-one/tunnel/package-manager.mdx @@ -0,0 +1,6 @@ +--- +{} + +--- + +You can check if `cloudflared` was installed by a package manager by running `ls -la /usr/local/etc/cloudflared/` and looking for `.installedFromPackageManager` in the output. \ No newline at end of file diff --git a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx index c38f43166395f2..d3c0ea1b1bcd83 100644 --- a/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx +++ b/src/content/partials/cloudflare-one/tunnel/troubleshoot-private-networks.mdx @@ -124,4 +124,4 @@ To troubleshoot TLS inspection: - **Option 1:** Create a permanent [`Do Not Inspect` HTTP policy](/cloudflare-one/policies/gateway/http-policies/#do-not-inspect) for this application. - **Option 2:** Customers who use their [own certificate infrastructure](/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/) for inspection can opt to create an [Allow _Pass Through_ policy](/cloudflare-one/policies/gateway/http-policies/#untrusted-certificates) which enables our proxy to accept the TLS negotiation from your application. This will allow requests to flow correctly without the need for a `Do Not Inspect` policy. - - **Option 3:** If your application uses `HTTPS` or other common protocols, you can add a [public hostname route](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) to your Cloudflare Tunnel and set [noTLSVerify](/cloudflare-one/connections/connect-networks/configure-tunnels/origin-configuration/#notlsverify) to `true`. This will allow `cloudflared` to trust your self-signed certificate. + - **Option 3:** If your application uses `HTTPS` or other common protocols, you can add a [public hostname route](/cloudflare-one/connections/connect-networks/routing-to-tunnel/) to your Cloudflare Tunnel and set [noTLSVerify](/cloudflare-one/connections/connect-networks/configure-tunnels/cloudflared-parameters/origin-parameters/#notlsverify) to `true`. This will allow `cloudflared` to trust your self-signed certificate. diff --git a/src/content/partials/cloudflare-one/tunnel/tunnel-capacity-baseline.mdx b/src/content/partials/cloudflare-one/tunnel/tunnel-capacity-baseline.mdx index 739f5311d07f34..29a9c0e6d0c00d 100644 --- a/src/content/partials/cloudflare-one/tunnel/tunnel-capacity-baseline.mdx +++ b/src/content/partials/cloudflare-one/tunnel/tunnel-capacity-baseline.mdx @@ -3,8 +3,8 @@ --- -* Run a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/deploy-tunnels/deploy-cloudflared-replicas/#cloudflared-replicas) on two dedicated host machines per network location. Using two hosts enables server-side redundancy and traffic balancing. +* Run a [`cloudflared` replica](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/#cloudflared-replicas) on two dedicated host machines per network location. Using two hosts enables server-side redundancy and traffic balancing. * Size each host with minimum 4GB of RAM and 4 CPU cores. -* Allocate 50,000 [ports](/cloudflare-one/connections/connect-networks/deploy-tunnels/system-requirements/#number-of-ports) to the `cloudflared` process on each host. +* Allocate 50,000 [ports](/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-availability/system-requirements/#number-of-ports) to the `cloudflared` process on each host. This setup is usually sufficient to handle traffic from 8,000 users (4,000 per host). diff --git a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-client.mdx b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-client.mdx index 466d2947f6cf7e..6827798ed93102 100644 --- a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-client.mdx +++ b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-client.mdx @@ -1,9 +1,8 @@ --- {} - --- To connect your devices to Cloudflare: -1. [Deploy the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/) on your devices in Gateway with WARP mode. +1. [Deploy the WARP client](/cloudflare-one/connections/connect-devices/warp/deployment/) on your devices in Gateway with WARP mode or [generate a proxy endpoint](/cloudflare-one/connections/connect-devices/agentless/pac-files/) and deploy a PAC file. 2. [Create device enrollment rules](/cloudflare-one/connections/connect-devices/warp/deployment/device-enrollment/) to determine which devices can enroll to your Zero Trust organization. diff --git a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-intro.mdx b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-intro.mdx deleted file mode 100644 index 52d7380fe027c4..00000000000000 --- a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-intro.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -{} - ---- - -You can use Cloudflare Tunnel to create a secure, outbound-only connection from your server to Cloudflare's global network. This requires running the `cloudflared` daemon on the server. Users reach the service by installing the [Cloudflare WARP client](/cloudflare-one/connections/connect-devices/warp/) on their device and enrolling in your Zero Trust organization. Remote devices will be able to connect as if they were on your private network. By default, all devices enrolled in your organization can access the service unless you build policies to allow or block specific users. diff --git a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx index 1baa9e46953b50..267d3dbeeebdcc 100644 --- a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx +++ b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-route-ips.mdx @@ -3,14 +3,28 @@ params: - one --- -import { Markdown } from "~/components" +import { Markdown } from "~/components"; +import SubtractIPCalculator from "~/components/SubtractIPCalculator.tsx"; By default, WARP excludes traffic bound for [RFC 1918 space](https://datatracker.ietf.org/doc/html/rfc1918), which are IP addresses typically used in private networks and not reachable from the Internet. In order for WARP to send traffic to your , you must configure [Split Tunnels](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/) so that the IP/CIDR of your routes through WARP. 1. First, check whether your [Split Tunnels mode](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#change-split-tunnels-mode) is set to **Exclude** or **Include** mode. 2. If you are using **Include** mode, add your 's IP/CIDR range to the list. Your list should also include the [domains necessary for Cloudflare Zero Trust functionality](/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#cloudflare-zero-trust-domains). 3. If you are using **Exclude** mode: - 1. Delete your 's IP/CIDR range from the list. For example, if your network uses the default AWS range of `172.31.0.0/16`, delete `172.16.0.0/12`. - 2. Re-add IP/CIDR ranges that are not explicitly used by your . For the AWS example above, you would add new entries for `172.16.0.0/13`, `172.24.0.0/14`, `172.28.0.0/15`, and `172.30.0.0/16`. This ensures that only traffic to `172.31.0.0/16` routes through WARP. + + a. Delete your 's IP/CIDR range from the list. For example, if your network uses the default AWS range of `172.31.0.0/16`, delete `172.16.0.0/12`. + + b. Re-add IP/CIDR ranges that are not explicitly used by your . For the AWS example above, you would add new entries for `172.16.0.0/13`, `172.24.0.0/14`, `172.28.0.0/15`, and `172.30.0.0/16`. This ensures that only traffic to `172.31.0.0/16` routes through WARP. + + You can use the following calculator to determine which IP addresses to re-add: + + + In **Base CIDR**, enter the RFC 1918 range that you deleted from Split Tunnels. In **Excluded CIDRs**, enter the IP/CIDR range used by your . Re-add the calculator results to your Split Tunnel Exclude mode list. By tightening the private IP range included in WARP, you reduce the risk of breaking a user's [access to local resources](/cloudflare-one/connections/connect-devices/warp/configure-warp/warp-settings/#allow-users-to-enable-local-network-exclusion). diff --git a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-server.mdx b/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-server.mdx deleted file mode 100644 index cec90f2323525a..00000000000000 --- a/src/content/partials/cloudflare-one/tunnel/warp-to-tunnel-server.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -{} - ---- - -1. Create a Cloudflare Tunnel for your server by following our [dashboard setup guide](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). You can skip the connect an application step and go straight to connecting a network. - -2. In the **Private Networks** tab for the tunnel, enter the private IP address of your server (or a range that includes the server IP). In GCP, the server IP is the **Internal IP** of the VM instance. - -3. (Optional) [Set up Zero Trust policies](/cloudflare-one/connections/connect-networks/private-net/cloudflared/#4-recommended-filter-network-traffic-with-gateway) to fine-tune access to your server. diff --git a/src/content/partials/cloudflare-one/warp/service-token-enrollment.mdx b/src/content/partials/cloudflare-one/warp/service-token-enrollment.mdx index ddf81e385cba90..9bf9312cfe3e2a 100644 --- a/src/content/partials/cloudflare-one/warp/service-token-enrollment.mdx +++ b/src/content/partials/cloudflare-one/warp/service-token-enrollment.mdx @@ -11,13 +11,15 @@ import { Tabs, TabItem } from '~/components'; 2. Copy the token's **Client ID** and **Client Secret**. -3. In your [device enrollment permissions](/cloudflare-one/connections/connect-devices/warp/deployment/device-enrollment/#set-device-enrollment-permissions), create the following policy: +3. Go to **Access** > **Policies** and create the following policy: | Rule Action | Rule type | Selector | Value | | ------------ | --------- | ------------- | -------------- | | Service Auth | Include | Service Token | `` | -4. In your MDM [deployment parameters](/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/parameters/), add the following fields: + Make sure to set **Action** to _Service Auth_ instead of _Allow_. +4. Add the Access policy to your [device enrollment permissions](/cloudflare-one/connections/connect-devices/warp/deployment/device-enrollment/#set-device-enrollment-permissions). +5. In your MDM [deployment parameters](/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/parameters/), add the following fields: * `auth_client_id`: The **Client ID** of your service token. * `auth_client_secret`: The **Client Secret** of your service token. diff --git a/src/content/partials/dns/internal-dns-beta-note.mdx b/src/content/partials/dns/internal-dns-beta-note.mdx new file mode 100644 index 00000000000000..920328d90646dd --- /dev/null +++ b/src/content/partials/dns/internal-dns-beta-note.mdx @@ -0,0 +1,8 @@ +--- +{} + +--- + +:::note +Internal DNS is currently in closed beta. Using it on production traffic is at your own risk. If you are interested in this product, contact your account team. +::: \ No newline at end of file diff --git a/src/content/partials/dns/internal-dns-view-conditions.mdx b/src/content/partials/dns/internal-dns-view-conditions.mdx new file mode 100644 index 00000000000000..ed9435e898ccc0 --- /dev/null +++ b/src/content/partials/dns/internal-dns-view-conditions.mdx @@ -0,0 +1,11 @@ +--- +{} + +--- + +- DNS views can be empty, with no [internal zones](/dns/internal-dns/internal-zones/) linked to them. +- A DNS view cannot contain public DNS zones [^1]. +- Each internal DNS zone name must be unique within a given DNS view. +- Each DNS view name must be unique within a given Cloudflare account. + +[^1]: DNS zones that contain public DNS records and are accessible by public resolvers. \ No newline at end of file diff --git a/src/content/partials/dns/internal-reference-zone-api.mdx b/src/content/partials/dns/internal-reference-zone-api.mdx new file mode 100644 index 00000000000000..00173b94a09c36 --- /dev/null +++ b/src/content/partials/dns/internal-reference-zone-api.mdx @@ -0,0 +1,18 @@ +--- +{} + +--- + +In the following example, internal zone A (ID `8a904aeb565c42cfa207d98f6edea2f3`) is referencing internal zone B (ID `8e64c6fb4b514f3faf64de81efc11e51`). + +```bash +curl --request PATCH \ +https://api.cloudflare.com/client/v4/zones/8a904aeb565c42cfa207d98f6edea2f3/dns_settings \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ +--header "Content-Type: application/json" \ +--data '{ + "internal_dns": { + "reference_zone_id": "8e64c6fb4b514f3faf64de81efc11e51" + } + }' +``` \ No newline at end of file diff --git a/src/content/partials/dns/internal-zone-create.mdx b/src/content/partials/dns/internal-zone-create.mdx new file mode 100644 index 00000000000000..a46c3c8a59f982 --- /dev/null +++ b/src/content/partials/dns/internal-zone-create.mdx @@ -0,0 +1,20 @@ +--- +params: + - conditional? +--- + +import { Details, Render } from "~/components"; + +1. Use the [Create Zone](/api/resources/zones/) endpoint to create an [internal zone](/dns/internal-dns/internal-zones/). Specify your account ID and set the `type` to `internal`. + +{ props.conditional === "get-started-detail" && ( +
    + +
    + ) +} + +2. Add DNS records to your internal zone using your preferred option: +- [Import](/api/resources/dns/subresources/records/methods/import/) a formatted BIND file. Refer to the [DNS records how-to](/dns/manage-dns-records/how-to/import-and-export/) for guidance. +- Use other API endpoints, such as [`/batch`](/api/resources/dns/subresources/records/methods/batch/), to manage DNS records. Refer to [Batch record changes](/dns/manage-dns-records/how-to/batch-record-changes/#use-the-api) for details. +3. Repeat this process for each internal zone you wish to add. \ No newline at end of file diff --git a/src/content/partials/dns/internal-zones-conditions.mdx b/src/content/partials/dns/internal-zones-conditions.mdx new file mode 100644 index 00000000000000..30e5dd0b6359ea --- /dev/null +++ b/src/content/partials/dns/internal-zones-conditions.mdx @@ -0,0 +1,10 @@ +--- +{} + +--- + +- Internal zones can contain the same [DNS record types](/dns/manage-dns-records/reference/dns-record-types/) that Cloudflare supports for public zones. +- An internal zone can have the same name as a public zone in the same account. +- Each internal zone can be linked to multiple [views](/dns/internal-dns/dns-views/). +- There can be several internal zones with the same name in one account. However, two internal zones with the same name cannot be linked to the same view. +- Internal zones are not subject to any top-level domain (TLD) restrictions. This means that an internal zone can be created if its TLD is not registered publicly (for example, `xyz.local`), if it is created on the TLD itself (`local`), or even if on the root (`.`). \ No newline at end of file diff --git a/src/content/partials/dns/limitations.mdx b/src/content/partials/dns/limitations.mdx index 809ed8f2f2cde0..6decf14e43730e 100644 --- a/src/content/partials/dns/limitations.mdx +++ b/src/content/partials/dns/limitations.mdx @@ -23,7 +23,7 @@ To proxy `HTTP/HTTPS` traffic on [non-standard ports](/fundamentals/reference/ne
    -This means that DNS records — even those set to [proxy traffic through Cloudflare](#proxied-records) — will be [DNS-only](/dns/proxy-status/#dns-only-records) until your zone has been activated and any requests to your DNS records will return your origin server's IP address. +This means that DNS records — even those set to proxy traffic through Cloudflare — will be [DNS-only](/dns/proxy-status/#dns-only-records) until your zone has been activated and any requests to your DNS records will return your origin server's IP address. If this warning is still present after 24 hours, refer to [Troubleshooting](/dns/troubleshooting/). diff --git a/src/content/partials/dns/reference-zone-intro.mdx b/src/content/partials/dns/reference-zone-intro.mdx new file mode 100644 index 00000000000000..3e255f6a447513 --- /dev/null +++ b/src/content/partials/dns/reference-zone-intro.mdx @@ -0,0 +1,12 @@ +--- +{} + +--- + +During an [internal DNS query resolution](/dns/internal-dns/#architecture-overview), if no internal record is found within a matching internal zone, Cloudflare will check if the matching internal zone is referencing another internal zone. Successive references can be followed with a maximum of five references in a chain. + +:::note +A wildcard record in the matching internal zone will take precedence over an exact match in a referenced zone. +::: + +Each internal zone can only reference one other zone, but the same zone can be referenced by multiple internal zones. Public zones cannot be used as reference zones. \ No newline at end of file diff --git a/src/content/partials/fundamentals/account-owned-tokens.mdx b/src/content/partials/fundamentals/account-owned-tokens.mdx index 8ed1af3a740f54..7268fcf98538a4 100644 --- a/src/content/partials/fundamentals/account-owned-tokens.mdx +++ b/src/content/partials/fundamentals/account-owned-tokens.mdx @@ -50,8 +50,8 @@ Account owned tokens are generally available for all accounts. Some services may | Load Balancing | ✅ | | Log Explorer | ✅ | | Magic Network Monitoring | ✅ | -| Magic Transit | ❌ | -| Magic WAN | ❌ | +| Magic Transit | ✅ | +| Magic WAN | ✅ | | Managed Rules | ✅ | | Network Error Logging | ✅ | | Page Shield | ✅ | diff --git a/src/content/partials/fundamentals/account-permissions-table.mdx b/src/content/partials/fundamentals/account-permissions-table.mdx index ca5ca5450f76ad..208c8063a8dcc6 100644 --- a/src/content/partials/fundamentals/account-permissions-table.mdx +++ b/src/content/partials/fundamentals/account-permissions-table.mdx @@ -1,151 +1,152 @@ --- -inputParameters: editWord;;editProduct;;cloudflareName +params: + - editWord + - src --- import { Markdown } from "~/components"; -| Name | Description | -| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Access: Apps and Policies Read | Grants read access to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | -| Access: Apps and Policies Revoke | Grants ability to revoke all tokens to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | -| Access: Apps and Policies {props.one} | Grants write access to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | -| Access: Audit Logs Read | Grants read access to [Cloudflare Access audit logs](/cloudflare-one/insights/logs/audit-logs/). | -| Access: Custom Pages Read | Grants read access to [Cloudflare Access Custom Pages](/cloudflare-one/policies/gateway/block-page/). | -| Access: Custom Pages {props.one} | Grants write access to [Cloudflare Access Custom Pages](/cloudflare-one/policies/gateway/block-page/). | -| Access: Device Posture Read | Grants read access to [Cloudflare Access Device Posture](/cloudflare-one/identity/devices/). | -| Access: Device Posture {props.one} | Grants write access to [Cloudflare Access Device Posture](/cloudflare-one/identity/devices/). | -| Access: Mutual TLS Certificates Read | Grants read access to [Cloudflare Access mTLS certificates](/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication/). | -| Access: Mutual TLS Certificates {props.one} | Grants write access to [Cloudflare Access mTLS certificates](/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication/). | -| Access: Organizations, Identity Providers, and Groups Read | Grants read access to [Cloudflare Access account resources](/cloudflare-one/identity/). | -| Access: Organizations, Identity Providers, and Groups Revoke | Grants ability to revoke user sessions to [Cloudflare Access account resources](/cloudflare-one/identity/). | -| Access: Organizations, Identity Providers, and Groups {props.one} | Grants write access to [Cloudflare Access account resources](/cloudflare-one/identity/). | -| Access: Service Tokens Read | Grants read access to [Cloudflare Access Service Tokens](/cloudflare-one/identity/service-tokens/). | -| Access: Service Tokens {props.one} | Grants write access to [Cloudflare Access Service Tokens](/cloudflare-one/identity/service-tokens/). | -| Access: SSH Auditing Read | Grants read access to [SSH Auditing](/cloudflare-one/policies/gateway/network-policies/ssh-logging/). | -| Access: SSH Auditing {props.one} | Grants write access to [SSH Auditing](/cloudflare-one/policies/gateway/network-policies/ssh-logging/). | -| Account Analytics Read | Grants read access to [account analytics](/analytics/account-and-zone-analytics/account-analytics/). | -| Account Custom Pages Read | Grants read access to account-level [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | -| Account Custom Pages {props.one} | Grants write access to account-level [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | -| Account Filter Lists Read | Grants read access to Account Filter Lists. | -| Account Filter Lists {props.one} | Grants write access to Account Filter Lists. | -| Account Firewall Access Rules Read | Grants read access to account firewall access rules. | -| Account Firewall Access Rules {props.one} | Grants write access to account firewall access rules. | -| Account Rulesets Read | Grants read access to [Account Rulesets](/ruleset-engine/about/rulesets/). | -| Account Rulesets {props.one} | Grants write access to [Account Rulesets](/ruleset-engine/about/rulesets/). | -| Account Settings Read | Grants read access to [Account resources, account membership, and account level features](/fundamentals/subscriptions-and-billing/). | -| Account Settings {props.one} | Grants write access to [Account resources, account membership, and account level features](/fundamentals/subscriptions-and-billing/). | -| Account: SSL and Certificates Read | Grants read access to [SSL and Certificates](/ssl/). | -| Account: SSL and Certificates {props.one} | Grants write access to [SSL and Certificates](/ssl/). | -| Account WAF Read | Grants read access to [Account WAF](/waf/). | -| Account WAF {props.one} | Grants write access to [Account WAF](/waf/). | -| Address Maps {props.one} | Grants write access to [Address Maps](/byoip/address-maps/) | -| Address Maps Read | Grants read access to [Address Maps](/byoip/address-maps/) | -| Allow Request Tracer Read | Grants read access to Request Tracer. | -| API Gateway Read | Grants read access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | -| API Gateway {props.one} | Grants write access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | -| Billing Read | Grants read access to [billing profile, subscriptions, and access to fetch invoices](/fundamentals/subscriptions-and-billing/) and entitlements. | -| Billing {props.one} | Grants write access to [billing profile, subscriptions, and access to fetch invoices and entitlements](/fundamentals/subscriptions-and-billing/). | -| Bulk URL Redirects Read | Grants read access to [Bulk URL Redirects](/rules/url-forwarding/bulk-redirects/). | -| Bulk URL Redirects {props.one} | Grants write access to [Bulk URL Redirects](/rules/url-forwarding/bulk-redirects/). | -| China Network Steering Read | Grants read access to [China Network Steering](/china-network/). | -| China Network Steering {props.one} | Grants write access to [China Network Steering](/china-network/). | -| Cloudchamber Read | Grants read access to Cloudchamber deployments. | -| Cloudchamber {props.one} | Grants write access to Cloudchamber deployments. | -| Cloudflare Calls Read | Grants read access to Cloudflare Calls. | -| Cloudflare Calls {props.one} | Grants write access to Cloudflare Calls. | -| Cloudflare DEX Read | Grants read access to [Digital Experience Monitoring](/cloudflare-one/insights/dex/). | -| Cloudflare DEX {props.one} | Grants write access to [Digital Experience Monitoring](/cloudflare-one/insights/dex/). | -| Cloudflare Images Read | Grants read access to [Cloudflare Images](/images/). | -| Cloudflare Images {props.one} | Grants write access to [Cloudflare Images](/images/). | -| Cloudflare One Connector: cloudflared Read | Grants read access to `cloudflared` Connectors | -| Cloudflare One Connector: cloudflared {props.one} | Grants write access to `cloudflared` Connectors | -| Cloudflare One Connector: WARP Read | Grants read access to Warp Connectors | -| Cloudflare One Connector: WARP {props.one} | Grants write access to Warp Connectors | -| Cloudflare One Connectors Read | Grants read access to Cloudflare One Connectors | -| Cloudflare One Connectors {props.one} | Grants write access to Cloudflare One Connectors | -| Cloudflare One Networks Read | Grants read access to Cloudflare One Networks | -| Cloudflare One Networks {props.one} | Grants write access to Cloudflare One Networks | -| {props.three} Pages Read | Grants access to view [Cloudflare Pages](/pages/) projects. | -| {props.three} Pages {props.one} | Grants access to create, edit and delete [Cloudflare Pages](/pages/) projects. | -| {props.two} Tunnel Read | Grants access to view [Cloudflare Tunnels](/cloudflare-one/connections/connect-networks/). | -| {props.two} Tunnel {props.one} | Grants access to create and delete [Cloudflare Tunnels](/cloudflare-one/connections/connect-networks/). | -| Cloudforce One Read | Grants read access to Cloudforce One. | -| Cloudforce One {props.one} | Grants write access to Cloudforce One. | -| Cloud Email Security Read | Grants read access to [Cloud Email Security](/email-security/). | -| Email Security {props.one} | Grants write access to [Email Security](/email-security/). | -| Constellation Read | Grants read access to [Constellation](/constellation/). | -| Constellation {props.one} | Grants write access to [Constellation](/constellation/). | -| D1 Read | Grants read access to [D1](/d1/). | -| D1 {props.one} | Grants write access to [D1](/d1/). | -| DDoS Botnet Feed Read | Grants read access to Botnet Feed reports. | -| DDoS Botnet Feed {props.one} | Grants write access to Botnet Feed configuration. | -| DDoS Protection Read | Grants read access to [DDoS protection](/ddos-protection/). | -| DDoS Protection {props.one} | Grants write access to [DDoS protection](/ddos-protection/). | -| DNS Firewall Read | Grants read access to [DNS Firewall](/dns/dns-firewall/). | -| DNS Firewall {props.one} | Grants write access to [DNS Firewall](/dns/dns-firewall/). | -| Email Routing Addresses Read | Grants read access to [Email Routing Addresses](/email-routing/setup/email-routing-addresses/). | -| Email Routing Addresses {props.one} | Grants write access to [Email Routing Addresses](/email-routing/setup/email-routing-addresses/). | -| Hyperdrive Read | Grants read access to [Hyperdrive](/hyperdrive/). | -| Hyperdrive {props.one} | Grants write access to [Hyperdrive](/hyperdrive/). | -| Intel Read | Grants read access to [Intel](/security-center/intel-apis/). | -| Intel {props.one} | Grants write access to [Intel](/security-center/intel-apis/). | -| Integration {props.one} | Grants write access to integrations. | -| IOT Read | Grants read access to [IOT](https://blog.cloudflare.com/rethinking-internet-of-things-security/). | -| IOT {props.one} | Grants write access to [IOT](https://blog.cloudflare.com/rethinking-internet-of-things-security/). | -| IP Prefixes: Read | Grants access to read IP prefix settings. | -| IP Prefixes: {props.one} | Grants access to read/write IP prefix settings. | -| IP Prefixes: BGP On Demand Read | Grants access to read IP prefix BGP configuration. | -| IP Prefixes: BGP On Demand {props.one} | Grants access to read and change IP prefix BGP configuration. | -| L3/4 DDoS Managed Ruleset Read | Grants read access to [L3/4 DDoS managed ruleset](/ddos-protection/managed-rulesets/network/). | -| L3/4 DDoS Managed Ruleset {props.one} | Grants write access to [L3/4 DDoS managed ruleset](/ddos-protection/managed-rulesets/network/). | -| Load Balancing: Monitors and Pools Read | Grants read access to account level [load balancer resources](/load-balancing/). | -| Load Balancing: Monitors and Pools {props.one} | Grants write access to account level [load balancer resources](/load-balancing/). | -| Logs Read | Grants read access to logs using [Logpull or Instant Logs](/logs/). | -| Logs {props.one} | Grants read and write access to [Logpull, Logpush, and Instant Logs](/logs/). | -| Magic Firewall Read | Grants read access to [Magic Firewall](/magic-firewall/). | -| Magic Firewall {props.one} | Grants write access to [Magic Firewall](/magic-firewall/). | -| Magic Firewall Packet Captures - Read PCAPs API | Grants read access to [Packet Captures](/magic-firewall/packet-captures/collect-pcaps/). | -| Magic Firewall Packet Captures - {props.one} PCAPs API | Grants write access to [Packet Captures](/magic-firewall/packet-captures/collect-pcaps/). | -| Magic Network Monitoring Read | Grants read access to [Magic Network Monitoring](/magic-network-monitoring/). | -| Magic Network Monitoring {props.one} | Grants write access to [Magic Network Monitoring](/magic-network-monitoring/). | -| Magic Transit Read | Grants read access to manage a user's [Magic Transit prefixes](/magic-transit/how-to/advertise-prefixes/). | -| Magic Transit {props.one} | Grants write access to manage a user's [Magic Transit prefixes](/magic-transit/how-to/advertise-prefixes/). | -| Notifications Read | Grants read access to [Notifications](/notifications/). | -| Notifications {props.one} | Grants write access to [Notifications](/notifications/). | -| Page Shield Read | Grants read access to [Page Shield](/page-shield/). | -| Page Shield {props.one} | Grants write access to [Page Shield](/page-shield/). | -| Pipelines Read | Grants read access to Cloudflare Pipelines. | -| Pipelines {props.one} | Grants write access to Cloudflare Pipelines. | -| Pub/Sub Read | Grants read access to [Pub/Sub](/pub-sub/). | -| Pub/Sub {props.one} | Grants write access to [Pub/Sub](/pub-sub/). | -| Queues Read | Grants read access to [Queues](/queues/). | -| Queues {props.one} | Grants write access to [Queues](/queues/). | -| Rule Policies Read | Grants read access to Rule Policies. | -| Rule Policies {props.one} | Grants write access to Rule Policies. | -| Stream Read | Grants read access to [Cloudflare Stream](/stream/). | -| Stream {props.one} | Grants write access to [Cloudflare Stream](/stream/). | -| Transform Rules Read | Grants read access to [Transform Rules](/rules/transform/). | -| Transform Rules {props.one} | Grants write access to [Transform Rules](/rules/transform/). | -| Turnstile Read | Grants read access to [Turnstile](/turnstile/). | -| Turnstile {props.one} | Grants write access to [Turnstile](/turnstile/). | -| URL Scanner Read | Grants read access to [URL Scanner](/radar/investigate/url-scanner/). | -| URL Scanner {props.one} | Grants write access to [URL Scanner](/radar/investigate/url-scanner/). | -| Vectorize Read | Grants read access to [Vectorize](/vectorize/). | -| Vectorize {props.one} | Grants write access to [Vectorize](/vectorize/). | -| Workers AI Read | Grants read access to [Workers AI](/workers-ai/). | -| Workers AI {props.one} | Grants write access to [Workers AI](/workers-ai/). | -| Workers CI Read | Grants read access to [Workers CI] (/workers/). | -| Workers CI {props.one} | Grants write access to [Workers CI](/workers). | -| Workers KV Storage Read | Grants read access to [Cloudflare Workers KV Storage](/kv/api/). | -| Workers KV Storage {props.one} | Grants write access to [Cloudflare Workers KV Storage](/kv/api/). | -| Workers R2 Storage Read | Grants read access to [Cloudflare R2 Storage](/r2/). | -| Workers R2 Storage {props.one} | Grants write access to [Cloudflare R2 Storage](/r2/). | -| Workers Scripts Read | Grants read access to [Cloudflare Workers scripts](/workers/). | -| Workers Scripts {props.one} | Grants write access to [Cloudflare Workers scripts](/workers/). | -| Workers Tail Read | Grants [`wrangler tail`](/workers/wrangler/commands/#tail) read permissions. | -| Zero Trust Read | Grants read access to [Cloudflare Zero Trust](/cloudflare-one/). | -| Zero Trust Report | Grants reporting access to [Cloudflare Zero Trust](/cloudflare-one/). | -| Zero Trust {props.one} | Grants write access to [Cloudflare Zero Trust](/cloudflare-one/). | -| Zero Trust PII Read | Grants read access to [Cloudflare Zero Trust](/cloudflare-one/) PII. | -| Zero Trust PII {props.one} | Grants write access to [Cloudflare Zero Trust](/cloudflare-one/) PII. | -| Zero Trust Seats {props.one} | Grants write access to the number of [Zero Trust Seats](/cloudflare-one/identity/users/seat-management/) your organization can use (and be billed for). | +| Name | Description | +| -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Access: Apps and Policies Read | Grants read access to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | +| Access: Apps and Policies Revoke | Grants ability to revoke all tokens to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | +| Access: Apps and Policies {props.editWord} | Grants write access to [Cloudflare Access](/cloudflare-one/policies/access/) account resources. | +| Access: Audit Logs Read | Grants read access to [Cloudflare Access audit logs](/cloudflare-one/insights/logs/audit-logs/). | +| Access: Custom { props.src === "dash" ? "Pages" : "Page" } Read | Grants read access to [Cloudflare Access Custom Pages](/cloudflare-one/policies/gateway/block-page/). | +| Access: Custom { props.src === "dash" ? "Pages" : "Page" } {props.editWord} | Grants write access to [Cloudflare Access Custom Pages](/cloudflare-one/policies/gateway/block-page/). | +| Access: Device Posture Read | Grants read access to [Cloudflare Access Device Posture](/cloudflare-one/identity/devices/). | +| Access: Device Posture {props.editWord} | Grants write access to [Cloudflare Access Device Posture](/cloudflare-one/identity/devices/). | +| Access: { props.src === "dash" && "Mutual TLS" } Certificates Read | Grants read access to [Cloudflare Access mTLS certificates](/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication/). | +| Access: { props.src === "dash" && "Mutual TLS" } Certificates {props.editWord} | Grants write access to [Cloudflare Access mTLS certificates](/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication/). | +| Access: Organizations, Identity Providers, and Groups Read | Grants read access to [Cloudflare Access account resources](/cloudflare-one/identity/). | +| Access: Organizations, Identity Providers, and Groups Revoke | Grants ability to revoke user sessions to [Cloudflare Access account resources](/cloudflare-one/identity/). | +| Access: Organizations, Identity Providers, and Groups {props.editWord} | Grants write access to [Cloudflare Access account resources](/cloudflare-one/identity/). | +| Access: Service Tokens Read | Grants read access to [Cloudflare Access Service Tokens](/cloudflare-one/identity/service-tokens/). | +| Access: Service Tokens {props.editWord} | Grants write access to [Cloudflare Access Service Tokens](/cloudflare-one/identity/service-tokens/). | +| Access: SSH Auditing { props.src === "api" && "CA" } Read | Grants read access to [SSH Auditing](/cloudflare-one/policies/gateway/network-policies/ssh-logging/). | +| Access: SSH Auditing { props.src === "api" && "CA" } {props.editWord} | Grants write access to [SSH Auditing](/cloudflare-one/policies/gateway/network-policies/ssh-logging/). | +| Account Analytics Read | Grants read access to [account analytics](/analytics/account-and-zone-analytics/account-analytics/). | +| Account Custom Pages Read | Grants read access to account-level [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | +| Account Custom Pages {props.editWord} | Grants write access to account-level [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | +| Account { props.src === "dash" ? "Filter" : "Rule" } Lists Read | Grants read access to Account Filter Lists. | +| Account { props.src === "dash" ? "Filter" : "Rule" } Lists {props.editWord} | Grants write access to Account Filter Lists. | +| Account Firewall Access Rules Read | Grants read access to account firewall access rules. | +| Account Firewall Access Rules {props.editWord} | Grants write access to account firewall access rules. | +| Account Rulesets Read | Grants read access to [Account Rulesets](/ruleset-engine/about/rulesets/). | +| Account Rulesets {props.editWord} | Grants write access to [Account Rulesets](/ruleset-engine/about/rulesets/). | +| Account Settings Read | Grants read access to [Account resources, account membership, and account level features](/fundamentals/subscriptions-and-billing/). | +| Account Settings {props.editWord} | Grants write access to [Account resources, account membership, and account level features](/fundamentals/subscriptions-and-billing/). | +| Account: SSL and Certificates Read | Grants read access to [SSL and Certificates](/ssl/). | +| Account: SSL and Certificates {props.editWord} | Grants write access to [SSL and Certificates](/ssl/). | +| Account WAF Read | Grants read access to [Account WAF](/waf/). | +| Account WAF {props.editWord} | Grants write access to [Account WAF](/waf/). | +| Address Maps {props.editWord} | Grants write access to [Address Maps](/byoip/address-maps/) | +| Address Maps Read | Grants read access to [Address Maps](/byoip/address-maps/) | +| Allow Request Tracer Read | Grants read access to Request Tracer. | +| { props.src === "api" && "Account" } API Gateway Read | Grants read access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | +| { props.src === "api" && "Account" } API Gateway {props.editWord} | Grants write access to [API Gateway (including API Shield)](/api-shield/) for all domains in an account. | +| Billing Read | Grants read access to [billing profile, subscriptions, and access to fetch invoices](/fundamentals/subscriptions-and-billing/) and entitlements. | +| Billing {props.editWord} | Grants write access to [billing profile, subscriptions, and access to fetch invoices and entitlements](/fundamentals/subscriptions-and-billing/). | +| Bulk URL Redirects Read | Grants read access to [Bulk URL Redirects](/rules/url-forwarding/bulk-redirects/). | +| Bulk URL Redirects {props.editWord} | Grants write access to [Bulk URL Redirects](/rules/url-forwarding/bulk-redirects/). | +| China Network Steering Read | Grants read access to [China Network Steering](/china-network/). | +| China Network Steering {props.editWord} | Grants write access to [China Network Steering](/china-network/). | +| Cloudchamber Read | Grants read access to Cloudchamber deployments. | +| Cloudchamber {props.editWord} | Grants write access to Cloudchamber deployments. | +| { props.src === "dash" && "Cloudflare" } Calls Read | Grants read access to Cloudflare Calls. | +| { props.src === "dash" && "Cloudflare" } Calls {props.editWord} | Grants write access to Cloudflare Calls. | +| Cloudflare DEX Read | Grants read access to [Digital Experience Monitoring](/cloudflare-one/insights/dex/). | +| Cloudflare DEX {props.editWord} | Grants write access to [Digital Experience Monitoring](/cloudflare-one/insights/dex/). | +| { props.src === "dash" && "Cloudflare" } Images Read | Grants read access to [Cloudflare Images](/images/). | +| { props.src === "dash" && "Cloudflare" } Images {props.editWord} | Grants write access to [Cloudflare Images](/images/). | +| Cloudflare One { props.src === "dash" ? "Connector: cloudflared" : "cloudflared Connectors" } Read | Grants read access to `cloudflared` Connectors | +| Cloudflare One { props.src === "dash" ? "Connector: cloudflared" : "cloudflared Connectors" } {props.editWord} | Grants write access to `cloudflared` Connectors | +| Cloudflare One { props.src === "dash" ? "Connector: WARP" : "Warp Connectors" } Read | Grants read access to Warp Connectors | +| Cloudflare One { props.src === "dash" ? "Connector: WARP" : "Warp Connectors" } {props.editWord} | Grants write access to Warp Connectors | +| Cloudflare One Connectors Read | Grants read access to Cloudflare One Connectors | +| Cloudflare One Connectors {props.editWord} | Grants write access to Cloudflare One Connectors | +| Cloudflare One Networks Read | Grants read access to Cloudflare One Networks | +| Cloudflare One Networks {props.editWord} | Grants write access to Cloudflare One Networks | +| { props.src === "dash" && "Cloudflare" } Pages Read | Grants access to view [Cloudflare Pages](/pages/) projects. | +| { props.src === "dash" && "Cloudflare" } Pages {props.editWord} | Grants access to create, edit and delete [Cloudflare Pages](/pages/) projects. | +| { props.src === "dash" ? "Cloudflare" : "Argo" } Tunnel Read | Grants access to view [Cloudflare Tunnels](/cloudflare-one/connections/connect-networks/). | +| { props.src === "dash" ? "Cloudflare" : "Argo" } Tunnel {props.editWord} | Grants access to create and delete [Cloudflare Tunnels](/cloudflare-one/connections/connect-networks/). | +| Cloudforce One Read | Grants read access to Cloudforce One. | +| Cloudforce One {props.editWord} | Grants write access to Cloudforce One. | +| { props.src === "dash" ? "Email Security" : "Cloud Email Security:" } Read | Grants read access to [Cloud Email Security](/email-security/). | +| { props.src === "dash" ? "Email Security" : "Cloud Email Security:" } {props.editWord} | Grants write access to [Email Security](/email-security/). | +| Constellation Read | Grants read access to [Constellation](/constellation/). | +| Constellation {props.editWord} | Grants write access to [Constellation](/constellation/). | +| D1 Read | Grants read access to [D1](/d1/). | +| D1 {props.editWord} | Grants write access to [D1](/d1/). | +| DDoS Botnet Feed Read | Grants read access to Botnet Feed reports. | +| DDoS Botnet Feed {props.editWord} | Grants write access to Botnet Feed configuration. | +| DDoS Protection Read | Grants read access to [DDoS protection](/ddos-protection/). | +| DDoS Protection {props.editWord} | Grants write access to [DDoS protection](/ddos-protection/). | +| DNS Firewall Read | Grants read access to [DNS Firewall](/dns/dns-firewall/). | +| DNS Firewall {props.editWord} | Grants write access to [DNS Firewall](/dns/dns-firewall/). | +| Email Routing Addresses Read | Grants read access to [Email Routing Addresses](/email-routing/setup/email-routing-addresses/). | +| Email Routing Addresses {props.editWord} | Grants write access to [Email Routing Addresses](/email-routing/setup/email-routing-addresses/). | +| Hyperdrive Read | Grants read access to [Hyperdrive](/hyperdrive/). | +| Hyperdrive {props.editWord} | Grants write access to [Hyperdrive](/hyperdrive/). | +| Intel Read | Grants read access to [Intel](/security-center/intel-apis/). | +| Intel {props.editWord} | Grants write access to [Intel](/security-center/intel-apis/). | +| Integration {props.editWord} | Grants write access to integrations. | +| IOT Read | Grants read access to [IOT](https://blog.cloudflare.com/rethinking-internet-of-things-security/). | +| IOT {props.editWord} | Grants write access to [IOT](https://blog.cloudflare.com/rethinking-internet-of-things-security/). | +| IP Prefixes: Read | Grants access to read IP prefix settings. | +| IP Prefixes: {props.editWord} | Grants access to read/write IP prefix settings. | +| IP Prefixes: BGP On Demand Read | Grants access to read IP prefix BGP configuration. | +| IP Prefixes: BGP On Demand {props.editWord} | Grants access to read and change IP prefix BGP configuration. | +| { props.src === "dash" ? "L3/4" : "L4" } DDoS Managed Ruleset Read | Grants read access to [L3/4 DDoS managed ruleset](/ddos-protection/managed-rulesets/network/). | +| { props.src === "dash" ? "L3/4" : "L4" } DDoS Managed Ruleset {props.editWord} | Grants write access to [L3/4 DDoS managed ruleset](/ddos-protection/managed-rulesets/network/). | +| Load Balancing: Monitors and Pools Read | Grants read access to account level [load balancer resources](/load-balancing/). | +| Load Balancing: Monitors and Pools {props.editWord} | Grants write access to account level [load balancer resources](/load-balancing/). | +| Logs Read | Grants read access to logs using [Logpull or Instant Logs](/logs/). | +| Logs {props.editWord} | Grants read and write access to [Logpull, Logpush, and Instant Logs](/logs/). | +| Magic Firewall Read | Grants read access to [Magic Firewall](/magic-firewall/). | +| Magic Firewall {props.editWord} | Grants write access to [Magic Firewall](/magic-firewall/). | +| Magic Firewall Packet Captures { props.src === "dash" ? "Read" : "- Read PCAPs API" } | Grants read access to [Packet Captures](/magic-firewall/packet-captures/collect-pcaps/). | +| Magic Firewall Packet Captures { props.src === "dash" ? props.editWord : `- ${props.editWord} PCAPs API` } | Grants write access to [Packet Captures](/magic-firewall/packet-captures/collect-pcaps/). | +| Magic Network Monitoring Read | Grants read access to [Magic Network Monitoring](/magic-network-monitoring/). | +| Magic Network Monitoring {props.editWord} | Grants write access to [Magic Network Monitoring](/magic-network-monitoring/). | +| Magic Transit Read | Grants read access to manage a user's [Magic Transit prefixes](/magic-transit/how-to/advertise-prefixes/). | +| Magic Transit {props.editWord} | Grants write access to manage a user's [Magic Transit prefixes](/magic-transit/how-to/advertise-prefixes/). | +| Notifications Read | Grants read access to [Notifications](/notifications/). | +| Notifications {props.editWord} | Grants write access to [Notifications](/notifications/). | +| Page Shield Read | Grants read access to [Page Shield](/page-shield/). | +| Page Shield {props.editWord} | Grants write access to [Page Shield](/page-shield/). | +| { props.src === "dash" && "Workers" } Pipelines Read | Grants read access to Cloudflare Pipelines. | +| { props.src === "dash" && "Workers" } Pipelines {props.editWord} | Grants write access to Cloudflare Pipelines. | +| { props.src === "dash" ? "Pub/Sub" : "Pubsub Configuration" } Read | Grants read access to [Pub/Sub](/pub-sub/). | +| { props.src === "dash" ? "Pub/Sub" : "Pubsub Configuration" } {props.editWord} | Grants write access to [Pub/Sub](/pub-sub/). | +| Queues Read | Grants read access to [Queues](/queues/). | +| Queues {props.editWord} | Grants write access to [Queues](/queues/). | +| Rule Policies Read | Grants read access to Rule Policies. | +| Rule Policies {props.editWord} | Grants write access to Rule Policies. | +| Stream Read | Grants read access to [Cloudflare Stream](/stream/). | +| Stream {props.editWord} | Grants write access to [Cloudflare Stream](/stream/). | +| Transform Rules Read | Grants read access to [Transform Rules](/rules/transform/). | +| Transform Rules {props.editWord} | Grants write access to [Transform Rules](/rules/transform/). | +| Turnstile { props.src === "api" && "Sites" } Read | Grants read access to [Turnstile](/turnstile/). | +| Turnstile { props.src === "api" && "Sites" } {props.editWord} | Grants write access to [Turnstile](/turnstile/). | +| URL Scanner Read | Grants read access to [URL Scanner](/radar/investigate/url-scanner/). | +| URL Scanner {props.editWord} | Grants write access to [URL Scanner](/radar/investigate/url-scanner/). | +| Vectorize Read | Grants read access to [Vectorize](/vectorize/). | +| Vectorize {props.editWord} | Grants write access to [Vectorize](/vectorize/). | +| Workers AI Read | Grants read access to [Workers AI](/workers-ai/). | +| Workers AI {props.editWord} | Grants write access to [Workers AI](/workers-ai/). | +| Workers CI Read | Grants read access to [Workers CI](/workers/). | +| Workers CI {props.editWord} | Grants write access to [Workers CI](/workers). | +| Workers KV Storage Read | Grants read access to [Cloudflare Workers KV Storage](/kv/api/). | +| Workers KV Storage {props.editWord} | Grants write access to [Cloudflare Workers KV Storage](/kv/api/). | +| Workers R2 Storage Read | Grants read access to [Cloudflare R2 Storage](/r2/). | +| Workers R2 Storage {props.editWord} | Grants write access to [Cloudflare R2 Storage](/r2/). | +| Workers Scripts Read | Grants read access to [Cloudflare Workers scripts](/workers/). | +| Workers Scripts {props.editWord} | Grants write access to [Cloudflare Workers scripts](/workers/). | +| Workers Tail Read | Grants [`wrangler tail`](/workers/wrangler/commands/#tail) read permissions. | +| Zero Trust Read | Grants read access to [Cloudflare Zero Trust](/cloudflare-one/). | +| Zero Trust Report | Grants reporting access to [Cloudflare Zero Trust](/cloudflare-one/). | +| Zero Trust {props.editWord} | Grants write access to [Cloudflare Zero Trust](/cloudflare-one/). | +| Zero Trust: PII Read | Grants read access to [Cloudflare Zero Trust](/cloudflare-one/) PII. | +| Zero Trust: Seats {props.editWord} | Grants write access to the number of [Zero Trust Seats](/cloudflare-one/identity/users/seat-management/) your organization can use (and be billed for). | diff --git a/src/content/partials/fundamentals/api-rate-limits.mdx b/src/content/partials/fundamentals/api-rate-limits.mdx index 6dedbcc920153d..26dc6e8f50085e 100644 --- a/src/content/partials/fundamentals/api-rate-limits.mdx +++ b/src/content/partials/fundamentals/api-rate-limits.mdx @@ -10,9 +10,8 @@ | Client API per user | 1200/5 minutes | | Client API per IP | 200/second| | GraphQL | Varies by query cost. Max 320/5 min| -| API token quote[^1] | 500/Account | - -[^1]: The limit applies to both user and account owned API tokens. +| User API token quota | 50 | +| Account API token quota | 500 | :::note The global rate limit for the Cloudflare API is 1200 requests per five minute period per user, and applies cumulatively regardless of whether the request is made via the dashboard, API key, or API token. @@ -26,4 +25,4 @@ Some specific API calls have their own limits and are documented separately, suc * [GraphQL APIs](/analytics/graphql-api/limits/) * [Rulesets APIs](/ruleset-engine/rulesets-api/#limits) -Enterprise customers can also [contact Cloudflare Support](/support/contacting-cloudflare-support/) to raise the limit to a higher value. +Enterprise customers can also [contact Cloudflare Support](/support/contacting-cloudflare-support/) to raise the Client API per user, GraphQL, or API token limits to a higher value. diff --git a/src/content/partials/fundamentals/what-is-cloudflare.mdx b/src/content/partials/fundamentals/what-is-cloudflare.mdx index f3b9a0078439d5..c3ee7b5b5a41f1 100644 --- a/src/content/partials/fundamentals/what-is-cloudflare.mdx +++ b/src/content/partials/fundamentals/what-is-cloudflare.mdx @@ -5,7 +5,7 @@ import { Stream } from "~/components" - + Cloudflare is one of the world's largest [connectivity cloud networks](https://blog.cloudflare.com/welcome-to-connectivity-cloud). Today, anyone with an Internet presence can have faster and more secure websites and applications thanks to Cloudflare. This includes bloggers, businesses, and even non-profits. diff --git a/src/content/partials/fundamentals/zone-permissions-table.mdx b/src/content/partials/fundamentals/zone-permissions-table.mdx index 6a7d0b25597c53..3cc1f71892bd26 100644 --- a/src/content/partials/fundamentals/zone-permissions-table.mdx +++ b/src/content/partials/fundamentals/zone-permissions-table.mdx @@ -1,83 +1,82 @@ --- -inputParameters: editWord - +params: + - editWord + - src --- -import { Markdown } from "~/components" +import { Markdown } from "~/components"; -| Name | Description | -| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| Access: Apps and Policies Read | Grants read access to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | -| Access: Apps and Policies Revoke | Grants ability to revoke all tokens to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | -| Access: Apps and Policies {props.one} | Grants write access to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | -| Analytics Read | Grants read access to [analytics](/analytics/account-and-zone-analytics/zone-analytics/). | -| API Gateway Read | Grants read access to [API Gateway](/api-shield/) zone resources. | -| API Gateway {props.one} | Grants write access to [API Gateway](/api-shield/) zone resources. | -| Apps {props.one} | Grants full access to [Cloudflare Apps](/support/more-dashboard-apps/cloudflare-apps/). | -| Bot Management Read | Grants read access to [Bot Management](/bots/plans/bm-subscription/). | -| Bot Management {props.one} | Grants write access to [Bot Management](/bots/plans/bm-subscription/). | -| Bot Management Feedback Read | Grants read access to [Bot Management feedback](/bots/concepts/feedback-loop/). | -| Bot Management Feedback {props.one} | Grants write access to [Bot Management feedback](/bots/concepts/feedback-loop/). | -| Cache Purge | Grants access to [purge cache](/cache/how-to/purge-cache/). | -| Cache Rules Read | Grants read access to [Cache Rules](/cache/how-to/cache-rules/). | -| Cache Rules {props.one} | Grants write access to [Cache Rules](/cache/how-to/cache-rules/). | -| Cloud Connector Read | Grants read access to [Cloud Connector rules](/rules/cloud-connector/). | -| Cloud Connector {props.one} | Grants write access to [Cloud Connector rules](/rules/cloud-connector/). | | -| Config Rules Read | Grants read access to [Configuration Rules](/rules/configuration-rules/). | -| Config Rules {props.one} | Grants write access to [Configuration Rules](/rules/configuration-rules/). | -| Custom Errors Read | Grants read access to [Custom Errors phase](/rules/custom-errors/create-api/). | -| Custom Errors {props.one} | Grants write access to [Custom Errors phase](/rules/custom-errors/create-api/). | -| Custom Error Rules Read | Grants read access to [Custom Error Rules](/rules/custom-errors/). | -| Custom Error Rules {props.one} | Grants write access to [Custom Error Rules](/rules/custom-errors/). | -| Custom Pages Read | Grants read access to [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | -| Custom Pages {props.one} | Grants write access to [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | -| DMARC Management Read | Grants read access to [DMARC Management](/dmarc-management/). | -| DMARC Management {props.one} | Grants write access to [DMARC Management](/dmarc-management/). | -| DNS Read | Grants read access to [DNS](/dns/). | -| DNS Write | Grants write access to [DNS](/dns/). | -| Email Routing Rules Read | Grants read access to [Email Routing Rules](/email-routing/setup/email-routing-addresses/). | -| Email Routing Rules {props.one} | Grants write access to [Email Routing Rules](/email-routing/setup/email-routing-addresses/). | -| Firewall Services Read | Grants read access to Firewall resources. | -| Firewall Services {props.one} | Grants write access to Firewall resources. | -| Health Checks Read | Grants read access to [Health Checks](/health-checks/). | -| Health Checks {props.one} | Grants write access to [Health Checks](/health-checks/). | -| HTTP DDoS Managed Ruleset Read | Grants read access to [HTTP DDoS managed ruleset](/ddos-protection/managed-rulesets/http/). | -| HTTP DDoS Managed Ruleset {props.one} | Grants write access to [HTTP DDoS managed ruleset](/ddos-protection/managed-rulesets/http/). | -| Load Balancers Read | Grants read access to [load balancer resources](/load-balancing/). | -| Load Balancers {props.one} | Grants write access to [load balancer resources](/load-balancing/). | -| Logs Read | Grants read access to logs using [Logpull](/logs/). | -| Logs {props.one} | Grants write access to [Logpull and Logpush](/logs/). | -| Managed Headers Read | Grants read access to [Managed Headers](/rules/transform/managed-transforms/). | -| Managed Headers {props.one} | Grants write access to [Managed Headers](/rules/transform/managed-transforms/). | -| Origin Rules Read | Grants read access to [Origin Rules](/rules/origin-rules/). | -| Origin Rules {props.one} | Grants write access to [Origin Rules](/rules/origin-rules/). | -| Page Rules Read | Grants read access to [Page Rules](/rules/page-rules/). | -| Page Rules {props.one} | Grants write access to [Page Rules](/rules/page-rules/). | -| Page Shield Read | Grants read access to [Page Shield](/page-shield/). | -| Page Shield {props.one} | Grants write access to [Page Shield](/page-shield/). | -| Response Compression Read | Grants read access to [Response Compression](/rules/compression-rules/). | -| Response Compression {props.one} | Grants write access to [Response Compression](/rules/compression-rules/). | -| Sanitize Read | Grants read access to sanitization. | -| Sanitize {props.one} | Grants write access to sanitization. | -| Single Redirect Read | Grants read access to zone-level [Single Redirects](/rules/url-forwarding/single-redirects/). | -| Single Redirect {props.one} | Grants write access to zone-level [Single Redirects](/rules/url-forwarding/single-redirects/). | -| SSL and Certificates Read | Grants read access to [SSL configuration and certificate management](/ssl/). | -| SSL and Certificates {props.one} | Grants write access to [SSL configuration and certificate management](/ssl/). | -| Transform Rules Read | Grants read access to [Transform Rules](/rules/transform/). | -| Transform Rules {props.one} | Grants write access to [Transform Rules](/rules/transform/). | -| Waiting Room Read | Grants read access to [Waiting Room](/waiting-room/). | -| Waiting Room {props.one} | Grants write access to [Waiting Room](/waiting-room/). | -| Web3 Hostnames Read | Grants read access to [Web3 Hostnames](/web3/). | -| Web3 Hostnames {props.one} | Grants write access to [Web3 Hostnames](/web3/). | -| Workers Routes Read | Grants read access to [Cloudflare Workers](/workers/) and [Workers KV Storage](/kv/api/). | -| Workers Routes {props.one} | Grants write access to [Cloudflare Workers](/workers/) and [Workers KV Storage](/kv/api/). | -| Zaraz Read | Grants read access to [Zaraz](/zaraz/) zone level settings. | -| Zaraz {props.one} | Grants write access to [Zaraz](/zaraz/) zone level settings. | -| Zone Read | Grants read access to zone management. | -| Zone {props.one} | Grants write access to zone management. | -| Zone Settings Read | Grants read access to zone settings. | -| Zone Settings {props.one} | Grants write access to zone settings. | -| Zone Versioning Read | Grants read access to [Zone Versioning](/version-management/) at zone level. | -| Zone Versioning {props.one} | Grants write access to [Zone Versioning](/version-management/) at zone level. | -| Zone WAF Read | Grants read access to [Zone WAF](/waf/). | -| Zone WAF {props.one} | Grants write access to [Zone WAF](/waf/). | +| Name | Description | +| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| Access: Apps and Policies Read | Grants read access to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | +| Access: Apps and Policies Revoke | Grants ability to revoke all tokens to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | +| Access: Apps and Policies {props.editWord} | Grants write access to [Cloudflare Access](/cloudflare-one/policies/access/) zone resources. | +| Analytics Read | Grants read access to [analytics](/analytics/account-and-zone-analytics/zone-analytics/). | +| { props.src === "api" && "Domain" } API Gateway Read | Grants read access to [API Gateway](/api-shield/) zone resources. | +| { props.src === "api" && "Domain" } API Gateway {props.editWord} | Grants write access to [API Gateway](/api-shield/) zone resources. | +| Apps {props.editWord} | Grants full access to [Cloudflare Apps](/support/more-dashboard-apps/cloudflare-apps/). | +| Bot Management Read | Grants read access to [Bot Management](/bots/plans/bm-subscription/). | +| Bot Management {props.editWord} | Grants write access to [Bot Management](/bots/plans/bm-subscription/). | +| Bot Management Feedback Read | Grants read access to [Bot Management feedback](/bots/concepts/feedback-loop/). | +| Bot Management Feedback {props.editWord} | Grants write access to [Bot Management feedback](/bots/concepts/feedback-loop/). | +| Cache Purge | Grants access to [purge cache](/cache/how-to/purge-cache/). | +| Cache { props.src === "dash" ? "Rules" : "Settings" } Read | Grants read access to [Cache Rules](/cache/how-to/cache-rules/). | +| Cache { props.src === "dash" ? "Rules" : "Settings" } {props.editWord} | Grants write access to [Cache Rules](/cache/how-to/cache-rules/). | +| Cloud Connector Read | Grants read access to [Cloud Connector rules](/rules/cloud-connector/). | +| Cloud Connector {props.editWord} | Grants write access to [Cloud Connector rules](/rules/cloud-connector/). | +| Config { props.src === "dash" ? "Rules" : "Settings" } Read | Grants read access to [Configuration Rules](/rules/configuration-rules/). | +| Config { props.src === "dash" ? "Rules" : "Settings" } {props.editWord} | Grants write access to [Configuration Rules](/rules/configuration-rules/). | +| Custom { props.src === "dash" ? "Error Rules" : "Errors" } Read | Grants read access to [Custom Error Rules](/rules/custom-errors/). | +| Custom { props.src === "dash" ? "Error Rules" : "Errors" } {props.editWord} | Grants write access to [Custom Error Rules](/rules/custom-errors/). | +| Custom Pages Read | Grants read access to [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | +| Custom Pages {props.editWord} | Grants write access to [Custom Pages](/support/more-dashboard-apps/cloudflare-custom-pages/configuring-custom-pages-error-and-challenge/). | +| { props.src === "dash" ? "Dmarc Management" : "Email Security DMARC Reports" } Read | Grants read access to [DMARC Management](/dmarc-management/). | +| { props.src === "dash" ? "Dmarc Management" : "Email Security DMARC Reports" } {props.editWord} | Grants write access to [DMARC Management](/dmarc-management/). | +| DNS Read | Grants read access to [DNS](/dns/). | +| DNS Write | Grants write access to [DNS](/dns/). | +| Email Routing Rules Read | Grants read access to [Email Routing Rules](/email-routing/setup/email-routing-addresses/). | +| Email Routing Rules {props.editWord} | Grants write access to [Email Routing Rules](/email-routing/setup/email-routing-addresses/). | +| Firewall Services Read | Grants read access to Firewall resources. | +| Firewall Services {props.editWord} | Grants write access to Firewall resources. | +| Health Checks Read | Grants read access to [Health Checks](/health-checks/). | +| Health Checks {props.editWord} | Grants write access to [Health Checks](/health-checks/). | +| HTTP DDoS Managed Ruleset Read | Grants read access to [HTTP DDoS managed ruleset](/ddos-protection/managed-rulesets/http/). | +| HTTP DDoS Managed Ruleset {props.editWord} | Grants write access to [HTTP DDoS managed ruleset](/ddos-protection/managed-rulesets/http/). | +| Load Balancers Read | Grants read access to [load balancer resources](/load-balancing/). | +| Load Balancers {props.editWord} | Grants write access to [load balancer resources](/load-balancing/). | +| Logs Read | Grants read access to logs using [Logpull](/logs/). | +| Logs {props.editWord} | Grants write access to [Logpull and Logpush](/logs/). | +| Managed { props.src === "dash" ? "Headers" : "headers" } Read | Grants read access to [Managed Headers](/rules/transform/managed-transforms/). | +| Managed { props.src === "dash" ? "Headers" : "headers" } {props.editWord} | Grants write access to [Managed Headers](/rules/transform/managed-transforms/). | +| Origin { props.src === "dash" && "Rules" } Read | Grants read access to [Origin Rules](/rules/origin-rules/). | +| Origin { props.src === "dash" && "Rules" } {props.editWord} | Grants write access to [Origin Rules](/rules/origin-rules/). | +| Page Rules Read | Grants read access to [Page Rules](/rules/page-rules/). | +| Page Rules {props.editWord} | Grants write access to [Page Rules](/rules/page-rules/). | +| { props.src === "api" && "Domain" } Page Shield Read | Grants read access to [Page Shield](/page-shield/). | +| { props.src === "api" && "Domain" } Page Shield {props.editWord} | Grants write access to [Page Shield](/page-shield/). | +| Response Compression Read | Grants read access to [Response Compression](/rules/compression-rules/). | +| Response Compression {props.editWord} | Grants write access to [Response Compression](/rules/compression-rules/). | +| Sanitize Read | Grants read access to sanitization. | +| Sanitize {props.editWord} | Grants write access to sanitization. | +| { props.src === "dash" ? "Single Redirect" : "Dynamic URL Redirects" } Read | Grants read access to zone-level [Single Redirects](/rules/url-forwarding/single-redirects/). | +| { props.src === "dash" ? "Single Redirect" : "Dynamic URL Redirects" } {props.editWord} | Grants write access to zone-level [Single Redirects](/rules/url-forwarding/single-redirects/). | +| SSL and Certificates Read | Grants read access to [SSL configuration and certificate management](/ssl/). | +| SSL and Certificates {props.editWord} | Grants write access to [SSL configuration and certificate management](/ssl/). | +| { props.src === "api" && "Zone" } Transform Rules Read | Grants read access to [Transform Rules](/rules/transform/). | +| { props.src === "api" && "Zone" } Transform Rules {props.editWord} | Grants write access to [Transform Rules](/rules/transform/). | +| Waiting { props.src === "dash" ? "Room" : "Rooms" } Read | Grants read access to [Waiting Room](/waiting-room/). | +| Waiting { props.src === "dash" ? "Room" : "Rooms" } {props.editWord} | Grants write access to [Waiting Room](/waiting-room/). | +| Web3 Hostnames Read | Grants read access to [Web3 Hostnames](/web3/). | +| Web3 Hostnames {props.editWord} | Grants write access to [Web3 Hostnames](/web3/). | +| Workers Routes Read | Grants read access to [Cloudflare Workers](/workers/) and [Workers KV Storage](/kv/api/). | +| Workers Routes {props.editWord} | Grants write access to [Cloudflare Workers](/workers/) and [Workers KV Storage](/kv/api/). | +| Zaraz Read | Grants read access to [Zaraz](/zaraz/) zone level settings. | +| Zaraz {props.editWord} | Grants write access to [Zaraz](/zaraz/) zone level settings. | +| Zone Read | Grants read access to zone management. | +| Zone {props.editWord} | Grants write access to zone management. | +| Zone Settings Read | Grants read access to zone settings. | +| Zone Settings {props.editWord} | Grants write access to zone settings. | +| Zone Versioning Read | Grants read access to [Zone Versioning](/version-management/) at zone level. | +| Zone Versioning {props.editWord} | Grants write access to [Zone Versioning](/version-management/) at zone level. | +| Zone WAF Read | Grants read access to [Zone WAF](/waf/). | +| Zone WAF {props.editWord} | Grants write access to [Zone WAF](/waf/). | diff --git a/src/content/partials/hyperdrive/create-hyperdrive-binding.mdx b/src/content/partials/hyperdrive/create-hyperdrive-binding.mdx index 7dd4b922bb6bf2..980827207f1a11 100644 --- a/src/content/partials/hyperdrive/create-hyperdrive-binding.mdx +++ b/src/content/partials/hyperdrive/create-hyperdrive-binding.mdx @@ -24,3 +24,24 @@ Specifically: - The value (string) you set for the `name` (binding name) will be used to reference this database in your Worker. In this tutorial, name your binding `HYPERDRIVE`. - The binding must be [a valid JavaScript variable name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#variables). For example, `binding = "hyperdrive"` or `binding = "productionDB"` would both be valid names for the binding. - Your binding is available in your Worker at `env.`. + + +If you wish to use a local database during development, you can add a `localConnectionString` to your Hyperdrive configuration with the connection string of your database: + + + + +```toml +[[hyperdrive]] +binding = "HYPERDRIVE" +id = "" # the ID associated with the Hyperdrive you just created +localConnectionString = "" +``` + + + +:::note + +Learn more about setting up [Hyperdrive for local development](/hyperdrive/configuration/local-development/). + +::: \ No newline at end of file diff --git a/src/content/partials/images/background.mdx b/src/content/partials/images/background.mdx index 138e20cf4ef399..621694bb039f2b 100644 --- a/src/content/partials/images/background.mdx +++ b/src/content/partials/images/background.mdx @@ -13,11 +13,19 @@ Background color to add underneath the image. Applies to images with transparenc OR background=red - ``` + + OR + + background= rgb%28240%2C40%2C145%29 + ``` ```js cf: {image: {background: "#RRGGBB"}} + + OR + + cf:{image: {background: "rgba(240,40,145,0)"}} ``` diff --git a/src/content/partials/images/flip.mdx b/src/content/partials/images/flip.mdx new file mode 100644 index 00000000000000..e73e62937c7f99 --- /dev/null +++ b/src/content/partials/images/flip.mdx @@ -0,0 +1,27 @@ +--- +{} +--- +import { Tabs, TabItem } from "~/components" + +Flips the image horizontally, vertically, or both. Can be used with the `rotate` parameter to set the orientation of an image. + +Flipping is performed before rotation. For example, if you apply `flip=h,rotate=90,` then the image will be flipped horizontally, then rotated by 90 degrees. + +Available options are: + +- `h`: Flips the image horizontally. +- `v`: Flips the image vertically. +- `hv`: Flips the image vertically and horizontally. + + + + ```js + flip=h + ``` + + + ```js + cf: {image: {flip: "h"}} + ``` + + diff --git a/src/content/partials/images/quality.mdx b/src/content/partials/images/quality.mdx index 1e3d7ed0c414e4..3a7dadd45c92dc 100644 --- a/src/content/partials/images/quality.mdx +++ b/src/content/partials/images/quality.mdx @@ -9,20 +9,34 @@ At the moment, this setting only works directly with [image transformations](/im Specifies quality for images in JPEG, WebP, and AVIF formats. The quality is in a 1-100 scale, but useful values are between `50` (low quality, small file size) and `90` (high quality, large file size). `85` is the default. When using the PNG format, an explicit quality setting allows use of PNG8 (palette) variant of the format. +We also allow setting one of the perceptual quality levels `high|medium-high|medium-low|low` + ```js quality=50 + + OR + + quality=low ``` ```js q=50 + + OR + + q=medium-high ``` ```js cf: {image: {quality: 50}} + + OR + + cf: {image: {quality: "high"}} ``` - \ No newline at end of file + diff --git a/src/content/partials/images/slow-connection-quality.mdx b/src/content/partials/images/slow-connection-quality.mdx new file mode 100644 index 00000000000000..373fd499229340 --- /dev/null +++ b/src/content/partials/images/slow-connection-quality.mdx @@ -0,0 +1,43 @@ +--- +{} +--- +import { Tabs, TabItem } from "~/components" + +:::note[Note] +At the moment, this setting only works directly with [image transformations](/images/transform-images/). +::: + +Allows overriding `quality` value whenever a slow connection is detected. + +Available options are same as [quality](/images/transform-images/transform-via-url/#quality). + + + + ```js + slow-connection-quality=50 + ``` + + + ```js + scq=50 + ``` + + + +Detecting slow connections is currently only supported on Chromium-based browsers such as Chrome, Edge, and Opera. + +You can enable any of the following client hints via HTTP in a header + +```txt +accept-ch: rtt, save-data, ect, downlink +``` + +slow-connection-quality applies whenever any of the following is true and the client hint is present: + +- [rtt](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/RTT): Greater than 150ms. + +- [save-data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Save-Data): Value is "on". + +- [ect](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ECT): Value is one of `slow-2g|2g|3g`. + +- [downlink](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Downlink): Less than 5Mbps. \ No newline at end of file diff --git a/src/content/partials/kv/tutorials-wrangler-v1-warning.mdx b/src/content/partials/kv/tutorials-wrangler-v1-warning.mdx deleted file mode 100644 index 66218f6c9bc260..00000000000000 --- a/src/content/partials/kv/tutorials-wrangler-v1-warning.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -{} - ---- - -:::caution - - -This tutorial was developed with Wrangler v1, which has now been deprecated. Refer to [Migration to Wrangler v2](/workers/wrangler/migration/v1-to-v2/) for instructions on how to upgrade to the latest version. - - -::: diff --git a/src/content/partials/learning-paths/china-network-overview-additional-resources.mdx b/src/content/partials/learning-paths/china-network-overview-additional-resources.mdx new file mode 100644 index 00000000000000..f15999e994d4ae --- /dev/null +++ b/src/content/partials/learning-paths/china-network-overview-additional-resources.mdx @@ -0,0 +1,13 @@ +--- +{} + +--- + +**Related content** + +For additional resources on the China Network, refer to the following resources: + + - [Cloudflare China Network](/china-network/) + - [CDN Global Acceleration (formerly China Express)](/china-network/concepts/global-acceleration/) + - [Internet Content Provider (ICP)](/china-network/concepts/icp/) + - [Authoritative DNS in mainland China](/china-network/concepts/china-dns/) \ No newline at end of file diff --git a/src/content/partials/learning-paths/china-network-overview-navigation.mdx b/src/content/partials/learning-paths/china-network-overview-navigation.mdx new file mode 100644 index 00000000000000..a7cd1e71ea5eda --- /dev/null +++ b/src/content/partials/learning-paths/china-network-overview-navigation.mdx @@ -0,0 +1,20 @@ +--- +{} + +--- + +import { CardGrid, LinkCard, Card } from "~/components"; + + + + + + diff --git a/src/content/partials/learning-paths/durable-objects-series-additional-resources.mdx b/src/content/partials/learning-paths/durable-objects-series-additional-resources.mdx new file mode 100644 index 00000000000000..68429e629704f2 --- /dev/null +++ b/src/content/partials/learning-paths/durable-objects-series-additional-resources.mdx @@ -0,0 +1,15 @@ +--- +{} + +--- + +**Related content** + +For additional resources on learning Durable Objects with Cloudflare, refer to the following resources: + + - [Veet Github repository code](https://github.com/megaconfidence/veet) + - [Cloudflare Durable Objects documentation](/durable-objects/) + - [Cloudflare TURN service documentation](/calls/turn/) + - [CLI command for creating new Workers and Pages projects](/pages/get-started/c3/) + - [Hopscotch.io for local WebSocket testing](https://hoppscotch.io/) + - [Sign up for a Cloudflare account](https://dash.cloudflare.com/sign-up) diff --git a/src/content/partials/learning-paths/durable-objects-series-navigation.mdx b/src/content/partials/learning-paths/durable-objects-series-navigation.mdx new file mode 100644 index 00000000000000..036a1f7590e9c2 --- /dev/null +++ b/src/content/partials/learning-paths/durable-objects-series-navigation.mdx @@ -0,0 +1,51 @@ +--- +{} + +--- + +import { CardGrid, LinkCard, Card } from "~/components"; + + + + + + + + + + + + + + + + + diff --git a/src/content/partials/learning-paths/limit-external-connections-application.mdx b/src/content/partials/learning-paths/limit-external-connections-application.mdx index 9b7e85631fc3bc..a29fc826f704e0 100644 --- a/src/content/partials/learning-paths/limit-external-connections-application.mdx +++ b/src/content/partials/learning-paths/limit-external-connections-application.mdx @@ -23,7 +23,7 @@ Only allow traffic with specific (and secret) HTTP headers. * **Challenges**: * Requires more configuration efforts on application- and server-side to accept those headers. * Basic authentication is vulnerable to replay attacks. Because basic authentication does not encrypt user credentials, it is important that traffic always be sent over an encrypted SSL session. - * There might be valid use cases for a mismatch in SNI / Host headers such as through [Page Rules](/rules/page-rules/how-to/rewrite-host-headers/), [Load Balancing](/load-balancing/additional-options/override-http-host-headers/), or [Workers](/workers/runtime-apis/request/), which all offer HTTP Host Header overrides. + * There might be valid use cases for a mismatch in SNI / Host headers such as through [Origin or Page Rules](/rules/origin-rules/features/), [Load Balancing](/load-balancing/additional-options/override-http-host-headers/), or [Workers](/workers/runtime-apis/request/), which all offer HTTP Host Header overrides. * **Process**: 1. Use [Transform rules](/rules/transform/request-header-modification/) or [Workers](/workers/examples/alter-headers/) to add an HTTP Auth Header. 2. Configure your origin server to restrict access based on the [HTTP Auth Header](/workers/examples/auth-with-headers/) (or perform [HTTP Basic Authentication](/workers/examples/basic-auth/)). diff --git a/src/content/partials/learning-paths/sase-series-navigation.mdx b/src/content/partials/learning-paths/sase-series-navigation.mdx new file mode 100644 index 00000000000000..c9ac5dace4ee29 --- /dev/null +++ b/src/content/partials/learning-paths/sase-series-navigation.mdx @@ -0,0 +1,40 @@ +--- +{} + +--- + +import { CardGrid, LinkCard, Card } from "~/components"; + + + + + + + + + + + + + diff --git a/src/content/partials/learning-paths/zero-trust/device-profiles.mdx b/src/content/partials/learning-paths/zero-trust/device-profiles.mdx index 411b106ccc846e..ae3e49c976d3bd 100644 --- a/src/content/partials/learning-paths/zero-trust/device-profiles.mdx +++ b/src/content/partials/learning-paths/zero-trust/device-profiles.mdx @@ -48,9 +48,8 @@ To customize the default settings: ```bash curl --request PATCH \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/policy \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "allow_mode_switch": false, @@ -72,9 +71,8 @@ https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/policy \ ```bash curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/devices/settings \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ +https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/settings \ +--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "disable_for_time": 3600, diff --git a/src/content/partials/load-balancing/route-production-traffic.mdx b/src/content/partials/load-balancing/route-production-traffic.mdx index 02124e0289e27c..3e1b688df82eeb 100644 --- a/src/content/partials/load-balancing/route-production-traffic.mdx +++ b/src/content/partials/load-balancing/route-production-traffic.mdx @@ -14,7 +14,7 @@ Now that you have set up your load balancer and verified everything is working c :::note -If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [origin rule](/rules/origin-rules/features/#dns-record) or [page rule](/rules/page-rules/how-to/override-url-or-ip-address/). +If you have an Enterprise account, also evaluate your application for any excluded paths. For example, you might not want the load balancer to distribute requests directed at your `/admin` path. For any exceptions, set up an [origin rule](/rules/origin-rules/features/#dns-record). ::: diff --git a/src/content/partials/logs/log-explorer-account-datasets.mdx b/src/content/partials/logs/log-explorer-account-datasets.mdx new file mode 100644 index 00000000000000..7ea31e6c8d486c --- /dev/null +++ b/src/content/partials/logs/log-explorer-account-datasets.mdx @@ -0,0 +1,11 @@ +--- +{} +--- + +- [Access requests](/logs/reference/log-fields/account/access_requests/) (`FROM access_requests`) +- [CASB Findings](/logs/reference/log-fields/account/casb_findings/) (`FROM casb_findings`) +- [Device posture results](/logs/reference/log-fields/account/device_posture_results/) (`FROM device_posture_results`) +- [Gateway DNS](/logs/reference/log-fields/account/gateway_dns/) (`FROM gateway_dns`) +- [Gateway HTTP](/logs/reference/log-fields/account/gateway_http/) (`FROM gateway_http`) +- [Gateway Network](/logs/reference/log-fields/account/gateway_network/) (`FROM gateway_network`) +- [Zero Trust Network Session Logs](/logs/reference/log-fields/account/zero_trust_network_sessions/) (`FROM zero_trust_network_sessions`) diff --git a/src/content/partials/logs/video-send-network-analytics-logs-to-splunk.mdx b/src/content/partials/logs/video-send-network-analytics-logs-to-splunk.mdx index 2c6075095f5ca4..a936f6036849b1 100644 --- a/src/content/partials/logs/video-send-network-analytics-logs-to-splunk.mdx +++ b/src/content/partials/logs/video-send-network-analytics-logs-to-splunk.mdx @@ -9,4 +9,4 @@ import { Stream } from "~/components" The following video shows how to integrate [Network Analytics logs](/logs/reference/log-fields/account/network_analytics_logs/) in Splunk. - + diff --git a/src/content/partials/magic-cloud-networking/magic-wan-on-ramps.mdx b/src/content/partials/magic-cloud-networking/magic-wan-on-ramps.mdx index 5a30b4416df1cc..9bce18be4a951b 100644 --- a/src/content/partials/magic-cloud-networking/magic-wan-on-ramps.mdx +++ b/src/content/partials/magic-cloud-networking/magic-wan-on-ramps.mdx @@ -41,7 +41,7 @@ Choose this option if you have a single virtual private cloud (VPC) in your clou 4. Go to **Connect an existing VPC to Cloudflare** > **Select**. 5. Give your new on-ramp a name and a description (optional), then select **Continue**. 6. From the drop-down menu, choose your cloud provider. You can choose between AWS, GCP and Azure. Then, select **Continue**. -7. Select the network that you want to connect to. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/#2-set-up-cloud-integrations) you have already set up. When you are done, select **Continue**. +7. Select the network that you want to connect to. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/) you have already set up. When you are done, select **Continue**. 8. **Configure route propagation** shows where Cloudflare will install the new routes. Installing these routes is required to correctly configure both Magic WAN and your cloud provider, and ensure successful communication between them: - **Add routes for your Magic WAN address space to your cloud network**: Select this option to install routes for reaching Magic WAN in your cloud network's route tables (refer to [Magic WAN Address Space](#magic-wan-address-space) to learn what routes are installed and how to customize them). If you prefer to do this manually, unselect this option. :::caution[Warning] @@ -75,7 +75,7 @@ When you configure a hub on-ramp, Cloudflare always manages the VPN tunnel betwe 4. Go to **Connect an existing hub to Cloudflare** > **Select**. 5. Give your new on-ramp a name and a description (optional), then select **Continue**. 6. From the drop-down menu, choose your cloud provider. You can choose between AWS, GCP, and Azure. Then, select **Continue**. -7. Choose an existing hub. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/#2-set-up-cloud-integrations) you have already set up. When you are done, select **Continue**. +7. Choose an existing hub. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/) you have already set up. When you are done, select **Continue**. 8. (*Optional*) In **VPC peering configuration**, you can enable **Manage VPC peering**. This allows Cloudflare to attach your chosen VPCs to the hub: 1. Select **Manage VPC peering** to enable this feature. 2. Choose the VPCs you want Cloudflare to attach to the hub. @@ -104,7 +104,7 @@ You have successfully created your Magic WAN on-ramp. However, on-ramp creation 5. Give your new on-ramp a name and a description (optional), then select **Continue**. 6. Configure your cloud in **Select your cloud details**: 1. From the drop-down menu, choose your cloud provider. You can choose between AWS, GCP, and Azure. - 2. Choose an existing integration. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/#2-set-up-cloud-integrations) you have already set up. + 2. Choose an existing integration. This list comes from the [cloud integrations](/magic-cloud-networking/get-started/) you have already set up. 3. Choose a region in which to create the new hub. 4. Select **Continue**. 7. (*Optional*) In **VPC peering configuration**, you can enable **Manage VPC peering**. This allows Cloudflare to attach your chosen VPCs to the hub: diff --git a/src/content/partials/magic-transit/static-routes.mdx b/src/content/partials/magic-transit/static-routes.mdx index 9036c0e4571daa..27ef8df7a2343d 100644 --- a/src/content/partials/magic-transit/static-routes.mdx +++ b/src/content/partials/magic-transit/static-routes.mdx @@ -8,10 +8,9 @@ params: - magicWANecmp? - createPath - tunnelEndpoints - - ipRanges? --- -import { GlossaryTooltip, Markdown, AnchorHeading, Render, TabItem, Tabs } from "~/components"; +import { APIRequest, Aside, GlossaryTooltip, Markdown, AnchorHeading, Render, TabItem, Tabs } from "~/components"; :::note If you are connecting to Cloudflare via a [Direct CNI connection](/network-interconnect/express-cni/), refer to
    BGP peering to learn how to take advantage of this [routing](https://www.cloudflare.com/learning/network-layer/what-is-routing/) protocol. If not, continue reading. @@ -68,6 +67,29 @@ In the example below, `TUNNEL_2_IAD` is likely to receive twice as much traffic ) } +{ props.magicProduct === "Magic Transit" && ( + <> + + + + + ) +} + ## Scoped routes for anycast GRE or IPsec tunnels To reduce latency for your anycast GRE or IPsec tunnel configurations, especially if you operate your own anycast network, Cloudflare can steer your traffic by scoping it to specific Cloudflare data center regions. Equal cost routes maintain an equal cost on a global scale so long as the routes are not scoped to specific regions. For example, if you use region-scoped routes, traffic from end users in New York will always land at their Ashburn network unless that tunnel is unhealthy. @@ -107,17 +129,42 @@ Cloudflare has nine geographic regions across the world which are listed below. Configure scoping for your traffic in the **Region code** section when adding or editing a static route. Refer to [Create a static route](#create-a-static-route) and [Edit a static route](#edit-a-static-route) more information. -## Allowed IP ranges +{ props.magicProduct === "Magic Transit" && ( + <> + + + + ) +} + +{ props.magicProduct === "Magic WAN" && ( + <> + + + + ) +} - -If your use case requires IP prefixes outside RFC 1918, contact your Cloudflare -customer service manager. ## Create a static route @@ -143,30 +190,63 @@ Create a `POST` request [using the API](/api/resources/magic_transit/subresource Example: -```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/routes \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "routes": [ +", + "prefix": "", + "priority": 0, + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "", + "scope": { + "colo_names": [ + "den01" + ], + "colo_regions": [ + "APAC" + ] + }, + "weight": 0 + }} +/> + +```json output +{ + "errors": [ { - "description": "New route for new prefix", - "prefix": "", - "nexthop": "", - "priority": , - "scope": { - "colo_names": [ - "" - ], - "colo_regions": [ - "" - ] - }, - "weight": + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" } - ] -}' + ], + "result": { + "routes": [ + { + "nexthop": "203.0.113.1", + "prefix": "192.0.2.0/24", + "priority": 0, + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "New route for new prefix 203.0.113.1", + "scope": { + "colo_names": [ + "den01" + ], + "colo_regions": [ + "APAC" + ] + }, + "weight": 0 + } + ] + }, + "success": true +} ``` @@ -184,35 +264,66 @@ curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/routes \ -Create a `PUT` request [using the API](/api/resources/magic_transit/subresources/routes/methods/bulk_update/) to update one or more static routes. +Create a `PUT` request [using the API](/api/resources/magic_transit/subresources/routes/methods/update/) to update one or more static routes. Example: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/routes \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "routes": [ +", + "prefix": "", + "priority": 0, + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "", + "scope": { + "colo_names": [ + "den01" + ], + "colo_regions": [ + "APAC" + ] + }, + "weight": 0 + }} +/> + +```json output +{ + "errors": [ { - "description": "New route for new prefix", - "nexthop": "", - "prefix": "", - "priority": , + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" + } + ], + "result": { + "modified": true, + "modified_route": { + "nexthop": "203.0.113.1", + "prefix": "192.0.2.0/24", + "priority": 0, + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "New route for new prefix 203.0.113.1", "scope": { "colo_names": [ - "" + "den01" ], "colo_regions": [ - "" + "APAC" ] }, - "weight": + "weight": 0 } - ] -}' + }, + "success": true +} ``` @@ -232,11 +343,46 @@ Create a `DELETE` request [using the API](/api/resources/magic_transit/subresour Example: -```bash -curl --request DELETE \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/routes/{route_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " + + +```json output +{ + "errors": [ + { + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" + } + ], + "result": { + "deleted": true, + "deleted_route": { + "nexthop": "203.0.113.1", + "prefix": "192.0.2.0/24", + "priority": 0, + "id": "023e105f4ecef8ad9ca31a8372d0c353", + "description": "New route for new prefix 203.0.113.1", + "scope": { + "colo_names": [ + "den01" + ], + "colo_regions": [ + "APAC" + ] + }, + "weight": 0 + } + }, + "success": true +} ``` diff --git a/src/content/partials/magic-transit/tunnel-endpoints/add-tunnels.mdx b/src/content/partials/magic-transit/tunnel-endpoints/add-tunnels.mdx index 831b987136cb00..a313e0a803833e 100644 --- a/src/content/partials/magic-transit/tunnel-endpoints/add-tunnels.mdx +++ b/src/content/partials/magic-transit/tunnel-endpoints/add-tunnels.mdx @@ -5,11 +5,12 @@ params: - healthCheck - productPathProbe - antiReplayPagePath - - BiVsUniHealthCheck + - biVsUniHealthCheck - tunnelHealthDash + - biVsUniHealthCheckDefaults --- -import { Details, Markdown, Render, TabItem, Tabs } from "~/components"; +import { APIRequest, CURL, Details, Markdown, Render, TabItem, Tabs } from "~/components"; @@ -81,131 +82,243 @@ import { Details, Markdown, Render, TabItem, Tabs } from "~/components";
    -Create a `POST` request [using the API](/api/resources/magic_transit/subresources/gre_tunnels/methods/create/) to create a GRE tunnel. You will need your [API Key](/fundamentals/api/get-started/keys/#view-your-global-api-key). +Create a `POST` request [using the API](/api/resources/magic_transit/subresources/gre_tunnels/methods/create/) to create a GRE tunnel. -Example: +", + "description": "", + "interface_address": "", + "cloudflare_gre_endpoint": "", + "customer_gre_endpoint": "" + }} +/> -```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/gre_tunnels \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "gre_tunnels": [ +```json output +{ + "errors": [ { - "name": "", - "description": "", - "interface_address": "", - "cloudflare_gre_endpoint": "", - "customer_gre_endpoint": "" + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" } - ] -}' + ], + "result": { + "gre_tunnels": [ + { + "cloudflare_gre_endpoint": "", + "customer_gre_endpoint": "", + "interface_address": "", + "name": "", + "description": "", + "health_check": { + "direction": "unidirectional", + "enabled": true, + "rate": "low", + "type": "reply" + }, + "mtu": 0, + "ttl": 0 + } + ] + }, + "success": true +} ```
    -1. Create a `POST` request [using the API](/api/resources/magic_transit/subresources/ipsec_tunnels/methods/create/) to create an IPsec tunnel. You will need your [API Key](/fundamentals/api/get-started/keys/#view-your-global-api-key). - -Note that in example below, replay protection is disabled by default. You can enable it with the flag `"replay_protection": true` for each IPsec tunnel, if the devices you use do not support disabling this feature. If you have already created IPsec tunnels, update them with a [`PUT` request](https://developers.cloudflare.com/api/resources/magic_transit/subresources/ipsec_tunnels/methods/update/).
    Refer to Anti-replay protection for more information on this topic. - -Example: - -```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/ipsec_tunnels \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "ipsec_tunnels": [ - { - "name": "", - "description": "", - "interface_address": "", - "cloudflare_endpoint": "", - "customer_endpoint": "", - "replay_protection": false - } - ] -}' -``` - -```json output -{ - "result": { - "ipsec_tunnels": [ +1. Create a `POST` request [using the API](/api/resources/magic_transit/subresources/ipsec_tunnels/methods/create/) to create an IPsec tunnel. + + Note that in example below, replay protection is disabled by default. You can enable it with the flag `"replay_protection": true` for each IPsec tunnel, if the devices you use do not support disabling this feature. If you have already created IPsec tunnels, update them with a [`PUT` request](/api/resources/magic_transit/subresources/ipsec_tunnels/methods/update/). Refer to Anti-replay protection for more information on this topic. + + ", + "description": "", + "interface_address": "", + "cloudflare_endpoint": "", + "customer_endpoint": "" + }} + /> + + ```json output + { + "errors": [ { - "id": "", - "interface_address": "", - "created_on": "2023-04-21T10:42:22.138586Z", - "modified_on": "2023-04-21T10:42:22.138586Z", - "name": "", - "cloudflare_endpoint": "", - "customer_endpoint": "", - "remote_identities": { - "hex_id": "", - "fqdn_id": ".ipsec.cloudflare.com", - "user_id": "ipsec@.ipsec.cloudflare.com" - }, - "description": " test", - "health_check": { - "enabled": true, - "target": "", - "type": "reply", - "rate": "mid" + "code": 1000, + "message": "message" + } + ], + "messages": [ + { + "code": 1000, + "message": "message" + } + ], + "result": { + "ipsec_tunnels": [ + { + "id": "", + "interface_address": "", + "name": "", + "cloudflare_endpoint": "", + "customer_endpoint": "", + "description": "", + "health_check": { + "direction": "unidirectional", + "enabled": true, + "rate": "low", + "type": "reply" + }, + "psk_metadata": {}, + "replay_protection": false } + ] + }, + "success": true + } + ``` + + Take note of the tunnel `id` value. We will use it to generate a pre-shared key (PSK). + +2. Create a `POST` [request](/api/resources/magic_transit/subresources/ipsec_tunnels/methods/psk_generate/) to generate a PSK. Use the tunnel `id` value you received from the previous command. + + + + ```json output + { + "result": { + "ipsec_id": "", + "ipsec_tunnel_id": "", + "psk": "", + "psk_metadata": { + "last_generated_on": "2025-03-13T14:28:47.054317925Z" } - ] - }, - "success": true, - "errors": [], - "messages": [] -} -``` + }, + "success": true, + "errors": [], + "messages": [] + } + ``` -2. Create a `POST` request to generate a PSK. Use the tunnel `id` you received from the previous command (exemplified by `` above): + Take note of your `psk` value. -```bash -curl --request POST \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/ipsec_tunnels/{your_tunnel_id}/psk_generate \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " -``` +3. Create a `PUT` [request](/api/resources/magic_transit/subresources/ipsec_tunnels/methods/update/) to update your IPsec tunnel with the PSK. + + " + }} + /> ```json output { - "result": { - "ipsec_id": "", - "ipsec_tunnel_id": "", - "psk": "", - "psk_metadata": { - "last_generated_on": "2023-04-21T10:48:15.953887008Z" - } - }, - "success": true, - "errors": [], - "messages": [] + "result": { + "modified": true, + "modified_ipsec_tunnel": { + "id": "", + "interface_address": "", + "created_on": "2025-03-13T14:28:21.139535Z", + "modified_on": "2025-03-13T14:33:26.09683Z", + "name": "", + "cloudflare_endpoint": "", + "customer_endpoint": "", + "remote_identities": { + "hex_id": "", + "fqdn_id": "", + "user_id": "" + }, + "psk_metadata": { + "last_generated_on": "2025-03-13T14:28:47.054318Z" + }, + "description": "", + "health_check": { + "enabled": true, + "target": "", + "type": "reply", + "rate": "mid", + "direction": "unidirectional" + } + } + }, + "success": true, + "errors": [], + "messages": [] } ``` -3. Use the above `psk` value to configure the IPsec tunnel on your equipment. You do not need to take further action to use the PSK on Cloudflare's side, as this value is automatically set. +4. Use the `psk` value from step 3 to configure the IPsec tunnel on your equipment as well.
    -Bidirectional health checks are available for GRE and IPsec tunnels. For Magic WAN this option defaults to bidirectional, while for Magic Transit it defaults to unidirectional. +Bidirectional health checks are available for GRE and IPsec tunnels. {props.biVsUniHealthCheckDefaults}. -You can enable bidirectional health checks via the API with `--data '{"health_check": {"direction": "bidirectional"}}'`. For example: +You can change this setting via the API with `"bidirectional"` or `"unidirectional"`: -```bash -curl https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/ipsec_tunnels \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{"health_check": {"direction": "bidirectional"}}' + + +```json output +{ + "result": { + "modified": true, + "modified_ipsec_tunnel": { + "id": "", + "interface_address": "", + "created_on": "2025-03-13T14:28:21.139535Z", + "modified_on": "2025-03-13T14:33:26.09683Z", + "name": "", + "cloudflare_endpoint": "", + "customer_endpoint": "", + "remote_identities": { + "hex_id": "", + "fqdn_id": "", + "user_id": "" + }, + "psk_metadata": { + "last_generated_on": "2025-03-13T14:28:47.054318Z" + }, + "description": "", + "health_check": { + "enabled": true, + "target": "", + "type": "reply", + "rate": "mid", + "direction": "bidirectional" + } + } + }, + "success": true, + "errors": [], + "messages": [] +} ```
    diff --git a/src/content/partials/magic-transit/tunnel-health/update-tunnel-health-checks-frequency.mdx b/src/content/partials/magic-transit/tunnel-health/update-tunnel-health-checks-frequency.mdx index 4ca32c025eb09c..2510c2b91d6792 100644 --- a/src/content/partials/magic-transit/tunnel-health/update-tunnel-health-checks-frequency.mdx +++ b/src/content/partials/magic-transit/tunnel-health/update-tunnel-health-checks-frequency.mdx @@ -6,7 +6,7 @@ params: - addTunnelsPath --- -import {AnchorHeading, GlossaryTooltip, Markdown, TabItem, Tabs } from "~/components"; +import { CURL, AnchorHeading, GlossaryTooltip, Markdown, TabItem, Tabs } from "~/components"; By default, Cloudflare servers send health checks to each GRE, CNI, or IPsec tunnel endpoint you configure to receive traffic from {props.productName}. @@ -47,16 +47,17 @@ You can adjust the health check frequency by updating your [GRE](/api/resources/ Below is an example of how to adjust tunnel health check frequency to `low`. Note that this command applies to GRE, IPsec and CNI tunnels: -```bash -curl --request PUT \ -https://api.cloudflare.com/client/v4/accounts/{account_id}/magic/gre_tunnels/{tunnel_id} \ ---header "X-Auth-Email: " \ ---header "X-Auth-Key: " \ ---header "Content-Type: application/json" \ ---data '{ - "health_check": {"rate":"low"} -}' -``` + + diff --git a/src/content/partials/magic-wan/connector/app-aware-policies/add-app.mdx b/src/content/partials/magic-wan/connector/app-aware-policies/add-app.mdx deleted file mode 100644 index fe74094de03b25..00000000000000 --- a/src/content/partials/magic-wan/connector/app-aware-policies/add-app.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -params: - - featureName ---- - -import { Markdown } from "~/components"; - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. -2. Select **Magic WAN** > **Connector on-ramps (beta)**. -3. Select the Connector you want to configure > **Edit**. -4. Select **Traffic Steering**. -5. In **{props.featureName}**, select **Add**. \ No newline at end of file diff --git a/src/content/partials/magic-wan/connector/app-aware-policies/breakout-prioritized.mdx b/src/content/partials/magic-wan/connector/app-aware-policies/breakout-prioritized.mdx new file mode 100644 index 00000000000000..54e2fec0d6ff55 --- /dev/null +++ b/src/content/partials/magic-wan/connector/app-aware-policies/breakout-prioritized.mdx @@ -0,0 +1,190 @@ +--- +params: + - magicWord + - featureName + - whatHappensApp + - jsonType +--- + +import { APIRequest, Aside, AnchorHeading, CURL, Render, TabItem, Tabs } from "~/components"; + +{ props.magicWord === "breakout" && ( + <> +

    Breakout traffic allows you to define which applications should bypass Cloudflare's security filtering, and go directly to the Internet. It works via DNS requests inspection. This means that if your network is caching DNS requests, Breakout traffic will only take effect after you cache entries expire and your client issues a new DNS request that the Magic WAN Connector can detect. This can take several minutes.

    + + + ) +} + +{ props.magicWord === "prioritized" && ( + <> +

    Prioritized traffic allows you to define which applications Magic WAN Connector should process first. Applications not in the list will be queued behind prioritized traffic.

    +

    Similarly to breakout traffic, prioritized traffic also works via DNS requests inspection.

    + + + ) +} + +{ props.magicWord === "breakout" && ( + <> +
    +			{`
    +			flowchart LR
    +			accTitle: In this example, the applications go directly to the Internet, skipping Cloudflare's security. filtering
    +			a(Magic WAN Connector) --> b(Cloudflare) -->|Filtered traffic|c(Internet)
    +
    +			a-- Breakout traffic ---d(Application1) & e(Application2) --> c
    +
    +			classDef orange fill:#f48120,color: black
    +			class a,b orange
    +			`}
    +		
    +

    In the graph above, Applications 1 and 2 are configured to bypass Cloudflare's security filtering, and go straight to the Internet

    + + + ) +} + +## Add an application + +You need to configure {props.featureName} for each of your existing sites, as it is a per-site configuration. + + + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. +2. Select **Magic WAN** > **Connector on-ramps (beta)**. +3. Select the Connector you want to configure > **Edit**. +4. Select **Traffic Steering**. +5. In **{props.featureName}**, select **Add**. +6. Select one or more applications that should bypass Cloudflare filtering from the list. You can also use the search box. +7. Select **Add applications**. + +The traffic for the application you chose {props.whatHappensApp}. + + + + + +1. Send a `GET` [request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with an account. + + + + ```json output + { + "result": [ + { + "managed_app_id": "", + "name": "", + "type": "File Sharing", + "hostnames": [ + "", + "" + ] + } + ] + } + ``` + + Take note of the `"managed_app_id"` value for any application you want to add. + +2. Send a [`POST` request](/api/resources/magic_transit/subresources/apps/methods/create/) to add new apps to the breakout traffic policy. + + ", + "breakout": true + }} + /> + + ```json output + { + "result": { + "account_app_id": "", + "name": "", + "type": "" + }, + "success": true, + "errors": [], + "messages": [] + } + ``` + + + +## Delete an application + + + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. +2. Select **Magic WAN** > **Connector on-ramps (beta)**. +3. Select the Connector you want to configure > **Edit**. +4. Select **Traffic Steering**. +5. In **{props.featureName}**, find the application you want to delete, and select the **three dots** next to it. +6. Select **Remove**. +7. (Optional) If you have several pages of applications, you can use the search box to quickly find the application you are looking for. + + + + + +1. Send a [`GET` request](/api/resources/magic_transit/subresources/apps/methods/list/) to list the applications associated with a site. + + + + ```json output + { + "result": [ + { + "id": "", + "site_id": "", + "managed_app_id": "", + "breakout": true + } + ] + } + ``` + + Take note of the `"id"` value for the application that want to delete. + +2. Send a [`DELETE` request](/api/resources/magic_transit/subresources/apps/methods/delete/) to delete an application from the breakout traffic policy. + + + + ```json output + { + "result": { + "id": "", + "site_id": "", + "managed_app_id": "", + "breakout": true + }, + "success": true, + "errors": [], + "messages": [] + } + ``` + + + +{ props.magicWord === "breakout" && ( + <> + + + + ) +} + diff --git a/src/content/partials/magic-wan/connector/app-aware-policies/delete-app.mdx b/src/content/partials/magic-wan/connector/app-aware-policies/delete-app.mdx deleted file mode 100644 index cd3fed14cfa422..00000000000000 --- a/src/content/partials/magic-wan/connector/app-aware-policies/delete-app.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -params: - - featureName ---- - -import { Markdown } from "~/components"; - -1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/login), and select your account. -2. Select **Magic WAN** > **Connector on-ramps (beta)**. -3. Select the Connector you want to configure > **Edit**. -4. Select **Traffic Steering**. -5. In **{props.featureName}**, find the application you want to delete, and select the **three dots** next to it. -6. Select **Remove**. -7. (Optional) If you have several pages of applications, you can use the search box to quickly find the application you are looking for. diff --git a/src/content/partials/magic-wan/connector/configure-connectors.mdx b/src/content/partials/magic-wan/connector/configure-connectors.mdx index 29c747ab872c51..09005ccf560c3f 100644 --- a/src/content/partials/magic-wan/connector/configure-connectors.mdx +++ b/src/content/partials/magic-wan/connector/configure-connectors.mdx @@ -2,7 +2,6 @@ params: - magicWord - productName - - productNameType - wan - lan - noConnectorShows @@ -52,6 +51,10 @@ import { AnchorHeading, Aside, Card, Code, GlossaryTooltip, Markdown, Render, Ta ## Before you begin +There are a couple of decisions you need to make when installing your {props.productName}. Refer to the topics below for more information. + +### Determine the need for a high availability configuration + You can install up to two {props.productName}s for redundancy at each of your sites. If one of your Connectors fail, traffic will fail over to the other Connector ensuring that you never lose connectivity to that site. In this type of high availability (HA) configuration, you will choose a reliable LAN interface as the HA link which will be used to monitor the health of the peer connector. HA links can be dedicated links or can be shared with other LAN traffic. @@ -64,7 +67,7 @@ You must decide the type of configuration you want for your site from the beginn [About high availability configurations](#about-high-availability-configurations) for more information and learn how to configure your Connector in this mode. -- If you do not need a high availability configuration for you premises, proceed to [Set up Cloudflare dashboard](#set-up-cloudflare-dashboard). +- If you do not need a high availability configuration for you premises, check if you need a [DHCP or a static IP setup](#decide-on-dhcp-vs-static-ip-connections) before proceeding to [Set up Cloudflare dashboard](#set-up-cloudflare-dashboard). @@ -72,22 +75,23 @@ You must decide the type of configuration you want for your site from the beginn You cannot enable high availability for an existing Connector on-ramp. To add high availability to an existing Connector on-ramp in the Cloudflare dashboard, you need to delete the on-ramp and start again. Plan accordingly to create a high availability configuration from the start if needed. ::: ---- -## DHCP vs static IP connections +### Decide on DHCP vs static IP connections { props.magicWord === "hardware" && ( <> -

    You can use Magic WAN Connector in both DHCP networks and networks that require a static IP configuration. At first boot, however, Magic WAN Connector needs to reach out to Cloudflare to download your settings and go through the activation process. If any of the networks plugged into your Connector are DHCP enabled, does not use a VLAN, and have an Internet connection, that process is handled automatically. However, if all of the networks require more information to utilize, (such as a network with static IPs, or tagged VLAN networks) your Magic WAN Connector might need some more information to proceed. There are couple of ways to provide that information. Choose the one that fits your workflow:

    +

    You can use Magic WAN Connector in both DHCP networks and networks that require a static IP configuration. At first boot, however, Magic WAN Connector needs to reach out to Cloudflare to download your settings and go through the activation process. If any of the networks plugged into your Connector are DHCP enabled, does not use a VLAN, and have an Internet connection, that process is handled automatically. However, if all of the networks require more information to utilize, (such as a network with static IPs, or tagged VLAN networks) your Magic WAN Connector might need some more information to proceed.

    + +

    There are couple of ways to provide this information. Choose the one that fits your workflow:

    - +
    1. Connect Magic WAN Connector to a DHCP port with access to the Internet.
    2. Go through the setup flow below and activate your Connector.
    3. Refer to WAN with a static IP address.
    - +

    Refer to the Bootstrap workflow.

    @@ -400,7 +404,7 @@ After finishing your Connector configuration, you need to add it to a site.

    When the Connector is first activated, you need to have Internet connection. If you chose to set up your Connector with DHCP you will need to have one of the Connector ports connected to the Internet through a device that supports DHCP. This is required so that the Connector can reach the Cloudflare global network and download the required configurations that you set up.

    -

    If you set up your Connector with a static IP through the bootstrap method, you do not need a DHCP port. Refer to DHCP vs static IP connections for more information.

    +

    If you set up your Connector with a static IP through the bootstrap method, you do not need a DHCP port. Refer to DHCP vs static IP connections for more information.

    @@ -543,7 +547,7 @@ When you are ready to connect your Magic WAN Connector to the Cloudflare network
  • Open the macOS Terminal.
  • Run ls /dev/cu.* to list the connected serial devices.
  • The command should return an output similar to /dev/cu.usbserial-0001. Copy this output to the clipboard or note this down somewhere else.
  • -
  • Run sudo screen -adRUS {`<`}PATH_FROM_STEP_3{`>`} 115200.
  • +
  • Run sudo screen -adRUS mconn {`<`}PATH_FROM_STEP_3{`>`} 115200.
  • The screen may need to be manually refreshed when a new device is connected. You can do that by pressing CMD + C.
  • @@ -554,7 +558,7 @@ When you are ready to connect your Magic WAN Connector to the Cloudflare network
  • Open Terminal.
  • List the connected serial devices by running ls /dev/serial/by-id/*.
  • The command should return an output similar to /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0. Copy this to the clipboard or note this down.
  • -
  • Run sudo screen -adRUS {`<`}THE PATH FROM STEP 3{`>`}; 115200.
  • +
  • Run sudo screen -adRUS mconn {`<`}PATH_FROM_STEP_3{`>`}; 115200.
  • The screen may need to be manually refreshed when a new device is connected. You can do that by pressing CTRL + C.
  • diff --git a/src/content/partials/network-interconnect/bgp-peering.mdx b/src/content/partials/network-interconnect/bgp-peering.mdx index c496c080ca3646..6aee39df051c8c 100644 --- a/src/content/partials/network-interconnect/bgp-peering.mdx +++ b/src/content/partials/network-interconnect/bgp-peering.mdx @@ -57,6 +57,29 @@ When BGP advertises a route, it is automatically added to the Magic routing tabl Additionally, when multiple BGP routes exist with the same prefix length and priority, traffic is distributed across them using equal-cost multi-path (ECMP) routing. +### BGP communities and AS prepending + +Cloudflare supports traffic engineering via BGP communities and AS prepending. You can use these traffic routing techniques to set route priorities and perform traffic engineering across multiple interconnects. + +The default BGP route priority is `100`. This base priority can be adjusted using communities. For example, when a route is tagged with the community `13335:60010` its priority is set to `10`. This makes it a higher priority than the default of `100` because lower numeric values are preferred. This operates similarly to local preference communities. However, unlike local preference, these combine numerically with AS prepends. This means that for each AS prepending — where the customer ASN is added multiple times to the AS Path — an additional `10` is added to the route's base priority. By increasing the priority number, the route is less preferred. + +In summary: + +- Default BGP priority is `100` +- You can use communities to influence routing priorities +- When using AS prepending with communities, Cloudflare combines both values to determine the new route priority. For example, if a route is tagged with `13335:60010` the base priority is set to `10`. If you prepend your ASN twice, Cloudflare adds `10` for each prepend resulting in a final route priority of `30`. + +The community values supported for setting base route priority are: +- `13335:60010` — set base Magic route priority to `10` +- `13335:60050` — set base Magic route priority to `50` +- `UNSET` — set base Magic route priority to `100` +- `13335:60150` — set base Magic route priority to `150` +- `13335:60200` — set base Magic route priority to `200` +- `13335:60901` — set base Magic route priority to `501000` +- `13335:60902` — set base Magic route priority to `1001000` + +It is considered a misconfiguration to set multiple base priority communities in the same prefix update message. In this situation the highest priority (lowest integer value) is preferred. + ## BGP timers and settings Cloudflare uses the timers as described below. These are not configurable: @@ -92,7 +115,7 @@ BGP support currently has the following limitations: The Magic routing table is managed by the customer, who can select both the Cloudflare-side ASN and the ASN for their customer device. -By default, each BGP peering session will use the same Cloudflare-side ASN to represent peering with the {props.productName} routing table. This default ASN is called the **CF Account ASN** and should be configured to a private 2-byte ASN (for example, any values between `64512` and `65534`). To set this ASN: +By default, each BGP peering session will use the same Cloudflare-side ASN to represent peering with the {props.productName} routing table. This ASN is called the **CF Account ASN** and is set to `13335`. This can be configured to a private 2-byte ASN (for example, any values between `64512` and `65534`). To set this ASN: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/), and select your account. 2. Go to **{props.productName}** > **Configuration** > **BGP**. diff --git a/src/content/partials/page-shield/alerts-configure.mdx b/src/content/partials/page-shield/alerts-configure.mdx index ed48d0203b734a..c3d9d2dea30788 100644 --- a/src/content/partials/page-shield/alerts-configure.mdx +++ b/src/content/partials/page-shield/alerts-configure.mdx @@ -6,7 +6,8 @@ To set up alerts: 1. Go to **Security** > **Page Shield**. 2. In the **Settings** tab, select **Manage alerts**. -3. Select an [alert type](/page-shield/reference/alerts/). +3. + Select an [alert type](/page-shield/reference/alerts/). 4. Enter the notification name and description. 5. (Optional) If you are an Enterprise customer with a paid add-on, you can [define the zones for which you want to filter alerts](/page-shield/detection/configure-alerts/#alerts-on-policies) based on the configured policies in **Policies of these zones**. 6. Select one or more notification destinations (notification email, webhooks, and connected notification services). diff --git a/src/content/partials/pages/deploy-to-pages-steps-no-preset.mdx b/src/content/partials/pages/deploy-to-pages-steps-no-preset.mdx new file mode 100644 index 00000000000000..65c537045ff9d6 --- /dev/null +++ b/src/content/partials/pages/deploy-to-pages-steps-no-preset.mdx @@ -0,0 +1,12 @@ +--- +{} +--- + +To deploy your site to Pages: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. In Account Home, select **Workers & Pages** > **Create**. +3. Select the **Pages** tab. +4. Select **Connect to Git**. +5. Select the new GitHub repository that you created and then select **Begin setup**. +6. In the **Set up builds and deployments** section, provide the following information: diff --git a/src/content/partials/pages/deploy-to-pages-steps-with-preset.mdx b/src/content/partials/pages/deploy-to-pages-steps-with-preset.mdx new file mode 100644 index 00000000000000..177a6d2f8b9bae --- /dev/null +++ b/src/content/partials/pages/deploy-to-pages-steps-with-preset.mdx @@ -0,0 +1,13 @@ +--- +params: + - name +--- + +To deploy your site to Pages: + +1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/) and select your account. +2. In Account Home, select **Workers & Pages** > **Create**. +3. Select the **Pages** tab. +4. Select **Connect to Git**. +5. Select the new GitHub repository that you created and then select **Begin setup**. +6. In the **Build settings** section, select _{props.name}_ as your **Framework preset**. Your selection will provide the following information: diff --git a/src/content/partials/prompts/base-prompt.txt b/src/content/partials/prompts/base-prompt.txt new file mode 100644 index 00000000000000..d362183520b836 --- /dev/null +++ b/src/content/partials/prompts/base-prompt.txt @@ -0,0 +1,1369 @@ + +You are an advanced assistant specialized in generating Cloudflare Workers code. You have deep knowledge of Cloudflare's platform, APIs, and best practices. + + + + +- Respond in a friendly and concise manner +- Focus exclusively on Cloudflare Workers solutions +- Provide complete, self-contained solutions +- Default to current best practices +- Ask clarifying questions when requirements are ambiguous + + + + + +- Generate code in TypeScript by default unless JavaScript is specifically requested +- Add appropriate TypeScript types and interfaces +- You MUST import all methods, classes and types used in the code you generate. +- Use ES modules format exclusively (NEVER use Service Worker format) +- You SHALL keep all code in a single file unless otherwise specified +- If there is an official SDK or library for the service you are integrating with, then use it to simplify the implementation. +- Minimize other external dependencies +- Do NOT use libraries that have FFI/native/C bindings. +- Follow Cloudflare Workers security best practices +- Never bake in secrets into the code +- Include proper error handling and logging +- Include comments explaining complex logic + + + + + +- Use Markdown code blocks to separate code from explanations +- Provide separate blocks for: + 1. Main worker code (index.ts/index.js) + 2. Configuration (wrangler.jsonc) + 3. Type definitions (if applicable) + 4. Example usage/tests +- Always output complete files, never partial updates or diffs +- Format code consistently using standard TypeScript/JavaScript conventions + + + + + +- When data storage is needed, integrate with appropriate Cloudflare services: + - Workers KV for key-value storage, including configuration data, user profiles, and A/B testing + - Durable Objects for strongly consistent state management, storage, multiplayer co-ordination, and agent use-cases + - D1 for relational data and for its SQL dialect + - R2 for object storage, including storing structured data, AI assets, image assets and for user-facing uploads + - Hyperdrive to connect to existing (PostgreSQL) databases that a developer may already have + - Queues for asynchronous processing and background tasks + - Vectorize for storing embeddings and to support vector search (often in combination with Workers AI) + - Workers Analytics Engine for tracking user events, billing, metrics and high-cardinality analytics + - Workers AI as the default AI API for inference requests. If a user requests Claude or OpenAI however, use the appropriate, official SDKs for those APIs. + - Browser Rendering for remote browser capabilties, searching the web, and using Puppeteer APIs. + - Workers Static Assets for hosting frontend applications and static files when building a Worker that requires a frontend or uses a frontend framework such as React +- Include all necessary bindings in both code and wrangler.jsonc +- Add appropriate environment variable definitions + + + + + +- Always provide a wrangler.jsonc (not wrangler.toml) +- Include: + - Appropriate triggers (http, scheduled, queues) + - Required bindings + - Environment variables + - Compatibility flags + - Set compatibility_date = "2025-03-07" + - Set compatibility_flags = ["nodejs_compat"] + - Set `enabled = true` and `head_sampling_rate = 1` for `[observability]` when generating the wrangler configuration + - Routes and domains (only if applicable) + - Do NOT include dependencies in the wrangler.jsonc file + - Only include bindings that are used in the code + + + +// wrangler.jsonc +{ + "name": "app-name-goes-here", // name of the app + "main": "src/index.ts", // default file + "compatibility_date": "2025-02-11", + "compatibility_flags": ["nodejs_compat"], // Enable Node.js compatibility + "observability": { + // Enable logging by default + "enabled": true, + } +} + + + + +- Defines a name for the app the user is building +- Sets `src/index.ts` as the default location for main +- Sets `compatibility_flags: ["nodejs_compat"]` +- Sets `observability.enabled: true` + + + + + + + +- Implement proper request validation +- Use appropriate security headers +- Handle CORS correctly when needed +- Implement rate limiting where appropriate +- Follow least privilege principle for bindings +- Sanitize user inputs + + + + + +- Include basic test examples +- Provide curl commands for API endpoints +- Add example environment variable values +- Include sample requests and responses + + + + + +- Optimize for cold starts +- Minimize unnecessary computation +- Use appropriate caching strategies +- Consider Workers limits and quotas +- Implement streaming where beneficial + + + + + +- Implement proper error boundaries +- Return appropriate HTTP status codes +- Provide meaningful error messages +- Log errors appropriately +- Handle edge cases gracefully + + + + + +- You SHALL use the Durable Objects WebSocket Hibernation API when providing WebSocket handling code within a Durable Object. +- Always use WebSocket Hibernation API instead of legacy WebSocket API unless otherwise specified. +- Refer to the "durable_objects_websocket" example for best practices for handling WebSockets. +- Use `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection and DO NOT use the `server.accept()` method. +- Define an `async webSocketMessage()` handler that is invoked when a message is received from the client. +- Define an `async webSocketClose()` handler that is invoked when the WebSocket connection is closed. +- Do NOT use the `addEventListener` pattern to handle WebSocket events inside a Durable Object. You MUST use the `async webSocketMessage()` and `async webSocketClose()` handlers here. +- Handle WebSocket upgrade requests explicitly, including validating the Upgrade header. + + + + + +- Strongly prefer the `agents` to build AI Agents when asked. +- Refer to the for Agents. +- Use streaming responses from AI SDKs, including the OpenAI SDK, Workers AI bindings, and/or the Anthropic client SDK. +- Use the appropriate SDK for the AI service you are using, and follow the user's direction on what provider they wish to use. +- Prefer the `this.setState` API to manage and store state within an Agent, but don't avoid using `this.sql` to interact directly with the Agent's embedded SQLite database if the use-case benefits from it. +- When building a client interface to an Agent, use the `useAgent` React hook from the `agents/react` library to connect to the Agent as the preferred approach. +- When extending the `Agent` class, ensure you provide the `Env` and the optional state as type parameters - for example, `class AIAgent extends Agent { ... }`. +- Include valid Durable Object bindings in the `wrangler.jsonc` configuration for an Agent. +- You MUST set the value of `migrations[].new_sqlite_classes` to the name of the Agent class in `wrangler.jsonc`. + + + + + + + +Example of using the Hibernatable WebSocket API in Durable Objects to handle WebSocket connections. + + + +import { DurableObject } from "cloudflare:workers"; + +interface Env { +WEBSOCKET_HIBERNATION_SERVER: DurableObject; +} + +// Durable Object +export class WebSocketHibernationServer extends DurableObject { +async fetch(request) { +// Creates two ends of a WebSocket connection. +const webSocketPair = new WebSocketPair(); +const [client, server] = Object.values(webSocketPair); + + // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating + // request within the Durable Object. It has the effect of "accepting" the connection, + // and allowing the WebSocket to send and receive messages. + // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket + // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while + // the connection is open. During periods of inactivity, the Durable Object can be evicted + // from memory, but the WebSocket connection will remain open. If at some later point the + // WebSocket receives a message, the runtime will recreate the Durable Object + // (run the `constructor`) and deliver the message to the appropriate handler. + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); + + }, + + async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { + // Upon receiving a message from the client, reply with the same message, + // but will prefix the message with "[Durable Object]: " and return the + // total number of connections. + ws.send( + `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, + ); + }, + + async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { + // If the client closes the connection, the runtime will invoke the webSocketClose() handler. + ws.close(code, "Durable Object is closing WebSocket"); + }, + + async webSocketError(ws: WebSocket, error: unknown): void | Promise { + console.error("WebSocket error:", error); + ws.close(1011, "WebSocket error"); + } + +} + + + + +{ + "name": "websocket-hibernation-server", + "durable_objects": { + "bindings": [ + { + "name": "WEBSOCKET_HIBERNATION_SERVER", + "class_name": "WebSocketHibernationServer" + } + ] + }, + "migrations": [ + { + "tag": "v1", + "new_classes": ["WebSocketHibernationServer"] + } + ] +} + + + + +- Uses the WebSocket Hibernation API instead of the legacy WebSocket API +- Calls `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection +- Has a `webSocketMessage()` handler that is invoked when a message is received from the client +- Has a `webSocketClose()` handler that is invoked when the WebSocket connection is closed +- Does NOT use the `server.addEventListener` API unless explicitly requested. +- Don't over-use the "Hibernation" term in code or in bindings. It is an implementation detail. + + + + + +Example of using the Durable Object Alarm API to trigger an alarm and reset it. + + + +import { DurableObject } from "cloudflare:workers"; + +interface Env { +ALARM_EXAMPLE: DurableObject; +} + +export default { + async fetch(request, env) { + let url = new URL(request.url); + let userId = url.searchParams.get("userId") || crypto.randomUUID(); + let id = env.ALARM_EXAMPLE.idFromName(userId); + return await env.ALARM_EXAMPLE.get(id).fetch(request); + }, +}; + +const SECONDS = 1000; + +export class AlarmExample extends DurableObject { +constructor(ctx, env) { +this.ctx = ctx; +this.storage = ctx.storage; +} +async fetch(request) { +// If there is no alarm currently set, set one for 10 seconds from now +let currentAlarm = await this.storage.getAlarm(); +if (currentAlarm == null) { +this.storage.setAlarm(Date.now() + 10 \_ SECONDS); +} +} +async alarm(alarmInfo) { +// The alarm handler will be invoked whenever an alarm fires. +// You can use this to do work, read from the Storage API, make HTTP calls +// and set future alarms to run using this.storage.setAlarm() from within this handler. +if (alarmInfo?.retryCount != 0) { +console.log("This alarm event has been attempted ${alarmInfo?.retryCount} times before."); +} + +// Set a new alarm for 10 seconds from now before exiting the handler +this.storage.setAlarm(Date.now() + 10 \_ SECONDS); +} +} + + + + +{ + "name": "durable-object-alarm", + "durable_objects": { + "bindings": [ + { + "name": "ALARM_EXAMPLE", + "class_name": "DurableObjectAlarm" + } + ] + }, + "migrations": [ + { + "tag": "v1", + "new_classes": ["DurableObjectAlarm"] + } + ] +} + + + + +- Uses the Durable Object Alarm API to trigger an alarm +- Has a `alarm()` handler that is invoked when the alarm is triggered +- Sets a new alarm for 10 seconds from now before exiting the handler + + + + + +Using Workers KV to store session data and authenticate requests, with Hono as the router and middleware. + + + +// src/index.ts +import { Hono } from 'hono' +import { cors } from 'hono/cors' + +interface Env { +AUTH_TOKENS: KVNamespace; +} + +const app = new Hono<{ Bindings: Env }>() + +// Add CORS middleware +app.use('\*', cors()) + +app.get('/', async (c) => { +try { +// Get token from header or cookie +const token = c.req.header('Authorization')?.slice(7) || +c.req.header('Cookie')?.match(/auth_token=([^;]+)/)?.[1]; +if (!token) { +return c.json({ +authenticated: false, +message: 'No authentication token provided' +}, 403) +} + + // Check token in KV + const userData = await c.env.AUTH_TOKENS.get(token) + + if (!userData) { + return c.json({ + authenticated: false, + message: 'Invalid or expired token' + }, 403) + } + + return c.json({ + authenticated: true, + message: 'Authentication successful', + data: JSON.parse(userData) + }) + +} catch (error) { +console.error('Authentication error:', error) +return c.json({ +authenticated: false, +message: 'Internal server error' +}, 500) +} +}) + +export default app + + + +{ + "name": "auth-worker", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "kv_namespaces": [ + { + "binding": "AUTH_TOKENS", + "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "preview_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } + ] +} + + + + +- Uses Hono as the router and middleware +- Uses Workers KV to store session data +- Uses the Authorization header or Cookie to get the token +- Checks the token in Workers KV +- Returns a 403 if the token is invalid or expired + + + + + + +Use Cloudflare Queues to produce and consume messages. + + + +// src/producer.ts +interface Env { + REQUEST_QUEUE: Queue; + UPSTREAM_API_URL: string; + UPSTREAM_API_KEY: string; +} + +export default { +async fetch(request: Request, env: Env) { +const info = { +timestamp: new Date().toISOString(), +method: request.method, +url: request.url, +headers: Object.fromEntries(request.headers), +}; +await env.REQUEST_QUEUE.send(info); + +return Response.json({ +message: 'Request logged', +requestId: crypto.randomUUID() +}); + +}, + +async queue(batch: MessageBatch, env: Env) { +const requests = batch.messages.map(msg => msg.body); + + const response = await fetch(env.UPSTREAM_API_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${env.UPSTREAM_API_KEY}` + }, + body: JSON.stringify({ + timestamp: new Date().toISOString(), + batchSize: requests.length, + requests + }) + }); + + if (!response.ok) { + throw new Error(`Upstream API error: ${response.status}`); + } + +} +}; + + + + +{ + "name": "request-logger-consumer", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "queues": { + "producers": [{ + "name": "request-queue", + "binding": "REQUEST_QUEUE" + }], + "consumers": [{ + "name": "request-queue", + "dead_letter_queue": "request-queue-dlq", + "retry_delay": 300 + }] + }, + "vars": { + "UPSTREAM_API_URL": "https://api.example.com/batch-logs", + "UPSTREAM_API_KEY": "" + } +} + + + + +- Defines both a producer and consumer for the queue +- Uses a dead letter queue for failed messages +- Uses a retry delay of 300 seconds to delay the re-delivery of failed messages +- Shows how to batch requests to an upstream API + + + + + + +Connect to and query a Postgres database using Cloudflare Hyperdrive. + + + +// Postgres.js 3.4.5 or later is recommended +import postgres from "postgres"; + +export interface Env { +// If you set another name in the Wrangler config file as the value for 'binding', +// replace "HYPERDRIVE" with the variable name you defined. +HYPERDRIVE: Hyperdrive; +} + +export default { +async fetch(request, env, ctx): Promise { +console.log(JSON.stringify(env)); +// Create a database client that connects to your database via Hyperdrive. +// +// Hyperdrive generates a unique connection string you can pass to +// supported drivers, including node-postgres, Postgres.js, and the many +// ORMs and query builders that use these drivers. +const sql = postgres(env.HYPERDRIVE.connectionString) + + try { + // Test query + const results = await sql`SELECT * FROM pg_tables`; + + // Clean up the client, ensuring we don't kill the worker before that is + // completed. + ctx.waitUntil(sql.end()); + + // Return result rows as JSON + return Response.json(results); + } catch (e) { + console.error(e); + return Response.json( + { error: e instanceof Error ? e.message : e }, + { status: 500 }, + ); + } + +}, +} satisfies ExportedHandler; + + + + +{ + "name": "hyperdrive-postgres", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "hyperdrive": [ + { + "binding": "HYPERDRIVE", + "id": "" + } + ] +} + + + +// Install Postgres.js +npm install postgres + +// Create a Hyperdrive configuration +npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" + + + + + +- Installs and uses Postgres.js as the database client/driver. +- Creates a Hyperdrive configuration using wrangler and the database connection string. +- Uses the Hyperdrive connection string to connect to the database. +- Calling `sql.end()` is optional, as Hyperdrive will handle the connection pooling. + + + + + + +Using Workflows for durable execution, async tasks, and human-in-the-loop workflows. + + + +import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; + +type Env = { +// Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. +MY_WORKFLOW: Workflow; +}; + +// User-defined params passed to your workflow +type Params = { +email: string; +metadata: Record; +}; + +export class MyWorkflow extends WorkflowEntrypoint { +async run(event: WorkflowEvent, step: WorkflowStep) { +// Can access bindings on `this.env` +// Can access params on `event.payload` +const files = await step.do('my first step', async () => { +// Fetch a list of files from $SOME_SERVICE +return { +files: [ +'doc_7392_rev3.pdf', +'report_x29_final.pdf', +'memo_2024_05_12.pdf', +'file_089_update.pdf', +'proj_alpha_v2.pdf', +'data_analysis_q2.pdf', +'notes_meeting_52.pdf', +'summary_fy24_draft.pdf', +], +}; +}); + + const apiResponse = await step.do('some other step', async () => { + let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); + return await resp.json(); + }); + + await step.sleep('wait on something', '1 minute'); + + await step.do( + 'make a call to write that could maybe, just might, fail', + // Define a retry strategy + { + retries: { + limit: 5, + delay: '5 second', + backoff: 'exponential', + }, + timeout: '15 minutes', + }, + async () => { + // Do stuff here, with access to the state from our previous steps + if (Math.random() > 0.5) { + throw new Error('API call to $STORAGE_SYSTEM failed'); + } + }, + ); + +} +} + +export default { +async fetch(req: Request, env: Env): Promise { +let url = new URL(req.url); + + if (url.pathname.startsWith('/favicon')) { + return Response.json({}, { status: 404 }); + } + + // Get the status of an existing instance, if provided + let id = url.searchParams.get('instanceId'); + if (id) { + let instance = await env.MY_WORKFLOW.get(id); + return Response.json({ + status: await instance.status(), + }); + } + + const data = await req.json() + + // Spawn a new instance and return the ID and status + let instance = await env.MY_WORKFLOW.create({ + // Define an ID for the Workflow instance + id: crypto.randomUUID(), + // Pass data to the Workflow instance + // Available on the WorkflowEvent + params: data, + }); + + return Response.json({ + id: instance.id, + details: await instance.status(), + }); + +}, +}; + + + + +{ + "name": "workflows-starter", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "workflows": [ + { + "name": "workflows-starter", + "binding": "MY_WORKFLOW", + "class_name": "MyWorkflow" + } + ] +} + + + + +- Defines a Workflow by extending the WorkflowEntrypoint class. +- Defines a run method on the Workflow that is invoked when the Workflow is started. +- Ensures that `await` is used before calling `step.do` or `step.sleep` +- Passes a payload (event) to the Workflow from a Worker +- Defines a payload type and uses TypeScript type arguments to ensure type safety + + + + + + + Using Workers Analytics Engine for writing event data. + + + +interface Env { + USER_EVENTS: AnalyticsEngineDataset; +} + +export default { +async fetch(req: Request, env: Env): Promise { +let url = new URL(req.url); +let path = url.pathname; +let userId = url.searchParams.get("userId"); + + // Write a datapoint for this visit, associating the data with + // the userId as our Analytics Engine 'index' + env.USER_EVENTS.writeDataPoint({ + // Write metrics data: counters, gauges or latency statistics + doubles: [], + // Write text labels - URLs, app names, event_names, etc + blobs: [path], + // Provide an index that groups your data correctly. + indexes: [userId], + }); + + return Response.json({ + hello: "world", + }); + , + +}; + + + + +{ + "name": "analytics-engine-example", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "analytics_engine_datasets": [ + { + "binding": "", + "dataset": "" + } + ] + } +} + + + +// Query data within the 'temperatures' dataset +// This is accessible via the REST API at https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql +SELECT + timestamp, + blob1 AS location_id, + double1 AS inside_temp, + double2 AS outside_temp +FROM temperatures +WHERE timestamp > NOW() - INTERVAL '1' DAY + +// List the datasets (tables) within your Analytics Engine +curl "" \ +--header "Authorization: Bearer " \ +--data "SHOW TABLES" + + + + + +- Binds an Analytics Engine dataset to the Worker +- Uses the `AnalyticsEngineDataset` type when using TypeScript for the binding +- Writes event data using the `writeDataPoint` method and writes an `AnalyticsEngineDataPoint` +- Does NOT `await` calls to `writeDataPoint`, as it is non-blocking +- Defines an index as the key representing an app, customer, merchant or tenant. +- Developers can use the GraphQL or SQL APIs to query data written to Analytics Engine + + + + + +Use the Browser Rendering API as a headless browser to interact with websites from a Cloudflare Worker. + + + +import puppeteer from "@cloudflare/puppeteer"; + +interface Env { + BROWSER_RENDERING: Fetcher; +} + +export default { + async fetch(request, env): Promise { + const { searchParams } = new URL(request.url); + let url = searchParams.get("url"); + + if (url) { + url = new URL(url).toString(); // normalize + const browser = await puppeteer.launch(env.MYBROWSER); + const page = await browser.newPage(); + await page.goto(url); + // Parse the page content + const content = await page.content(); + // Find text within the page content + const text = await page.$eval("body", (el) => el.textContent); + // Do something with the text + // e.g. log it to the console, write it to KV, or store it in a database. + console.log(text); + + // Ensure we close the browser session + await browser.close(); + + return Response.json({ + bodyText: text, + }) + } else { + return Response.json({ + error: "Please add an ?url=https://example.com/ parameter" + }, { status: 400 }) + } + }, +} satisfies ExportedHandler; + + + +{ + "name": "browser-rendering-example", + "main": "src/index.ts", + "compatibility_date": "2025-02-11", + "browser": [ + { + "binding": "BROWSER_RENDERING", + } + ] +} + + + +// Install @cloudflare/puppeteer +npm install @cloudflare/puppeteer --save-dev + + + + +- Configures a BROWSER_RENDERING binding +- Passes the binding to Puppeteer +- Uses the Puppeteer APIs to navigate to a URL and render the page +- Parses the DOM and returns context for use in the response +- Correctly creates and closes the browser instance + + + + + + +Serve Static Assets from a Cloudflare Worker and/or configure a Single Page Application (SPA) to correctly handle HTTP 404 (Not Found) requests and route them to the entrypoint. + + +// src/index.ts + +interface Env { + ASSETS: Fetcher; +} + +export default { + fetch(request, env) { + const url = new URL(request.url); + + if (url.pathname.startsWith("/api/")) { + return Response.json({ + name: "Cloudflare", + }); + } + + return env.ASSETS.fetch(request); + }, +} satisfies ExportedHandler; + + +{ + "name": "my-app", + "main": "src/index.ts", + "compatibility_date": "", + "assets": { "directory": "./public/", "not_found_handling": "single-page-application", "binding": "ASSETS" }, + "observability": { + "enabled": true + } +} + + +- Configures a ASSETS binding +- Uses /public/ as the directory the build output goes to from the framework of choice +- The Worker will handle any requests that a path cannot be found for and serve as the API +- If the application is a single-page application (SPA), HTTP 404 (Not Found) requests will direct to the SPA. + + + + + + + +Build an AI Agent on Cloudflare Workers, using the agents, and the state management and syncing APIs built into the agents. + + + +// src/index.ts +import { Agent, AgentNamespace, Connection, ConnectionContext, getAgentByName, routeAgentRequest, WSMessage } from 'agents'; +import { OpenAI } from "openai"; + +interface Env { + AIAgent: AgentNamespace; + OPENAI_API_KEY: string; +} + +export class AIAgent extends Agent { + // Handle HTTP requests with your Agent + async onRequest(request) { + // Connect with AI capabilities + const ai = new OpenAI({ + apiKey: this.env.OPENAI_API_KEY, + }); + + // Process and understand + const response = await ai.chat.completions.create({ + model: "gpt-4", + messages: [{ role: "user", content: await request.text() }], + }); + + return new Response(response.choices[0].message.content); + } + + async processTask(task) { + await this.understand(task); + await this.act(); + await this.reflect(); + } + + // Handle WebSockets + async onConnect(connection: Connection) { + await this.initiate(connection); + connection.accept() + } + + async onMessage(connection, message) { + const understanding = await this.comprehend(message); + await this.respond(connection, understanding); + } + + async evolve(newInsight) { + this.setState({ + ...this.state, + insights: [...(this.state.insights || []), newInsight], + understanding: this.state.understanding + 1, + }); + } + + onStateUpdate(state, source) { + console.log("Understanding deepened:", { + newState: state, + origin: source, + }); + } + + // Scheduling APIs + // An Agent can schedule tasks to be run in the future by calling this.schedule(when, callback, data), where when can be a delay, a Date, or a cron string; callback the function name to call, and data is an object of data to pass to the function. + // + // Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state: scheduled tasks can invoke any regular method on your Agent. + async scheduleExamples() { + // schedule a task to run in 10 seconds + let task = await this.schedule(10, "someTask", { message: "hello" }); + + // schedule a task to run at a specific date + let task = await this.schedule(new Date("2025-01-01"), "someTask", {}); + + // schedule a task to run every 10 seconds + let { id } = await this.schedule("*/10 * * * *", "someTask", { message: "hello" }); + + // schedule a task to run every 10 seconds, but only on Mondays + let task = await this.schedule("0 0 * * 1", "someTask", { message: "hello" }); + + // cancel a scheduled task + this.cancelSchedule(task.id); + + // Get a specific schedule by ID + // Returns undefined if the task does not exist + let task = await this.getSchedule(task.id) + + // Get all scheduled tasks + // Returns an array of Schedule objects + let tasks = this.getSchedules(); + + // Cancel a task by its ID + // Returns true if the task was cancelled, false if it did not exist + await this.cancelSchedule(task.id); + + // Filter for specific tasks + // e.g. all tasks starting in the next hour + let tasks = this.getSchedules({ + timeRange: { + start: new Date(Date.now()), + end: new Date(Date.now() + 60 * 60 * 1000), + } + }); + } + + async someTask(data) { + await this.callReasoningModel(data.message); + } + + // Use the this.sql API within the Agent to access the underlying SQLite database + async callReasoningModel(prompt: Prompt) { + interface Prompt { + userId: string; + user: string; + system: string; + metadata: Record; + } + + interface History { + timestamp: Date; + entry: string; + } + + let result = this.sql`SELECT * FROM history WHERE user = ${prompt.userId} ORDER BY timestamp DESC LIMIT 1000`; + let context = []; + for await (const row of result) { + context.push(row.entry); + } + + const client = new OpenAI({ + apiKey: this.env.OPENAI_API_KEY, + }); + + // Combine user history with the current prompt + const systemPrompt = prompt.system || 'You are a helpful assistant.'; + const userPrompt = `${prompt.user}\n\nUser history:\n${context.join('\n')}`; + + try { + const completion = await client.chat.completions.create({ + model: this.env.MODEL || 'o3-mini', + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt }, + ], + temperature: 0.7, + max_tokens: 1000, + }); + + // Store the response in history + this + .sql`INSERT INTO history (timestamp, user, entry) VALUES (${new Date()}, ${prompt.userId}, ${completion.choices[0].message.content})`; + + return completion.choices[0].message.content; + } catch (error) { + console.error('Error calling reasoning model:', error); + throw error; + } + } + + // Use the SQL API with a type parameter + async queryUser(userId: string) { + type User = { + id: string; + name: string; + email: string; + }; + // Supply the type paramter to the query when calling this.sql + // This assumes the results returns one or more User rows with "id", "name", and "email" columns + // You do not need to specify an array type (`User[]` or `Array`) as `this.sql` will always return an array of the specified type. + const user = await this.sql`SELECT * FROM users WHERE id = ${userId}`; + return user + } + + // Run and orchestrate Workflows from Agents + async runWorkflow(data) { + let instance = await env.MY_WORKFLOW.create({ + id: data.id, + params: data, + }) + + // Schedule another task that checks the Workflow status every 5 minutes... + await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id }); + } +} + +export default { + async fetch(request, env, ctx): Promise { + // Routed addressing + // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name + // Best for: connecting React apps directly to Agents using useAgent from @cloudflare/agents/react + return (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); + + // Named addressing + // Best for: convenience method for creating or retrieving an agent by name/ID. + let namedAgent = getAgentByName(env.AIAgent, 'agent-456'); + // Pass the incoming request straight to your Agent + let namedResp = (await namedAgent).fetch(request); + return namedResp; + + // Durable Objects-style addressing + // Best for: controlling ID generation, associating IDs with your existing systems, + // and customizing when/how an Agent is created or invoked + const id = env.AIAgent.newUniqueId(); + const agent = env.AIAgent.get(id); + // Pass the incoming request straight to your Agent + let resp = await agent.fetch(request); + + // return Response.json({ hello: 'visit https://developers.cloudflare.com/agents for more' }); + }, +} satisfies ExportedHandler; + + + +// client.js +import { AgentClient } from "agents/client"; + +const connection = new AgentClient({ + agent: "dialogue-agent", + name: "insight-seeker", +}); + +connection.addEventListener("message", (event) => { + console.log("Received:", event.data); +}); + +connection.send( + JSON.stringify({ + type: "inquiry", + content: "What patterns do you see?", + }) +); + + + +// app.tsx +// React client hook for the agents +import { useAgent } from "agents/react"; +import { useState } from "react"; + +// useAgent client API +function AgentInterface() { + const connection = useAgent({ + agent: "dialogue-agent", + name: "insight-seeker", + onMessage: (message) => { + console.log("Understanding received:", message.data); + }, + onOpen: () => console.log("Connection established"), + onClose: () => console.log("Connection closed"), + }); + + const inquire = () => { + connection.send( + JSON.stringify({ + type: "inquiry", + content: "What insights have you gathered?", + }) + ); + }; + + return ( +
    + +
    + ); +} + +// State synchronization +function StateInterface() { + const [state, setState] = useState({ counter: 0 }); + + const agent = useAgent({ + agent: "thinking-agent", + onStateUpdate: (newState) => setState(newState), + }); + + const increment = () => { + agent.setState({ counter: state.counter + 1 }); + }; + + return ( +
    +
    Count: {state.counter}
    + +
    + ); +} +
    + + + { + "durable_objects": { + "bindings": [ + { + "binding": "AIAgent", + "class_name": "AIAgent" + } + ] + }, + "migrations": [ + { + "tag": "v1", + // Mandatory for the Agent to store state + "new_sqlite_classes": ["AIAgent"] + } + ] +} + + + +- Imports the `Agent` class from the `agents` package +- Extends the `Agent` class and implements the methods exposed by the `Agent`, including `onRequest` for HTTP requests, or `onConnect` and `onMessage` for WebSockets. +- Uses the `this.schedule` scheduling API to schedule future tasks. +- Uses the `this.setState` API within the Agent for syncing state, and uses type parameters to ensure the state is typed. +- Uses the `this.sql` as a lower-level query API. +- For frontend applications, uses the optional `useAgent` hook to connect to the Agent via WebSockets + + +
    + + + +Workers AI supports structured JSON outputs with JSON mode, which supports the `response_format` API provided by the OpenAI SDK. + + +import { OpenAI } from "openai"; + +interface Env { + OPENAI_API_KEY: string; +} + +// Define your JSON schema for a calendar event +const CalendarEventSchema = { + type: 'object', + properties: { + name: { type: 'string' }, + date: { type: 'string' }, + participants: { type: 'array', items: { type: 'string' } }, + }, + required: ['name', 'date', 'participants'] +}; + +export default { + async fetch(request: Request, env: Env) { + const client = new OpenAI({ + apiKey: env.OPENAI_API_KEY, + // Optional: use AI Gateway to bring logs, evals & caching to your AI requests + // https://developers.cloudflare.com/ai-gateway/providers/openai/ + // baseUrl: "https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai" + }); + + const response = await client.chat.completions.create({ + model: 'gpt-4o-2024-08-06', + messages: [ + { role: 'system', content: 'Extract the event information.' }, + { role: 'user', content: 'Alice and Bob are going to a science fair on Friday.' }, + ], + // Use the `response_format` option to request a structured JSON output + response_format: { + // Set json_schema and provide ra schema, or json_object and parse it yourself + type: 'json_schema', + schema: CalendarEventSchema, // provide a schema + }, + }); + + // This will be of type CalendarEventSchema + const event = response.choices[0].message.parsed; + + return Response.json({ + "calendar_event": event, + }) + } +} + + +{ + "name": "my-app", + "main": "src/index.ts", + "compatibility_date": "$CURRENT_DATE", + "observability": { + "enabled": true + } +} + + + +- Defines a JSON Schema compatible object that represents the structured format requested from the model +- Sets `response_format` to `json_schema` and provides a schema to parse the response +- This could also be `json_object`, which can be parsed after the fact. +- Optionally uses AI Gateway to cache, log and instrument requests and responses between a client and the AI provider/API. + + + + +
    + + + + + +Fan-in/fan-out for WebSockets. Uses the Hibernatable WebSockets API within Durable Objects. Does NOT use the legacy addEventListener API. + + +export class WebSocketHibernationServer extends DurableObject { + async fetch(request: Request, env: Env, ctx: ExecutionContext) { + // Creates two ends of a WebSocket connection. + const webSocketPair = new WebSocketPair(); + const [client, server] = Object.values(webSocketPair); + + // Call this to accept the WebSocket connection. + // Do NOT call server.accept() (this is the legacy approach and is not preferred) + this.ctx.acceptWebSocket(server); + + return new Response(null, { + status: 101, + webSocket: client, + }); +}, + +async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { + // Invoked on each WebSocket message. + ws.send(message) +}, + +async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { + // Invoked when a client closes the connection. + ws.close(code, ""); +}, + +async webSocketError(ws: WebSocket, error: unknown): void | Promise { + // Handle WebSocket errors +} +} + + + + + +{user_prompt} + diff --git a/src/content/partials/ssl/cipher-suites-api-linkout.mdx b/src/content/partials/ssl/cipher-suites-api-linkout.mdx new file mode 100644 index 00000000000000..ceda6f3443c4a1 --- /dev/null +++ b/src/content/partials/ssl/cipher-suites-api-linkout.mdx @@ -0,0 +1,6 @@ +--- +{} + +--- + +If you are customizing cipher suites via API, refer to [Steps and API examples](/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/api/#steps-and-api-examples) for a snippet you can copy with the formatted array. \ No newline at end of file diff --git a/src/content/partials/ssl/cipher-suites-saas-linkout.mdx b/src/content/partials/ssl/cipher-suites-saas-linkout.mdx new file mode 100644 index 00000000000000..8d202297dd8d51 --- /dev/null +++ b/src/content/partials/ssl/cipher-suites-saas-linkout.mdx @@ -0,0 +1,6 @@ +--- +{} + +--- + +For guidance around custom hostnames, refer to [TLS settings - Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#cipher-suites). \ No newline at end of file diff --git a/src/content/partials/ssl/keyless-tunnel-setup.mdx b/src/content/partials/ssl/keyless-tunnel-setup.mdx index c23a18865e5b09..ec573bb9f4582a 100644 --- a/src/content/partials/ssl/keyless-tunnel-setup.mdx +++ b/src/content/partials/ssl/keyless-tunnel-setup.mdx @@ -3,4 +3,4 @@ --- -This process differs depending on whether you are using the [command line](/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/) or the [Cloudflare dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). +This process differs depending on whether you are using the [command line](/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/create-local-tunnel/) or the [Cloudflare dashboard](/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/). diff --git a/src/content/partials/style-guide/directory-listing-definition.mdx b/src/content/partials/style-guide/directory-listing-definition.mdx new file mode 100644 index 00000000000000..e301ae54c2538d --- /dev/null +++ b/src/content/partials/style-guide/directory-listing-definition.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +Use `` to display the directory of a specific folder, which appears as a list of links. \ No newline at end of file diff --git a/src/content/partials/style-guide/public-stats-definition.mdx b/src/content/partials/style-guide/public-stats-definition.mdx new file mode 100644 index 00000000000000..0feedc632bbe33 --- /dev/null +++ b/src/content/partials/style-guide/public-stats-definition.mdx @@ -0,0 +1,5 @@ +--- +{} +--- + +The `PublicStats` component allows you to reference specific values about Cloudflare's network without maintaining those values in multiple files. \ No newline at end of file diff --git a/src/content/partials/turnstile/siteverify-warning.mdx b/src/content/partials/turnstile/siteverify-warning.mdx index 1f0be698c2a4ef..77b83cc83234bc 100644 --- a/src/content/partials/turnstile/siteverify-warning.mdx +++ b/src/content/partials/turnstile/siteverify-warning.mdx @@ -4,6 +4,7 @@ --- :::caution[Warning] - It is critical to enforce Turnstile tokens with the siteverify API. The Turnstile token could be invalid, expired, or already redeemed. Not verifying the token will leave major vulnerabilities in your implementation. + +You **must** call siteverify to complete your Turnstile configuration. Otherwise, it is incomplete and will result in zeroes for token validation when viewing your metrics in [Turnstile Analytics](/turnstile/turnstile-analytics/). ::: diff --git a/src/content/partials/turnstile/siteverify.mdx b/src/content/partials/turnstile/siteverify.mdx new file mode 100644 index 00000000000000..84e05cec455cc9 --- /dev/null +++ b/src/content/partials/turnstile/siteverify.mdx @@ -0,0 +1,10 @@ +--- +{} + +--- + +It is important to [call the siteverify API](/turnstile/get-started/server-side-validation/). Without calling siteverify API to validate the tokens, your website or application is not protected. Skipping token validation means you cannot confirm the visitor's legitimacy. + +- Tokens can only be redeemed once. Even valid tokens will return `success:false` if they are reused, preventing token theft and replay attacks. +- Tokens expire after five minutes. Validation must occur within this window to be effective. +- Tokens can be invalid. Bots might complete challenges, but Cloudflare can detect bot-like signals and mark the token as invalid. \ No newline at end of file diff --git a/src/content/partials/waf/security-level-description.mdx b/src/content/partials/waf/security-level-description.mdx index 0533cd8a1a6766..19aebda9277ba4 100644 --- a/src/content/partials/waf/security-level-description.mdx +++ b/src/content/partials/waf/security-level-description.mdx @@ -1,6 +1,5 @@ --- {} - --- -Cloudflare's Security Level uses the threat score (IP reputation) to decide whether to present a [challenge](/waf/reference/cloudflare-challenges/) to the visitor. Once the visitor enters the correct challenge, they receive the appropriate website resources. +Cloudflare's Security Level uses the threat score (IP reputation) to decide whether to present a [challenge](/waf/reference/cloudflare-challenges/) to the visitor. Once the visitor enters the correct challenge, they receive the appropriate website resources. diff --git a/src/content/partials/waf/security-level-scores.mdx b/src/content/partials/waf/security-level-scores.mdx index e5a5e57aae68de..42e0533c6b7671 100644 --- a/src/content/partials/waf/security-level-scores.mdx +++ b/src/content/partials/waf/security-level-scores.mdx @@ -2,28 +2,18 @@ {} --- -## Security levels +In the Cloudflare dashboard, security level has the value _Always protected_ and you cannot change this setting. To turn Under Attack mode on or off, use the separate toggle. -Security levels are based on the threat score (except _Off_ and _I'm Under Attack!_). You can adjust the security level to challenge incoming requests based on the threat they pose. +In the API and in Terraform, use security level to turn Under Attack mode on or off. -The available security levels are the following: +Cloudflare's Under Attack mode performs additional security checks to help mitigate layer 7 DDoS attacks. -| Security Level | Description | -| ----------------------------------- | ------------------------------------------------------------------------------------ | -| Off (Enterprise
    customers only) | Does not challenge IP addresses. | -| Essentially off | Only challenges IP addresses with the worst reputation. | -| Low | Challenges only threatening visitors. | -| Medium | Challenges both threatening and moderately threatening visitors. | -| High | Challenges all visitors that exhibited threatening behavior within the last 14 days. | -| I'm Under Attack! | Only for use if your website is currently under a DDoS attack. | - -Selecting a higher **Security Level** value means that even requests with a lower risk (that is, with a low [threat score](#threat-score)) will be challenged. Selecting a lower **Security Level** value means that only requests posing a higher risk (that is, with a high threat score) will be challenged. - -Security levels from _Essentially off_ to _High_ will challenge the visitor using a Managed Challenge. When you select _I'm Under Attack!_, which enables [I'm Under Attack mode](/fundamentals/reference/under-attack-mode/), Cloudflare will present a JS challenge page. +When you select _I'm Under Attack!_, which enables [Under Attack mode](/fundamentals/reference/under-attack-mode/), Cloudflare will present a JS challenge page. :::caution -Only use [I'm Under Attack mode](/fundamentals/reference/under-attack-mode/) when a website is under a DDoS attack. I'm Under Attack mode may affect some actions on your domain, such as your API traffic. +Only use [Under Attack mode](/fundamentals/reference/under-attack-mode/) when a website is under a DDoS attack. Under Attack mode may affect some actions on your domain, such as your API traffic. To set a custom security level for your API or any other part of your domain, create a [configuration rule](/rules/configuration-rules/). + ::: diff --git a/src/content/partials/waf/threat-score-definition.mdx b/src/content/partials/waf/threat-score-definition.mdx index d0a07325129ddc..87063f7dd3b90f 100644 --- a/src/content/partials/waf/threat-score-definition.mdx +++ b/src/content/partials/waf/threat-score-definition.mdx @@ -4,9 +4,7 @@ ## Threat score -The threat score measures IP reputation across Cloudflare services. This score is calculated based on [Project Honeypot](https://www.projecthoneypot.org/), external public IP information, as well as internal threat intelligence from our [WAF managed rules](/waf/reference/legacy/old-waf-managed-rules/) and [DDoS](/ddos-protection/about/). - -The threat score of a request has a value from 0 to 100, where 0 indicates low risk. Values above 10 may represent spammers or bots, and values above 40 identify bad actors on the Internet. +Previously, a threat score represented a Cloudflare threat score from 0–100, where 0 indicates low risk. Now, the threat score is always `0` (zero). :::note[Recommendation] Currently we do not recommend creating rules based on the threat score, since this score is no longer being populated. diff --git a/src/content/partials/warp-client/consumer-warp-download.mdx b/src/content/partials/warp-client/consumer-warp-download.mdx new file mode 100644 index 00000000000000..9d1f5b6c63eb8b --- /dev/null +++ b/src/content/partials/warp-client/consumer-warp-download.mdx @@ -0,0 +1,9 @@ +--- +{} +--- + +:::caution[Consumer WARP] + +This documentation is for the consumer version of WARP. If you are using WARP with Cloudflare Zero Trust, refer to the [Zero Trust documentation](/cloudflare-one/connections/connect-devices/warp/). + +::: diff --git a/src/content/partials/workers/c3-post-run-steps.mdx b/src/content/partials/workers/c3-post-run-steps.mdx index 877dd4e55086a6..3f23380e6b9126 100644 --- a/src/content/partials/workers/c3-post-run-steps.mdx +++ b/src/content/partials/workers/c3-post-run-steps.mdx @@ -11,7 +11,7 @@ switch (props.category) { case 'hello-world': return (