How to Self-Host MinIO in 2026: S3 Endpoints, TLS and Durable Storage
A practical MinIO self-hosting guide covering Docker, ports, persistent data, TLS, security, backups and the failures that block production use. Step by step.
A failed MinIO deployment does not always crash. It may serve a login page while clients sign requests for the console URL instead of the S3 API URL. Start with an end-to-end check instead: create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered.
That check matches the cataloged purpose of MinIO: S3-compatible object storage on disks you control. It also exposes missing dependencies, wrong proxy assumptions and ephemeral data earlier than an uptime probe can.
What MinIO depends on
The MinIO HTTP process listens on 9000; keep that port on the application network and publish only the platform route. The local runtime requirement is a second disk or remote target for recoverable backups. Keep its lifecycle explicit so moving MinIO between hosts does not silently change behavior.
Write the boundary down as a short contract: who owns the requirement, which credential is used, what timeout is acceptable and how failure appears. Then run this transaction: create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered. Observe disk latency, concurrent multipart uploads, free-space headroom and network throughput between applications and the S3 endpoint during the run, because that workload gives a more useful starting size than an idle container.
A Docker baseline for MinIO
A production-shaped launch is intentionally boring: named state, explicit port and no secret inside the image.
docker run -d \
--name minio \
--restart unless-stopped \
-p 127.0.0.1:9000:9000 \
-p 127.0.0.1:9001:9001 \
-v minio-data:/data \
-e MINIO_ROOT_PASSWORD=replace-with-a-long-random-value \
-e MINIO_ROOT_USER=dockup-admin \
quay.io/minio/minio:latest server /data --console-address :9001
The example is a baseline rather than a complete supporting stack. Confirm the local requirement before exposure: a second disk or remote target for recoverable backups. Check the effective mounts and listener, then try to create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered. Pin the working image before the next restart.
Domains, proxy headers and port 9000
TLS issuance is only half of the MinIO route. Route the S3 API and console as separate hostnames when both are exposed. Send traffic internally to 9000 and forward the external scheme so generated URLs and secure cookies remain consistent.
Use the complete MinIO scenario from a clean network, not merely the root page. A 502 or certificate failure can be isolated with automatic domain and TLS setup. If traffic reaches the process and clients sign requests for the console URL instead of the S3 API URL, diagnose that condition where it occurs instead of stacking redirects.
Design the MinIO restore before launch
Make a recovery manifest for MinIO: bucket data, policies, users and tested object-level replicas. Mount /data before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. Check ownership and free space now, because a mounted but unwritable path behaves like no persistence at all.
Back up to a failure domain separate from the running server. Recreate MinIO from its pinned image and verify that bucket versions, policies, users and a representative multipart object survive recovery on different storage. The persistent-volume guide helps translate that exercise into snapshot and retention policy.
Choose the MinIO trust boundary
Threat-model the action MinIO performs, not just its login form. Here the high-risk mistake is using short default root credentials or exposing the admin console broadly. Implement this boundary: separate the S3 API from the administrative console and issue application keys that cannot manage the whole server.
Treat MINIO_ROOT_PASSWORD according to its MinIO role: keep sensitive values out of Git, document rotation effects and never substitute a public example in production. Do not solve a permission error by running the container as root or mounting the host broadly. Resource limits also belong to the security design when disk latency, concurrent multipart uploads, free-space headroom and network throughput between applications and the S3 endpoint can be triggered by users.
Logs that answer the next question
Observe the work MinIO performs: disk latency, concurrent multipart uploads, free-space headroom and network throughput between applications and the S3 endpoint. Set limits with headroom for that work and avoid a liveness probe that competes with it. The operator check should still attempt to create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered on a schedule.
For updates, remember that server releases, client signing behavior and any erasure-set layout must be tested with a copy of real bucket metadata. Deploy the candidate against a recovered copy and repeat the known test. If clients sign requests for the console URL instead of the S3 API URL, use runtime logs and the actual network request to find which assumption changed.
Evidence to collect before MinIO goes live
Before real users arrive, make a release worksheet for MinIO. It must name the pinned image, port 9000, canonical origin, persistent paths and the owner of a second disk or remote target for recoverable backups. Attach the expected result of this transaction: create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered.
Use the worksheet after a normal replacement and after a clean restore. Recovery is accepted only if bucket versions, policies, users and a representative multipart object survive recovery on different storage. Also collect a short resource trace covering disk latency, concurrent multipart uploads, free-space headroom and network throughput between applications and the S3 endpoint; keep it beside the release so future capacity changes are compared with the same workload.
Include one controlled failure: submit harmless input near the resource or format limit associated with this boundary: clients sign requests for the console URL instead of the S3 API URL. Confirm MinIO reports the problem at the correct boundary, put the valid condition back and rerun the transaction. This checks error visibility, not merely success, and prevents a healthy-looking interface from concealing a broken worker, callback or database connection.
Deploy MinIO on Dockup without losing its boundaries
A Dockup template should encode the image, port 9000, mounts, health timing, domain, TLS and secret delivery. Dockup should preserve the MinIO runtime settings while the operator confirms this local requirement: a second disk or remote target for recoverable backups. The same deployment can target Dockup servers or customer-attached capacity.
After the route is live, apply the public setting and try to create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered. Back up bucket data, policies, users and tested object-level replicas and keep the restore exercise in the operating plan; those are MinIO responsibilities that remain visible after infrastructure provisioning.
Frequently asked questions
What does MinIO need for a production deployment?
Route the MinIO container on port 9000 through one HTTPS origin. The local runtime requirement is a second disk or remote target for recoverable backups. Do not call MinIO ready until you can create a bucket, upload a multipart object, fetch it through a presigned URL and verify a versioned delete can be recovered.
Which MinIO data belongs in a backup?
Persist /data and include bucket data, policies, users and tested object-level replicas in the same recovery manifest. A clean MinIO restore passes only when bucket versions, policies, users and a representative multipart object survive recovery on different storage.
Does MinIO require HTTPS behind a reverse proxy?
Use HTTPS for the public MinIO origin and keep port 9000 on the internal route. Apply the MinIO setting correctly: route the S3 API and console as separate hostnames when both are exposed. For MinIO, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.
How should a MinIO upgrade be tested?
Restore current MinIO state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because server releases, client signing behavior and any erasure-set layout must be tested with a copy of real bucket metadata. Keep the previous MinIO image until its data-migration and rollback boundary are understood.
