Repository navigation
Conversation
Adds a craft-cloud disk driver (S3 on the project bucket with CDN URLs on Cloud, a local disk in public/uploads elsewhere), a default craft-cloud assets disk, bucket disks for upload session staging and temporary asset uploads on Cloud, and a cloud:disks command that prints disks for 3.x AssetsFs filesystems before upgrading. Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2 Co-authored-by: Amp <amp@ampcode.com>
Craft 6 is removing CRAFT_EPHEMERAL (craftcms/cms#20547), which is what turned it off before. Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2 Co-authored-by: Amp <amp@ampcode.com>
Requires a core newer than 6.0.0-alpha.20, and locks 6.x at 8a13417, which has disk-owned asset transformers (craftcms/cms#20542). Packagist hadn't indexed that commit yet, so the lock was pointed at it by hand; core's composer.json is the same as at the indexed commit (cc77dd6). Also checks that Cloud disks share the credentials and endpoint Craft needs to copy staged uploads within S3. Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2 Co-authored-by: Amp <amp@ampcode.com>
This was referenced Nov 10, 2026
Replaces the craft-cloud driver, its local fallback and subpath option, and
the cloud:disks command. On Craft Cloud, the provider sets the craft-cloud
disk's connection to the bucket's {env}/assets prefix and the CDN, keeping
the project's other options, and adds a craft-cloud-tmp disk in
{env}/storage/tmp for upload sessions and temporary asset uploads.
Elsewhere, the project defines craft-cloud itself, and upgraded filesystem
handles scope it.
Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2
Co-authored-by: Amp <amp@ampcode.com>
Brings back the craft-cloud driver, without its local fallback: it always builds an S3 disk on the project's bucket, and throws when resolved without the bucket variables, so it works off Cloud against a dev bucket or MinIO but never quietly becomes another disk. Subfolders use Laravel's own prefix option. Drops the default craft-cloud disk, and documents choosing a local disk per environment instead. Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2 Co-authored-by: Amp <amp@ampcode.com>
It isn't part of Craft Cloud storage, and CRAFT_EPHEMERAL already turns it off. Amp-Thread-ID: https://ampcode.com/threads/T-79ed60c5-5654-4f30-8dbd-da4b0ecd4fb2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Craft 6 replaced Craft filesystems with Laravel disks. Volumes name a disk, and core applies each volume's subpath with a
scopeddisk. This PR adds Craft Cloud storage as an ordinary Laravel disk driver. It's designed for Craft 6 on its own terms, not ported from the 3.x filesystems.The
craft-clouddriver always means the project's Cloud bucket.s3disk, so it resolves to Laravel'sAwsS3V3Adapter. Core checks for that class to use S3 multipart uploads and to copy uploads within the bucket.CRAFT_CLOUD_PROJECT_ID, and the root is{env}/assets.https://cdn.craft.cloud/{env}/assets/….prefix(a subfolder),visibility,throwandasset_transformerwork as on any disk. The driver doesn't addasset_transformer; a disk that should use Cloud transforms sets'asset_transformer' => 'craft-cloud'itself.rootis optional and relative to the environment's folder. Left out, the disk is{env}/assets.'root' => 'storage'makes it{env}/storage. The package uses that for its owncraft-cloud-tmpdisk.CRAFT_CLOUD_PROJECT_ID,CRAFT_CLOUD_ENVIRONMENT_ID, andCRAFT_CLOUD_REGIONorAWS_REGION.CRAFT_CLOUD_ACCESS_KEY/_SECRET/_TOKEN(otherwise the SDK finds credentials itself, such as the function's role),CRAFT_CLOUD_STORAGE_ENDPOINT(path-style), andCRAFT_CLOUD_CDN_BASE_URL.craftcommands and installs still run.Upload staging, on Cloud only. The provider adds a
craft-cloud-tmpdisk ({env}/storage/tmp). Unless the project sets them, it defaultsuploadSessionDiskandtempAssetUploadDiskto that disk, because the function's own disk doesn't outlive an invocation.upload-sessions/{id}anduser_{id}), so one disk covers both.CopyObjectinstead of downloading it.craft-tmpandcraft-asset-tempdisks on boot, so this PR changes the settings instead.Local development uses ordinary Laravel config. The README documents choosing the disk per environment:
Upgrading from Craft 5. Core's
remove_craft_filesystemsmigration needs a disk for each old filesystem handle. For each Craft Cloud filesystem, the README says to add'{handle}' => ['driver' => 'craft-cloud', 'prefix' => '{old subpath}'].What changed from the first revision, and why
public/uploadsfallback is gone (Tim's call). Acraft-clouddisk no longer turns into a different disk when it runs off Cloud.subpathoption is gone. Laravel's ownprefixoption does the same thing, including URLs and core's scoped volume subpaths.craft-clouddisk is gone. Without a fallback, a disk that only exists on Cloud would break the same volume locally. Projects name their disks inconfig/filesystems.php, as with any Laravel disk.cloud:disksis gone. It only printed one line per filesystem. The README's upgrade note does the same job.craft-cloud-uploadsandcraft-cloud-tempare merged intocraft-cloud-tmp.urlandexpiresare gone. Projects that need a different URL can define their owns3disk.Infra requirements
CRAFT_EPHEMERAL=trueon Cloud functions. Core uses it to turn off project config YAML writes, putcraft-tmpin/tmp, and skip publishing legacy asset bundles.PUTfrom control panel origins, and exposeETagfor multipart uploads.GetObject,PutObjectandDeleteObjecton{env}/assetsand{env}/storage.{env}/storage/tmp/. It should expire old objects and abort incomplete multipart uploads.Contract changes to consider (not made here)
CRAFT_CLOUD_REGION: if buckets are always in the function's region,AWS_REGION(which Lambda always sets) is enough. For off-Cloud use, it's one fewer variable to document.CRAFT_CLOUD_ACCESS_KEY/_SECRET/_TOKEN: if Lambda never receives them, they only matter off Cloud. StandardAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, which the SDK already reads, could replace them.CRAFT_CLOUD_CDN_BASE_URL: this comes from 3.x'scdnBaseUrlsetting. If infra doesn't use it to point at another CDN host, the URL can be hardcoded.Notes for review
env('CRAFT_CLOUD')in config. If Cloud ever caches config at build time without that variable set, the cache would pick the local disk.AwsS3V3AdapterwhosebucketisCRAFT_CLOUD_PROJECT_IDas a Cloud disk, and that still holds. Off Cloud with a dev bucket, the same check would also match, so transforms would expect the CDN to serve that bucket.league/flysystem-aws-s3-v3, requirescraftcms/cms^6.0.0-alpha.21, and locks the6.xbranch at craftcms/cms@8a13417. No tag includes #20542 yet. Packagist hadn't indexed that commit when the lock was made, so the lock'scraftcms/cmsandcraftcms/cms-assetsreferences were set to it by hand. Core'scomposer.jsonis unchanged from the indexed commit.Follow-ups
max-ageandvisibilityobject metadata the CDN relies on, likely through the disk'soptions.Related issues