After I connected MinIO through Laravel's standard S3 disk, the next question was whether local MinIO needed a separate filesystem configuration.
I decided it did not.
Local development and production use the same filesystem contract. Laravel works through s3 in both environments.
Only the destination behind that disk changes.
I therefore keep config/filesystems.php generic and move environment differences into environment variables.
One filesystems.php Across Environments
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'endpoint' =>There is no current-environment check in this file.
There is no dedicated minio disk for local development and a separate s3 disk for production.
There is one s3 disk whose values come from the environment.
The environment decides which server, bucket, and credentials are used.
I Avoid if local Branches in Filesystem Configuration
'endpoint' => app()->environment('local') ? 'http://minio:9000' : null, 'use_path_style_endpoint' => app()->environment('local'),This code can work, but it moves knowledge about local MinIO into general application configuration.
Later there may be another environment, another S3-compatible provider, or another deployment target, and the branching grows.
I prefer keeping configuration declarative: Laravel reads values instead of deciding which environment is currently active.
Only Environment Values Change Locally
AWS_ACCESS_KEY_ID=laradockAWS_SECRET_ACCESS_KEY=laradock AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET=local-files AWS_ENDPOINT=http://minio:9000 AWS_USE_PATH_STYLE_ENDPOINT=trueThese values describe local infrastructure.
MinIO has its Docker-network endpoint, local credentials, and a local bucket.
Nothing changes in application code.
In Production the Same Disk Receives Different Values
AWS_ACCESS_KEY_ID=<production value>AWS_SECRET_ACCESS_KEY=<production secret> AWS_DEFAULT_REGION=<region> AWS_BUCKET=<production bucket> AWS_ENDPOINT=<provider endpoint if required> AWS_USE_PATH_STYLE_ENDPOINT=<true or false>Real production secrets, bucket names, and provider endpoints should not be committed to the repository.
The important point is that the configuration structure does not change.
Another environment simply supplies different values for the same parameters.
The Endpoint Belongs to the Environment, Not Laravel Code
Locally, AWS_ENDPOINT=http://minio:9000 makes sense because Laravel runs inside Docker.
I covered why the container uses minio:9000 instead of localhost separately.
Another environment may use a different endpoint or may not need an explicit AWS_ENDPOINT when the driver uses the provider default.
Laravel application code does not need to know why those values differ.
Credentials Are Environment Data Too
Local MinIO credentials may be simple values intended only for development.
Production secrets should be stored according to the deployment environment security rules.
In both cases Laravel reads them through the same configuration keys.
Application code does not access AWS_SECRET_ACCESS_KEY directly or make decisions based on it.
The Bucket Can Change Without Code Changes
Local AWS_BUCKET=local-files | vMinIO bucket Production AWS_BUCKET=<production bucket> | vProduction storage Addressing Mode Is Environment Configuration Too
Local MinIO at minio:9000 works conveniently with AWS_USE_PATH_STYLE_ENDPOINT=true.
Another provider may have different requirements.
This is another reason not to hardcode the addressing mode into filesystems.php as a special MinIO case.
File Operations Stay the Same
Storage::disk('s3')->put( $path, $contents,); $contents = Storage::disk('s3')->get( $path,); Storage::disk('s3')->delete( $path,);This is the main sign that the boundary is in the right place.
Store, read, and delete operations should not need to know whether the application is running locally.
They use the s3 disk. The environment configuration handles the rest.
A Separate minio Disk Often Only Duplicates s3
'minio' => [ 'driver' => 's3', // ...], 's3' => [ 'driver' => 's3', // ...],A separate disk can make sense when the application intentionally uses two storage systems at the same time.
But if MinIO only replaces production S3-compatible storage locally, a second disk creates an unnecessary difference between environments.
Local code then uses minio while production uses s3, even though they represent the same application dependency.
I keep one disk name and change only its infrastructure parameters.
After Environment Changes I Check Laravel Configuration Cache
php artisan config:clearIf .env has changed but Laravel still contacts the old endpoint, I check the configuration cache.
This is especially easy to miss while switching from local storage to S3-compatible storage.
I Verify Laravel's Resolved Configuration, Not Only .env
config( 'filesystems.disks.s3.endpoint',); config( 'filesystems.disks.s3.bucket',); config( 'filesystems.disks.s3.use_path_style_endpoint',);The .env file alone does not prove that application configuration is correct.
During debugging I inspect the resolved filesystems.disks.s3 values.
This makes it easier to separate a configuration problem from Docker networking or storage connectivity.
What Stays Stable and What Changes
Stays the same: - driver = s3- disk name = s3- Storage::disk('s3')- application code- file-handling rules Changes by environment: - endpoint- credentials- region- bucket- path-style settingWhat I Check Before Adding Separate Local Configuration
My short checklist:
- Do local and production storage support the same S3 contract?
- Is a second disk actually necessary?
- Can one
driver=s3remain in place? - Can the endpoint come from the environment?
- Are credentials kept out of the repository?
- Is the bucket name supplied externally?
- Is addressing mode configurable as well?
- Is there no
if localin application code? - Does every environment use the same
Storage::disk('s3')contract?
The Environment Changes Values, Not Application Structure
For me, local MinIO is not a separate Laravel operating mode.
It is another implementation of the same infrastructure dependency.
I therefore do not add a separate minio disk, branch filesystems.php by environment, or add local-storage-specific application code.
Laravel continues using the standard s3 disk.
Only the endpoint, credentials, bucket, and addressing mode change locally.
When the contract stays the same, environment differences should stay in configuration rather than spreading through application code.
A local environment should place different infrastructure behind the same contract rather than make the application follow different rules.



