Skip to content

Storage providers

Any S3-compatible bucket works, because presigning is Flysystem's job and this package only asks for it. Pick one, set its env keys, point LARASPRING_STORAGE_DISK at the s3 disk.

bash
cd apps/saas          # or apps/vue, whichever edition you have
composer require league/flysystem-aws-s3-v3

That package is not a dependency of the kit. Without it the local disk fallback is the only upload path, which is the right default for a fresh clone and the wrong one for production.

Amazon S3

dotenv
LARASPRING_STORAGE_DISK=s3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=eu-west-1
AWS_BUCKET=

Cloudflare R2

No egress fees, which matters a lot if your uploads are images people look at often. R2 has one region, so AWS_DEFAULT_REGION is auto.

dotenv
LARASPRING_STORAGE_DISK=s3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=auto
AWS_BUCKET=
AWS_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
AWS_URL=https://cdn.yourdomain.com
AWS_USE_PATH_STYLE_ENDPOINT=true

Set AWS_URL to your public R2 domain. Without it, public URLs point at the API endpoint, which is not readable without a signature.

DigitalOcean Spaces

dotenv
LARASPRING_STORAGE_DISK=s3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=fra1
AWS_BUCKET=
AWS_ENDPOINT=https://fra1.digitaloceanspaces.com
AWS_URL=https://<bucket>.fra1.cdn.digitaloceanspaces.com

MinIO, for local development

The repository ships a docker-compose.yml with MinIO and a one-shot container that creates the bucket:

bash
docker compose up -d
dotenv
LARASPRING_STORAGE_DISK=s3
AWS_ACCESS_KEY_ID=laraspring
AWS_SECRET_ACCESS_KEY=laraspring-secret
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=laraspring
AWS_ENDPOINT=http://localhost:9000
AWS_URL=http://localhost:9000/laraspring
AWS_USE_PATH_STYLE_ENDPOINT=true

The console is at http://localhost:9001, user laraspring, password laraspring-secret.

Worth doing before you ship uploads: MinIO speaks the S3 API, so presigned uploads take exactly the same code path they will take in production, and the local fallback stops being involved.

CORS

The browser PUTs to your bucket from your application's origin, so the bucket has to allow it. This is the step that catches everybody, and the symptom is an upload that fails in the browser with no useful error while the presign request looked fine.

json
[
    {
        "AllowedOrigins": ["https://yourdomain.com"],
        "AllowedMethods": ["PUT"],
        "AllowedHeaders": ["*"],
        "ExposeHeaders": ["ETag"],
        "MaxAgeSeconds": 3000
    }
]

Add http://localhost:8000 while developing against a real bucket. MinIO allows every origin by default, which is convenient locally and one more reason to test against a real bucket before launch.

The local disk

The default, and the reason a fresh clone can change a profile photo with no credentials anywhere.

A local disk has nothing to presign against: there is no bucket and no signature scheme, so temporaryUploadUrl() throws. Rather than making the kit require S3 before anything works, the package registers an upload endpoint of its own and hands back a Laravel temporary signed URL to it. The browser does the same PUT it would do against a bucket and never learns which it hit.

Three things keep that honest:

  • It only exists when the disk is local. Point laraspring-storage.disk at S3 and the route stops being registered, rather than lingering as a second way in that nothing exercises.
  • The signature covers the key, so it is exactly as forgeable as a presigned S3 URL: a caller cannot move the write somewhere else.
  • The auth middleware is still in front of it, and the controller re-checks that the key belongs to the caller.

Set LARASPRING_STORAGE_LOCAL_FALLBACK=false to refuse it outright. An installation that does so and leaves the disk local then fails loudly on the first presign, which is the correct answer to a misconfiguration.

Files on the public disk need php artisan storage:link once, as usual.

In tests

Storage::fake() works as it does in any Laravel application. The edition's own avatar and logo tests fake the configured disk and drive the three real requests end to end, which is the shape to copy for an upload of your own.

Laraspring is a commercial starter kit. Buying it gets you the source.