MinIO self-hosted na VPS

    MinIO é o storage de objetos S3-compatível open-source mais rápido do mundo — substitui o Amazon S3 para arquivos, backups e assets da aplicação rodando inteiramente na sua VPS. Com a mesma API do S3, você troca apenas o endpoint e continua usando o AWS SDK sem mudar código.

    Instalar MinIO com Docker Compose

    Stack completa com MinIO e configuração de produção:

    yaml
    # docker-compose.yml
    services:
      minio:
        image: minio/minio:latest
        restart: always
        command: server /data --console-address ":9001"
        ports:
          - "127.0.0.1:9000:9000"   # API S3
          - "127.0.0.1:9001:9001"   # Console web
        environment:
          MINIO_ROOT_USER: ${MINIO_ROOT_USER}
          MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
          MINIO_BROWSER_REDIRECT_URL: https://minio-console.seudominio.com.br
        volumes:
          - minio_data:/data
        healthcheck:
          test: ["CMD", "mc", "ready", "local"]
          interval: 30s
          timeout: 20s
          retries: 3
    
    volumes:
      minio_data:

    Configurar Nginx para API e Console

    Dois virtual hosts: um para a API S3 e outro para o console web:

    nginx
    # /etc/nginx/conf.d/minio.conf
    
    # API S3 (para as aplicações)
    server {
        listen 443 ssl http2;
        server_name s3.seudominio.com.br;
    
        ssl_certificate     /etc/letsencrypt/live/s3.seudominio.com.br/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/s3.seudominio.com.br/privkey.pem;
    
        ignore_invalid_headers off;
        client_max_body_size 0;         # sem limite de tamanho
        proxy_buffering off;
        proxy_request_buffering off;
    
        location / {
            proxy_pass http://127.0.0.1:9000;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_connect_timeout 300s;
            proxy_read_timeout 300s;
            proxy_send_timeout 300s;
            chunked_transfer_encoding off;
        }
    }
    
    # Console web (restrito por IP)
    server {
        listen 443 ssl http2;
        server_name minio-console.seudominio.com.br;
    
        ssl_certificate     /etc/letsencrypt/live/minio-console.seudominio.com.br/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/minio-console.seudominio.com.br/privkey.pem;
    
        allow 177.10.0.1;
        deny all;
    
        location / {
            proxy_pass http://127.0.0.1:9001;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $http_host;
        }
    }

    Criar buckets e políticas via mc (MinIO Client)

    CLI do MinIO para gerenciar buckets e permissões:

    bash
    # Instalar mc (MinIO Client)
    curl -O https://dl.min.io/client/mc/release/linux-amd64/mc
    chmod +x mc
    sudo mv mc /usr/local/bin/
    
    # Configurar alias para o servidor
    mc alias set myminio https://s3.seudominio.com.br \
      SEU_ROOT_USER SEU_ROOT_PASSWORD
    
    # Verificar conexão
    mc ready myminio
    
    # Criar buckets
    mc mb myminio/uploads         # uploads de usuários
    mc mb myminio/backups         # backups de banco de dados
    mc mb myminio/assets          # assets públicos
    
    # Tornar bucket público (para assets estáticos acessíveis sem autenticação):
    mc anonymous set public myminio/assets
    
    # Criar usuário específico para a aplicação (menor privilégio):
    mc admin user add myminio app_user senha_app_user
    mc admin policy attach myminio readwrite --user app_user
    
    # Listar buckets e objetos:
    mc ls myminio
    mc ls myminio/uploads/

    Integrar com Node.js (AWS SDK)

    Usar o MinIO como drop-in replacement do S3 na aplicação:

    typescript
    // Node.js — usando AWS SDK v3 com MinIO
    import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'
    import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
    
    const s3 = new S3Client({
      endpoint: 'https://s3.seudominio.com.br',  // URL do MinIO
      region: 'us-east-1',                        // qualquer valor
      credentials: {
        accessKeyId: process.env.MINIO_ACCESS_KEY!,
        secretAccessKey: process.env.MINIO_SECRET_KEY!,
      },
      forcePathStyle: true,    // OBRIGATÓRIO para MinIO
    })
    
    // Upload de arquivo
    async function uploadFile(key: string, body: Buffer, contentType: string) {
      await s3.send(new PutObjectCommand({
        Bucket: 'uploads',
        Key: key,
        Body: body,
        ContentType: contentType,
      }))
      return `https://s3.seudominio.com.br/uploads/${key}`
    }
    
    // URL pré-assinada para download temporário (1 hora)
    async function getPresignedUrl(key: string) {
      return getSignedUrl(s3, new GetObjectCommand({
        Bucket: 'uploads',
        Key: key,
      }), { expiresIn: 3600 })
    }
    Dica
    forcePathStyle: true é obrigatório com MinIO self-hosted — o S3 da AWS usa virtual-hosted style (bucket.s3.amazonaws.com) mas o MinIO usa path style (s3.dominio.com/bucket).

    Backup e monitoramento do MinIO

    Monitorar uso de storage e configurar replicação de bucket:

    bash
    # Ver uso de storage por bucket:
    mc du myminio/uploads
    mc du myminio/backups
    
    # Replicação para outro MinIO ou S3 (DR):
    mc replicate add myminio/backups \
      --remote-bucket s3://meu-bucket-aws/backups \
      --arn "arn:minio:replication::..." \
      --priority 1
    
    # Lifecycle policy — deletar objetos antigos automaticamente:
    mc ilm rule add myminio/backups \
      --expiry-days 30              # deletar após 30 dias
    
    # Backup do volume MinIO com rsync para armazenamento externo:
    rsync -av --progress /var/lib/docker/volumes/minio_data/_data/ \
      usuario@backup-server:/backups/minio/
    
    # Métricas com Prometheus:
    mc admin prometheus generate myminio
    # Adicionar o scrape config gerado ao prometheus.yml

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o MinIO em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes