Kituwa IT · Self-hosting guides

Install MinIO with Docker Compose

Self-hosted S3-compatible object storage

S3storagebackups

MinIO is an S3-compatible object store: the API surface AWS S3 exposes, on your own disk. Almost every backup tool, photo app and "cloud storage" replacement speaks S3, and this is how you give them all a target that costs nothing.

Category
Dev & data
License
AGPL-3.0
Needs
Nothing
Image
minio/minio

What it is

Buckets, objects, presigned URLs, versioning, lifecycle rules, and a web console. It replaces S3 for private infrastructure, and it makes backups to a second physical location straightforward because there's a real mc client that mirrors, syncs and encrypts.

Before you start

  • Recent MinIO images gate the web console behind a licence for some features, and the console port can change. Check the release notes for the tag you pin rather than assuming :latest is stable.
  • The root credentials are god credentials. Make them long and random, and never use them as your backup app's credentials — create a scoped service account instead.
  • Versioning is off by default. If the point is "my own dropbox", turn it on before you start uploading.

1 — Create the directory

Command / configuration
mkdir -p ~/services/minio/data
cd ~/services/minio
openssl rand -base64 32   # root password

2 — Write the compose file

Command / configuration
services:
  minio:
    image: minio/minio:latest
    container_name: minio
    restart: always
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: CHANGE_ME_16_chars_min
      MINIO_ROOT_PASSWORD: CHANGE_ME_48_random_bytes
    volumes:
      - ./data:/data
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9001:9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 5s
      retries: 3

  createbuckets:
    image: minio/mc:latest
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      mc alias set local http://minio:9000 CHANGE_ME_16_chars_min CHANGE_ME_48_random_bytes;
      mc mb --ignore-existing local/backups;
      mc mb --ignore-existing local/photos;
      mc mb --ignore-existing local/documents;
      mc version enable local/backups;
      mc anonymous set none local/backups;
      mc anonymous set download local/photos;
      echo 'buckets ready';
      "
    restart: "no"
Don't make private buckets publicmc anonymous set download turns a bucket into a world-readable unauthenticated endpoint. The example above does it for photos to show the syntax — for anything private use none and hand out presigned URLs instead.

3 — Start it

Command / configuration
docker compose up -d
docker compose logs createbuckets     # should end with 'buckets ready'

4 — First-run setup

  1. Log into the console at http://yourhost:9001 with the root credentials.
  2. Under Identity → Users, create a service user with only the policies it needs for its bucket. Use that in Restic, Duplicati, rclone, Immich — not root.
  3. Confirm the port split: 9000 is the S3 API, 9001 is the console. Anything you point an S3 client at uses 9000.
  4. Decide on erasure or replication. With a single volume, MinIO runs in a single-drive configuration — fine for a home server, and honest about the fact that a disk failure is a data loss event.

5 — Use it from the command line

Command / configuration
docker run --rm --network host minio/mc \
  alias set local http://127.0.0.1:9000 CHANGE_ME CHANGE_ME

docker run --rm --network host minio/mc \
  mirror --watch --overwrite local/photos ~/pictures

Help when you need it

Want help getting this running?

We can help with a supported Linux host, application setup, migration or troubleshooting. Contact us to confirm the software, scope and scheduling before ordering.

Related guides

← Browse all 30 guides · Back to top