Why self-host MinIO on a VPS
MinIO exposes a 100% S3-compatible API: all your SDKs, tools (aws s3, rclone, mc) and frameworks that speak S3 work without modification. Instead of paying for storage, requests and especially the egress of a public cloud, you get local object storage at the fixed price of your VPS. It is perfect for serving application assets, storing user uploads, receiving database snapshots, or building a backup target for your other servers, all on infrastructure you control.
The strengths of in-house object storage
- A native S3 API: immediate compatibility with
aws-cli,rclone, existing SDKs and frameworks - No egress fees or per-request GET/PUT billing
- A built-in web console to manage buckets, policies and users
- Server-side encryption and object versioning enabled per bucket
- An ideal backup target for your VPS, databases and containers
- Granular access policies and presigned links to share files securely
Realistic prerequisites
MinIO is light on CPU/RAM: a 2 vCPU / 2 GB RAM VPS is enough to get started. The determining factor is the disk: plan for an SSD volume sized according to your target capacity, with headroom for versioning. Docker + Compose installed, a subdomain for the API (s3.yourdomain.com) and another for the console (console.yourdomain.com). A TLS certificate is essential because MinIO carries credentials.
Step-by-step deployment
Prepare storage on the VPS
Create the data directory on your SSD: mkdir -p /opt/minio/data. If you have several volumes, MinIO can aggregate them in erasure-coding mode for resilience.
Define the service with strong credentials
In docker-compose.yml, use the minio/minio image, the server /data --console-address ":9001" command, and set MINIO_ROOT_USER / MINIO_ROOT_PASSWORD with randomly generated values. Mount /opt/minio/data:/data.
Start and bind the ports locally
Run docker compose up -d. Expose API port 9000 and console port 9001 only on 127.0.0.1: they will be published exclusively via the reverse proxy.
Set up the TLS reverse proxy
Configure two HTTPS virtual hosts: s3.yourdomain.com to port 9000 and console.yourdomain.com to 9001. Remember to allow large uploads with client_max_body_size 0; (Nginx) on the API host.
Create a bucket and an application user
With the mc client: mc alias set local https://s3.yourdomain.com ..., then mc mb local/mon-bucket and create a dedicated user with a readwrite policy limited to that bucket rather than using the root account.
Enable versioning and encryption
Enable versioning (mc version enable) to protect against accidental deletions and configure server-side encryption (SSE) on sensitive buckets.
Use the bucket replication feature (mc replicate) between your MinIO and a second remote VPS: you get a near real-time copy of your objects in another location, which constitutes a robust disaster-recovery strategy without depending on a third-party cloud. Combine it with lifecycle rules to automatically expire old versions and keep disk space in check.