The Wayback Machine - https://web.archive.org/web/20251204203126/https://github.com/TryGhost/Ghost/pull/25436
Skip to content

Conversation

@allouis
Copy link
Collaborator

@allouis allouis commented Nov 13, 2025

ref https://linear.app/ghost/issue/PRO-1534

The idea behind this approach is to be non-intrusive to existing development flows, but allow a zero-config approach to run locally.

We're using MinIO as the S3 compatible backend, and all of the object storage related services and config is in a new compose file.


Note

Introduces a MinIO-backed object storage profile with a setup script and compose file, wiring Ghost to the S3 storage adapter and adding a helper Docker script.

  • Object Storage (Docker Compose)
    • Adds compose.object-storage.yml with minio service (ports 9000/9001, healthcheck, volume) and minio-setup init job.
    • Extends ghost service to use S3Storage via env vars (bucket, region, endpoint, cdnUrl, credentials, URL prefixes, forcePathStyle).
  • MinIO Setup Script
    • Adds .docker/minio/setup.sh to configure mc alias, ensure ghost-dev bucket, and enable anonymous download.
  • Dev Scripts
    • Adds package.json script docker:dev:object-storage to start Ghost with the object-storage profile.

Written by Cursor Bugbot for commit f63925f. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds object-storage support: a new MinIO setup script at .docker/minio/setup.sh that configures a MinIO alias, ensures a bucket exists (default ghost-dev, overridable via MINIO_BUCKET), and applies an anonymous download policy; a Docker Compose override compose.object-storage.yml introducing minio, minio-setup, and an extended ghost service configured to use S3Storage with endpoint, bucket, URL mappings, and a persistent minio-data volume; and a new npm script docker:dev:object-storage in package.json to run Docker Compose with the object-storage profile.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • .docker/minio/setup.sh: verify shell options, credential handling, idempotent bucket creation, policy JSON correctness, and logging/exit behavior.
  • compose.object-storage.yml: validate service definitions, healthcheck command and timing, dependency ordering (ghost depends on MinIO health and setup), env vars for S3 adapter and URL mappings, volume and port configuration.
  • package.json: confirm the new npm script references both compose files and the object-storage profile.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: wiring up local S3 adapter support for development using MinIO and Docker Compose.
Description check ✅ Passed The description provides clear context about the change, referencing the related issue and explaining the zero-config approach using MinIO for S3-compatible storage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch push-snrzqlzuuvtr

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0cf27b and f63925f.

