When managing large volumes of unstructured data — images, logs, or backups — object storage is often the best fit. MinIO is an open-source, S3-compatible object storage server you can run on your own infrastructure. This guide automates installing and configuring MinIO using Ansible on Ubuntu or Debian (e.g. Debian 12).
You will use a single playbook that updates the system, installs the MinIO binary, creates a dedicated user and directories, configures environment variables and a systemd service, and starts MinIO. The S3 API will listen on port 9000 and the web console on port 9001.
Prerequisites: Ansible installed on your control node (see How to Install and Configure Ansible on Rocky Linux or install via pip/apt); SSH access to one or more Ubuntu or Debian hosts; an inventory file defining your target hosts (e.g. citizixsrv).
What is Object Storage?
Object storage is a way of storing data as objects, rather than as files in a hierarchy or blocks on a disk. It’s ideal for large-scale, distributed systems. MinIO brings this architecture to your own infrastructure and is often used as a self-hosted alternative to AWS S3.
Why Use Ansible?
Ansible is an agentless configuration management tool that allows you to describe server configuration using YAML. It’s perfect for automating repeatable tasks like software installation and systemd configuration.
What This Playbook Does
This playbook will:
- Update and upgrade system packages
- Install common utilities like
vim,git, andufw - Download the latest MinIO binary
- Create a non-login system user for MinIO
- Set up the necessary directory structure
- Configure environment variables and a systemd service
- Start and enable the MinIO service
Set Up Required Variables
Here are the core variables used in the playbook. These make the playbook more reusable and configurable:
vars:
minio_user: minio
minio_bin_path: /usr/local/bin/minio
minio_data_dir: /data
minio_work_dir: /usr/local/minio
minio_env_file: /etc/default/minio
minio_service_file: /etc/systemd/system/minio.service
minio_download_url: https://dl.min.io/server/minio/release/linux-amd64/minio
minio_root_user: admin
minio_root_password: "Admin@123$"
You can update the password or path values to match your environment. Security: avoid committing plain-text passwords to version control. Use Ansible Vault to encrypt minio_root_password (e.g. in a vars file or --extra-vars) and pass the vault password at run time.
Step-by-Step Breakdown
Update the OS
We start by ensuring the server is up-to-date:
- name: Update and upgrade apt packages
apt:
update_cache: yes
upgrade: dist
cache_valid_time: 3600
force_apt_get: yes
Install Useful Utilities
These are helpful tools to have on any server:
- name: Install essential utilities
apt:
name:
- vim
- git
- ufw
state: present
Download the MinIO Binary
We fetch the MinIO binary directly from MinIO’s official release:
- name: Download MinIO binary
get_url:
url: "{{ minio_download_url }}"
dest: "{{ minio_bin_path }}"
mode: "0750"
Create a Dedicated System User
We’ll run MinIO as a non-login system user for security:
- name: Create dedicated system user for MinIO
user:
name: "{{ minio_user }}"
shell: /sbin/nologin
system: yes
state: present
Create Required Directories
Create the working and data directories for MinIO:
- name: Create MinIO data and working directories
file:
path: "{{ item }}"
state: directory
owner: "{{ minio_user }}"
group: "{{ minio_user }}"
loop:
- "{{ minio_data_dir }}"
- "{{ minio_work_dir }}"
Set Up MinIO Environment Configuration
We define runtime configuration in /etc/default/minio:
- name: Create MinIO environment file
copy:
dest: "{{ minio_env_file }}"
owner: "{{ minio_user }}"
group: "{{ minio_user }}"
mode: "0600"
content: |
MINIO_ROOT_USER={{ minio_root_user }}
MINIO_ROOT_PASSWORD={{ minio_root_password }}
MINIO_VOLUMES={{ minio_data_dir }}
MINIO_OPTS="--address :9000 --console-address :9001"
Create systemd Service
This service file ensures MinIO is managed by systemd:
- name: Create MinIO systemd service file
copy:
dest: "{{ minio_service_file }}"
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=MinIO S3-compatible Object Storage
Documentation=https://min.io/docs/
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable={{ minio_bin_path }}
[Service]
WorkingDirectory={{ minio_work_dir }}
User={{ minio_user }}
Group={{ minio_user }}
EnvironmentFile=-{{ minio_env_file }}
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo 'MINIO_VOLUMES not set'; exit 1; fi"
ExecStart={{ minio_bin_path }} server ${MINIO_OPTS} ${MINIO_VOLUMES}
Restart=always
LimitNOFILE=65536
TimeoutStopSec=infinity
SendSIGKILL=no
[Install]
WantedBy=multi-user.target
Enable and Start the MinIO Service
This ensures MinIO starts on boot and is running:
- name: Reload systemd and enable MinIO service
systemd:
daemon_reload: true
name: minio
enabled: true
state: started
Full Playbook: setup-minio.yml
Here is the complete playbook for reference:
---
- name: Set up MinIO on Debian
hosts: citizixsrv
become: true
gather_facts: false
vars:
minio_user: minio
minio_bin_path: /usr/local/bin/minio
minio_data_dir: /data
minio_work_dir: /usr/local/minio
minio_env_file: /etc/default/minio
minio_service_file: /etc/systemd/system/minio.service
minio_download_url: https://dl.min.io/server/minio/release/linux-amd64/minio
minio_root_user: admin
minio_root_password: "Admin@123$"
tasks:
- name: Update and upgrade apt packages
apt:
update_cache: yes
upgrade: dist
cache_valid_time: 3600
force_apt_get: yes
- name: Install essential utilities
apt:
name:
- vim
- git
- ufw
state: present
- name: Download MinIO binary
get_url:
url: "{{ minio_download_url }}"
dest: "{{ minio_bin_path }}"
mode: "0750"
- name: Create dedicated system user for MinIO
user:
name: "{{ minio_user }}"
shell: /sbin/nologin
system: yes
state: present
- name: Create MinIO data and working directories
file:
path: "{{ item }}"
state: directory
owner: "{{ minio_user }}"
group: "{{ minio_user }}"
loop:
- "{{ minio_data_dir }}"
- "{{ minio_work_dir }}"
- name: Create MinIO environment file
copy:
dest: "{{ minio_env_file }}"
owner: "{{ minio_user }}"
group: "{{ minio_user }}"
mode: "0600"
content: |
MINIO_ROOT_USER={{ minio_root_user }}
MINIO_ROOT_PASSWORD={{ minio_root_password }}
MINIO_VOLUMES={{ minio_data_dir }}
MINIO_OPTS="--address :9000 --console-address :9001"
- name: Create MinIO systemd service file
copy:
dest: "{{ minio_service_file }}"
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=MinIO S3-compatible Object Storage
Documentation=https://min.io/docs/
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable={{ minio_bin_path }}
[Service]
WorkingDirectory={{ minio_work_dir }}
User={{ minio_user }}
Group={{ minio_user }}
EnvironmentFile=-{{ minio_env_file }}
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo 'MINIO_VOLUMES not set'; exit 1; fi"
ExecStart={{ minio_bin_path }} server ${MINIO_OPTS} ${MINIO_VOLUMES}
Restart=always
LimitNOFILE=65536
TimeoutStopSec=infinity
SendSIGKILL=no
[Install]
WantedBy=multi-user.target
- name: Reload systemd and enable MinIO service
systemd:
daemon_reload: true
name: minio
enabled: true
state: started
Running the Playbook
Save the playbook as setup-minio.yml and run it with your inventory (replace inventory with your inventory file or group name):
ansible-playbook -i inventory setup-minio.yml
If you use Ansible Vault for minio_root_password, add --ask-vault-pass or provide a vault password file.
Verifying MinIO
After a successful run, MinIO should be listening on the target host:
- S3 API:
http://your-server-ip:9000 - Web Console:
http://your-server-ip:9001
Check the service:
ssh your-user@your-server-ip 'systemctl status minio'Open the console: In a browser, go to
http://your-server-ip:9001and log in withminio_root_userandminio_root_passwordfrom your vars.Test the API: Use the MinIO Client (
mc) or any S3-compatible client (e.g. AWS CLI with--endpoint-url http://your-server-ip:9000).
If you enabled ufw on the host, allow ports 9000 and 9001 (e.g. ufw allow 9000/tcp, ufw allow 9001/tcp, ufw reload) or restrict them to your IP/subnet.
Troubleshooting
- Service fails to start: Check
journalctl -u minio -n 50. EnsureMINIO_VOLUMESis set in/etc/default/minioand the data directory exists and is owned by the MinIO user. Ensure the binary atminio_bin_pathis executable (chmod +x /usr/local/bin/minio). - Port already in use: Another process may be using 9000 or 9001. Change
MINIO_OPTSin the env file (e.g.--address :9002 --console-address :9003) and reload the playbook or service. - Ansible “Permission denied” or “Failed to connect”: Ensure SSH keys or credentials are set up for the inventory host and that
become(sudo) is allowed for the user.
Summary
You automated MinIO installation on Ubuntu or Debian with Ansible: system update, MinIO binary, dedicated user, directories, environment file, and systemd service. MinIO gives you S3-compatible object storage on your own infrastructure for backups, logs, or custom applications.
For other deployment options, see How to Run MinIO in Docker and Docker Compose or How to Set Up MinIO as Object Storage on Rocky Linux.
Related Posts
- How to Run MinIO in Docker and Docker Compose – MinIO in containers
- How to Set Up MinIO as Object Storage on Rocky Linux – Manual MinIO on Rocky Linux
- How to Install and Configure Ansible on Rocky Linux – Install Ansible
- How to Install Docker Engine in Debian 11 Using Ansible – Ansible on Debian