siberfx/laravel-rustfs
Connect Laravel to RustFS, the S3-compatible object storage written in Rust. The package provides a filesystem driver so you can register a RustFS disk and use Laravel's familiar Storage facade to upload, read, delete, and manage files through the same API you already use for S3.
1.0.1 is a documentation-and-test release only — no code changes since 1.0.0, so any existing install upgrades safely with a composer update and nothing else. If this is your first time with the package, the release is effectively your onboarding: the new README is now the single source of truth and replaces guesswork with copy-pasteable recipes.
Minimal path:
config/filesystems.php (endpoint, key/secret, bucket, region, path-style endpoint, use SSL). The disk behaves like any other Laravel disk, so Storage::disk('rustfs') is the first thing to try..env at your RustFS instance — locally that's usually the Docker image the package's own CI runs (rustfs/rustfs:1.0.3), which is the version the new security notes were verified against.put/get round trip before touching any advanced feature.First real use case: public-read assets plus private downloads. Read the README's "private downloads" recipe first, because presigned URLs are where most Laravel developers' S3 intuition needs correcting (see Gotchas). Then move to whichever recipe matches your actual workload — form uploads, direct browser uploads, or versioning.
Where to look first, in order: the README table of contents → the presigned PUT vs POST section (read before writing any upload code) → the "application testing" section (so you can fake the disk in feature tests from day one) → the error-handling section.
Treat the disk as the default, presigning as the exception. The package registers a Laravel filesystem disk; use the normal Storage facade for internal read/write, and reach for presigned URLs only when the browser or an external service must talk to RustFS directly.
Browser uploads: default to presigned POST, not PUT. This is the most important workflow decision in 1.0.1. The tested behavior against RustFS 1.0.x is:
Content-Type and does not enforce any size limit;EntityTooLarge, wrong key prefixes fail with InvalidPolicyDocument.So the pattern is: server issues a presigned POST with a content-length-range condition and an exact key prefix, ships the policy fields plus the JavaScript from the README to the browser, and the browser posts a multipart form directly. Reserve presigned PUT for cases where the client is trusted (your own backend job, a controlled CLI, an internal service) and validation already happened server-side.
Direct browser upload flow (canonical):
multipart/form-data with the policy fields before the file part — order matters in S3-style POST policies.head before marking it ready.Private downloads: store keys, never public URLs. Generate a short-lived presigned GET at render time (or redirect to it from a controller after your own Gate/policy check). Keep TTLs short and aligned with your auth session.
Versioning and restore: enable versioning per bucket, then restore by copying the older version's bytes onto the same key — this is exactly what the new live test covers, so it's a supported, tested path rather than an improvised one. Encapsulate it in a service method (restoreVersion($key, $versionId)) instead of scattering copy calls.
Multipart/resumable uploads: use these for large files and for anything over your reverse proxy's body limit. Pair them with presigned POST policy limits so a broken client can't stream unbounded bytes into the bucket.
Object lock (WORM), lifecycle/tiering, KMS, replication: configure as infrastructure-level bucket policy via the package's admin recipes, not per-request in application code. Application code should only read those behaviors (e.g. expecting a delete to fail on a locked object).
Events: the README includes a receiving route for notifications. Use it to decouple post-upload work (thumbnailing, virus scan, indexing) from the request cycle — but make the handler idempotent, since notification delivery can repeat.
Bulk operations and S3 Select: reach for S3 Select when you'd otherwise download a CSV/JSON object just to filter it; keep the query narrow and the result small.
Testing pattern: use the README's application-testing recipe to fake the disk in feature tests so unit tests stay fast, and keep a small tagged suite that hits a real RustFS container (mirroring the package's own 14-test live suite against rustfs/rustfs:1.0.3) for presigning and policy enforcement, which cannot be meaningfully faked.
Content-Type on a PUT is advisory — the client can send anything. If your app assumes "I signed image/png and a 5 MB limit, so that's what arrives," you have an unbounded upload and a content-type spoof. Switch those flows to presigned POST. Verify Content-Type and size with a head after upload if you must use PUT.EntityTooLarge and InvalidPolicyDocument come back as XML from the storage layer, not as Laravel validation errors. Map them to friendly messages in your frontend and log the raw body — a wrong field order or an expired policy looks identical to a size violation from the browser's perspective.uploads/2025/…) will trip InvalidPolicyDocument if the condition doesn't cover it.1.0.3. If policy enforcement is load-bearing for you, treat storage-server upgrades as a change that needs the live suite re-run.RequestTimeTooSkewed)./health endpoint so a storage outage surfaces as a failed check rather than a wave of 500s.How can I help you explore Laravel packages today?