Cloudflare Services: Cloudflare 服务一览、R2 对象存储与 Tunnel

Cloudflare 起家是 CDN 和 DNS,现在的产品线已经覆盖网络、安全、开发者平台和存储。这篇先按用途列一遍常用服务,再单独讲 R2 对象存储和 Tunnel。各服务的额度和价格会调整,以官方文档为准(本文核对于 2026-10)。 服务一览 网络与安全 服务 说明 DNS 权威 DNS,免费。域名的 NS 指到 Cloudflare 以后,其他服务才能接上 CDN / 代理 DNS 记录打开代理(橙色云朵)后,流量先经过 Cloudflare 边缘节点,静态内容在边缘缓存 SSL/TLS 边缘证书自动签发;回源可用 Origin CA 证书(只被 Cloudflare 信任,有效期最长 15 年),模式应选 Full (strict) WAF / DDoS 防护 代理开着时自动生效,免费版有基础规则 Turnstile 人机验证,替代 reCAPTCHA,免费 Registrar 域名注册,按成本价续费,不加价 开发者平台 服务 说明 Pages 静态站点和前端项目托管,连 Git 仓库自动构建,见 Hugo + Cloudflare Pages 搭建个人博客 Workers 边缘 Serverless 运行环境,见 Cloudflare Workers KV 全球分布的键值存储,读多写少,最终一致 D1 基于 SQLite 的关系型数据库 R2 对象存储,兼容 S3 API,没有出口流量费,见下文 Durable Objects 带强一致状态的单实例对象,适合协同编辑、计数、WebSocket Queues 消息队列 Workers AI 在边缘调用推理模型 KV、D1、R2、Durable Objects、Queues 都可以通过 binding 注入 Worker 使用。 ...

Created 14146-10-14 · Updated 20206-10-20 · 4 min · 690 words · -

Cloudflare Workers: 边缘 Serverless 运行环境

Cloudflare Workers 是什么 Cloudflare Workers 是 Cloudflare 提供的 Serverless 运行环境:把一段 JavaScript / TypeScript(也支持 Python 和编译成 WebAssembly 的 Rust、Go 等)部署到 Cloudflare 全球的边缘节点上,请求打到离用户最近的节点时直接在那里执行代码并返回响应,不需要自己管服务器。 和 AWS Lambda 这类传统 FaaS 相比,主要区别在运行时: 对比项 Cloudflare Workers 传统 FaaS(如 Lambda) 隔离方式 V8 Isolate,多个 Worker 共享一个进程 容器 / microVM 冷启动 毫秒级,基本可忽略 百毫秒到秒级 部署位置 全球所有边缘节点 选定的一个或几个 region 运行时 类浏览器的 Web 标准 API(fetch、Request、Response 等),部分兼容 Node.js API 完整的 Node.js / Python 等运行时 限制 CPU 时间、内存(128 MB)、包体积有限制 限制相对宽松 V8 Isolate 是 Chrome 的 JS 引擎里用来隔离不同页面的机制,开销比容器小很多,所以冷启动快、单机能跑大量 Worker;代价是不能运行任意二进制,也不能使用依赖原生模块的 npm 包。 ...

Created 4046-10-04 · Updated 4046-10-04 · 3 min · 500 words · -

WeChat QR to PDF: 微信扫码查看与下载 PDF

设计目标:用户用微信扫事先印好的二维码,在手机里查看 PDF,并能下载。技术栈固定为自购域名、GitHub 私有仓库、Cloudflare Pages、离线生成二维码。不使用 Hugo,也不需要后端。 域名购买、DNS 切到 Cloudflare、Pages 绑自定义域名的操作步骤,与本站博客相同,见 Hugo + Cloudflare Pages 搭建个人博客。本文只写和「微信扫码 + PDF」有关的设计选择。 目标与非目标 目标 微信扫码打开 HTTPS 页面,能预览 PDF 页面上提供下载 PDF 源文件放在 GitHub 私有仓库里,不在 GitHub 网页上公开浏览 更新 PDF 时尽量不换二维码(同一 URL 覆盖文件即可) 非目标 不做登录、不做按人授权。知道链接的人都能打开 不接入微信公众号、JS-SDK、微信支付 不在微信里做「仅好友可见」之类的权限 单文件超过 Cloudflare Pages 限制(25 MiB)时,本方案不够,需改对象存储 整体结构 二维码里只放一个 URL,不放 PDF 本身。扫码等于用微信内置浏览器打开这个地址。 Printed QR --> https://files.example.com/catalog/ | +-- index.html landing page +-- catalog.pdf the file 组件 作用 自购域名 二维码里的长期地址,例如 files.example.com GitHub 私有仓库 存放 HTML 和 PDF,只有仓库成员能在 GitHub 上看到 Cloudflare Pages 从私有仓库拉取并托管静态文件,对外提供 HTTPS 二维码图片 事先生成、打印或贴到物料上,内容是落地页 URL 仓库私有只挡住 GitHub 上的浏览和 clone。部署到 Pages 之后,站点是公开的。这是预期行为:扫码的人没有 GitHub 账号,也必须能打开。 ...

