Saltar al contenido
Infrastructure 2026-09-06 14 min de lectura

Cómo instalar MinIO y crear tu propio almacenamiento S3 en un VPS

MinIO convierte un VPS en un servidor de almacenamiento de objetos compatible con la API de Amazon S3. Tus aplicaciones siguen usando el SDK de S3 de siempre; solo cambian el endpoint y las credenciales. Esta guía instala MinIO con Docker, lo publica con HTTPS y lo deja administrado con permisos mínimos.

Cómo instalar MinIO y crear tu propio almacenamiento S3 en un VPS
#MinIO#S3#almacenamiento#VPS#Docker#object storage
T
Equipo Terranode
Editorial

Qué es MinIO y cuándo tiene sentido

MinIO es un servidor de almacenamiento de objetos escrito en Go, distribuido bajo licencia AGPLv3, que implementa el protocolo S3. Almacenamiento de objetos significa guardar archivos completos identificados por una clave dentro de un contenedor llamado bucket, en vez de un sistema de archivos con carpetas y permisos POSIX. Es el modelo que usan las imágenes de un catálogo, los adjuntos de un CRM, los respaldos o los artefactos de un pipeline.

Encaja bien en estos casos:

  • Aplicaciones ya escritas contra S3 que quieres alojar sin factura de AWS.
  • Adjuntos y subidas de usuario que no deben vivir en el disco del contenedor de la aplicación.
  • Destino de respaldos de otras herramientas: Restic, Duplicati, Velero, n8n o Supabase Storage hablan S3.
  • Entornos de desarrollo que necesitan un S3 real sin tocar producción.

No encaja si necesitas durabilidad de varias zonas geográficas sin construirla tú, o si vas a servir decenas de terabytes de tráfico público: ahí el ancho de banda del VPS y un CDN pesan más que el software.

Dimensionar el VPS antes de instalar

MinIO consume poca memoria en reposo (unos 200-400 MB) y el cuello de botella real es el disco y el ancho de banda. Para un uso normal de adjuntos y respaldos, 2 GB de RAM y 2 vCPU son suficientes; la cifra que debes calcular con cuidado es el espacio.

Uso previstoRAM sugeridaDiscoComentario
Desarrollo y pruebas1-2 GB25-30 GBUn solo disco, sin redundancia
Adjuntos de una app en producción2-4 GB80 GB NVMeDeja 30 % libre para crecimiento
Destino de backups4 GB120 GB o másEl disco crece por retención, no por tráfico
Multimedia servida a usuarios4-8 GB150 GB + CDNEl ancho de banda manda sobre la RAM

Dos advertencias honestas. Primera: con un solo disco no hay erasure coding, la técnica con la que MinIO reconstruye datos si falla una unidad. En un VPS de un solo volumen, la protección la aporta el backup externo, no MinIO. Segunda: MinIO no comprime ni deduplica. Un objeto de 1 GB ocupa 1 GB, más un pequeño coste de metadatos.

Comprueba el servidor antes de empezar:

bash
free -h
df -h /
nproc

Si dudas del tamaño, la guía sobre cuánta RAM necesita un VPS ayuda a sumar servicios en el mismo host.

Instalar MinIO con Docker Compose

El despliegue oficial usa la imagen quay.io/minio/minio, expone el puerto 9000 para la API S3 y el 9001 para la consola web. Parte de un VPS con Docker ya instalado; si no lo tienes, sigue primero Docker en un VPS.

Crea el directorio de datos y el archivo de configuración:

bash
sudo mkdir -p /srv/minio/data
cd /srv/minio

docker-compose.yml:

yaml
services:
  minio:
    image: quay.io/minio/minio:latest
    container_name: minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
      MINIO_SERVER_URL: https://s3.ejemplo.com
      MINIO_BROWSER_REDIRECT_URL: https://consola.ejemplo.com
    volumes:
      - /srv/minio/data:/data
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9001:9001"
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 30s
      timeout: 10s
      retries: 3

Genera credenciales raíz que no vas a reutilizar en ninguna aplicación:

bash
umask 077
cat > /srv/minio/.env <<EOF
MINIO_ROOT_USER=$(openssl rand -hex 8)
MINIO_ROOT_PASSWORD=$(openssl rand -base64 32)
EOF
cat /srv/minio/.env
docker compose up -d
docker compose logs --tail=50 minio

Fíjate en el detalle de ports: publicar en 127.0.0.1 deja MinIO accesible solo desde el propio servidor. Internet llegará a través de Nginx, no directamente al contenedor. Si omites el prefijo, Docker abre el puerto en todas las interfaces y salta por encima de reglas simples de UFW.

Publicar MinIO con HTTPS detrás de Nginx

MinIO necesita dos nombres distintos: uno para la API S3 y otro para la consola, porque el navegador y el SDK esperan comportamientos diferentes. Crea dos registros A, s3.ejemplo.com y consola.ejemplo.com, apuntando a la IP del VPS.

nginx
server {
    listen 443 ssl;
    server_name s3.ejemplo.com;

    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        proxy_pass http://127.0.0.1:9000;
        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 300;
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
    }
}

client_max_body_size 0 quita el límite de subida de Nginx, que por defecto rechaza cuerpos mayores de 1 MB con un error 413. Es el fallo número uno al subir archivos a un MinIO recién instalado. Desactivar el buffering evita que Nginx escriba en disco cada archivo antes de reenviarlo.

Repite el bloque para consola.ejemplo.com apuntando a 127.0.0.1:9001 y emite los certificados:

bash
sudo certbot --nginx -d s3.ejemplo.com -d consola.ejemplo.com
curl -I https://s3.ejemplo.com/minio/health/live

Ese endpoint de salud responde 200 OK cuando el servidor está operativo y sirve para el monitoreo externo.

La consola comunitaria ya no administra: usa mc

Desde la versión RELEASE.2025-05-24, la consola web de la edición comunitaria de MinIO quedó reducida a un explorador de objetos. La gestión de usuarios, políticas, buckets, ciclo de vida y replicación se retiró de la interfaz gráfica y pasó a la edición comercial AIStor. Fue un cambio polémico y conviene saberlo antes de montar un flujo de trabajo alrededor de una pantalla que ya no existe.

La buena noticia: toda esa administración sigue disponible, gratis, desde mc, el cliente oficial de línea de comandos.

bash
curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc \
  -o /usr/local/bin/mc
sudo chmod +x /usr/local/bin/mc
mc alias set local https://s3.ejemplo.com "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD"
mc admin info local

Si el flujo gráfico es innegociable para tu equipo, las opciones reales son AIStor de pago, un cliente S3 de escritorio como Cyberduck o S3 Browser apuntando a tu endpoint, o alternativas como Garage y SeaweedFS. No hay una versión comunitaria con consola de administración completa.

Crear buckets, usuarios y políticas de acceso mínimo

Nunca entregues las credenciales raíz a una aplicación: crea un usuario por servicio con una política limitada a su bucket. Si una clave se filtra, el daño queda contenido en un bucket en lugar de en todo el almacenamiento.

bash
mc mb local/uploads
mc version enable local/uploads

cat > /tmp/uploads-policy.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": ["arn:aws:s3:::uploads/*"]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::uploads"]
    }
  ]
}
EOF

mc admin policy create local uploads-rw /tmp/uploads-policy.json
mc admin user add local app-uploads "$(openssl rand -base64 24)"
mc admin policy attach local uploads-rw --user app-uploads

mc version enable activa el versionado del bucket: una sobrescritura o un borrado accidental deja la versión anterior recuperable. Cuesta espacio, así que combínalo con una regla de expiración:

bash
mc ilm rule add --expire-delete-marker --noncurrent-expire-days 30 local/uploads

Si el bucket debe servir imágenes públicas, hazlo explícito en vez de dejarlo abierto por descuido:

bash
mc anonymous set download local/publico

Conectar la aplicación desde Laravel y Node.js

Cualquier SDK de S3 funciona con MinIO si defines el endpoint y activas el estilo de ruta. El estilo de ruta significa que la URL queda como https://s3.ejemplo.com/mi-bucket/archivo.jpg en lugar de https://mi-bucket.s3.ejemplo.com/archivo.jpg. Sin él, el SDK intenta resolver un subdominio por bucket y falla si no tienes DNS comodín.

En Laravel, sobre el disco s3 ya incluido en config/filesystems.php:

bash
AWS_ACCESS_KEY_ID=app-uploads
AWS_SECRET_ACCESS_KEY=la_clave_generada
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=uploads
AWS_ENDPOINT=https://s3.ejemplo.com
AWS_USE_PATH_STYLE_ENDPOINT=true

En Node.js con el SDK v3:

javascript
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  endpoint: "https://s3.ejemplo.com",
  region: "us-east-1",
  forcePathStyle: true,
  credentials: {
    accessKeyId: process.env.MINIO_ACCESS_KEY,
    secretAccessKey: process.env.MINIO_SECRET_KEY,
  },
});

await s3.send(new PutObjectCommand({
  Bucket: "uploads",
  Key: "facturas/2026-09.pdf",
  Body: buffer,
  ContentType: "application/pdf",
}));

region es obligatoria en el SDK aunque MinIO la ignore en una instalación de un solo nodo: cualquier valor válido sirve. Para subidas grandes desde el navegador, genera URLs prefirmadas y evita que el archivo pase por tu servidor de aplicación.

MinIO frente a S3 y otras opciones

CriterioMinIO en VPSAWS S3Cloudflare R2Garage
CosteFijo, el del VPSPor GB + salidaPor GB, salida gratuitaFijo, el del VPS
Consola de administraciónSolo mc en la edición libreCompletaCompletaCLI y API
Durabilidad multizonaLa construyes túIncluidaIncluidaEntre tus nodos
Compatibilidad S3Muy altaReferenciaAltaAlta, subconjunto
LicenciaAGPLv3PropietariaPropietariaAGPLv3
Mejor paraAdjuntos y backups propiosEscala sin operaciónTráfico público altoClústeres pequeños distribuidos

Reconocer lo ajeno da criterio: si sirves mucho tráfico público, la salida gratuita de R2 gana por coste; y si necesitas once nueves de durabilidad sin equipo de operaciones, S3 lo entrega y un VPS no.

Backups y replicación

mc mirror copia objetos y metadatos hacia otro destino, y es la base de un respaldo verificable. Programa el espejo hacia un segundo VPS, un disco de otro proveedor o un bucket de un tercero:

bash
mc alias set remoto https://s3-backup.otroproveedor.com CLAVE SECRETO
mc mirror --overwrite --remove local/uploads remoto/uploads-backup

Usa --remove con cuidado: propaga borrados. Para copias de seguridad reales conviene omitirlo y depurar aparte, de modo que un borrado accidental en origen no destruya la copia.

La replicación de bucket entre dos MinIO da continuidad, no protección contra errores humanos. Si alguien elimina un objeto, la réplica lo elimina también. Versionado más copia fría fuera del servidor es la combinación que sí protege. Revisa la guía de backups en VPS para encajar MinIO en tu política general.

Prueba la restauración de verdad: descarga un objeto en otro servidor y ábrelo. Un mc mirror que termina sin error no demuestra que el archivo sea legible.

Problemas frecuentes al instalar MinIO

SíntomaCausa habitualSolución
Error 413 al subirLímite de cuerpo en Nginxclient_max_body_size 0
SignatureDoesNotMatchReloj desincronizado o Host alteradotimedatectl status y proxy_set_header Host $http_host
El SDK busca bucket.dominioFalta el estilo de rutaforcePathStyle: true o AWS_USE_PATH_STYLE_ENDPOINT=true
La consola redirige malMINIO_BROWSER_REDIRECT_URL sin definirDeclarar la URL pública de la consola
No hay pestaña de usuariosConsola comunitaria recortadaAdministrar con mc admin
Disco lleno sin explicaciónVersiones antiguas retenidasRegla de ciclo de vida con mc ilm

Instalar MinIO son diez minutos de Docker; operarlo bien son las decisiones que vienen después: publicarlo solo detrás de HTTPS, dejar el puerto 9000 atado a 127.0.0.1, crear un usuario por aplicación con política mínima y aceptar que la administración vive en mc, no en la consola. Con un solo disco no tienes redundancia: el backup externo verificado es lo que convierte tu MinIO en almacenamiento en el que se puede confiar.

Terranode ofrece VPS KVM con disco NVMe en Ecuador desde $2,99 al mes, con planes de 4 GB de RAM y 40 GB de disco por $9 que sirven de sobra para auto-alojar MinIO junto a tu aplicación.

¿Listo para llevar tu sitio al siguiente nivel?

Hosting con LiteSpeed, NVMe y soporte 24/7 desde $3/mes.

Ver planes de hosting

Preguntas frecuentes