MinIO is a high-performance, S3-compatible object storage server. It's the go-to choice when you want S3 semantics — buckets, objects, presigned URLs, the full S3 API — without depending on AWS. It pairs beautifully with the other apps in this series: Strapi media, Vendure assets, n8n binary data, and database backups can all live in a MinIO bucket. This guide covers a solid production deployment.
What MinIO is (and isn't)
MinIO speaks the S3 API, so any S3 SDK or tool works against it unchanged. It is *stateful* — objects live on disk — which is the central deployment consideration. You must give MinIO durable, persistent storage. It is not a CDN and not a database; it's blob storage.
Step 1: Plan storage
MinIO's golden rule: data lives on the volume, and the volume must persist. For a single-node deployment, that means one persistent volume mounted at MinIO's data directory. Size it for your expected object volume plus headroom.
volumes:
- mount: /data
size: 50GiFor true high availability, MinIO supports distributed mode across multiple nodes with erasure coding — but that's a multi-server topology. A single-node deployment is perfectly fine for development, internal tooling, and many production workloads; just understand it's a single point of failure unless you back it up.
Step 2: Set credentials
MinIO uses a root access key and secret key, set via environment variables. Never use the defaults in production.
MINIO_ROOT_USER=<a strong access key, 20+ chars>
MINIO_ROOT_PASSWORD=<a strong secret, 40+ chars>
MINIO_BROWSER_REDIRECT_URL=https://console.yourdomain.comGenerate both with a password manager or openssl rand. These are effectively root credentials for all your data.
Step 3: Understand the two ports
MinIO exposes two distinct services:
| Port | Service | Purpose |
|---|---|---|
| 9000 | S3 API | Where your apps and SDKs connect |
| 9001 | Console | The web admin UI |
The start command sets the console port explicitly:
minio server /data --console-address ":9001"Step 4: Deploy on PandaStack
MinIO publishes an official Docker image, so this is a container deploy with a persistent volume:
- 1Create a container app using
minio/minio. - 2Set the start command:
minio server /data --console-address ":9001". - 3Attach a persistent volume at
/data. - 4Set
MINIO_ROOT_USERandMINIO_ROOT_PASSWORD. - 5Expose the S3 API port (9000) on your service. Attach a custom domain like
s3.yourdomain.comwith automatic SSL — TLS is important for object storage carrying credentials and presigned URLs.
For the console, you can expose 9001 on a separate subdomain or restrict it behind your network/firewall rules.
Step 5: Create buckets and scoped users
Don't use the root credentials in your applications. Use the MinIO Client (mc) to create a bucket and a scoped user with a least-privilege policy:
mc alias set myminio https://s3.yourdomain.com $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
mc mb myminio/app-media
mc admin user add myminio app-user <app-secret>
mc admin policy attach myminio readwrite --user app-userThen your application uses app-user's credentials, scoped only to what it needs — root stays locked away.
Step 6: Connect your apps
Any S3-compatible client connects with four values:
S3_ENDPOINT=https://s3.yourdomain.com
S3_ACCESS_KEY=app-user
S3_SECRET_KEY=<app-secret>
S3_BUCKET=app-media
# crucial for MinIO:
S3_FORCE_PATH_STYLE=trueThe forcePathStyle / path-style flag matters — MinIO uses endpoint/bucket/key rather than the virtual-hosted bucket.endpoint/key style. Most SDKs need this flag set for MinIO.
Production checklist
- Persistent volume sized with headroom; backups configured.
- Strong, non-default root credentials in a secret manager.
- TLS on the S3 endpoint (automatic SSL).
- Scoped users per application, never root.
- Bucket policies following least privilege.
- Versioning enabled on buckets where you need object history.
Honest caveats
Single-node MinIO has no built-in redundancy — if the volume dies, the data is gone. For important data, either run distributed MinIO across multiple nodes with erasure coding, or schedule regular backups (e.g., mc mirror to another bucket or provider). Also, MinIO is excellent but it's *your* responsibility to operate: upgrades, capacity, and durability are now yours. For many teams that control is exactly the point; just go in clear-eyed.
Wrapping up
MinIO gives you the entire S3 API on infrastructure you own. The deployment essentials are durable storage, strong credentials, TLS, and scoped per-app users. Once it's up, it becomes the storage backbone for media, backups, and assets across your whole stack.
PandaStack supports persistent volumes, custom domains, and automatic SSL, making a production MinIO instance straightforward — and the free tier lets you try it. Deploy yours at https://dashboard.pandastack.io.
References
- MinIO documentation: https://min.io/docs/minio/linux/index.html
- MinIO Docker deployment: https://min.io/docs/minio/container/index.html
- MinIO Client (mc) reference: https://min.io/docs/minio/linux/reference/minio-mc.html
- MinIO access management / policies: https://min.io/docs/minio/linux/administration/identity-access-management.html
- AWS S3 API reference (for compatibility): https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html