Ghost添加S3支持(Cloudflare R2)
在Cloudflare创建好bucket、配置自定义域、CORS 策略
自定义域:
CNAME files.ghost.xxx.xxx <cloudflare account id>.r2.cloudflarestorage.com
创建文件夹&拉取源代码
cd ~/docker/social/ghost/data/ghost
mkdir -p adapters/storage && cd adapters/storage
git clone https://github.com/colinmeinke/ghost-storage-adapter-s3.git s3
cd s3安装下載 Node.js® 24 LTS & 安装S3支持
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 24
node -v
npm -v
npm install在.env 添加如下内容,确保compose.yaml定义了.env
env_file:
- .envstorage__active=s3
AWS_ACCESS_KEY_ID=xxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxx
AWS_DEFAULT_REGION=auto
GHOST_STORAGE_ADAPTER_S3_PATH_BUCKET=ghost
GHOST_STORAGE_ADAPTER_S3_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
GHOST_STORAGE_ADAPTER_S3_PATH_PREFIX=ghost
GHOST_STORAGE_ADAPTER_S3_FORCE_PATH_STYLE=true
GHOST_STORAGE_ADAPTER_S3_ASSET_HOST=https://files.ghost.xxx.xxx重构容器
cd ~/docker/social/ghost
docker compose down
docker compose up -d参考文献:
Official Ghost + Amazon S3 Integration
Connect your Ghost site with Amazon S3 for secure, scalable image storage & use the Amazon service as an integrated media library interface! Find out how 👉

GitHub - colinmeinke/ghost-storage-adapter-s3: An AWS S3 storage adapter for Ghost
An AWS S3 storage adapter for Ghost. Contribute to colinmeinke/ghost-storage-adapter-s3 development by creating an account on GitHub.
可参考的最小化compose.yaml(不包括activitypub、tinybird、caddy)
# yaml-language-server: $schema=https://raw.githubusercontent.com/compose-spec/compose-spec/main/schema/compose-spec.json
services:
ghost:
container_name: ghost
# Do not alter this without updating the Tinybird Sync container as well
image: ghost:${GHOST_VERSION:-6-alpine}
ports:
- "127.0.0.1:2368:2368"
restart: always
# This is required to import current config when migrating
env_file:
- .env
environment:
NODE_ENV: production
url: https://${DOMAIN:?DOMAIN environment variable is required}
database__client: mysql
database__connection__host: ghost_db
database__connection__user: ${DATABASE_USER:-ghost}
database__connection__password: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required}
database__connection__database: ghost
volumes:
- ${UPLOAD_LOCATION:-./data/ghost}:/var/lib/ghost/content
depends_on:
ghost_db:
condition: service_healthy
networks:
- ghost_network
ghost_db:
container_name: ghost_db
image: mysql:8.0.44@sha256:f37951fc3753a6a22d6c7bf6978c5e5fefcf6f31814d98c582524f98eae52b21
restart: always
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD:?DATABASE_ROOT_PASSWORD environment variable is required}
MYSQL_USER: ${DATABASE_USER:-ghost}
MYSQL_PASSWORD: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required}
MYSQL_DATABASE: ghost
volumes:
- ${MYSQL_DATA_LOCATION:-./data/mysql}:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: mysqladmin ping -p$$MYSQL_ROOT_PASSWORD -h 127.0.0.1
interval: 1s
start_period: 30s
start_interval: 10s
retries: 120
networks:
- ghost_network
networks:
ghost_network:可参考的最小化.env 文件
DOMAIN=ghost.feddit.social
DATABASE_ROOT_PASSWORD=
DATABASE_PASSWORD=
mail__transport=SMTP
mail__options__host=smtp.xxx.xxx
mail__options__port=465
mail__options__secure=true
mail__options__auth__user=
mail__options__auth__pass=
mail__from="'Ghost.Feddit.Social' <>"
UPLOAD_LOCATION=./data/ghost
MYSQL_DATA_LOCATION=./data/mysql
storage__active=s3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=auto
GHOST_STORAGE_ADAPTER_S3_PATH_BUCKET=ghost
GHOST_STORAGE_ADAPTER_S3_ENDPOINT=https://<cloudflare id>.r2.cloudflarestorage.com
GHOST_STORAGE_ADAPTER_S3_PATH_PREFIX=ghost
GHOST_STORAGE_ADAPTER_S3_FORCE_PATH_STYLE=true
GHOST_STORAGE_ADAPTER_S3_ASSET_HOST=https://files.ghost.feddit.social