Created 28286-08-28 · Updated 28286-08-28 · 2 min · 413 words · -

Hugo + Cloudflare Pages 搭建个人博客

本文记录这个博客的搭建方式,从买域名到发布一个静态站点。技术选型和步骤与本站的实现保持一致。 这套技术栈长什么样 一句话概览:用 Hugo 把 Markdown 编译成静态页面,源码在 GitHub,Cloudflare Pages 连接 GitHub 仓库并在 Cloudflare 侧构建、托管,域名解析和 CDN 也在 Cloudflare。 各部分的分工: 组件 作用 Hugo 静态站点生成器,把 content/ 下的 Markdown 编译成 HTML GitHub 存放源码,作为部署的触发源 Cloudflare Pages 连接 GitHub 仓库,执行 hugo --minify 构建并托管产物 Cloudflare DNS 域名解析,把自定义域名指向 Pages 项目 Cloudflare CDN 边缘缓存与加速,Pages 默认自带 整个流程没有用 GitHub Actions,也没有容器化构建,构建这一步完全由 Cloudflare Pages 在它自己的环境里完成。基础站点的构建命令就是一句 hugo --minify;本站为了顺带生成搜索索引,把它包成了一个很短的脚本(见下文进阶模块),思路一样。 基础模块 这一部分从 0 到「能访问」。 买域名 域名可以在任意注册商购买,我最早是在 GoDaddy 买的。以 GoDaddy 为例: 打开 godaddy.com,在搜索框里输入想要的域名,看是否可注册。 选一个后缀(.com、.dev 等),加入购物车,结账。注意第一年常有促销价,续费价通常更高,下单前看清续费价格。 结账时可关掉 GoDaddy 自家的一堆增值服务(邮箱、隐私保护等),后面把 DNS 切到 Cloudflare 后这些大多用不上。 Cloudflare 自己也能直接注册域名(Cloudflare Registrar,按批发价、免费 WHOIS 隐私保护),但支持的后缀有限。如果想要的后缀在它的列表里,直接在 Cloudflare 买、省去后面改 Nameserver 的步骤也可以;后缀不在列表里就按上面的思路在别的注册商买,再把 DNS 切过来。 ...

Created 9096-07-09 · Updated 9096-07-09 · 3 min · 452 words · -

Cloudflare Pages with OpenTofu: 用 IaC 管理 Pages 项目

在 Cloudflare 后台点几下就能建好一个 Pages 项目、绑好域名。想把这些配置变成可版本化、可复现的代码,就用 OpenTofu 来管理。本文只讲 Cloudflare 场景的具体写法,Provider、Resource、State 这些基础概念见 OpenTofu 入门。 目标 用 OpenTofu 声明式地管理三样东西: 一个连接 GitHub 仓库的 Cloudflare Pages 项目(含构建命令、产物目录、环境变量) 项目绑定的自定义域名 指向 Pages 的 DNS 记录 准备 需要两个 Cloudflare 侧的标识和一个 API Token: 变量 从哪来 Account ID Cloudflare 后台任意页面右侧栏,或 Workers & Pages 概览页 Zone ID 域名的 Overview 页面右侧栏 API Token My Profile → API Tokens → Create Token,授予 Pages 编辑和 DNS 编辑权限 Token 属于机密,不要写进代码,用环境变量注入: export TF_VAR_cloudflare_api_token="your-token-here" Provider 配置 terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" version = "~> 4" } } } variable "cloudflare_api_token" { type = string sensitive = true } variable "account_id" { type = string } variable "zone_id" { type = string } provider "cloudflare" { api_token = var.cloudflare_api_token } Pages 项目 cloudflare_pages_project 对应后台的一个 Pages 项目,source 块声明连接哪个 GitHub 仓库,build_config 对应构建命令和产物目录,deployment_configs 里可以设环境变量(例如 HUGO_VERSION)。 ...

Created 9096-07-09 · Updated 9096-07-09 · 2 min · 272 words · -

Why the Blog Looked Quiet 一次构建失败导致的「假性停更」

