How to Install MinIO on Ubuntu 24.04: A Step-by-Step Guide

|
Published:
|
|

In this tutorial, you will learn how to install MinIO on Ubuntu 24.04 server. MinIO is a high-performance, open-source object storage server that is compatible with the Amazon S3 API (Simple Storage Service). It’s designed to handle large-scale unstructured data like photos, videos, log files, backups, and container images. In this step-by-step guide, we’ll walk you through installing and configuring MinIO on Ubuntu 24.04, including setting up a secure Nginx reverse proxy and Let’s Encrypt SSL.

How to Install MinIO on Ubuntu 24.04: Step-by-Step

Why Choose MinIO as your Object Storage?

MinIO stands out as a the best alternative to cloud-based storage solutions like Amazon S3. Some of the reasons why you may consider for your local object storage include:

  • Open-Source and Cost-Effective: MinIO is free to use, with no licensing fees, making it ideal for startups, developers, and enterprises looking to reduce costs.
  • Amazon S3 Compatibility: MinIO supports the S3 API, allowing seamless integration with tools and applications designed for AWS S3. If you feel like you are ready to use AWS S3, you can simply make the switch with very little changes on your applications, and vice versa is true (switching from AWS S3 to MinIO).
  • High Performance: Built in Go, MinIO delivers exceptional speed for data-intensive workloads like machine learning and analytics.
  • Self-Hosted Flexibility: Host MinIO on your own infrastructure, giving you full control over data privacy and compliance.
  • Scalability: MinIO scales from a single server to distributed clusters, handling petabytes of data effortlessly.
  • Enterprise Features: Includes encryption, erasure coding, and versioning for robust data protection.

Whether you’re building a private cloud or need a local S3-compatible storage solution, MinIO is a versatile choice.

What are the Common Use Cases for MinIO?

MinIO object storage provides a scalable, high-performance alternative to traditional storage solutions. Some of the most common use cases for MinIO object storage include:

  • Data Backup and Archiving: Store backups securely with MinIO’s versioning and encryption, perfect for Veeam or custom backup solutions. Organizations can implement tiered retention policies and benefit from immutable backups for ransomware protection.
  • Big Data and Analytics: Serve as a data lake for Hadoop, Spark, or Presto, enabling fast access to large datasets. MinIO’s high throughput makes it ideal for data-intensive workloads where performance matters.
  • Machine Learning Workflows: Store training datasets and models for ML pipelines, with high throughput for frameworks like TensorFlow. The S3 API compatibility ensures seamless integration with popular ML tools and platforms.
  • Content Delivery: Host media files (e.g., images, videos) for web applications, with MinIO’s low-latency access. Content can be easily distributed and managed at scale across global deployments.
  • Private Cloud Storage: Replace public cloud storage with MinIO for GDPR or HIPAA-compliant environments. Organizations maintain full control over their data while benefiting from cloud-like elasticity.
  • Development and Testing: Simulate S3 environments locally for developers building S3-compatible applications. This accelerates development cycles and reduces cloud costs during testing phases.
  • IoT Data Collection: Capture and store high-velocity data streams from IoT devices and sensors. MinIO’s lightweight architecture makes it suitable for edge deployments while maintaining compatibility with central data processing systems.
  • Hybrid Cloud Deployments: Bridge on-premises and cloud environments with consistent object storage interfaces. MinIO provides the flexibility to move workloads between environments without changing application code.
  • Log and Metrics Storage: Store application logs, system metrics, and monitoring data at scale. MinIO integrates well with observability tools like Prometheus, Grafana, and the ELK stack.

MinIO Deployment Topology Options

