2042 字
10 分钟
Chevereto + Cloudflare R2 搭建图床
2026-03-27
2026-04-01
- 次浏览

背景说明#

记录一下准备搭建图床时的选型思路,以及为什么选择 Chevereto + Cloudflare R2 这套方案。

为什么不是继续用 PicGo + GitHub#

之前用过 PicGo + GitHub + Cloudflare 的方案,这种方式在早期很省事,但越往后越容易遇到问题:

PicGo + GitHub + Cloudflare 搭建图床
搭建 PicGo + GitHub 图床,并通过 Cloudflare 实现全站 CDN 加速。
🔗/posts/blog/github-image-hosting-with-picgo/
Blog
  • GitHub 仓库并不适合长期堆大量图片资源
  • 图片管理能力很弱,更像“上传文件”而不是“管理图片”
  • 后续想做图库、随机图、分类整理时会比较别扭
  • 一旦图片越来越多,迁移和维护都会变麻烦

所以这次我更希望直接把图床搭成一个“能长期用的图片管理系统”。

选择 Chevereto + Cloudflare R2 的原因#

Chevereto 更接近一个完整的图片托管系统,而不是单纯的上传工具:

chevereto
/
chevereto
Waiting for api.github.com...
00K
0K
0K
Waiting...
  • 支持图片托管和管理
  • 支持相册、分类、公开访问
  • 更适合后续给博客做图库数据源
  • 支持 API 和更完整的后台思路
  • 官方支持 S3 兼容存储

Cloudflare R2 的优势主要在于:

  • 兼容 S3 API
  • 和对象存储生态兼容性好
  • 适合作为图片底层存储
  • 后续要切换展示层时,存储层可以尽量保持不变

Chevereto 官方支持 S3 Compatible 存储,而 R2 本身也提供 S3-compatible API,所以两者组合起来是成立的。

实际使用后的补充说明#

这套方案在图片管理、相册组织、存储解耦这些方面,确实比之前的 PicGo + GitHub + Cloudflare 更完整,也更像一套正式的图床系统。

不过在实际使用一段时间后,我也发现一个很现实的问题:

Chevereto + Cloudflare R2 并不一定在访问速度上优于 PicGo + GitHub + Cloudflare。

在部分使用场景里,虽然图片请求已经可以命中 Cloudflare 缓存,但整体体感速度仍然未必比原先方案更快。

所以如果核心诉求是:

  • 博客配图尽量快
  • 更在意访问速度而不是后台管理
  • 希望方案越简单越好

那么 PicGo + GitHub + Cloudflare 这类纯静态资源方案,可能依然是更适合的选择。

Chevereto + Cloudflare R2 更适合这些场景:

  • 想要完整的图片管理后台
  • 需要相册、分类、公开访问能力
  • 希望把图片存储和博客系统彻底分离
  • 后续可能把图床作为图库或内容源继续扩展

整体架构#

上传链路:
浏览器 / Chevereto 后台
Chevereto
R2
访问链路:
用户
img.example.com(自定义域名)
Cloudflare Cache / CDN
R2

Chevereto 部署#

如果是第一次搭建,建议直接走 Docker 部署

创建项目目录#

Terminal window
sudo mkdir -p /opt/chevereto
cd /opt/chevereto
sudo mkdir -p data/mysql
sudo mkdir -p data/images

创建 docker-compose.yml#

Terminal window
sudo vim /opt/chevereto/docker-compose.yml
/opt/chevereto/docker-compose.yml
services:
mariadb:
image: mariadb:11
container_name: chevereto-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: change_this_root_password # MariaDB root 密码
MYSQL_DATABASE: chevereto # 自动创建的数据库名
MYSQL_USER: chevereto # 应用连接数据库使用的用户名
MYSQL_PASSWORD: change_this_db_password # 应用连接数据库的密码
volumes:
- ./data/mysql:/var/lib/mysql # 挂载数据库数据目录,防止容器删除后数据丢失
chevereto:
image: chevereto/chevereto:latest
container_name: chevereto
restart: unless-stopped
depends_on:
- mariadb # 先启动数据库,再启动 chevereto
ports:
- "8080:80" # 宿主机 8080 映射到容器 80
environment:
CHEVERETO_DB_HOST: mariadb # 数据库主机名,对应上面的服务名
CHEVERETO_DB_USER: chevereto # 数据库用户名
CHEVERETO_DB_PASS: change_this_db_password # 数据库密码
CHEVERETO_DB_PORT: 3306 # 数据库端口
CHEVERETO_DB_NAME: chevereto # 数据库名
CHEVERETO_MAX_POST_SIZE: 128M # POST 请求大小限制
CHEVERETO_MAX_UPLOAD_SIZE: 128M # 单次上传大小限制
volumes:
- ./data/images:/var/www/html/images # 本地图片目录挂载

启动容器#

Terminal window
docker compose up -d

查看状态:

Terminal window
docker ps
docker compose logs -f

如果两个容器都正常运行,说明本体已经起来了。

常见问题

Chevereto 容器里的 PHP 运行用户 www-data,没有权限写入 /images/ 目录

宿主机上的 ./data/images 被挂进容器后,容器里的 www-data 没法写。

问题原因