本文是一条故障记录。 最近两天 wiloon.com 看起来像是“停更”,停在6月28号。但其实 blog 仓库是有更新的,也提交了,只是没能发布出来——博客有大约两天卡在一次构建失败上,而我自己一直不知道。 不是停更,是没发布出去 现象很简单:本地写好、git push 之后,wiloon.com 上看不到新内容。一开始我以为是 CDN 缓存或者部署延迟,没太在意。后来才发现是构建一直在失败——新提交根本没被发布出去。 怎么坏的 原因是文章标题里的一个冒号。 博客用 Hugo,文章开头的 front matter 是一段 YAML。我有几篇 Java/Spring 的文章标题是英中混写的,里面带了「冒号 + 空格」,比如: # breaks the build: ": " makes YAML parse it as a mapping title: Spring WebFlux: 响应式 Web 框架 在 YAML 里,: (冒号加空格)是 key/value 的分隔符。没加引号时,解析器会把这一行当成一个嵌套映射来读,于是报错、Hugo 构建中止。一篇的 front matter 解析失败,整站就一个页面都不生成。 修复其实只要把整个标题值用引号包起来: # fixed: quote the whole value so the colon is just text title: "Spring WebFlux: 响应式 Web 框架" 加上引号之后,构建立刻就恢复了。 ...

Created 30306-06-30 · Updated 30306-06-30 · 2 min · 233 words · -

ddns-go 与 aliyun-ddns-cli

ddns-go ddns-go 是一个轻量、可视化配置的 DDNS 工具,支持多家 DNS 服务商。这里主要用于检测家里公网 IP 变化后自动更新 Cloudflare 记录。 https://github.com/jeessy2/ddns-go aliyun-ddns-cli https://github.com/honwen/aliyun-ddns-cli aliyun-ddns-cli --access-key-id=ak0 --access-key-secret=sk0 auto-update --domain=domain0.wiloon.com --redo=600 docker run -d \ -e "AKID=[ALIYUN's AccessKey-ID]" \ -e "AKSCT=[ALIYUN's AccessKey-Secret]" \ -e "DOMAIN=ddns.aliyun.win" \ -e "REDO=600" \ -e "TTL=600" \ chenhw2/aliyun-ddns-cli

Created 26266-01-26 · Updated 4046-06-04 · 1 min · 42 words · -

网站访问统计:Umami + Cloudflare Web Analytics

背景 Hugo 博客(PaperMod 主题)默认没有访问统计。为了了解谁在访问、访问了哪些页面,选择同时接入两套统计: Umami:隐私友好,无 cookie,数据存储在 Umami 服务器 Cloudflare Web Analytics:与 Cloudflare 基础设施集成,数据存储在 Cloudflare 两者不冲突,可以同时运行,便于对比数据。 Umami 特点 无 cookie,无跨站追踪,不需要 GDPR 同意弹窗 免费 Hobby 计划:100K 事件/月,3 个站点,6 个月数据保留 地理位置精度:国家级别 统计维度 页面浏览量(PV)、独立访客数(UV) 每次会话浏览页数、跳出率、平均停留时间 引荐来源、UTM 参数 国家/地区、操作系统、浏览器、设备类型 各页面访问量排行 Browsers:Chrome、Chrome (iOS) 与 iOS Umami 在 Environment → Browsers 里根据访问请求的 User-Agent(UA) 解析浏览器名称,与 Environment → OS 里的操作系统是两套维度,不要混看。 显示名称 含义 Chrome 桌面端或 Android 等环境下的 Chrome;UA 不含 iOS 专用标记 Chrome (iOS) iPhone / iPad 上用 Chrome App 打开;UA 含 CriOS/版本号 iOS 能判断是 iOS 上的浏览器或 WebView,但 未识别 为 Safari、Chrome、Firefox、Edge 等时的兜底分类 列表里 Chrome (iOS) 与 iOS 各计 1 个访客,通常表示 两次不同访问(不同人或不同设备 / 浏览器),不是同一次访问被记了两遍。 ...

Created 10106-05-10 · Updated 30306-05-30 · 2 min · 341 words · W10N

Pomodoro — A Minimal Timer PWA for Always-On Phone Display

Live: https://pomodoro.wiloon.com · Source: github.com/wiloon/pomodoro-vue The Problem Sitting for long periods is hard on your back and neck. I wanted a simple reminder to stand up and move every 30 minutes. Most Pomodoro apps I tried were overly complex — they required accounts, had task lists, synced to the cloud, or sent too many notifications. I didn’t need any of that. I just needed a countdown on a screen I could glance at. ...

Created 18186-05-18 · Updated 18186-05-18 · 3 min · 547 words · -