Configure MinIO lifecycle policies to automatically transition and expire objects based on age and storage class. Set up intelligent tiering and automated archival to optimize storage costs and compliance with data retention requirements.
Prerequisites
- MinIO server installed and running
- Administrative access to MinIO
- Basic understanding of S3 storage classes
- Network access for remote storage tiers
What this solves
MinIO lifecycle management automatically transitions objects between storage classes and expires data based on configurable rules. This reduces storage costs by moving infrequently accessed data to cheaper storage tiers and ensures compliance by automatically deleting data after specified retention periods. Lifecycle policies help manage petabytes of data without manual intervention.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you have the latest security patches.
sudo apt update && sudo apt upgrade -y
Install MinIO client
Download and install the MinIO client to manage lifecycle policies and interact with your MinIO deployment.
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
mc --version
Configure MinIO client alias
Set up an alias for your MinIO server to simplify command execution. Replace the endpoint and credentials with your actual MinIO configuration.
mc alias set myminio http://203.0.113.10:9000 minioadmin minioadmin
mc admin info myminio
Create test buckets for lifecycle policies
Create buckets to demonstrate different lifecycle management scenarios including archival and expiration.
mc mb myminio/production-data
mc mb myminio/archive-bucket
mc mb myminio/temp-logs
mc ls myminio
Create basic expiration lifecycle policy
Create a lifecycle policy JSON file that expires objects after 90 days for temporary data storage.
{
"Rules": [
{
"ID": "expire-temp-logs",
"Status": "Enabled",
"Expiration": {
"Days": 90
}
}
]
}
Apply expiration policy to temp logs bucket
Apply the lifecycle policy to automatically delete log files older than 90 days.
mc ilm add --expiry-days 90 myminio/temp-logs
mc ilm ls myminio/temp-logs
Create tiered storage lifecycle policy
Configure a policy that transitions objects to different storage classes based on age for cost optimization.
{
"Rules": [
{
"ID": "production-tiering",
"Status": "Enabled",
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 2555
}
}
]
}
Configure remote storage tier for archival
Set up a remote storage tier for archival. This example uses AWS S3, but you can configure other compatible backends.
mc admin tier add s3 myminio ARCHIVE \
--endpoint https://s3.amazonaws.com \
--access-key AKIAIOSFODNN7EXAMPLE \
--secret-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
--bucket archive-storage \
--region us-east-1
Apply tiered lifecycle policy
Apply the comprehensive lifecycle policy with multiple storage tiers to the production data bucket.
mc ilm add --transition-days 30 --storage-class STANDARD_IA myminio/production-data
mc ilm add --transition-days 90 --storage-class ARCHIVE myminio/production-data
mc ilm add --expiry-days 2555 myminio/production-data
mc ilm ls myminio/production-data
Create prefix-based lifecycle rules
Configure different lifecycle policies for specific object prefixes within the same bucket for granular data management.
{
"Rules": [
{
"ID": "logs-retention",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Expiration": {
"Days": 30
}
},
{
"ID": "backup-archival",
"Status": "Enabled",
"Filter": {
"Prefix": "backups/"
},
"Transitions": [
{
"Days": 7,
"StorageClass": "ARCHIVE"
}
],
"Expiration": {
"Days": 365
}
}
]
}
Apply prefix-based policies
Use the MinIO client to apply different lifecycle rules based on object prefixes for fine-grained control.
mc ilm add --prefix "logs/" --expiry-days 30 myminio/production-data
mc ilm add --prefix "backups/" --transition-days 7 --storage-class ARCHIVE myminio/production-data
mc ilm add --prefix "backups/" --expiry-days 365 myminio/production-data
Configure tag-based lifecycle rules
Set up lifecycle policies that apply to objects with specific tags for advanced data classification.
{
"Rules": [
{
"ID": "sensitive-data-retention",
"Status": "Enabled",
"Filter": {
"Tag": {
"Key": "DataClass",
"Value": "Sensitive"
}
},
"Expiration": {
"Days": 2555
}
},
{
"ID": "temporary-data",
"Status": "Enabled",
"Filter": {
"Tag": {
"Key": "Retention",
"Value": "Temporary"
}
},
"Expiration": {
"Days": 7
}
}
]
}
Enable lifecycle monitoring and alerting
Configure MinIO to track lifecycle transitions and send notifications for monitoring purposes.
mc admin config set myminio notify_webhook:1 endpoint="http://203.0.113.10:9001/webhook" \
auth_token="your-webhook-token"
mc admin service restart myminio
mc event add myminio/production-data arn:minio:sqs::1:webhook --event put,delete
Create monitoring script for lifecycle status
Create a script to monitor lifecycle policy execution and generate reports on storage optimization.
#!/bin/bash
MinIO Lifecycle Monitoring Script
DATE=$(date '+%Y-%m-%d %H:%M:%S')
LOG_FILE="/var/log/minio-lifecycle.log"
echo "[$DATE] Checking lifecycle policies..." >> $LOG_FILE
Check lifecycle policies for all buckets
for bucket in $(mc ls myminio | awk '{print $5}'); do
echo "[$DATE] Bucket: $bucket" >> $LOG_FILE
mc ilm ls myminio/$bucket >> $LOG_FILE 2>&1
# Get bucket usage statistics
mc du myminio/$bucket >> $LOG_FILE 2>&1
done
Check tier status
echo "[$DATE] Storage tier status:" >> $LOG_FILE
mc admin tier ls myminio >> $LOG_FILE 2>&1
echo "[$DATE] Lifecycle monitoring completed" >> $LOG_FILE
Make monitoring script executable and schedule
Set proper permissions and create a cron job to run lifecycle monitoring automatically.
sudo chmod +x /usr/local/bin/minio-lifecycle-monitor.sh
sudo crontab -e
Add this line to run monitoring every 6 hours:
0 /6 /usr/local/bin/minio-lifecycle-monitor.sh
Test lifecycle policy execution
Upload test files and verify that lifecycle policies are applied correctly with different scenarios.
# Create test files with different prefixes
echo "Test log data" > /tmp/test-log.txt
echo "Backup data" > /tmp/backup-file.txt
echo "Production data" > /tmp/prod-data.txt
Upload to different prefixes
mc cp /tmp/test-log.txt myminio/production-data/logs/
mc cp /tmp/backup-file.txt myminio/production-data/backups/
mc cp /tmp/prod-data.txt myminio/production-data/data/
Add tags to objects for tag-based policies
mc tag set myminio/production-data/data/prod-data.txt "DataClass=Sensitive"
mc tag set myminio/temp-logs/test-log.txt "Retention=Temporary"
Configure automated compliance reporting
Create compliance reporting script
Generate automated reports on data retention compliance and lifecycle policy effectiveness.
#!/bin/bash
REPORT_DATE=$(date '+%Y-%m-%d')
REPORT_FILE="/var/log/minio-compliance-$REPORT_DATE.json"
Initialize JSON report
cat > $REPORT_FILE << EOF
{
"report_date": "$REPORT_DATE",
"buckets": [
EOF
Generate compliance report for each bucket
BUCKET_COUNT=0
for bucket in $(mc ls myminio | awk '{print $5}'); do
if [ $BUCKET_COUNT -gt 0 ]; then
echo "," >> $REPORT_FILE
fi
OBJECT_COUNT=$(mc ls --recursive myminio/$bucket | wc -l)
BUCKET_SIZE=$(mc du myminio/$bucket | awk '{print $1}')
cat >> $REPORT_FILE << EOF
{
"name": "$bucket",
"object_count": $OBJECT_COUNT,
"size_bytes": "$BUCKET_SIZE",
"lifecycle_policies": [
EOF
mc ilm ls myminio/$bucket --json >> $REPORT_FILE 2>/dev/null
echo " ]" >> $REPORT_FILE
echo " }" >> $REPORT_FILE
BUCKET_COUNT=$((BUCKET_COUNT + 1))
done
cat >> $REPORT_FILE << EOF
],
"storage_tiers": [
EOF
mc admin tier ls myminio --json >> $REPORT_FILE 2>/dev/null
cat >> $REPORT_FILE << EOF
]
}
EOF
echo "Compliance report generated: $REPORT_FILE"
Set up automated compliance reporting
Configure the compliance report to run weekly and optionally email results to administrators.
sudo chmod +x /usr/local/bin/minio-compliance-report.sh
Add to crontab for weekly execution
sudo crontab -e
Add this line for weekly reports on Sundays at 2 AM:
0 2 0 /usr/local/bin/minio-compliance-report.sh
Verify your setup
Confirm that your lifecycle policies are working correctly and monitoring is operational.
# Check all configured lifecycle policies
mc ilm ls myminio/production-data
mc ilm ls myminio/temp-logs
mc ilm ls myminio/archive-bucket
Verify storage tiers
mc admin tier ls myminio
Check recent lifecycle events
mc admin trace myminio --verbose
Test monitoring script
/usr/local/bin/minio-lifecycle-monitor.sh
cat /var/log/minio-lifecycle.log
Generate test compliance report
/usr/local/bin/minio-compliance-report.sh
ls -la /var/log/minio-compliance-*.json
Advanced lifecycle configurations
Configure multipart upload cleanup
Set up automatic cleanup of incomplete multipart uploads to free up storage space.
mc ilm add --incomplete-upload-days 7 myminio/production-data
mc ilm add --incomplete-upload-days 1 myminio/temp-logs
Set up version-aware lifecycle policies
Configure policies that handle object versioning for comprehensive data lifecycle management.
{
"Rules": [
{
"ID": "version-management",
"Status": "Enabled",
"NoncurrentVersionTransitions": [
{
"NoncurrentDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"NoncurrentDays": 90,
"StorageClass": "ARCHIVE"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 365
}
}
]
}
Enable bucket versioning and apply version policies
Enable versioning on buckets and apply lifecycle policies that manage both current and non-current object versions.
# Enable versioning
mc version enable myminio/production-data
Apply version-aware lifecycle policies
mc ilm add --noncurrent-version-transition-days 30 --noncurrent-version-transition-storage-class STANDARD_IA myminio/production-data
mc ilm add --noncurrent-version-expiration-days 365 myminio/production-data
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Lifecycle policies not executing | MinIO service lacks permissions or storage tier configuration error | Check mc admin trace myminio for errors, verify tier connectivity with mc admin tier ls myminio |
| Objects not transitioning to archive tier | Remote storage credentials incorrect or endpoint unreachable | Test tier connectivity: mc admin tier verify myminio ARCHIVE |
| Lifecycle monitoring script fails | Missing MinIO client configuration or insufficient permissions | Verify alias configuration: mc admin info myminio and check script permissions |
| Tag-based policies not working | Objects missing required tags or policy syntax error | List object tags: mc tag list myminio/bucket/object and validate JSON policy syntax |
| Compliance reports incomplete | Script lacks read permissions on buckets or JSON formatting error | Test bucket access: mc ls myminio/bucket and validate JSON output |
| Storage costs not reducing | Lifecycle policies too conservative or transition timing issues | Review policy effectiveness with mc du --versions myminio/bucket and adjust transition days |
mc admin config get myminio scanner to check scan frequency and modify if needed for testing purposes.Next steps
- Configure MinIO high availability clustering for production with multi-node setup and automatic failover
- Implement MinIO security hardening with IAM policies and audit logging
- Configure MinIO backup and disaster recovery with automated snapshots and replication
- Set up comprehensive MinIO monitoring with Prometheus and Grafana dashboards
- Configure MinIO bucket notifications with Apache Kafka for real-time event processing
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Script configuration
TOTAL_STEPS=12
MINIO_CLIENT_URL="https://dl.min.io/client/mc/release/linux-amd64/mc"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIFECYCLE_DIR="/etc/minio/lifecycle"
# Default configuration
MINIO_ENDPOINT="${1:-http://localhost:9000}"
MINIO_ACCESS_KEY="${2:-minioadmin}"
MINIO_SECRET_KEY="${3:-minioadmin}"
MINIO_ALIAS="${4:-myminio}"
usage() {
echo "Usage: $0 [minio_endpoint] [access_key] [secret_key] [alias]"
echo "Example: $0 http://203.0.113.10:9000 admin password123 minio-prod"
echo "Defaults: http://localhost:9000 minioadmin minioadmin myminio"
exit 1
}
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
rm -f /tmp/mc
exit 1
}
trap cleanup ERR
log() {
echo -e "${GREEN}$1${NC}"
}
warn() {
echo -e "${YELLOW}$1${NC}"
}
error() {
echo -e "${RED}$1${NC}"
}
check_prerequisites() {
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root or with sudo"
exit 1
fi
if ! command -v wget &> /dev/null && ! command -v curl &> /dev/null; then
error "Either wget or curl is required"
exit 1
fi
}
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
;;
*)
error "Unsupported distribution: $ID"
exit 1
;;
esac
else
error "Cannot detect distribution"
exit 1
fi
}
if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then
usage
fi
check_prerequisites
detect_distro
log "[1/$TOTAL_STEPS] Updating system packages..."
$PKG_UPDATE
log "[2/$TOTAL_STEPS] Installing required dependencies..."
case "$PKG_MGR" in
apt)
$PKG_INSTALL wget curl jq
;;
dnf|yum)
$PKG_INSTALL wget curl jq
;;
esac
log "[3/$TOTAL_STEPS] Creating MinIO lifecycle directory..."
mkdir -p "$LIFECYCLE_DIR"
chmod 755 "$LIFECYCLE_DIR"
log "[4/$TOTAL_STEPS] Downloading MinIO client..."
if command -v wget &> /dev/null; then
wget -O /tmp/mc "$MINIO_CLIENT_URL"
else
curl -L -o /tmp/mc "$MINIO_CLIENT_URL"
fi
log "[5/$TOTAL_STEPS] Installing MinIO client..."
chmod 755 /tmp/mc
mv /tmp/mc /usr/local/bin/mc
chown root:root /usr/local/bin/mc
log "[6/$TOTAL_STEPS] Verifying MinIO client installation..."
mc --version
log "[7/$TOTAL_STEPS] Configuring MinIO client alias..."
mc alias set "$MINIO_ALIAS" "$MINIO_ENDPOINT" "$MINIO_ACCESS_KEY" "$MINIO_SECRET_KEY"
log "[8/$TOTAL_STEPS] Testing MinIO connection..."
if ! mc admin info "$MINIO_ALIAS" &> /dev/null; then
warn "Cannot connect to MinIO server. Continuing with policy creation..."
fi
log "[9/$TOTAL_STEPS] Creating lifecycle policy files..."
# Basic expiration policy
cat > "$LIFECYCLE_DIR/expiration-policy.json" << 'EOF'
{
"Rules": [
{
"ID": "expire-temp-logs",
"Status": "Enabled",
"Expiration": {
"Days": 90
}
}
]
}
EOF
# Tiered storage policy
cat > "$LIFECYCLE_DIR/tiered-policy.json" << 'EOF'
{
"Rules": [
{
"ID": "production-tiering",
"Status": "Enabled",
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 2555
}
}
]
}
EOF
# Prefix-based policy
cat > "$LIFECYCLE_DIR/prefix-policy.json" << 'EOF'
{
"Rules": [
{
"ID": "logs-retention",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Expiration": {
"Days": 30
}
},
{
"ID": "backup-archival",
"Status": "Enabled",
"Filter": {
"Prefix": "backups/"
},
"Transitions": [
{
"Days": 7,
"StorageClass": "ARCHIVE"
}
],
"Expiration": {
"Days": 365
}
}
]
}
EOF
chmod 644 "$LIFECYCLE_DIR"/*.json
chown root:root "$LIFECYCLE_DIR"/*.json
log "[10/$TOTAL_STEPS] Creating management script..."
cat > /usr/local/bin/minio-lifecycle << EOF
#!/usr/bin/env bash
set -euo pipefail
MINIO_ALIAS="$MINIO_ALIAS"
case "\${1:-help}" in
create-buckets)
mc mb "\$MINIO_ALIAS/production-data" 2>/dev/null || true
mc mb "\$MINIO_ALIAS/archive-bucket" 2>/dev/null || true
mc mb "\$MINIO_ALIAS/temp-logs" 2>/dev/null || true
echo "Buckets created successfully"
;;
apply-basic)
mc ilm add --expiry-days 90 "\$MINIO_ALIAS/temp-logs"
echo "Basic expiration policy applied to temp-logs"
;;
apply-tiered)
mc ilm add --transition-days 30 --storage-class STANDARD_IA "\$MINIO_ALIAS/production-data"
mc ilm add --expiry-days 2555 "\$MINIO_ALIAS/production-data"
echo "Tiered lifecycle policy applied to production-data"
;;
list-policies)
echo "Lifecycle policies:"
mc ilm ls "\$MINIO_ALIAS/temp-logs" 2>/dev/null || echo "No policies for temp-logs"
mc ilm ls "\$MINIO_ALIAS/production-data" 2>/dev/null || echo "No policies for production-data"
;;
help)
echo "Usage: \$0 {create-buckets|apply-basic|apply-tiered|list-policies}"
echo " create-buckets - Create test buckets"
echo " apply-basic - Apply basic expiration policy"
echo " apply-tiered - Apply tiered storage policy"
echo " list-policies - List current lifecycle policies"
;;
*)
echo "Unknown command: \$1"
\$0 help
exit 1
;;
esac
EOF
chmod 755 /usr/local/bin/minio-lifecycle
chown root:root /usr/local/bin/minio-lifecycle
log "[11/$TOTAL_STEPS] Creating configuration summary..."
cat > "$LIFECYCLE_DIR/README.md" << EOF
# MinIO Lifecycle Management Configuration
## Generated Configuration
- MinIO Endpoint: $MINIO_ENDPOINT
- Alias: $MINIO_ALIAS
- Policy Files: $LIFECYCLE_DIR/
## Available Commands
\`\`\`bash
# Create test buckets
minio-lifecycle create-buckets
# Apply basic expiration policy
minio-lifecycle apply-basic
# Apply tiered storage policy
minio-lifecycle apply-tiered
# List current policies
minio-lifecycle list-policies
\`\`\`
## Manual Commands
\`\`\`bash
# List MinIO aliases
mc alias ls
# Check server info
mc admin info $MINIO_ALIAS
# List buckets
mc ls $MINIO_ALIAS
# Remove lifecycle policy
mc ilm rm $MINIO_ALIAS/bucket-name
\`\`\`
EOF
chmod 644 "$LIFECYCLE_DIR/README.md"
log "[12/$TOTAL_STEPS] Verifying installation..."
if ! command -v mc &> /dev/null; then
error "MinIO client installation failed"
exit 1
fi
if ! command -v minio-lifecycle &> /dev/null; then
error "Management script installation failed"
exit 1
fi
log "✅ MinIO lifecycle management setup completed successfully!"
echo ""
log "Next steps:"
echo "1. Run 'minio-lifecycle create-buckets' to create test buckets"
echo "2. Run 'minio-lifecycle apply-basic' to apply basic policies"
echo "3. Check $LIFECYCLE_DIR/ for policy templates"
echo "4. View $LIFECYCLE_DIR/README.md for usage instructions"
Review the script before running. Execute with: bash install.sh