Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

MinIO: S3-Compatible Object Storage

By Kokil Thapa | Last reviewed: September 2026

Your Laravel app stores PDFs on local disk. Traffic grows. Backups balloon. A restore takes hours. MinIO: S3-Compatible Object Storage solves this without rewriting upload code—you point the same S3 SDK calls at a self-hosted endpoint. I've used this pattern on production enterprise applications where clients need document retention without AWS bills. This guide covers architecture, Ubuntu install, Laravel wiring, and production hardening.

What Is MinIO S3-Compatible Object Storage?

MinIO is an open-source object store built for cloud-native workloads. It stores files as objects inside buckets—the same mental model as Amazon S3. Your application uses path-style or virtual-host URLs. It sends PUT, GET, DELETE, and LIST requests. MinIO responds with S3-compatible XML or JSON.

Object storage differs from block storage (EBS, iSCSI) and file storage (NFS, SMB). Objects are immutable blobs with metadata. You do not mount them as a filesystem for random writes. That trade-off buys you horizontal scale and cheap bulk retention.

On legal-tech portals I've shipped—client document uploads, notary scans, attestation PDFs—object storage keeps the web server stateless. Files live on a dedicated tier. You scale app servers independently. See our Mijar Law Associates portfolio case for a document-heavy workflow example.

MinIO S3-Compatible Object StorageLaravel AppS3 SDK / FlysystemMinIO ServerS3 REST API :9000MinIO ConsoleWeb UI :9001Erasure-Coded Drive Pool4+ drives, single node or distributed clusterBackup Jobsrestic, rclone, mc mirrorCI Artifactsbuild logs, deploy bundlesMedia Filesimages, PDFs, video
MinIO S3-compatible object storage sits between your application and durable drives, exposing the standard S3 API on port 9000.

MinIO implements core S3 operations: bucket lifecycle rules, versioning, server-side encryption, and IAM-style policies. It does not replicate every AWS edge case. Glacier tiers and some obscure API calls may differ. For Laravel file uploads, backup tools, and static asset offloading, parity is usually complete enough to swap endpoints.

If you want a deeper self-hosting walkthrough, read our companion post on MinIO self-hosted S3 storage. For AWS-native setups, see AWS S3 for Laravel file storage.

How Do You Install MinIO on Ubuntu for S3-Compatible Storage?

A single-node MinIO install on Ubuntu 22.04 or 24.04 takes under ten minutes. You need a dedicated data directory on fast storage. SSD or NVMe is strongly preferred for metadata latency.

Download and create a system user

Run these commands as root or with sudo on a fresh Ubuntu server with at least two CPU cores and 4 GB RAM for light workloads.

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/

sudo useradd -r minio-user -s /sbin/nologin
sudo mkdir -p /mnt/minio-data
sudo chown minio-user:minio-user /mnt/minio-data

Configure environment and systemd service

Create /etc/default/minio with your root credentials and data path. Never commit these values to Git.

MINIO_ROOT_USER="minioadmin"
MINIO_ROOT_PASSWORD="ChangeThisToALongRandomSecret"
MINIO_VOLUMES="/mnt/minio-data"
MINIO_OPTS="--console-address :9001"

Install the systemd unit at /etc/systemd/system/minio.service:

[Unit]
Description=MinIO S3-Compatible Object Storage
After=network-online.target
Wants=network-online.target

[Service]
User=minio-user
Group=minio-user
EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
Restart=always
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now minio
sudo systemctl status minio

Create your first bucket

Install the MinIO client mc and alias your server:

wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc && sudo mv mc /usr/local/bin/

mc alias set local https://minio.example.com minioadmin 'ChangeThisToALongRandomSecret'
mc mb local/app-uploads
mc anonymous set none local/app-uploads

Put Nginx or Apache in front with TLS. Terminate HTTPS on the reverse proxy. Forward port 9000 for the S3 API and 9001 for the console. Our Linux system administration service covers hardened production configs for Nepal-hosted VPS and dedicated servers.

MinIO Install Pipeline1. Download2. Systemd3. TLS Proxy4. mc BucketProduction ChecklistUFW allow 443 only, fail2ban, separate data disk, nightly mc mirror off-siteGotcha: Port 9000 PublicNever expose API without TLS + authFix: Nginx + CertbotHTTPS only, restrict console IP
Install MinIO on Ubuntu, lock it behind TLS, then create private buckets before wiring application credentials.

How Does MinIO Compare to AWS S3 and Other Object Storage?

