Install MinIO on AlmaLinux 10 with Nginx and ZeroSSL

MinIO gives you a high-performance, S3-compatible object storage server that fits well on a small VPS when you want private buckets, simple API-compatible storage, and a clean web console without deploying a larger storage platform.

In this guide, we restore a fresh AlmaLinux 10.1 server on Shape.Host, verify the latest MinIO community release from the official project, install the current stable Go toolchain from the official Go download site, build MinIO from the exact upstream release tag using MinIO’s own release-aware ldflags path, configure the official MinIO systemd service template, publish the MinIO Console through Nginx on tutorials.shape.host, secure it with a trusted ZeroSSL certificate, and validate the finished deployment from both the terminal and a browser.

Application MinIO
Application version RELEASE.2025-10-15T17-29-55Z
Operating system AlmaLinux 10.1
Build toolchain Go 1.26.1
Reverse proxy Nginx 1.26.3
Public hostname tutorials.shape.host
TLS issuer ZeroSSL ECC Domain Secure Site CA
Validated on Live Shape.Host AlmaLinux 10.1 server

Why Use MinIO on AlmaLinux 10?

  • AlmaLinux 10.1 gives you a current RHEL-compatible base for a storage service you want to keep stable.
  • The current MinIO community distribution is source-only, so you can build the latest release directly from upstream on your own server.
  • The official MinIO service repository provides a maintained systemd template that is a better baseline than inventing a custom unit from scratch.
  • Nginx plus ZeroSSL gives you a clean public HTTPS endpoint for the MinIO Console while the native MinIO ports stay local to the server.

Before You Begin

Make sure the following prerequisites are in place before you start:

  • A fresh AlmaLinux 10 server
  • Root or sudo access
  • A DNS record pointing tutorials.shape.host to your server IP
  • Ports 80 and 443 open to the internet
  • Your ZeroSSL EAB key ID and EAB HMAC key for ACME account registration

1. Verify the AlmaLinux 10 Release

Start by confirming that the restored server is actually running AlmaLinux 10.1.

cat /etc/os-release
AlmaLinux 10.1 os-release output on the MinIO tutorial server
Fresh AlmaLinux 10.1 deployment used for the MinIO installation.

2. Install Go, Nginx, Firewalld, and Base Dependencies

The MinIO upstream README now recommends installing the community edition from source, so this guide uses the current stable Go release from the official Go download site instead of relying on an older distro compiler. We also install Git because MinIO’s release-aware build path depends on the tagged upstream repository metadata, plus Nginx, firewalld, and the helper packages needed for certificate automation and SELinux-aware administration.

dnf -y install curl git tar gzip nginx openssl socat firewalld policycoreutils-python-utils

curl -fsSLO https://go.dev/dl/go1.26.1.linux-amd64.tar.gz
rm -rf /usr/local/go
tar -C /usr/local -xzf go1.26.1.linux-amd64.tar.gz
ln -sf /usr/local/go/bin/go /usr/local/bin/go
ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
rm -f go1.26.1.linux-amd64.tar.gz

systemctl enable --now nginx firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

go version
nginx -v
firewall-cmd --state
getenforce

On the validated AlmaLinux 10.1 deployment, this installed the official Go 1.26.1 toolchain, Git 2.47.3, Nginx 1.26.3, and firewalld successfully, with SELinux reported as Disabled on this template.

Go, Nginx, and firewalld installed on AlmaLinux 10 for MinIO
Base tooling installed on the AlmaLinux 10.1 server for the MinIO deployment.

3. Build MinIO from Source and Prepare the Official Service Configuration

The current MinIO community README explicitly says the community edition is source-only. In practice, building from a tagged checkout with MinIO’s own ldflags path gives you a release-aware binary, which is more useful for verification than a plain go install build that reports a development marker. For the service layer, the official minio-service repository provides the current systemd template and a two-file configuration layout under /etc/default/minio and /etc/minio/config.env.

export PATH=/usr/local/go/bin:/usr/local/bin:$PATH

id minio-user >/dev/null 2>&1 || useradd --system --home /var/lib/minio --shell /sbin/nologin minio-user
mkdir -p /mnt/data /etc/minio /var/lib/minio /usr/local/src
rm -rf /usr/local/src/minio
git clone --branch RELEASE.2025-10-15T17-29-55Z --depth 1 https://github.com/minio/minio.git /usr/local/src/minio

cd /usr/local/src/minio
VERSION="$(git describe --tags --abbrev=0 | sed 's#RELEASE\.\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)T\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)Z#\1-\2-\3T\4:\5:\6Z#')"
LDFLAGS="$(MINIO_RELEASE=RELEASE go run buildscripts/gen-ldflags.go "$VERSION")"
CGO_ENABLED=0 GOOS="$(go env GOOS)" GOARCH="$(go env GOARCH)" go build -tags kqueue -trimpath --ldflags "$LDFLAGS" -o ./minio 1>/dev/null
install -m 0755 ./minio /usr/local/bin/minio
curl -fsSL https://raw.githubusercontent.com/minio/minio-service/master/linux-systemd/minio.service -o /etc/systemd/system/minio.service

MINIO_ROOT_USER="minioadmin"
MINIO_ROOT_PASSWORD="$(openssl rand -base64 24 | tr -d '\n' | tr '/+' 'AB' | cut -c1-24)"

cat > /etc/default/minio <<'EOF'
MINIO_VOLUMES="/mnt/data"
MINIO_OPTS="--address 127.0.0.1:9000 --console-address 127.0.0.1:9001"
MINIO_CONFIG_ENV_FILE=/etc/minio/config.env
EOF

cat > /etc/minio/config.env <<EOF
MINIO_ROOT_USER=${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
EOF

chown -R minio-user:minio-user /mnt/data /etc/minio /var/lib/minio
chmod 600 /etc/default/minio /etc/minio/config.env

systemctl daemon-reload

go version
minio --version | head -n 1
git -C /usr/local/src/minio describe --tags --abbrev=0
grep '^MINIO_VOLUMES=' /etc/default/minio
grep '^MINIO_OPTS=' /etc/default/minio
grep '^MINIO_CONFIG_ENV_FILE=' /etc/default/minio
grep '^MINIO_ROOT_USER=' /etc/minio/config.env
grep '^MINIO_ROOT_PASSWORD=' /etc/minio/config.env | sed 's/=.*$/=[redacted]/'
grep '^User=' /etc/systemd/system/minio.service
grep '^Group=' /etc/systemd/system/minio.service
grep '^ExecStart=' /etc/systemd/system/minio.service

On the validated server, MinIO built cleanly from the pinned release tag, the binary was installed into /usr/local/bin/minio, the official service template referenced the local MinIO binary, and the generated root password stayed redacted in the verification output.

MinIO source build and official service configuration prepared on AlmaLinux 10
MinIO source build and official service configuration prepared on AlmaLinux 10.

4. Start MinIO and Validate the Local Service

With the binary and service files in place, start MinIO under systemd and confirm that both the S3 API and the Console answer on localhost before you expose the Console through Nginx.

4.1 Start the MinIO Service

systemctl enable --now minio
sleep 20
systemctl is-active minio

On the live server, systemd enabled the MinIO service at boot, the first startup completed cleanly, and the final state check returned active.

Starting the MinIO systemd service on AlmaLinux 10
First startup of the MinIO systemd service on AlmaLinux 10.

4.2 Validate the MinIO Ports and Local Health Endpoints

systemctl status --no-pager minio | sed -n '1,15p'
ss -lntp | grep -E ':9000|:9001'
minio --version | head -n 1
curl -I http://127.0.0.1:9000/minio/health/live
curl -I http://127.0.0.1:9001/login

On the validated deployment, MinIO listened on 127.0.0.1:9000 for the API and 127.0.0.1:9001 for the Console, the S3 health endpoint returned a successful response, and the local Console login page answered correctly.

MinIO local service validation on AlmaLinux 10
Local MinIO port, health, and Console validation on AlmaLinux 10.

5. Configure Nginx, Firewalld, SELinux, and ZeroSSL for the MinIO Console

This guide publishes the MinIO Console on tutorials.shape.host through Nginx while keeping the native MinIO API and Console ports on localhost only. That gives you a trusted public HTTPS login page without exposing the raw service ports directly.

mkdir -p /var/www/_letsencrypt /etc/nginx/ssl/tutorials.shape.host

cat > /etc/nginx/conf.d/tutorials.shape.host.conf <<'EOF'
server {
    listen 80;
    server_name tutorials.shape.host;

    location /.well-known/acme-challenge/ {
        root /var/www/_letsencrypt;
        default_type "text/plain";
    }

    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

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

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

# Run this if SELinux is enforcing on your server.
setsebool -P httpd_can_network_connect 1

nginx -t
systemctl reload nginx

curl -fsSL https://get.acme.sh | sh -s email=contact@shape.host
/root/.acme.sh/acme.sh --set-default-ca --server zerossl
/root/.acme.sh/acme.sh --register-account --server zerossl --eab-kid YOUR_ZEROSSL_EAB_KID --eab-hmac-key YOUR_ZEROSSL_EAB_HMAC_KEY
/root/.acme.sh/acme.sh --issue --server zerossl --webroot /var/www/_letsencrypt -d tutorials.shape.host --keylength ec-256
/root/.acme.sh/acme.sh --install-cert -d tutorials.shape.host --ecc \
  --fullchain-file /etc/nginx/ssl/tutorials.shape.host/fullchain.cer \
  --key-file /etc/nginx/ssl/tutorials.shape.host/tutorials.shape.host.key \
  --reloadcmd "systemctl reload nginx"

cat > /etc/nginx/conf.d/tutorials.shape.host.conf <<'EOF'
server {
    listen 80;
    server_name tutorials.shape.host;

    location /.well-known/acme-challenge/ {
        root /var/www/_letsencrypt;
        default_type "text/plain";
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    http2 on;
    server_name tutorials.shape.host;

    ssl_certificate /etc/nginx/ssl/tutorials.shape.host/fullchain.cer;
    ssl_certificate_key /etc/nginx/ssl/tutorials.shape.host/tutorials.shape.host.key;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

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

nginx -t
systemctl reload nginx

On the validated AlmaLinux 10.1 run, firewalld allowed the public services, Nginx accepted the configuration cleanly, and ZeroSSL issued a trusted ECC certificate for tutorials.shape.host.

Nginx and ZeroSSL setup for the MinIO Console on AlmaLinux 10
Nginx, firewalld, and ZeroSSL setup completed for the MinIO Console hostname.

6. Validate the Public HTTPS MinIO Console

Finish by confirming that MinIO is still running under systemd, the local API health endpoint stays healthy, the firewall and SELinux state look correct, and the public HTTPS Console route loads through Nginx with the expected ZeroSSL certificate.

systemctl status --no-pager minio | sed -n '1,12p'
ss -lntp | grep -E ':80|:443|:9000|:9001'
firewall-cmd --list-services
echo "SELinux status: $(getenforce)"
getsebool httpd_can_network_connect || true
minio --version | head -n 1
curl -I http://127.0.0.1:9000/minio/health/live
curl -I --resolve tutorials.shape.host:443:51.89.69.216 https://tutorials.shape.host/login
openssl x509 -in /etc/nginx/ssl/tutorials.shape.host/fullchain.cer -noout -issuer -subject

On the live server, MinIO stayed active under systemd, the local API health endpoint answered successfully, the public Console route loaded over HTTPS, and the installed certificate issuer resolved to ZeroSSL ECC Domain Secure Site CA.

Final MinIO HTTPS validation on AlmaLinux 10
Final terminal validation of the MinIO deployment on AlmaLinux 10.

7. Confirm the MinIO Console Login Page in a Browser

The final browser check confirms that the public HTTPS route renders the MinIO Console login page instead of a blank page, proxy error, or certificate warning.

MinIO Console login page over HTTPS on AlmaLinux 10
MinIO Console login page served over trusted HTTPS on AlmaLinux 10.

Hardening Notes

  • Move the MinIO API off localhost only if you truly need public S3 access. Keeping it local reduces the exposed surface.
  • Replace the generated root credentials with values stored in your own secret-management workflow if you plan to keep this node long term.
  • Back up both /mnt/data and the configuration files under /etc/default/minio and /etc/minio/config.env.
  • If your host runs SELinux in enforcing mode, keep httpd_can_network_connect enabled so Nginx can continue proxying to the local Console port.

Conclusion

You now have MinIO running on AlmaLinux 10.1 with the current community release built from source, managed by the official MinIO systemd template, and published through Nginx with a trusted ZeroSSL certificate on tutorials.shape.host. The final live validation confirms the local API health endpoint stays healthy, the Console loads over HTTPS, and the browser reaches the MinIO login screen successfully.