MinIO can be deployed using various topology options depending on your requirements for availability, scalability, and data protection. From simple development setups to enterprise-grade distributed systems, MinIO offers flexible deployment models to meet different needs:

  • Single Node, Single Drive (SNSD): A basic MinIO installation running on a single server with one storage volume. This configuration provides zero data redundancy or fault tolerance. If the server or disk fails, your data is lost. Suitable only for development, testing, or learning environments where data persistence isn’t critical.
  • Single Node, Multi-Drive (SNMD/JBOD (Just a Bunch of Drives)): MinIO running on a single server but utilizing multiple disks (Just a Bunch Of Disks). This increases storage capacity and can provide data redundancy through erasure coding across the drives. However, if the server itself fails, the entire system is down. Good for environments needing more storage and some data protection, but not mission-critical workloads.
  • Distributed (Multi-Node, Multi-Drive): MinIO deployed across at least four independent servers, each with one or more drives. Uses erasure coding to distribute data across nodes, ensuring data remains available even if servers fail. This configuration provides true high availability, fault tolerance, and horizontal scalability. Recommended for production environments where uptime and data integrity are critical.
  • Multi-Site Active-Active: Two or more complete MinIO clusters deployed in different physical locations that continuously replicate data between them. This setup enables geographic disaster recovery – if an entire data center fails, data remains accessible from another location. Provides the highest level of availability and protection against catastrophic failures. Ideal for globally distributed applications or mission-critical systems.

More info on documentation page.

Installing MinIO on Ubuntu 24.04

As you can see, there are multiple deployment options for MinIO for various use cases. In this tutorial, we will deploy MinIO on Ubuntu 24.04 using single node, multi drive topology just for the purposes of demonstrating how to set it up.

So, how can one deploy MinIO object storage on Ubuntu 24.04? Let’s dive in;

Before you proceed, ensure you have access to a non-root account with sudo rights on your Ubuntu 24.04 LTS.

Step 1: MinIO Resource Requirements

The summary outlines the compute and storage requirements for deploying MinIO in production, based on MinIO’s recommended configuration. These are baseline guidelines and should be validated with MinIO’s Performance Diagnostics or support for specific workloads. All nodes in a server pool must have identical hardware and software configurations to ensure consistent performance.

Compute Requirements:

  • Hosts:
    • Minimum: 4 dedicated baremetal or virtual hosts.
    • Recommended: 8+ dedicated hosts for scalability and reliability.
  • CPU:
    • Minimum: 8 CPU cores/socket or vCPUs per host, supporting modern SIMD instructions (e.g., AVX-512, Intel® Xeon® Scalable or better).
    • Recommended: 16+ CPU cores/socket or vCPUs per host for high-performance workloads (e.g., AI/ML, analytics).
    • Identical CPUs across all nodes to avoid performance bottlenecks.
  • Memory:
    • Minimum: 32GB of available RAM per host.
    • Recommended: 128GB+ per host, especially for concurrent connections or large-scale workloads.
    • Starting with RELEASE.2024-01-28T22-35-53Z, MinIO preallocates 2GB (distributed) or 1GB (single-node) per node.
    • Memory scales with storage:
      • Up to 1 TiB: 8GB
      • Up to 10 TiB: 16GB
      • Up to 100 TiB: 32GB
      • Up to 1 PiB: 64GB
      • Over 1 PiB: 128GB
    • Identical memory across nodes to prevent constraints on concurrent requests.

Networking:

  • Minimum: 25GbE network infrastructure.
  • Recommended: 100GbE for maximum throughput (supports ~12.5GBps aggregated storage throughput).
  • Network bandwidth is critical, as it directly impacts performance (e.g., 25GbE supports ~30 spinning disks at 100MB/s each).

Storage Requirements:

  • Drives:
    • Minimum: 4 drives per MinIO server (locally attached).
    • Recommended: 8+ drives per server for better redundancy and performance.
    • Exclusive access required; no other processes should modify MinIO’s data shards, parity shards, or metadata.
  • Storage Type:
    • Recommended: Flash-based storage (NVMe preferred, SSD acceptable) for all workloads due to superior performance.
    • HDD Usage: Only for cold-tier storage (e.g., aged data transitioned via Object Transition). HDDs underperform for modern workloads, negating cost benefits.
    • Use Direct-Attached Storage (DAS) like JBOD arrays, avoiding networked storage (NAS, SAN, NFS) for performance and consistency.
  • Drive Consistency:
    • Identical drive type (NVMe, SSD, or HDD) and capacity across all nodes in a server pool. Mixing types or sizes limits usable capacity to the smallest drive (e.g., one 1TB drive in a pool of 10TB drives caps all at 1TB).
  • Filesystem Settings:
    • Format drives as XFS with unique labels (e.g., mkfs.xfs /dev/vdb -L MINIODRIVE1).
    • Mount drives consistently via /etc/fstab using labels, not UUIDs, for easier drive replacement (e.g., LABEL=MINIODRIVE1 /mnt/drive-1 xfs defaults,noatime 0 2).
    • Disable XFS retry-on-error for EIO, ENOSPC, and default errors to avoid latency (e.g., set max_retries to 0 via a script run at @reboot with cron).

Read more on the documentation page.

As already mentioned, we will be setting up an SNMD MinIO server.

We have four drives to use;

lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
vda     253:0    0  8.5G  0 disk 
├─vda1  253:1    0  7.5G  0 part /
├─vda14 253:14   0    4M  0 part 
├─vda15 253:15   0  106M  0 part /boot/efi
└─vda16 259:0    0  913M  0 part /boot
vdb     253:16   0    5G  0 disk 
vdc     253:32   0    5G  0 disk 
vdd     253:48   0    5G  0 disk 
vde     253:64   0    5G  0 disk

As recommended, the drives need to be formatted with an XFS filesystem each with its unique label.

sudo mkfs.xfs /dev/vdb -L MINIODRIVE0
sudo mkfs.xfs /dev/vdc -L MINIODRIVE1
sudo mkfs.xfs /dev/vdd -L MINIODRIVE2
sudo mkfs.xfs /dev/vde -L MINIODRIVE3

Create the Drives mount points. We will be using /opt/minio in this setup:

sudo mkdir -p /opt/minio/{miniodrive0,miniodrive1,miniodrive2,miniodrive3}

Mount the drives;

sudo mount /dev/vdb /opt/minio/miniodrive0
sudo mount /dev/vdc /opt/minio/miniodrive1
sudo mount /dev/vdd /opt/minio/miniodrive2
sudo mount /dev/vde /opt/minio/miniodrive3

Update the FSTAB for automounting during system reboot. MinIO strongly recommends using label-based mounting rules over UUID-based rules. Hence:

echo "
LABEL=MINIODRIVE0      /opt/minio/miniodrive0	xfs     defaults,noatime  0       2
LABEL=MINIODRIVE1      /opt/minio/miniodrive1	xfs     defaults,noatime  0       2
LABEL=MINIODRIVE2      /opt/minio/miniodrive2   xfs	defaults,noatime  0       2
LABEL=MINIODRIVE3      /opt/minio/miniodrive3   xfs     defaults,noatime  0       2" \
| sudo tee -a /etc/fstab

If you have not mounted them already, just run;

sudo mount -a

Create a script to disable XFS retry on error. In the script below, replace the /opt/minio path to match the pattern used for your MinIO drives.

cat /opt/minio/disable-xfs-retry-on-error.sh
#!/bin/bash

for dev in $(df -h | grep /opt/minio | awk '{ print $1 }'); do
      mountPath="$(df -h | grep $dev | awk '{ print $6 }')"
      deviceName="$(basename $dev)"
      echo "Modifying xfs max_retries and retry_timeout_seconds for drive $dev mounted at $mountPath"
      echo 0 > /sys/fs/xfs/$deviceName/error/metadata/EIO/max_retries
      echo 0 > /sys/fs/xfs/$deviceName/error/metadata/ENOSPC/max_retries
      echo 0 > /sys/fs/xfs/$deviceName/error/metadata/default/max_retries
done
exit 0

Ensure the script is executable;

sudo chmod +x /opt/minio/disable-xfs-retry-on-error.sh

Run the script;

sudo /opt/minio/disable-xfs-retry-on-error.sh

Sample output;

Modifying xfs max_retries and retry_timeout_seconds for drive /dev/vdb mounted at /opt/minio/miniodrive0
Modifying xfs max_retries and retry_timeout_seconds for drive /dev/vdc mounted at /opt/minio/miniodrive1
Modifying xfs max_retries and retry_timeout_seconds for drive /dev/vdd mounted at /opt/minio/miniodrive2
Modifying xfs max_retries and retry_timeout_seconds for drive /dev/vde mounted at /opt/minio/miniodrive3

If you have multiple nodes, ensure the script is installed on all of them.

Schedule the script on run on every node reboot;

echo "@reboot /opt/minio/disable-xfs-retry-on-error.sh" | sudo crontab -

You can list jobs to confirm;

sudo crontab -l

Step 2: Update Your System

Start by updating your Ubuntu 24.04 system to ensure all packages are current. Run the command below to update your system;

sudo apt update

Next, install some of the commands that we may require;

sudo apt install wget curl -y

Step 2: Create a MinIO User and Directories

For security purposes, run MinIO as a non-root user. Therefore, create a system user and group called minio. You can use any suitable system account name.

sudo useradd -r -M -s /sbin/nologin minio

Let’s create MinIO configs directory as well (We will use this to keep TLS certs).

sudo mkdir /etc/minio

Update MinIO data directories ownership;

sudo chown -R minio: /opt/minio /etc/minio

Step 3: Download and Install MinIO on Ubuntu 24.04

MinIO provides precompiled binaries for various system architectures for easy installation. Follow these steps to download and install MinIO on Ubuntu 24.04.

Download the MinIO DEB Binary

On the MinIO binary releases page, navigate into your respective OS architecture page, for example, I am running an Ubuntu 24.04 under AMD64 Arch, hence, MinIO binary would be in the linux-amd64 directory.

You will find a DEB binary file in that directory. Grab its link and pull it into the MinIO server using wget or curl command.

wget https://dl.min.io/server/minio/release/linux-amd64/minio_20250422221226.0.0_amd64.deb -P /tmp

The command above will download MinIO DEB binary and store it under the /tmp directory.

Similarly, you can download respective SHASUM file to calculate the hash and check the integrity of the binary.

wget https://dl.min.io/server/minio/release/linux-amd64/minio_20250422221226.0.0_amd64.deb.sha256sum -P /tmp

To calcuate the hashes, navigate into the directory where both files are;

cd /tmp

The check the HASH;

sha256sum -c minio_20250422221226.0.0_amd64.deb.sha256sum

The output should be Ok to confirm that the integrity of the file is intact. Sample output;

minio_20250422221226.0.0_amd64.deb: OK
cd

Install MinIO on Ubuntu 24.04

Next, run the command below to install MinIO;

sudo apt install /tmp/minio_20250422221226.0.0_amd64.deb

This will install the minio binary under /usr/local/bin directory as /usr/local/bin/minio. As such, MinIO should already be available on CLI. Just to verify, let’s check its version;

minio --version

Output;

minio version RELEASE.2025-04-22T22-12-26Z (commit-id=0d7408fc9969caf07de6a8c3a84f9fbb10a6739e)
Runtime: go1.24.2 linux/amd64
License: GNU AGPLv3 - https://www.gnu.org/licenses/agpl-3.0.html
Copyright: 2015-2025 MinIO, Inc.

It also creates a Systemd service unit (minio.service) under, /usr/lib/systemd/system/minio.service.

Step 4: Configure MinIO Environment

Next, let create a few configurations for MinIO server.

To begin with, let’s create MinIO environment variables to get us started with.

sudo vim /etc/default/minio

Sample configs;

# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD sets the root account for the MinIO server.
# This user has unrestricted permissions to perform S3 and administrative API operations on any resource in the deployment.
# Omit to use the default values 'minioadmin:minioadmin'.
# MinIO recommends setting non-default values as a best practice, regardless of environment.

MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minIO-s3c-change-me

# MINIO_VOLUMES sets the storage volumes or paths to use for the MinIO server.
# The specified path uses MinIO expansion notation to denote a sequential series of drives between 1 and 4, inclusive.
# All drives or paths included in the expanded drive list must exist *and* be empty or freshly formatted for MinIO to start successfully.

MINIO_VOLUMES="/opt/minio/miniodrive{0...3}"