Choosing storage is a cost, control, and compliance decision—not a performance contest on day one. MinIO wins when you need S3 API compatibility on hardware you already own or on a budget VPS in Kathmandu.

CriteriaMinIO (self-hosted)AWS S3Cloudflare R2
S3 API compatibilityHigh for core opsNative referenceHigh, no egress fees
Monthly cost at 500 GBServer only (~Rs 3,000–8,000 VPS)Storage + requests + egressFlat per-GB, zero egress
Data residency controlFull—you pick the diskRegion-boundCloudflare edge
Ops burdenYou patch, backup, monitorManaged by AWSManaged by Cloudflare
Best fitOn-prem, dev/staging, Nepal VPSGlobal scale, full AWS stackPublic assets, CDN-heavy sites

For a full cost breakdown between cloud providers, read Cloudflare R2 vs AWS S3 cost breakdown. Ceph and GlusterFS solve different problems—block and distributed file layers—whereas MinIO focuses purely on object APIs. See Ceph storage fundamentals if you need unified block, file, and object in one cluster.

A pattern I use often: MinIO on a staging VPS mirrors production S3 behaviour. Developers test uploads locally against MinIO. Production points at AWS S3 or R2 with identical Flysystem config. Only the endpoint and credentials change.

MinIO vs AWS S3 DecisionChoose MinIOOwn hardware or fixed VPS costStrict data residency in NepalDev/staging S3 parityChoose AWS S3Global CDN + Lambda triggersNo ops team for storage tierPetabyte scale without planningHybrid Pattern (Common on Client Projects)MinIO staging + S3/R2 production, same Laravel Flysystem disk configmc mirror nightly to off-site bucket for disaster recovery
MinIO S3-compatible object storage fits self-hosted and staging workloads; AWS S3 fits fully managed global scale.

How Do You Connect Laravel to MinIO S3-Compatible Object Storage?

Laravel 12 and 13 ship with Flysystem v3 and an S3 adapter. You do not need MinIO-specific packages. Set the disk driver to s3. Point endpoint at your MinIO URL. Set use_path_style_endpoint to true—MinIO requires path-style addressing on single-node setups.

Configure filesystems.php

'disks' => [
    'minio' => [
        'driver' => 's3',
        'key' => env('MINIO_ACCESS_KEY'),
        'secret' => env('MINIO_SECRET_KEY'),
        'region' => env('MINIO_REGION', 'us-east-1'),
        'bucket' => env('MINIO_BUCKET'),
        'url' => env('MINIO_URL'),
        'endpoint' => env('MINIO_ENDPOINT'),
        'use_path_style_endpoint' => true,
        'throw' => true,
    ],
],

Add matching entries to your .env file:

MINIO_ACCESS_KEY=your-access-key
MINIO_SECRET_KEY=your-secret-key
MINIO_BUCKET=app-uploads
MINIO_ENDPOINT=https://minio.example.com
MINIO_URL=https://minio.example.com/app-uploads
MINIO_REGION=us-east-1
FILESYSTEM_DISK=minio

Install the AWS SDK if it is not already present:

composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies

Upload and retrieve files

Use Laravel's Storage facade exactly as you would with AWS:

use Illuminate\Support\Facades\Storage;

Storage::disk('minio')->put('contracts/agreement.pdf', $request->file('document'));

$url = Storage::disk('minio')->temporaryUrl(
    'contracts/agreement.pdf',
    now()->addMinutes(15)
);

For a broader comparison of local, S3, and R2 disks, see Laravel file uploads with S3, R2, and local storage. On booking platforms like Adventure Third Pole Trek, itinerary PDFs and voucher images benefit from off-server storage that survives app redeploys.

Official Laravel filesystem documentation covers driver options and testing fakes. The MinIO docs describe bucket policies and the mc CLI in detail—both are worth bookmarking (Laravel 12 filesystem docs, MinIO Linux documentation).

What Are the Best Practices for MinIO Production Deployments?

A MinIO node that holds client documents is production infrastructure. Treat it like a database server. Backups, monitoring, and access control are not optional extras.

  1. Use erasure coding across four or more drives. A single directory on one disk works for dev. Production needs parity shards so one drive failure does not lose data.
  2. Rotate credentials away from MINIO_ROOT_USER defaults. Create scoped service accounts per application with bucket-level IAM policies.
  3. Enable versioning on buckets that store legal or financial documents. Accidental deletes become recoverable.
  4. Mirror buckets off-site nightly. Use mc mirror, restic, or rclone to a second MinIO cluster or AWS S3. Our guide on offsite backups to S3 or R2 with restic applies directly.
  5. Monitor disk usage and API error rates. A full disk returns 507 errors that break uploads silently in poorly handled code paths.
  6. Keep the MinIO binary updated. Subscribe to release notes. Schedule maintenance windows like any other server patch cycle.

For automated backup pipelines triggered from cron or GitLab CI, read automate off-site backups to S3. If you run the full stack on EC2, our Laravel on AWS EC2 with RDS and S3 post shows how object storage fits a cloud architecture—you can swap S3 for MinIO on a secondary VPS to cut storage line items.

Encryption at rest is available via KMS integrations or automatic SSE-S3 on newer MinIO releases. For compliance-sensitive legal portals, encrypt before upload in the application layer as well. Defense in depth beats a single toggle.

Production MinIO TopologyLaravel Fleet (PHP 8.3+)Drive 1NVMe shardDrive 2NVMe shardDrive 3NVMe shardDrive 4NVMe shardMinIO Erasure Pool (EC:2)Off-Site mc mirrorAWS S3 / R2 DR copy
Production MinIO S3-compatible object storage spans four drives with erasure coding and nightly off-site mirroring.

When sizing hardware, plan for 20–30% free space headroom. Object storage performance degrades sharply above 85% capacity. On a Rs 5,000/month VPS (~USD 37), you can run MinIO for a small law-firm portal's document archive if traffic stays moderate. Heavy video workloads need dedicated nodes.

For data-lake analytics workloads—CSV exports, log aggregation—MinIO also works as an S3 landing zone. See build a data lake on S3 for pipeline patterns that translate directly to MinIO endpoints. The AWS S3 API reference remains the canonical contract for supported operations (Amazon S3 API reference).

If you need help auditing an existing upload pipeline or migrating local storage to object storage, our support and maintenance team handles migrations with zero-downtime cutover plans. You can also validate encoded payloads during integration tests with our Base64 encoder and decoder tool.

Key Takeaways

  • MinIO exposes the S3 REST API on your hardware—Laravel, restic, rclone, and Terraform S3 backends work with endpoint changes only.
  • Install on Ubuntu via binary + systemd, terminate TLS at Nginx, and never expose port 9000 without authentication.
  • Set use_path_style_endpoint => true in Laravel's S3 disk config when pointing Flysystem at MinIO.
  • Use erasure coding on four or more drives and nightly mc mirror jobs for production-grade durability.
  • MinIO beats AWS S3 on cost and data residency for Nepal VPS deployments; AWS wins on zero-ops global scale.
  • Treat bucket IAM policies, versioning, and disk monitoring as mandatory—not afterthoughts—for document-heavy apps.

People Also Ask

Is MinIO really compatible with the Amazon S3 API?

Yes, for the operations most web apps use daily—bucket CRUD, object PUT/GET/DELETE, presigned URLs, lifecycle rules, and versioning. Edge cases like Glacier transitions or obscure ListObjectsV2 parameters may differ. Test your specific SDK calls in staging before cutover.

Can MinIO run on a single VPS with one disk?

It can, and that is fine for development or low-stakes staging. Production workloads should use at least four drives with erasure coding so a single disk failure does not destroy data. A one-disk setup has no redundancy.

Does Laravel need a special MinIO package?

No. Laravel's built-in s3 Flysystem driver works with MinIO when you set a custom endpoint and enable path-style URLs. Install league/flysystem-aws-s3-v3 and configure credentials in .env.

How do you back up MinIO buckets?

Use the mc mirror command to replicate buckets to a second MinIO cluster, AWS S3, or Cloudflare R2. Tools like restic and rclone also speak S3 and therefore work against MinIO endpoints with no code changes.

Deploy MinIO S3-Compatible Object Storage With Confidence

You now have a complete path from Ubuntu install to Laravel integration. MinIO: S3-Compatible Object Storage gives you vendor-neutral object APIs on infrastructure you control—ideal for Nepal-hosted legal portals, eCommerce media, and staging environments that must mirror production S3 behaviour without the AWS bill.

Start with a staging bucket this week. Wire your Laravel disk config. Run one backup mirror job. If you want a production review of your storage architecture, contact us for a consultation or explore more guides on the Kokil Thapa blog and homepage.

Frequently Asked Questions

MinIO is an open-source object store that exposes the Amazon S3 REST API on your own hardware. Files live as immutable objects inside buckets, not as mounted filesystem paths.