Docker 挂载目录时,容器内程序以 www-data 身份运行,但宿主机目录可能是 root:root 所以容器虽然能看到目录,但不能写入,这在 PHP 程序里很常见。

解决办法

项目目录下执行:

Terminal window
cd /opt/chevereto
sudo chown -R 33:33 ./data/images
sudo chmod -R 775 ./data/images

这里的 33:33 通常就是 Debian/Ubuntu 系里 www-data 的 uid/gid。

然后重启容器:

Terminal window
docker compose restart

配置 Nginx#

创建站点配置文件(推荐独立文件,便于管理):

Terminal window
sudo vim /etc/nginx/conf.d/chevereto.conf
/etc/nginx/conf.d/chevereto.conf
server {
# 80 强制跳转到 443
listen 80;
server_name chevereto.example.com;
# HTTP 请求永久重定向到 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
# 当前 HTTPS 站点绑定的域名
server_name chevereto.example.com;
# ssl证书配置
ssl_certificate /etc/nginx/ssl/chevereto.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/chevereto.example.com/privkey.pem;
# 关闭 session tickets,减少某些场景下的安全风险
ssl_session_tickets off;
# 关闭“优先使用服务端加密套件”设置
ssl_prefer_server_ciphers off;
# 日志配置
access_log /var/log/nginx/chevereto.example.com.access.log;
error_log /var/log/nginx/chevereto.example.com.error.log warn;
# 上传大小限制
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
# 与后端建立连接的超时时间
proxy_connect_timeout 60s;
# 向后端发送请求的超时时间
proxy_send_timeout 60s;
# 等待后端响应的超时时间
proxy_read_timeout 60s;
# 关闭代理缓冲
proxy_buffering off;
}
}

检查并重载 Nginx:

Terminal window
nginx -t
nginx -s reload

完成 Chevereto 首次安装#

浏览器打开:https://chevereto.example.com

进入初始化页面:

完成管理员账号创建

chevereto r2 astro guide 1

修改为中文界面

chevereto r2 astro guide 2


创建 Cloudflare R2 Bucket#

创建 R2 Bucket#

在 Cloudflare 控制台里操作:

  1. 点左侧存储和数据库

  2. 进入 R2 对象存储

  3. 点击创建存储桶

chevereto r2 astro guide 3

  1. 填写存储桶信息,点击创建

chevereto r2 astro guide 4

创建 API 密钥#

  1. 回到 R2 对象存储

  2. 点击创建 API 密钥

chevereto r2 astro guide 5

记录 S3 API,后续配置 Chevereto 的 Endpoint 时需要。

  1. 填写密钥信息,点击创建

chevereto r2 astro guide 6

创建 API 密钥,拿到:

  • Access Key ID (访问密钥 ID)
  • Secret Access Key (机密访问密钥)

chevereto r2 astro guide 7

机密访问密钥

通常只显示一次。 如果没保存,后面一般只能重新生成。

公网访问地址#

  1. 回到 R2 对象存储

  2. 进入新建的 images,点击设置

  3. 启用公共开发 URL,点击保存(生产环境建议使用自定义域名,公共开发 URL 存在限速问题)

chevereto r2 astro guide 8


配置 Chevereto 连接 R2#

进入配置页面#

仪表盘 -> 设置 -> Upload storage -> Add 存储

chevereto r2 astro guide 9

配置 R2 存储桶#

项目
APIS3 Compatible
名称Cloudflare R2
区域auto
Bucketimages
访问密钥 IDAccess Key ID
私有访问密钥Secret Access Key
EndpointS3 API
存储容量1 TB
URLR2 自定义域名(测试可用公共开发 URL)

chevereto r2 astro guide 10

保存完成后需要勾选启用存储

chevereto r2 astro guide 11

部署完成后的访问推荐#

图片访问域名与后台域名分离

建议:

  • chevereto.example.com:Chevereto 管理站
  • img.example.com:R2 图片访问域名(开发测试阶段可临时使用 R2 公共开发 URL,正式环境更建议绑定自定义域名)

配置定时任务#

Chevereto 需要 cron 来执行后台任务。

这些任务包括:

  • 清理未确认用户
  • 删除过期图片
  • 删除待清理存储文件
  • 删除废弃上传分片
  • 检查更新等

可以加到系统 cron 里,例如每 5 分钟执行一次:

Terminal window
*/5 * * * * docker exec --user www-data chevereto app/bin/cli -C cron >/dev/null 2>&1

前面 compose 里已经指定了容器为 chevereto,所以如果你的容器不是 chevereto,记得替换掉。


上传测试图验证连接#

接入 R2 后,上传一张图片,检查三件事:

1. Chevereto 后台能看到图片

说明应用逻辑正常。

2. R2 bucket 里出现对象

说明上传已经真正写进对象存储。

3. 图片 URL 能直接访问

sample pictures

说明 Storage URL 和公网访问配置正确。

如果第 2 条成功但第 3 条失败,通常问题不在 Chevereto,而在:

  • Storage URL 填错
  • R2 公共访问没开
  • 自定义域名没配好
  • Cloudflare 代理规则不对
Chevereto + Cloudflare R2 搭建图床
https://blog.xhwen.cn/posts/blog/chevereto-r2-astro-guide/
作者
朗姆提子冰淇淋
发布于
2026-03-27
许可协议
CC BY-NC-SA 4.0
评论
评论加载中…