MinIO Setup on Ubuntu 24.04 (Headless Deployment)
At a glance#
- Purpose: Install and secure MinIO object storage on a headless Ubuntu server with LVM storage and optional TLS.
- Applies to: MinIO on Ubuntu Server 24.04.
- Risk: Medium - new service deployment; storage layout decisions are hard to change later.
- Time: 1-2 hours.
Overview#
This guide explains how to install, configure, and secure MinIO on Ubuntu Server 24.04.
It uses SystemD, LVM storage, CLI management, and optionally Nginx for HTTPS termination.
It also includes AWS CLI integration for full S3 API compatibility.
System Details#
| Item | Value |
|---|---|
| OS | Ubuntu Server 24.04 |
| Storage | /dev/sdb → /mnt/minio-data (LVM) |
| Network | LAN only |
| API Port | 9000 |
| Console Port | 9001 |
| HTTPS Reverse Proxy | Nginx (s3.example.com) |
| Management Tools | mc (MinIO Client), awscli (S3-compatible) |
Installation Steps#
1. Update System#
sudo apt update && sudo apt upgrade -y2. Create MinIO User#
sudo useradd -r -s /sbin/nologin minio-user3. Install MinIO Server#
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/4. Prepare MinIO Data Directory (with LVM setup)#
We’ll create an LVM volume on /dev/sdb, format it, and mount it to /mnt/minio-data.
⚠️ Warning: These steps will erase all data on /dev/sdb. Double-check your disk withlsblkorsudo fdisk -lbefore proceeding.
1 Create a Partition for LVM#
sudo fdisk /dev/sdbInside fdisk, run:
g # create a new GPT partition table
n # create new partition
<enter> # default partition number (1)
<enter> # default first sector
<enter> # default last sector (use full disk)
t # change partition type
8e # set type to "Linux LVM"
w # write changes and exitCheck the new partition:
lsblkYou should now see /dev/sdb1.
2 Create the LVM Structure#
# Create a physical volume
sudo pvcreate /dev/sdb1
# Create a volume group (VG)
sudo vgcreate vg_minio /dev/sdb1
# Create a logical volume (LV)
sudo lvcreate -n lv_minio -l 100%FREE vg_minioVerify:
sudo lvdisplay3 Format the Logical Volume#
sudo mkfs.ext4 /dev/vg_minio/lv_minio4 Create Mount Point and Mount Volume#
sudo mkdir -p /mnt/minio-data
sudo mount /dev/vg_minio/lv_minio /mnt/minio-data5 Enable Persistent Mounting#
Add the mount entry to /etc/fstab:
sudo blkid /dev/vg_minio/lv_minioCopy the UUID from output, then:
sudo nano /etc/fstabAdd this line (replace the UUID with yours):
UUID=<your-uuid> /mnt/minio-data ext4 defaults 0 2Apply:
sudo mount -a6 Set Permissions for MinIO#
sudo chown -R minio-user:minio-user /mnt/minio-data✅ Result:
Your LVM volume is now mounted at /mnt/minio-data and ready for MinIO to use.
5. Create SystemD Service#
sudo nano /etc/systemd/system/minio.servicePaste:
[Unit]
Description=MinIO Object Storage
Documentation=https://min.io/docs/
Wants=network-online.target
After=network-online.target
[Service]
User=minio-user
Group=minio-user
EnvironmentFile=-/etc/default/minio
ExecStart=/usr/local/bin/minio server /mnt/minio-data --console-address ":9001"
Restart=always
LimitNOFILE=65536
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target6. Configure Credentials#
sudo nano /etc/default/minioPaste:
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=Password123 (Put strong password here)Secure permissions:
sudo chown root:minio-user /etc/default/minio
sudo chmod 640 /etc/default/minio7. Start and Enable Service#
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable minio
sudo systemctl start minio
systemctl status minioView logs:
sudo journalctl -u minio -f8. (Optional) Firewall Rules#
sudo ufw allow 9000/tcp
sudo ufw allow 9001/tcpOptional: HTTPS via Nginx Reverse Proxy#
Configure secure HTTPS access for MinIO API and Console.
1. Install and Configure Nginx#
sudo apt install nginx nginx-extras -y
sudo mkdir -p /etc/nginx/ssl
sudo cp s3.fullchain.crt /etc/nginx/ssl/
sudo cp s3.key /etc/nginx/ssl/2. Add Nginx Config#
Create:
sudo nano /etc/nginx/sites-available/minio.confPaste:
server {
listen 80;
listen [::]:80;
server_name s3.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name s3.example.com;
ssl_certificate /etc/nginx/ssl/s3.fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/s3.key;
ssl_trusted_certificate /etc/nginx/ssl/s3.fullchain.crt;
server_tokens off;
more_clear_headers Server;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
ignore_invalid_headers off;
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_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_hide_header Server;
proxy_hide_header x-minio-version;
more_clear_headers Server;
more_clear_headers x-minio-version;
}
location /minio/ui/ {
rewrite ^/minio/ui/(.*) /$1 break;
proxy_pass http://127.0.0.1:9001;
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_set_header X-NginX-Proxy true;
real_ip_header X-Real-IP;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_hide_header Server;
proxy_hide_header x-minio-version;
more_clear_headers Server;
more_clear_headers x-minio-version;
}
}Enable and restart:
sudo ln -s /etc/nginx/sites-available/minio.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl enable nginxNow access:
- API:
https://s3.example.com - Console:
https://s3.example.com/minio/ui/
Managing MinIO with mc (MinIO Client)#
Install and Configure#
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
mc alias set minio https://s3.example.com minioadmin Password123 --api s3v4Common Commands#
| Action | Command |
|---|---|
| List Buckets | mc ls minio |
| Create Bucket | mc mb minio/mybucket |
| Upload File | mc cp file.txt minio/mybucket/ |
| Download File | mc cp minio/mybucket/file.txt ./ |
| Public Access | mc anonymous set download minio/mybucket |
Using AWS CLI with MinIO (S3 API)#
1. Install AWS CLI#
Ubuntu/Debian:
sudo apt update
sudo apt install unzip -y
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --versionWindows (PowerShell):
# Download and install:
# https://awscli.amazonaws.com/AWSCLIV2.msi
aws --version
2. Configure AWS CLI for MinIO#
aws configure --profile minio-adminFill in:
AWS Access Key ID: YOUR_MINIO_ACCESS_KEY
AWS Secret Access Key: YOUR_MINIO_SECRET_KEY
Default region name: us-east-1
Default output format: jsonThen edit:
nano ~/.aws/configAdd:
[profile minio-admin]
region = us-east-1
output = json
s3 =
endpoint_url = https://s3.example.com
addressing_style = pathSet as default for this session:
export AWS_PROFILE=minio-admin3. Common AWS CLI (S3-Compatible) Commands#
| Action | Command |
|---|---|
| Create Bucket | aws s3 mb s3://mybucket |
| List Buckets | aws s3 ls |
| Upload File | aws s3 cp /path/to/file.txt s3://mybucket/ |
| Upload Folder | aws s3 cp /path/to/folder s3://mybucket/ --recursive |
| List Objects | aws s3 ls s3://mybucket --recursive --human-readable --summarize |
| Download File | aws s3 cp s3://mybucket/file.txt /local/path/ |
| Delete File | aws s3 rm s3://mybucket/file.txt |
| Delete All Files in Bucket | aws s3 rm s3://mybucket --recursive |
| Delete Bucket | aws s3api delete-bucket --bucket mybucket |
Maintenance & Updates#
Check versions:
minio --version
mc --version
aws --versionTo update MinIO:
sudo systemctl stop minio
sudo wget -O /usr/local/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio
sudo chmod +x /usr/local/bin/minio
sudo systemctl start minio