At roughly 500 GB, self-hosted MinIO costs only your server bill—about Rs 3,000–8,000/month (~USD 22–59) on a Nepal VPS—while AWS S3 adds storage, request, and egress charges on top.

No. Laravel 12 and 13 use Flysystem v3 with the built-in s3 driver. Install league/flysystem-aws-s3-v3 and point the endpoint at MinIO.

Yes for everyday web-app operations: bucket CRUD, object PUT/GET/DELETE, presigned URLs, lifecycle rules, and versioning. Glacier transitions and obscure ListObjectsV2 parameters may differ. Run your exact SDK calls against a staging MinIO bucket before production cutover, especially if you rely on less common S3 features.

On Ubuntu 22.04 or 24.04, download the linux-amd64 binary, create a minio-user, set MINIO_ROOT_USER, MINIO_ROOT_PASSWORD, and MINIO_VOLUMES in /etc/default/minio, then run it via a systemd unit. Install the mc client, create private buckets, and put Nginx or Apache in front with TLS terminating HTTPS while forwarding port 9000 for the S3 API and 9001 for the console.

The article recommends at least two CPU cores and 4 GB RAM for light workloads on a fresh Ubuntu server. Store data on a dedicated directory on fast SSD or NVMe storage—metadata latency matters. A single-node install takes under ten minutes, but that sizing is for dev, staging, or moderate document archives, not heavy video ingestion without a dedicated node.

Add a minio disk in config/filesystems.php using driver s3, your MinIO endpoint URL, bucket name, and use_path_style_endpoint set to true. Put MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_BUCKET, MINIO_ENDPOINT, and MINIO_URL in .env, set FILESYSTEM_DISK=minio, then use Storage::disk('minio')->put() and temporaryUrl() exactly as you would with AWS S3.

MinIO on single-node setups requires path-style addressing, where the bucket name appears in the URL path rather than as a subdomain. Laravel's S3 Flysystem config must set use_path_style_endpoint to true. Without it, requests may hit the wrong host or fail signature checks. Virtual-host style works on some multi-node setups, but the article's Ubuntu single-node pattern always needs path-style URLs.

MinIO gives high S3 API compatibility with full data residency control on hardware you manage—ideal for Nepal VPS or on-prem workloads. AWS S3 is the native reference with zero ops and global scale but adds request and egress fees. Cloudflare R2 offers high compatibility with flat per-GB pricing and no egress fees, suited to CDN-heavy public assets. Pick based on cost, compliance, and who patches the server.

Yes—for development, staging, or low-stakes testing. Production should use erasure coding across four or more drives so one disk failure does not destroy data. A one-disk node has no redundancy.

Mirror buckets off-site nightly with mc mirror to a second MinIO cluster, AWS S3, or Cloudflare R2. restic and rclone also speak S3 and work against MinIO endpoints with no code changes. On legal-tech portals I've shipped, versioning plus off-site mirroring turns accidental deletes into recoverable events instead of permanent data loss.

Treat MinIO like a database server: rotate away from default MINIO_ROOT_USER credentials, create scoped service accounts with bucket-level IAM policies, enable versioning on legal or financial document buckets, and terminate TLS at Nginx or Apache without exposing port 9000 without authentication. Use erasure coding on four or more drives, keep 20–30% disk headroom, monitor API error rates, and patch the MinIO binary on a scheduled maintenance cycle.

A full disk returns HTTP 507 errors that break uploads. In poorly handled Laravel code paths, failures can look silent to end users. Monitor disk usage proactively and plan for 20–30% free space headroom because object storage performance degrades sharply above roughly 85% capacity. Treat disk alerts with the same urgency as database connection failures.

Choose MinIO when you need a pure S3 object API for Laravel uploads, backup tools, static assets, or staging environments that mirror production S3 behaviour. Ceph and GlusterFS target block and distributed file layers for workloads that need unified block, file, and object storage in one cluster. If your app only speaks PUT/GET/DELETE to buckets, MinIO is the simpler fit.

Create private buckets with mc anonymous set none, never commit root credentials to Git, and issue per-application access keys with bucket-scoped IAM policies instead of sharing MINIO_ROOT_USER. Enable versioning on document buckets, mirror off-site nightly, and use encryption at rest via SSE-S3 or KMS on supported MinIO releases. For compliance-sensitive legal portals, encrypt sensitive PDFs in the application layer before upload as defense in depth.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: