MinIO es un servidor de almacenamiento de objetos compatible con la API de Amazon S3: cualquier aplicación, SDK o herramienta de copias de seguridad que hable S3 puede usarlo sin cambios. En este tutorial instalarás MinIO en un único servidor Ubuntu 24.04 como servicio systemd, lo publicarás con HTTPS detrás de Nginx y usarás el cliente mc para crear un bucket, un usuario con permisos limitados y una regla de caducidad de objetos.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS de 64 bits (x86_64), por ejemplo un VPS de CubePath, con al menos 2 GB de RAM.
  • Un usuario no root con privilegios sudo y UFW activo permitiendo SSH.
  • Un disco o volumen para los datos. En esta guía se usa /srv/minio/data; si tienes un volumen adicional, móntalo en esa ruta antes de empezar.
  • Dos nombres DNS con registro A apuntando a la IP del servidor: minio.your_domain para la API S3 y console.your_domain para la consola web. Sustituye your_domain por tu dominio en todos los comandos.

Esta guía despliega un nodo con una sola unidad. Es adecuado para desarrollo, copias de seguridad y cargas pequeñas, pero no ofrece redundancia de disco ni versionado de objetos, que en MinIO requieren un despliegue con varias unidades (erasure coding).

Paso 1: Descargar el binario de MinIO

MinIO se distribuye como un único binario estático. Descárgalo en /usr/local/bin:

cd /tmp
curl -fLO https://dl.min.io/server/minio/release/linux-amd64/minio
sudo install -m 0755 minio /usr/local/bin/minio

Comprueba que se ejecuta:

minio --version
minio version RELEASE.2025-... (commit-id=...)
Runtime: go1.24 linux/amd64

Paso 2: Crear el usuario del servicio y el directorio de datos

MinIO no debe ejecutarse como root. Crea un usuario de sistema sin shell ni directorio personal y dale la propiedad del directorio de datos:

sudo groupadd --system minio-user
sudo useradd --system --no-create-home --shell /usr/sbin/nologin -g minio-user minio-user
sudo mkdir -p /srv/minio/data
sudo chown -R minio-user:minio-user /srv/minio

Paso 3: Configurar las variables de entorno

El servicio lee su configuración de /etc/default/minio. Crea el archivo:

sudo nano /etc/default/minio

Añade este contenido, sustituyendo el usuario y la contraseña de administrador por valores propios. La contraseña debe tener al menos 8 caracteres; usa una larga y aleatoria (por ejemplo, generada con openssl rand -base64 24):

MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=your_strong_password
MINIO_VOLUMES="/srv/minio/data"
MINIO_OPTS="--address :9000 --console-address :9001"
MINIO_SERVER_URL="https://minio.your_domain"
MINIO_BROWSER_REDIRECT_URL="https://console.your_domain"
  • MINIO_OPTS fija el puerto de la API S3 (9000) y el de la consola (9001). No los abrirás en el firewall: Nginx será el único punto de entrada.
  • MINIO_SERVER_URL y MINIO_BROWSER_REDIRECT_URL indican a MinIO las URL públicas que usarán los clientes.

Protege el archivo, ya que contiene la contraseña de administrador:

sudo chown root:minio-user /etc/default/minio
sudo chmod 640 /etc/default/minio

Paso 4: Crear el servicio systemd

Crea la unidad de systemd:

sudo nano /etc/systemd/system/minio.service
[Unit]
Description=MinIO object storage
Documentation=https://github.com/minio/minio
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
Type=notify
User=minio-user
Group=minio-user
EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
Restart=always
LimitNOFILE=65536
TasksMax=infinity
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

Las variables se escriben sin llaves ($MINIO_OPTS) para que systemd las separe en argumentos. Recarga systemd y arranca el servicio:

sudo systemctl daemon-reload
sudo systemctl enable --now minio

Comprueba el estado:

sudo systemctl status minio --no-pager
● minio.service - MinIO object storage
     Loaded: loaded (/etc/systemd/system/minio.service; enabled; preset: enabled)
     Active: active (running) since ...

Verifica que la API responde en local con el endpoint de salud:

curl -I http://127.0.0.1:9000/minio/health/live
HTTP/1.1 200 OK

Si el servicio no arranca, revisa el registro con sudo journalctl -u minio -n 50.

Paso 5: Publicar MinIO con Nginx y Let's Encrypt

Instala Nginx y Certbot:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Crea un sitio con dos bloques server, uno para la API y otro para la consola:

sudo nano /etc/nginx/sites-available/minio
server {
    listen 80;
    server_name minio.your_domain;

    # Sin límite de tamaño ni buffering: los objetos pueden ser grandes
    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;
    ignore_invalid_headers off;

    location / {
        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_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
        proxy_connect_timeout 300;
        proxy_pass http://127.0.0.1:9000;
    }
}

server {
    listen 80;
    server_name console.your_domain;

    client_max_body_size 0;

    location / {
        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;
        # La consola usa WebSockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://127.0.0.1:9001;
    }
}

Activa el sitio, comprueba la sintaxis y recarga Nginx:

sudo ln -s /etc/nginx/sites-available/minio /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Abre HTTP y HTTPS en el firewall y solicita los certificados. Certbot modifica el sitio para servir HTTPS y redirigir HTTP:

sudo ufw allow 'Nginx Full'
sudo certbot --nginx -d minio.your_domain -d console.your_domain

Comprueba la API desde tu equipo o desde el propio servidor:

curl -I https://minio.your_domain/minio/health/live
HTTP/2 200

Abre https://console.your_domain en el navegador e inicia sesión con MINIO_ROOT_USER y MINIO_ROOT_PASSWORD.

Paso 6: Instalar y configurar el cliente mc

mc es el cliente de línea de comandos de MinIO. Instálalo con el nombre mcli para no chocar con Midnight Commander, que en Ubuntu también usa el comando mc:

cd /tmp
curl -fLO https://dl.min.io/client/mc/release/linux-amd64/mc
sudo install -m 0755 mc /usr/local/bin/mcli

Registra un alias con las credenciales de administrador:

mcli alias set myminio https://minio.your_domain minioadmin your_strong_password
Added `myminio` successfully.

Comprueba la conexión y el estado del servidor:

mcli admin info myminio
●  minio.your_domain
   Uptime: 10 minutes
   Version: ...
   Network: 1/1 OK
   Drives: 1/1 OK

Paso 7: Crear un bucket y subir objetos

Crea un bucket llamado backups y sube un archivo de prueba:

mcli mb myminio/backups
echo "hola minio" > /tmp/prueba.txt
mcli cp /tmp/prueba.txt myminio/backups/
mcli ls myminio/backups
Bucket created successfully `myminio/backups`.
...
[2026-09-25 10:12:03 UTC]    11B STANDARD prueba.txt

Para sincronizar un directorio completo usa mcli mirror, que solo copia los archivos nuevos o modificados:

mcli mirror /var/www myminio/backups/www

Paso 8: Crear un usuario con acceso limitado

Las aplicaciones no deben usar las credenciales de administrador. Crea una política que solo permita trabajar dentro del bucket backups:

nano ~/backups-rw.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:GetBucketLocation"],
      "Resource": ["arn:aws:s3:::backups"]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": ["arn:aws:s3:::backups/*"]
    }
  ]
}

Registra la política, crea el usuario appbackup y asóciale la política. Sustituye app_secret_key por una clave secreta larga y aleatoria:

mcli admin policy create myminio backups-rw ~/backups-rw.json
mcli admin user add myminio appbackup app_secret_key
mcli admin policy attach myminio backups-rw --user appbackup

Verifica los permisos con un alias que use el nuevo usuario. Debe poder listar backups y recibir un error de acceso al intentar crear otro bucket:

mcli alias set appminio https://minio.your_domain appbackup app_secret_key
mcli ls appminio/backups
mcli mb appminio/otro-bucket
[2026-09-25 10:12:03 UTC]    11B STANDARD prueba.txt
mcli: <ERROR> Unable to make bucket `appminio/otro-bucket`. Access Denied.

Con estas credenciales (endpoint https://minio.your_domain, clave de acceso appbackup y su clave secreta) ya puedes configurar cualquier cliente S3, como rclone, restic o el SDK de AWS.

Paso 9: Borrar objetos antiguos automáticamente

Las reglas de ciclo de vida (ILM) eliminan objetos pasado un tiempo. Esta regla borra los objetos del prefijo tmp/ a los 7 días:

mcli ilm rule add --prefix "tmp/" --expire-days 7 myminio/backups
mcli ilm rule ls myminio/backups

La salida muestra la regla con el prefijo tmp/, estado Enabled y 7 días hasta la caducidad.

Solución de problemas

  • systemctl status muestra failed y el registro dice que la contraseña es demasiado corta: MINIO_ROOT_PASSWORD necesita al menos 8 caracteres. Corrígela en /etc/default/minio y ejecuta sudo systemctl restart minio.
  • Error file access denied al arrancar: el directorio de datos no pertenece a minio-user. Repite sudo chown -R minio-user:minio-user /srv/minio.
  • Las subidas grandes fallan con 413 Request Entity Too Large: falta client_max_body_size 0; en el bloque server de la API en Nginx.
  • Errores de firma (SignatureDoesNotMatch) a través del proxy: Nginx debe enviar la cabecera Host $http_host sin modificar, como en la configuración del paso 5.

Conclusión

Tienes MinIO funcionando como servicio systemd, accesible por HTTPS a través de Nginx, con un bucket, un usuario de aplicación limitado a ese bucket y una regla de caducidad. Como siguientes pasos puedes configurar restic o rclone para enviar copias de seguridad a este bucket, montar un despliegue con varias unidades para disponer de redundancia y versionado, o replicar el bucket a otro servidor con mcli mirror --watch.