📒 Files selected for processing (3)
  • .docker/minio/setup.sh (1 hunks)
  • compose.object-storage.yml (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 24862
File: .github/workflows/ci-docker.yml:320-324
Timestamp: 2025-09-10T21:24:49.363Z
Learning: In GitHub Actions workflows using docker compose, the `docker compose pull` command works correctly with fork PRs even when some images (like the Ghost development image) are only loaded locally and not available in remote registries. The command doesn't fail when it encounters locally-loaded images during the pull process.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.
📚 Learning: 2025-09-10T21:24:49.363Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 24862
File: .github/workflows/ci-docker.yml:320-324
Timestamp: 2025-09-10T21:24:49.363Z
Learning: In GitHub Actions workflows using docker compose, the `docker compose pull` command works correctly with fork PRs even when some images (like the Ghost development image) are only loaded locally and not available in remote registries. The command doesn't fail when it encounters locally-loaded images during the pull process.

Applied to files:

  • .docker/minio/setup.sh
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.

Applied to files:

  • compose.object-storage.yml
  • package.json
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.

Applied to files:

  • compose.object-storage.yml
  • package.json
🪛 Shellcheck (0.11.0)
.docker/minio/setup.sh

[warning] 2-2: In POSIX sh, set option pipefail is undefined.

(SC3040)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Setup
  • GitHub Check: Build & Push
  • GitHub Check: Setup
🔇 Additional comments (3)
.docker/minio/setup.sh (1)

1-15: Approved: Setup script is well-structured and operational.

The shebang, error handling, and environment variable usage are all working correctly in the minio-setup container context as previously confirmed. The script idempotently creates the bucket, sets the alias, and configures the anonymous download policy. No changes needed.

package.json (1)

42-42: Approved: NPM script correctly configured.

The docker:dev:object-storage script is properly structured with correct compose file ordering, explicit profile specification, and consistent flag usage. This aligns with similar scripts like docker:dev:analytics.

compose.object-storage.yml (1)

1-64: Approved: Compose file structure and service orchestration are correct.

The override file correctly implements object-storage setup with proper service isolation via profiles, correct dependency ordering, and fixed healthcheck. Specific observations:

  • Ghost service (lines 2–27): Correctly extends compose.yml's ghost and activates only with --profile object-storage, allowing coexistence with default/split profiles.
  • MinIO service (lines 29–46): Healthcheck now uses curl against the correct HTTP endpoint (/minio/health/ready), resolving the previous mc-availability issue. Restart policy and credential handling appropriate for local dev.
  • MinIO-setup service (lines 48–61): One-shot initialization service correctly depends on minio health before running setup.sh, with proper volume mount and environment variables.
  • Profile configuration: minio and minio-setup correctly specify only [object-storage] profile since they're exclusive to this feature, not dependencies for all ghost profiles.
  • Non-intrusive design: Object-storage setup only activates when explicitly requested via --profile object-storage, maintaining compatibility with existing development workflows.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on December 3

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
package.json (1)

42-42: Verify that hardcoding the profile doesn't conflict with profile flexibility.

The script explicitly uses --profile object-storage and bypasses the COMPOSE_PROFILES environment variable mechanism used by other docker:dev:* scripts (e.g., docker:dev at line 41). This forces the object-storage profile and makes it incompatible with the COMPOSE_PROFILES env var pattern.

Consider whether this is intentional or if the script should support the profile flexibility pattern:

-    "docker:dev:object-storage": "docker compose -f compose.yml -f compose.object-storage.yml --profile object-storage up --attach=ghost --force-recreate --no-log-prefix",
+    "docker:dev:object-storage": "COMPOSE_PROFILES=${COMPOSE_PROFILES:-object-storage} docker compose -f compose.yml -f compose.object-storage.yml up --attach=ghost --force-recreate --no-log-prefix --wait",

Additionally, consider adding --wait for consistency with docker:dev:analytics (line 43), which waits for services to be ready.

compose.object-storage.yml (1)

14-14: Consider documenting hardcoded credentials and verifying the prefix path.

The following values are hardcoded in the configuration:

  • S3 prefix path: ab/ab1234567890abcdef1234567890abcd (line 14) — appears to be a placeholder or example. Verify this is intentional.
  • MinIO credentials: minio-user / minio-pass (lines 19–20, 36–37) — acceptable for local development but should be documented or made environment-driven for flexibility across development environments.

Consider whether these should reference environment variables or be documented in a developer guide to prevent confusion.

Also applies to: 19-20, 36-37

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42dae57 and fe9b7cd.

📒 Files selected for processing (3)
  • .docker/minio/setup.sh (1 hunks)
  • compose.object-storage.yml (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: TryGhost/Ghost PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-09T17:25:12.439Z
Learning: Applies to ghost/core/config.development.json : Add Tinybird configuration to ghost/core/config.development.json for local development
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 24862
File: .github/workflows/ci-docker.yml:320-324
Timestamp: 2025-09-10T21:24:49.363Z
Learning: In GitHub Actions workflows using docker compose, the `docker compose pull` command works correctly with fork PRs even when some images (like the Ghost development image) are only loaded locally and not available in remote registries. The command doesn't fail when it encounters locally-loaded images during the pull process.
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.

Applied to files:

  • package.json
  • compose.object-storage.yml
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.

Applied to files:

  • package.json
  • compose.object-storage.yml
🪛 Shellcheck (0.11.0)
.docker/minio/setup.sh

[warning] 2-2: In POSIX sh, set option pipefail is undefined.

(SC3040)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Ghost-CLI tests
  • GitHub Check: Acceptance tests (Node 22.13.1, mysql8)
  • GitHub Check: Acceptance tests (Node 22.13.1, sqlite3)
  • GitHub Check: Comments-UI tests
  • GitHub Check: Signup-form tests
  • GitHub Check: Legacy tests (Node 22.13.1, sqlite3)
  • GitHub Check: Admin-X Settings tests
  • GitHub Check: Legacy tests (Node 22.13.1, mysql8)
  • GitHub Check: ActivityPub tests
  • GitHub Check: Unit tests (Node 22.13.1)
  • GitHub Check: Admin tests - Chrome
  • GitHub Check: Build & Push
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (5)
.docker/minio/setup.sh (2)

1-2: Note: Shell portability warning from static analysis.

The shebang #!/bin/sh combined with set -euo pipefail (line 2) triggers ShellCheck SC3040 because pipefail is a bash extension, not POSIX shell standard. While this works in most modern Linux environments where /bin/sh is symlinked to bash, it may not be portable to strict POSIX systems.

If portability is a concern, consider switching to #!/bin/bash. Otherwise, this is acceptable for Docker-based development environments.


6-14: Script structure and bucket initialization logic look solid.

The idempotent bucket creation (line 10 with --ignore-existing), policy configuration (line 13), and environment-driven bucket naming (line 4) are well-designed for the development setup. Error handling via set -euo pipefail ensures the script fails fast if any step encounters an issue.

compose.object-storage.yml (3)

2-27: Service dependencies and Ghost configuration look correct.

The ghost service correctly extends the base compose.yml service and applies the object-storage profile isolation. The dependency chain is well-structured: Ghost depends on minio being healthy AND minio-setup completing successfully, which ensures proper initialization order before Ghost attempts to use S3 storage.

The S3Storage configuration (lines 8–22) correctly separates internal service communication (http://minio:9000) from external URLs (http://127.0.0.1:9000), which is appropriate for a local development setup.


29-47: MinIO service configuration with healthcheck is sound.

The MinIO service includes proper health checks (line 44), volume persistence (line 42), and a pinned version (line 31), which are all good practices for development environments. The restart policy ensures the service stays running for the development session.


48-61: MinIO setup service correctly orchestrates initialization.

The minio-setup service uses the minio/mc image to run the initialization script (.docker/minio/setup.sh), depends on minio being healthy, and uses restart: 'no' to prevent repeated re-runs. This is the correct pattern for one-shot setup tasks in Docker Compose.

@codecov
Copy link

codecov bot commented Nov 13, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.97%. Comparing base (1340962) to head (f63925f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #25436   +/-   ##
=======================================
  Coverage   71.97%   71.97%           
=======================================
  Files        1528     1528           
  Lines      116466   116466           
  Branches    13884    13884           
=======================================
+ Hits        83821    83822    +1     
+ Misses      31630    31629    -1     
  Partials     1015     1015           
Flag Coverage Δ
admin-tests 51.57% <ø> (+<0.01%) ⬆️
e2e-tests 71.97% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.docker/minio/setup.sh (1)

1-3: POSIX sh compatibility: pipefail is a bash extension.

The script uses #!/bin/sh with set -euo pipefail, but pipefail is not defined in strict POSIX sh (SC3040 warning). While widely supported on modern systems, you may prefer set -o pipefail for explicit option syntax. For local development purposes, the current approach is acceptable unless you have strict POSIX compliance requirements.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe9b7cd and add2a54.

📒 Files selected for processing (3)
  • .docker/minio/setup.sh (1 hunks)
  • compose.object-storage.yml (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 24862
File: .github/workflows/ci-docker.yml:320-324
Timestamp: 2025-09-10T21:24:49.363Z
Learning: In GitHub Actions workflows using docker compose, the `docker compose pull` command works correctly with fork PRs even when some images (like the Ghost development image) are only loaded locally and not available in remote registries. The command doesn't fail when it encounters locally-loaded images during the pull process.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.

Applied to files:

  • package.json
  • compose.object-storage.yml
📚 Learning: 2025-05-27T18:08:00.458Z
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.

Applied to files:

  • package.json
  • compose.object-storage.yml
🪛 Shellcheck (0.11.0)
.docker/minio/setup.sh

[warning] 2-2: In POSIX sh, set option pipefail is undefined.

(SC3040)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Setup
  • GitHub Check: Build & Push
  • GitHub Check: Setup
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (3)
package.json (1)

42-42: LGTM! Consistent with existing Docker development scripts.

The npm script correctly chains compose files, specifies the object-storage profile, and uses standard options for local development. The pattern aligns with other docker:dev:* commands.

compose.object-storage.yml (2)

8-22: Hardcoded S3Storage configuration acceptable for local development.

The ghost service includes hardcoded bucket (ghost-dev), region (us-east-1), prefix, path-style setting, endpoint, and credentials. These defaults are appropriate for local zero-config development and don't pose a security concern since this is a local-only setup. Consider documenting these defaults in a README or inline comment for developers who may want to customize them.


21-22: Verify: Media and files URLs point to identical paths.

Both urls__media and urls__files are set to the same path: http://127.0.0.1:9000/ghost-dev/ab/ab1234567890abcdef1234567890abcd. Confirm whether Ghost expects different URL prefixes for media vs. files, or if sharing the same path is the intended configuration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between add2a54 and f0cf27b.

📒 Files selected for processing (3)
  • .docker/minio/setup.sh (1 hunks)
  • compose.object-storage.yml (1 hunks)
  • package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • compose.object-storage.yml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 24862
File: .github/workflows/ci-docker.yml:320-324
Timestamp: 2025-09-10T21:24:49.363Z
Learning: In GitHub Actions workflows using docker compose, the `docker compose pull` command works correctly with fork PRs even when some images (like the Ghost development image) are only loaded locally and not available in remote registries. The command doesn't fail when it encounters locally-loaded images during the pull process.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: The Ghost Docker Compose setup has two independent profiles: `ghost` profile (v0, runs all apps in a single container) and `split` profile (work in progress, runs Ghost server, admin, and frontend apps in separate services). The `split` profile will eventually replace `ghost` as the default.
Learnt from: cmraible
Repo: TryGhost/Ghost PR: 23546
File: compose.yml:58-59
Timestamp: 2025-05-27T18:08:00.458Z
Learning: Services that are dependencies for both Ghost Docker Compose profiles (`ghost` and `split`) need to include both profiles in their `profiles` configuration to ensure they start correctly under either profile.
🪛 Shellcheck (0.11.0)
.docker/minio/setup.sh

[warning] 2-2: In POSIX sh, set option pipefail is undefined.

(SC3040)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Unit tests (Node 22.13.1)
  • GitHub Check: Ghost-CLI tests
  • GitHub Check: Acceptance tests (Node 22.13.1, mysql8)
  • GitHub Check: Admin-X Settings tests
  • GitHub Check: Acceptance tests (Node 22.13.1, sqlite3)
  • GitHub Check: Signup-form tests
  • GitHub Check: Comments-UI tests
  • GitHub Check: Legacy tests (Node 22.13.1, sqlite3)
  • GitHub Check: ActivityPub tests
  • GitHub Check: Legacy tests (Node 22.13.1, mysql8)
  • GitHub Check: Admin tests - Chrome
  • GitHub Check: Build & Push
ref https://linear.app/ghost/issue/PRO-1534

The idea behind this approach is to be non-intrusive to existing
development flows, but allow a zero-config approach to run locally.

We're using MinIO as the S3 compatible backend, and all of the object
storage related services and config is in a new compose file.
@allouis allouis merged commit 98a4101 into main Nov 17, 2025
34 checks passed
@allouis allouis deleted the push-snrzqlzuuvtr branch November 17, 2025 07:33
9larsons pushed a commit that referenced this pull request Nov 17, 2025
ref https://linear.app/ghost/issue/PRO-1534

In order to use object storage locally we need a local S3 compatible
service running, but we didn't want to make that mandatory, or break
existing development setups, so we've tried to be non-intrusive to
existing flows but allow a zero-config approach to run locally.

We're using MinIO as the S3 compatible backend, and all of the object
storage related services and config is in a new compose file, which keeps
everything separate for now.

We do need to eventually converge on how to run Ghost with all the
different possible options, but for now this massively improves DX for
object storage project and we can continue to improve this in future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants