Laravel talks to object storage through the Flysystem package and its s3 driver. For intercolo you only swap endpoint and region in config/filesystems.php — your application code using Storage::disk() stays unchanged line for line. Uploads, user assets, generated PDFs or CSV exports then land in a GDPR-compliant German object storage in the Frankfurt data center instead of a US hyperscaler. Endpoint https://de-fra.i3storage.com, region de-fra, SigV4 auth, strong read-after-write and 99.999999% durability. From €2.49 per TB/month, 1 TB egress included per stored TB.
The s3 driver needs exactly one Composer package: composer require league/flysystem-aws-s3-v3 "^3.0". That is the only dependency — Composer pulls in the AWS SDK automatically as a sub-dependency. Compatible with Laravel 9, 10 and 11.
Add a new disk under disks (see the terminal above): driver s3, region de-fra, endpoint https://de-fra.i3storage.com, use_path_style_endpoint false and visibility private. Pull key, secret and bucket from the .env via env(). Storage::disk('intercolo') is then available everywhere in the app.
Enter the credentials: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from your intercolo API key pair, AWS_BUCKET with your bucket name, AWS_DEFAULT_REGION=de-fra, AWS_ENDPOINT=https://de-fra.i3storage.com and AWS_USE_PATH_STYLE_ENDPOINT=false. No passwords, no bucket policies — access runs exclusively through this SigV4 key pair.
From now on you address storage through the familiar facade: Storage::disk('intercolo')->put(...), ->get(...) and ->temporaryUrl(...). Existing code that already uses Storage::disk() keeps working unchanged after the pure config switch.
Storage::disk('intercolo') returns a perfectly ordinary Flysystem adapter — put, get, exists, size, readStream and temporaryUrl behave identically to any other disk. temporaryUrl signs the URL with SigV4 against the endpoint set on the disk.
intercolo does not support public buckets via ACL. So set visibility to private on the disk, not public — a call to Storage::disk('intercolo')->url() for permanently public links deliberately goes nowhere. That is intent, not a gap: instead of making files globally readable through bucket ACLs (and risking accidental data leaks), you deliver every download via temporaryUrl() as a presigned URL — signed with SigV4, valid for a limited time and authorised per file. Public, non-sensitive assets such as CSS, JS or logos still go the classic way into public/ or behind a CDN PoP in the DACH region and Europe; confidential uploads stay private and are signed on demand only. That way there is no global read access you forget to close again.
If your app already uses the s3 driver against AWS, the switch is trivial: you set endpoint to https://de-fra.i3storage.com and region to de-fra on the disk — that is it in code. The AWS SDK, Flysystem, every Storage::disk() and Storage::put() call and your queue workers stay unchanged, because intercolo speaks the same S3 API (SigV4 signing, multipart upload, presigned URLs). In the .env you replace AWS_DEFAULT_REGION with de-fra and add AWS_ENDPOINT plus AWS_USE_PATH_STYLE_ENDPOINT=false. You mirror existing objects once via rclone or aws-cli sync to Frankfurt — over 500 million files have already moved this way.
intercolo does not encrypt at rest; what is secured is transport over TLS. For confidential uploads you therefore encrypt the content client-side before it goes into put() — for example with sodium_crypto_secretstream (libsodium ships with current PHP versions) and your own key from your Laravel config or secrets store, or you mirror whole directories into the bucket via rclone crypt or Restic. Then object storage holds only ciphertext, the key never leaves your app infrastructure, and no provider — us included — can read the files. For public, non-sensitive assets you skip this step; you make the call per file or per bucket.
put, get, exists, size, delete, copy, move, readStream and writeStream for large files, multipart uploads, directory listing and presigned temporaryUrl() — all through the familiar Storage facade and comfortably from queue jobs.
Public buckets via ACLs do not exist. Instead of visibility public you use private plus temporaryUrl() for signed, expiring links; permanently public assets you deliver via public/ or a CDN PoP.
Object versioning and Object Lock/WORM do not exist. You model history and retention in your app logic through your own paths and timestamps, or additionally protect the bucket with a backup tool.
Only TLS transport is secured. Confidential data you encrypt client-side before upload (libsodium, rclone crypt, Restic). No AES-256 at-rest promise — in return full key ownership stays with you.
| AWS S3 (native) | Cloudflare R2 | intercolo i3 | |
|---|---|---|---|
| Location / data residency | EU region selectable, US corp (CLOUD Act) | EU/global, US corp | Frankfurt DC, 100% DE, GDPR/DPA |
| Config change | native s3 driver | override endpoint | endpoint https://de-fra.i3storage.com, region de-fra |
| Egress model | per GB, can get expensive | no egress, but US operator | 1 TB incl./TB, then +€3.99/TB |
| Public files | public ACL / CloudFront | r2.dev / public bucket | private + presigned temporaryUrl() |
| Starting storage price | list price US$/TB | list price US$/TB | €2.49/TB |
| GDPR / DPA (Art. 28) | DPA, but US access possible | DPA, US corp | DPA, German operator, Schrems II safe |
If you run several client projects, create a dedicated bucket and a dedicated API key pair (access/secret) per project and store it in the respective .env as a separate disk. Access runs exclusively through these SigV4 keys — no password login, no bucket policies. If a project ends or a key is compromised, you rotate exactly that key pair without touching other clients. Time-consuming uploads such as video encoding results or large exports you push into the bucket from a queued job with ShouldQueue, so the web request stays fast. Every project is thus cleanly separated, billable per bucket and cancellable individually.
ประสบการณ์ของเราพูดแทนตัวเอง: เราย้ายข้อมูลสำเร็จแล้วหลายเพตะไบต์และไฟล์กว่า 500 ล้านไฟล์