# MINIO_OPTS sets any additional commandline options to pass to the MinIO server.
# For example, `--console-address :9001` sets the MinIO Console listen port
MINIO_OPTS="--address :9000 --console-address :9001"

MinIO recommends access credentials with at least 3-character access key (starting with a letter) and 8-character secret key. Replace the values provided above.

MinIO, by default, uses port 9000 for its S3 API and port 9001 for the MinIO Console (web interface)

Replace the path to the MinIO volumes accordingly.

Save and exit the file.

Step 5: Set Up MinIO as a Systemd Service

As mentioned above, when you install MinIO via DEB, it will create a systemd service unit.

The service unit comes pre-configured. Let’s update it to make a few changes.

The default contents of the file;

cat /usr/lib/systemd/system/minio.service
[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
Type=notify

WorkingDirectory=/usr/local

User=minio-user
Group=minio-user
ProtectProc=invisible

EnvironmentFile=-/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=1048576

# Turn-off memory accounting by systemd, which is buggy.
MemoryAccounting=no

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutSec=infinity

# Disable killing of MinIO by the kernel's OOM killer
OOMScoreAdjust=-1000

SendSIGKILL=no

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

We will only make a few adjustments here:

  • the minio user/group
  • make the envs file non-optional (remove dash (-))
  • the working directory of the service

The final unit file now looks like below;

cat /usr/lib/systemd/system/minio.service
[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
Type=notify

WorkingDirectory=/opt/minio

User=minio
Group=minio
ProtectProc=invisible

EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=1048576

# Turn-off memory accounting by systemd, which is buggy.
MemoryAccounting=no

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutSec=infinity

# Disable killing of MinIO by the kernel's OOM killer
OOMScoreAdjust=-1000

SendSIGKILL=no

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

Reload systemd;

sudo systemctl daemon-reload

Start MinIO;

sudo systemctl enable --now minio

Check the status;

systemctl status minio
● minio.service - MinIO
     Loaded: loaded (/usr/lib/systemd/system/minio.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-04-30 10:17:34 UTC; 3s ago
       Docs: https://docs.min.io
   Main PID: 4754 (minio)
      Tasks: 10
        CPU: 1.398s
     CGroup: /system.slice/minio.service
             └─4754 /usr/local/bin/minio server --address :9000 --console-address :9001 /opt/minio/miniodrive{0...3}

Confirm the ports are listening:

sudo ss -altnp | grep 900
LISTEN 0      4096       127.0.0.1:9000      0.0.0.0:*    users:(("minio",pid=4754,fd=7))                        
LISTEN 0      4096           [::1]:9000         [::]:*    users:(("minio",pid=4754,fd=9))                        
LISTEN 0      4096               *:9000            *:*    users:(("minio",pid=4754,fd=8))                        
LISTEN 0      4096               *:9001            *:*    users:(("minio",pid=4754,fd=6))

Step 6: Configure Firewall

As per our configuration above, MinIO listend on TCP port 9000 for API requests and TCP port 9001 for web console access.

Hence, open these ports on Firewall to allow access to MinIO;

I am using UFW on Ubuntu.

sudo ufw allow 9000/tcp
sudo ufw allow 9001/tcp

If you are using Firewalld/Iptables, use the appropriate commands to open these ports.

Step 7: Access the MinIO Console

Open a browser and navigate to http://your-server-ip:9001.

Install MinIO on Ubuntu 24.04

Log in with the MINIO_ROOT_USER and MINIO_ROOT_PASSWORD set in Step 4.

Upon successful login, you’ll see the MinIO web console dashboard. By default, you land on where you can create buckets and manage objects.

Install MinIO on Ubuntu 24.04

To create a bucket:

  1. Click the Create a Bucket.
  2. If you already have existing buckets, just click the + button in the console to add more.
  3. Enter a bucket name (e.g., my-bucket) and click Create.
Install MinIO on Ubuntu 24.04

Step 8: Secure MinIO with Nginx and Let’s Encrypt (Optional)

For production, you can secure MinIO with HTTPS using Nginx as a reverse proxy and Let’s Encrypt SSL.

Install Nginx

To install Nginx on Ubuntu 24.04;

sudo apt install nginx

Install Certbot for Let’s Encrypt

sudo apt install certbot python3-certbot-nginx -y

Create an Nginx HTTP configuration for the MinIO console.

Replace the FQDN minio-console.yourdomain.com appropriately.

sudo tee /etc/nginx/sites-enabled/minio-console.conf << EOF
server {
    listen 80;
    server_name minio-console.yourdomain.com;

    location / {
        proxy_pass http://localhost:9001;
        proxy_set_header Host \$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;
    }
}
EOF

Confirm the file for syntax errors:

sudo nginx -t

It should be okay;

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Start and enable Nginx service;

sudo systemctl enable --now nginx

Open HTTP port on Firewall;

sudo ufw allow 80/tcp

You should now be able to access MinIO web console via your server domain address without specifying the web console port on the address.

Generate Let's Encrypt TLS Certificates

Now, to use SSL/TLS certs with Let's encrypt, you can generate them for your domain. I assume that you domain is already public and mapped to a public DNS.

In this example guide, I will generate wildcard SSL/TLS certs via Let's encrypt. I will do it a manual way.

Replace yourdomain.com accordingly.

sudo certbot certonly \
  --manual \
  --preferred-challenges dns \
  --server https://acme-v02.api.letsencrypt.org/directory \
  -d "*.yourdomain.com" \
  -d "yourdomain.com"

When the command runs, Certbot pauses and asks you to provide your email address, accept terms of service, if you need to receive info about Let's encrypt and then finally to manually add a DNS TXT record to your DNS provider.

After adding the record, wait 1-5 minutes for DNS propagation, then press Enter in the Certbot prompt to continue.

Note that you might be asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.) Before continuing, verify the TXT record has been deployed. Depending on the DNS provider, this may take some time, from a few seconds to multiple minutes.

You can even verify the propagation using DIG before pressing ENTER.

dig TXT _acme-challenge.yourdomian.com +short

Or you can use online tools, such as the Google Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.yourdomain.com. Look for one or more bolded line(s) below the line ';ANSWER'. It should show the value(s) you've just added.

Press ENTER to complete the generation.

...
Press Enter to Continue

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/yourdomain.com/privkey.pem
This certificate expires on 2025-07-29.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le

Remember we just did the cert generation manually. Hence, you will have to repeat SSL/TLS cert generation every 90 days before expiry. No automation is configured. But you can choose to automate the whole process.

Configure MinIO Server with TLS

You can configure MinIO server itself with TLS.

So, create the MinIO certs directory under the MinIO configs directory we created above, /etc/minio.

sudo mkdir -p /etc/minio/certs

Next, copy the Let's Encrypt TLS certs:

  • Copy the fullchain.pem certificate as public.crt
  • Copy the privkey.pem private key as private.key
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/minio/certs/public.crt
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem /etc/minio/certs/private.key

Update the ownership of the certs directory;

sudo chown -R minio: /etc/minio/certs/

Next, update the configuration value of the MINIO_OPTS to include the TLS certs.

sudo sed -i '/^MINIO_OPTS=.*/ s/"$/ --certs-dir \/etc\/minio\/certs"/' /etc/default/minio

The line should now look like;

grep ^MINIO_OPTS /etc/default/minio
MINIO_OPTS="--address :9000 --console-address :9001 --certs-dir /etc/minio/certs"

Restart MinIO service;

sudo systemctl restart minio

Update MinIO Web Console and API Nginx Configs with TLS certs to enable HTTPS

Now that we have the TLS certs, update the configs;

sudo tee /etc/nginx/sites-enabled/minio-console.conf << EOF
# HTTP server block for redirecting to HTTPS
server {
    listen 80;
    server_name minio-console.yourdomain.com;

    # Redirect all HTTP traffic to HTTPS
    return 301 https://\$host\$request_uri;
}

# HTTPS server block
server {
    listen 443 ssl;
    server_name minio-console.yourdomain.com;

    # SSL certificate and key
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # SSL settings for security
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;

    location / {
        proxy_pass https://minio-console.yourdomain.com:9001;
        proxy_set_header Host \$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;
    }
}
EOF

Generate same config for the API;

sudo tee /etc/nginx/sites-enabled/minio-api.conf << EOF
# HTTP server block for redirecting to HTTPS
server {
    listen 80;
    server_name minio-api.yourdomain.com;

    # Redirect all HTTP traffic to HTTPS
    return 301 https://\$host\$request_uri;
}

# HTTPS server block
server {
    listen 443 ssl;
    server_name minio-api.yourdomain.com;

    # SSL certificate and key
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # SSL settings for security
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;

    location / {
        proxy_pass https://minio-api.yourdomain.com:9000;
        proxy_set_header Host \$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;
    }
}
EOF

Check Nginx for any errors;

sudo nginx -t

Ensure there are no errors!

Restart Nginx.

sudo systemctl restart nginx

Now, access the MinIO console at https://minio.yourdomain.com and the S3 API at https://minio-api.yourdomain.com. HTTP requests to http://minio.yourdomain.com or http://minio-api.yourdomain.com will automatically redirect to HTTPS.

Ensure your domain’s DNS records for minio.yourdomain.com and minio-api.yourdomain.com point to your server’s IP address. If you encounter SSL errors, verify the certificate paths and permissions

Minio let's encrypt ssl/tls configuration

Step 9: Install MinIO Client on Ubuntu 24.04 (Optional)

The MinIO client allows command-line interaction with your server. Debian based systems ships the mc package as mcli. You can optionally install the MinIO client on Ubuntu 24.04 as follows;

wget https://dl.min.io/client/mc/release/linux-amd64/mcli_20250416181326.0.0_amd64.deb -P /tmp

Install the client:

sudo apt install /tmp/mcli_20250416181326.0.0_amd64.deb

You should be now be having MinIO client, mcli command in place;

mcli --version

Step 10: Using MinIO Client to Interact with MinIO Server

You can begin the usage of MinIO client by creating MinIO server alias. An alias in MinIO is a shortcut name that stores:

  • The server API endpoint (e.g., https://minio.yourdomain.com:9000).
  • Access credentials (access/secret keys).
  • SSL/TLS settings (if using HTTPS).

Instead of typing the full server URL and credentials every time, you use the alias (e.g., minioapi) to interact with the MinIO server via CLI tools like mc (MinIO Client).

Before you can proceed, enable MinIO client command auto-completion:

mcli --autocompletion

Please reload your shell;

source ~/.bashrc

To create an alias for my MinIO endpoint, use mcli alias set command:

mcli alias set ALIAS

For example:

mcli alias set minioapi http[s]://minio-api.yourdomain.com

This will prompt for your ACCESS_KEY and SECRET_KEY. These values usually corresponds to:

  • Default Values (if not customized):
    • MINIO_ROOT_USER
    • MINIO_ROOT_PASSWORD
  • Custom Values (set in /etc/default/minio)

You can provide the values in CLI;

mcli alias set minioapi URL ACCESS_KEY SECRET_KEY

List aliases;

mcli alias ls

You can basically use the client to interact with the MinIO server. For example, you can list any buckets

mcli ls minioapi

Get info;

mcli admin info minioapi

Want non root user? Create as follows:

mcli admin user add SERVER_ALIAS

You will be prompted for username and password:

Enter Access Key: kifarunix
Enter Secret Key: 
Added user `kifarunix` successfully.

Assign the roles/policies! You can list available roles/policies;

mcli admin policy list TARGET

TARGET is equivalent to MinIO server alias.

E.g

mcli admin policy list minioapi
consoleAdmin
diagnostics
readonly
readwrite
writeonly

Assign a role to the user.

  mcli admin policy attach [FLAGS] TARGET POLICY [POLICY...] [--user USER | --group GROUP]                                                                                                                       

e.g

mcli admin policy attach minioapi readwrite --user kifarunix

To confirm the policy has been successfully attached, use the mcli admin user info TARGET USER command:

mcli admin user info minioapi kifarunix

Step 11: Complete list of MinIO Client CLI Options

To see a complete list of MinIO client commands you can use to interact with the server:

NAME:
  mcli - MinIO Client for object storage and filesystems.

USAGE:
  mcli [FLAGS] COMMAND [COMMAND FLAGS | -h] [ARGUMENTS...]

COMMANDS:
  alias      manage server credentials in configuration file
  admin      manage MinIO servers
  anonymous  manage anonymous access to buckets and objects
  batch      manage batch jobs
  cp         copy objects
  cat        display object contents
  cors       manage bucket CORS configuration
  diff       list differences in object name, size, and date between two buckets
  du         summarize disk usage recursively
  encrypt    manage bucket encryption config
  event      manage object notifications
  find       search for objects
  get        get s3 object to local
  head       display first 'n' lines of an object
  ilm        manage bucket lifecycle
  idp        manage MinIO IDentity Provider server configuration
  license    license related commands
  legalhold  manage legal hold for object(s)
  ls         list buckets and objects
  mb         make a bucket
  mv         move objects
  mirror     synchronize object(s) to a remote site
  od         measure single stream upload and download
  ping       perform liveness check
  pipe       stream STDIN to an object
  put        upload an object to a bucket
  quota      manage bucket quota
  rm         remove object(s)
  retention  set retention for object(s)
  rb         remove a bucket
  replicate  configure server side bucket replication
  ready      checks if the cluster is ready or not
  sql        run sql queries on objects
  stat       show object metadata
  support    support related commands
  share      generate URL for temporary access to an object
  tree       list buckets and objects in a tree format
  tag        manage tags for bucket and object(s)
  undo       undo PUT/DELETE operations
  update     update mc to latest release
  version    manage bucket versioning
  watch      listen for object notification events

GLOBAL FLAGS:
  --autocompletion                 install auto-completion for your shell
  --config-dir value, -C value     path to configuration folder (default: "/home/kifarunix/.mcli") [$MC_CONFIG_DIR]
  --quiet, -q                      disable progress bar display [$MC_QUIET]
  --disable-pager, --dp            disable mc internal pager and print to raw stdout [$MC_DISABLE_PAGER]
  --no-color                       disable color theme [$MC_NO_COLOR]
  --json                           enable JSON lines formatted output [$MC_JSON]
  --debug                          enable debug output [$MC_DEBUG]
  --resolve value                  resolves HOST[:PORT] to an IP address. Example: minio.local:9000=10.10.75.1 [$MC_RESOLVE]
  --insecure                       disable SSL certificate verification [$MC_INSECURE]
  --limit-upload value             limits uploads to a maximum rate in KiB/s, MiB/s, GiB/s. (default: unlimited) [$MC_LIMIT_UPLOAD]
  --limit-download value           limits downloads to a maximum rate in KiB/s, MiB/s, GiB/s. (default: unlimited) [$MC_LIMIT_DOWNLOAD]
  --custom-header value, -H value  add custom HTTP header to the request. 'key:value' format.
  --help, -h                       show help
  --version, -v                    print the version

TIP:
  Use 'mcli --autocompletion' to enable shell autocompletion

COPYRIGHT:
  Copyright (c) 2015-2025 MinIO, Inc.

LICENSE:
  GNU AGPLv3 

Conclusion

You’ve successfully installed MinIO on Ubuntu 24.04, configured it as a systemd service, and secured it with Nginx and Let’s Encrypt SSL. MinIO is now ready to store your data as an Amazon S3-compatible object storage solution.

Explore further by creating buckets, uploading files, or integrating MinIO with your applications. For more details, check the official MinIO documentation.

SUPPORT US VIA A VIRTUAL CUP OF COFFEE

We're passionate about sharing our knowledge and experiences with you through our blog. If you appreciate our efforts, consider buying us a virtual coffee. Your support keeps us motivated and enables us to continually improve, ensuring that we can provide you with the best content possible. Thank you for being a coffee-fueled champion of our work!

Photo of author
Kifarunix
Linux Certified Engineer, with a passion for open-source technology and a strong understanding of Linux systems. With experience in system administration, troubleshooting, and automation, I am skilled in maintaining and optimizing Linux infrastructure.

Leave a Comment