Skip to content

Document built-in S3 storage adapter - #118

Open
allouis wants to merge 1 commit into
mainfrom
fabien-hkg-1948-document-built-in-s3-storage-adapter
Open

Document built-in S3 storage adapter#118
allouis wants to merge 1 commit into
mainfrom
fabien-hkg-1948-document-built-in-s3-storage-adapter

Conversation

@allouis

@allouis allouis commented Aug 11, 2026

Copy link
Copy Markdown

Ghost now ships an S3Storage adapter in core, but the config docs only listed third-party storage modules. This documents the built-in adapter and its full configuration options so operators can set up S3-compatible object storage (Amazon S3, MinIO, GCS, Cloudflare R2, etc.) without reverse-engineering the schema.

ref https://linear.app/ghost/issue/HKG-1948

Test plan

  • pnpm lint passes
  • Preview config.mdx with pnpm dev, confirm the new "Ghost's built-in S3-compatible storage adapter" subsection renders under Storage adapters with the JSON block and options table intact

ref https://linear.app/ghost/issue/HKG-1948

Ghost now ships an S3Storage adapter in core, but the config docs only
listed third-party storage modules. Document the built-in adapter and
its configuration options so operators can set up S3-compatible object
storage without reverse-engineering the schema.
@mintlify

mintlify Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Ghost 🟢 Ready View Preview Aug 11, 2026, 5:53 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The documentation adds coverage for Ghost’s built-in S3Storage adapter. It describes image, media, and file configuration, supported S3-compatible providers, a complete JSON example, and required and optional settings.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: praveen902012, renatoworks

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: documenting Ghost’s built-in S3 storage adapter.
Description check ✅ Passed The description explains the documentation change, supported providers, configuration scope, and validation steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fabien-hkg-1948-document-built-in-s3-storage-adapter

Comment @coderabbitai help to get the list of available commands.

@allouis
allouis marked this pull request as ready for review August 11, 2026 06:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config.mdx`:
- Line 550: Update the multipartUploadThresholdBytes description in the
S3Storage configuration table to state that files at least this size use
multipart upload, reflecting the inclusive greater-than-or-equal threshold
behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2805eb9c-3ebf-4698-992b-54fd70b4f91d

📥 Commits

Reviewing files that changed from the base of the PR and between ac41a35 and ed7c4c5.

📒 Files selected for processing (1)
  • config.mdx

Comment thread config.mdx
| `bucket` | Yes | Name of the S3 bucket. |
| `cdnUrl` | Yes | Public base URL that stored files are served from (your CDN or the bucket's public URL). Ghost builds each file's public URL from this value. |
| `staticFileURLPrefix` | Yes | Path prefix within the bucket that files are stored under, e.g. `content/images`. |
| `multipartUploadThresholdBytes` | Yes | Files larger than this size (in bytes) are uploaded using S3 multipart upload. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- candidate files ---'
git ls-files | rg '(^|/)(config\.mdx|S3Storage(\.[^/]*)?|.*S3.*[Tt]est.*)$' || true

printf '%s\n' '--- threshold references ---'
rg -n -C 4 'multipartUploadThresholdBytes|multipart upload' . \
  -g '!node_modules' -g '!dist' -g '!build' || true

Repository: TryGhost/Docs

Length of output: 1715


🏁 Script executed:

#!/bin/bash
set -eu

url='https://unpkg.com/ghost@6.13.2/core/server/adapters/storage/S3Storage.ts'
printf '%s\n' '--- published S3Storage.ts threshold logic ---'
curl -fsSL "$url" | rg -n -C 8 \
  'multipartUploadThresholdBytes|createMultipartUpload|uploadPart|>=|>'

printf '%s\n' '--- exact source lines ---'
curl -fsSL "$url" | nl -ba | rg -n -C 5 \
  'multipartUploadThresholdBytes|createMultipartUpload|uploadPart'

Repository: TryGhost/Docs

Length of output: 9917


Document the threshold as inclusive.

S3Storage uses multipart upload when the file size is greater than or equal to multipartUploadThresholdBytes. Change “Files larger than this size” to “Files at least this size.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config.mdx` at line 550, Update the multipartUploadThresholdBytes description
in the S3Storage configuration table to state that files at least this size use
multipart upload, reflecting the inclusive greater-than-or-equal threshold
behavior.

Source: MCP tools

@vershwal vershwal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments!

Comment thread config.mdx
"multipartUploadThresholdBytes": 52428800,
"multipartChunkSizeBytes": 10485760
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config should also have urls.image / urls.media / urls.files. When assets are served from a different CDN host, Ghost needs these values to recognize them as its own. Without them, responsive image sizes aren't generated, and the CDN URL gets stored directly in your content instead of Ghost's portable __GHOST_URL__ form.

Comment thread config.mdx

| Option | Required | Description |
|---|---|---|
| `bucket` | Yes | Name of the S3 bucket. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT - Bucket must be publicly readable. "Name of the public S3 bucket." maybe?

Comment thread config.mdx
|---|---|---|
| `bucket` | Yes | Name of the S3 bucket. |
| `cdnUrl` | Yes | Public base URL that stored files are served from (your CDN or the bucket's public URL). Ghost builds each file's public URL from this value. |
| `staticFileURLPrefix` | Yes | Path prefix within the bucket that files are stored under, e.g. `content/images`. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example is correct but staticFileURLPrefix isn't really a free-form value. It needs to be content/images, content/media, or content/files depending on the feature, since Ghost matches those prefixes when building URLs.

Comment thread config.mdx

Ghost ships with an `S3Storage` adapter that stores files in Amazon S3 or any S3-compatible provider (such as MinIO, Google Cloud Storage, or Cloudflare R2). No additional module needs to be installed.

Because images, media, and files each need their own path prefix, share a single `S3Storage` configuration block and override `staticFileURLPrefix` per feature:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worth mentioning that adapters can be mixed per feature. Media and files can use S3 while images stay on local storage; they don't all need to move together.

Comment thread config.mdx

#### Ghost's built-in S3-compatible storage adapter

Ghost ships with an `S3Storage` adapter that stores files in Amazon S3 or any S3-compatible provider (such as MinIO, Google Cloud Storage, or Cloudflare R2). No additional module needs to be installed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users will have to do the migration as existing images on the local will start failing - this is something that's needed, but not sure if we need to add this in the docs.

Copy the existing content/images|media|files into the bucket under the same prefix first

Comment thread config.mdx
| `staticFileURLPrefix` | Yes | Path prefix within the bucket that files are stored under, e.g. `content/images`. |
| `multipartUploadThresholdBytes` | Yes | Files larger than this size (in bytes) are uploaded using S3 multipart upload. |
| `multipartChunkSizeBytes` | Yes | Size (in bytes) of each multipart part. Must be at least 5 MiB (`5242880`). |
| `region` | No | Region of the bucket. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT - Not a required field but AWS S3 needs it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants