SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-10-21

Cài MinIO trên VPS Ubuntu 24.04 làm S3 riêng

Dựng MinIO trên một VPS Ubuntu 24.04 với binary build từ source đã xác minh, systemd, mc, presigned URL và làm đích backup cho restic.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Những gì bạn nhận được từ self-hosted object storage với MinIO

MinIO là giải pháp self-hosted object storage hỗ trợ API Amazon S3. Bạn chỉ cần trỏ restic hoặc S3 SDK về máy chủ của mình, thay đổi một thiết lập endpoint, và mọi thao tác đọc, ghi, liệt kê object hay tạo presigned link hàng ngày đều hoạt động ngay. Tuy nhiên, tương thích không có nghĩa là giống hệt. Ví dụ, MinIO không triển khai object ACL của Amazon và đội ngũ phát triển cho biết họ không có ý định làm điều đó, vì vậy các ứng dụng phụ thuộc vào hành vi của ACL sẽ cần nhiều hơn là chỉ thay đổi endpoint. Hướng dẫn này xây dựng một node đơn lẻ trên Ubuntu 24.04: một binary được biên dịch từ source đã xác thực, một system user riêng, một systemd unit không chứa thông tin xác thực root trong file cấu hình, và một bucket để restic thực hiện backup.

S3 (simple storage service) là một HTTP API chứ không phải là một filesystem. Bạn PUT một object vào bucket dưới một key và GET nó ra; trong một bucket tiêu chuẩn, không có khái niệm ghi một phần hay đổi tên. Các directory bucket trong S3 Express One Zone của Amazon là ngoại lệ, với các lệnh append và rename riêng, nhưng đó chỉ là một storage class và hướng dẫn này không phụ thuộc vào nó. Các công cụ backup ưa thích mô hình tiêu chuẩn này vì một object hoặc là đã được truyền tải trọn vẹn, hoặc là chưa hề tới nơi.

Một node chỉ lưu trữ một bản sao dữ liệu của bạn. Đó là sự đánh đổi bạn phải chấp nhận. Bạn nhận được một S3 endpoint do chính mình kiểm soát với chi phí của một VPS, nhưng đồng thời bạn cũng phải đảm nhận mọi công việc mà nhà cung cấp cloud từng làm, từ việc thay thế ổ cứng hỏng cho đến vá lỗi phần mềm máy chủ. Phần cuối của hướng dẫn sẽ nêu rõ khi nào thì sự đánh đổi này là hợp lý.

Tình trạng của bản community edition của MinIO vào tháng 10 năm 2026

Hãy đọc phần này trước khi dựa vào đó, vì nội dung đã thay đổi gần đây. Vào tháng 5 năm 2025, MinIO đã loại bỏ các tính năng quản trị khỏi web console trong bản community edition. Trình duyệt hiện chỉ còn object browser, vì vậy hãy quản lý bucket và access key bằng mc command line client.

Cuối năm 2025, MinIO đã ngừng phát hành các binary community được biên dịch sẵn. README của dự án cho biết community edition hiện chỉ được phân phối dưới dạng mã nguồn. Từ tháng 4 năm 2026, repository minio/minio đã được lưu trữ với thông báo THIS REPOSITORY IS NO LONGER MAINTAINED. Download server cũ cũng đã ngừng cung cấp các file community.

Kiểm tra vào ngày 20 tháng 10 năm 2026 cho thấy mọi đường dẫn dl.min.io mà hướng dẫn này từng dùng để tải xuống — binary server, binary client và các file checksum tương ứng — đều trả về 410 Gone. Đây là việc gỡ bỏ có chủ đích, không phải sự cố ngừng hoạt động. Binary mc duy nhất vẫn còn trên server đó là AIStor Client tại /aistor/mc/release/, thuộc dòng sản phẩm thương mại.

Trang download trên min.io hiện liệt kê AIStor Server, AIStor Client, AIStor SDK và một số add-on AIStor, cùng một tier AIStor miễn phí được mô tả là dành cho developer, researcher và các tổ chức nhỏ chạy deployment độc lập. Trang này không còn cung cấp community build.

Mã nguồn vẫn còn đó và mới hơn bản binary gần nhất. Bản phát hành community cuối cùng là RELEASE.2025-10-15T17-29-55Z, được phát hành vào ngày 16 October 2025 dưới dạng bản cập nhật bảo mật: bản này sửa lỗi leo thang đặc quyền do bypass session policy trong service account và STS. Release notes khuyến cáo tất cả người dùng nâng cấp ngay. Binary được biên dịch sẵn gần nhất là bản build tháng 9 năm 2025, nên chưa bao giờ nhận được bản sửa lỗi này. Tutorial này biên dịch bản phát hành tháng 10. Vì repository đã được lưu trữ, đây cũng là bản sửa lỗi cuối cùng mà community edition sẽ nhận được.

Một thực tế duy nhất định hình toàn bộ hướng dẫn này. Vì vậy, MinIO ở đây lắng nghe trên 127.0.0.1 và chỉ truy cập Internet thông qua proxy do bạn kiểm soát.

Cài binary MinIO và xác minh bản tải xuống

MinIO được viết bằng Go. README của nhà cung cấp build MinIO bằng một lệnh go install duy nhất và lệnh này cần Go 1.24 trở lên. Trước tiên, hãy cài Go từ tarball chính thức. Vào ngày 20 October 2026, bản stable hiện tại trên go.dev/dl là go1.27.3, được phát hành vào ngày 19 October 2026 với bản sửa lỗi bảo mật cho package crypto/x509. Hash bên dưới là hash được công bố trên trang đó cho archive linux-amd64. Nếu chọn bản Go mới hơn, hãy lấy hash của bản đó từ cùng trang. Flag -f khiến curl fail khi gặp lỗi HTTP thay vì lưu trang lỗi dưới tên bạn yêu cầu. Nếu không dùng flag này, bạn có thể giải nén một trang 404 rồi thắc mắc vì sao nó không phải archive.

cd /tmp
GOVER=go1.27.3
curl -fsSL "https://go.dev/dl/$GOVER.linux-amd64.tar.gz" -o go.tar.gz

So sánh hai hash với nhau. Chỉ so sánh hash.

published=65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40
downloaded=$(sha256sum go.tar.gz | awk '{print $1}')
[ "$published" = "$downloaded" ] && echo "checksum ok"

Cần hiểu rõ kiểm tra này chứng minh điều gì. Hash trùng nhau chứng minh bản tải xuống đầy đủ và không bị hỏng hoặc thay đổi trong quá trình truyền. Nó không chứng minh nhà cung cấp đáng tin cậy. Đó là một vấn đề khác và không có lệnh sha256sum nào giải quyết được.

sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version

Bây giờ hãy build bản community release cuối cùng bằng user thông thường của bạn. go install kiểm tra mọi module được tải xuống, bao gồm cả source của MinIO, bằng public checksum database của Go tại sum.golang.org. Vì vậy, module bị can thiệp hoặc bị thay thế sẽ khiến quá trình build dừng với lỗi bảo mật thay vì tạo ra một binary.

go install github.com/minio/minio@RELEASE.2025-10-15T17-29-55Z
sudo install -o root -g root -m 755 ~/go/bin/minio /usr/local/bin/minio
minio --version
go version -m /usr/local/bin/minio | head -n 3

minio --version in DEVELOPMENT.GOGET ở vị trí trước đây dùng cho tên release, vì go install không áp dụng các build flag mà nhà cung cấp đã dùng để ghi thông tin vào các binary của họ. go version -m đọc thông tin module được Go nhúng vào mọi binary. Dòng mod github.com/minio/minio của nó ghi commit bạn đã build. Permission denied ở đây có nghĩa là mode không đúng. command not found có nghĩa là /usr/local/bin không nằm trên PATH của bạn. Nếu VPS không đủ memory để compile, hãy chạy cùng lệnh go install trên một máy Linux khác có cùng architecture, rồi copy binary sang.

Tạo system user và thư mục dữ liệu

MinIO nhận tệp tải lên từ network, vì vậy không nên chạy dưới quyền root. Tạo cho MinIO một account không có thư mục home và không có login shell.

sudo groupadd -r minio-user
sudo useradd -M -r -g minio-user -s /usr/sbin/nologin minio-user
sudo mkdir -p /var/lib/minio/data
sudo chown -R minio-user:minio-user /var/lib/minio
sudo chmod 750 /var/lib/minio

-r tạo một system account với UID nhỏ hơn 1000, nhờ đó account này nằm ngoài dải thường dùng cho người dùng. -M bỏ qua việc tạo thư mục home vì account không bao giờ đăng nhập thì không cần thư mục này. Kiểm tra kết quả bằng id minio-user và bằng stat -c '%U %a' /var/lib/minio; lệnh này phải in ra minio-user 750.

Thư mục dữ liệu phải cho user đó quyền ghi, không chỉ quyền đọc. Khi khởi động lần đầu, MinIO tạo một thư mục .minio.sys bên trong volume để lưu cấu hình riêng. Vì vậy, nếu thư mục thuộc quyền sở hữu của root, MinIO sẽ thoát trong lúc khởi động với thông báo kết thúc bằng permission denied. Quy tắc này áp dụng cho mọi service bạn chạy theo cách này. Bài viết về system user theo nguyên tắc đặc quyền tối thiểu trên VPS trình bày đầy đủ cách thực hiện.

Đặt thông tin xác thực root trong file môi trường

Thông tin xác thực root có quyền truy cập vào mọi bucket, vì vậy không được đặt trong unit file, vốn có quyền đọc cho mọi người. Trước tiên, hãy tạo file với mode phù hợp rồi mới ghi nội dung vào đó. Như vậy, password không bao giờ nằm trong một file có thể đọc được, dù chỉ trong chốc lát.

sudo install -o root -g root -m 600 /dev/null /etc/default/minio
printf 'MINIO_ROOT_USER=minio-root\nMINIO_ROOT_PASSWORD=%s\nMINIO_VOLUMES="/var/lib/minio/data"\nMINIO_OPTS="--address 127.0.0.1:9000 --console-address 127.0.0.1:9001"\n' "$(openssl rand -base64 24)" | sudo tee /etc/default/minio > /dev/null
sudo sed -n 's/^MINIO_ROOT_PASSWORD=//p' /etc/default/minio

tee cắt ngắn file hiện có thay vì tạo lại file, nên mode vẫn là 600 và owner vẫn là root. Đây là chủ ý. systemd đọc EnvironmentFile dưới quyền root trước khi hạ quyền xuống User=, nên service account không bao giờ cần tự đọc thông tin xác thực của mình. Sau khi service chạy, hãy xác nhận bằng sudo -u minio-user cat /etc/default/minio. Lệnh đó phải in ra Permission denied.

Trước khi khởi động, cần biết 2 hành vi của MinIO. Khi không có MINIO_ROOT_USER và MINIO_ROOT_PASSWORD trong environment, MinIO không từ chối khởi động. Nó khởi động với thông tin xác thực mặc định được tài liệu ghi nhận là minioadmin:minioadmin. Đây là cặp thông tin đầu tiên mà mọi scanner thử, nhưng MinIO vẫn trông hoàn toàn bình thường trong lúc đó. Password ngắn hơn 8 ký tự sẽ bị từ chối. MinIO thoát ngay khi khởi động và báo thông tin xác thực không hợp lệ, vì access key cần ít nhất 3 ký tự còn secret key cần ít nhất 8 ký tự.

MINIO_VOLUMES là đường dẫn dữ liệu, còn MINIO_OPTS chứa các flag. Bind vào 127.0.0.1 nghĩa là hiện tại không có gì bên ngoài VPS này có thể truy cập S3 API. Đây là thiết lập mặc định phù hợp. Sau đó, bạn có thể chủ động mở truy cập thông qua một proxy có certificate.

Viết systemd unit

Tạo /etc/systemd/system/minio.service:

[Unit]
Description=MinIO object storage
Documentation=https://github.com/minio/minio
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 $MINIO_VOLUMES $MINIO_OPTS
Restart=always
RestartSec=5
LimitNOFILE=65536
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Không có - ở đầu EnvironmentFile. Đây là chủ ý, không phải lỗi đánh máy. Khi có dấu gạch ngang, systemd bỏ qua file bị thiếu và vẫn khởi động MinIO. Vì vậy, file bị xóa hoặc đường dẫn bị viết sai có thể âm thầm khiến bạn có một server chạy trên minioadmin:minioadmin. Khi không có dấu gạch ngang, file bị thiếu sẽ làm unit fail trước khi MinIO chạy, và journalctl -u minio hiển thị Failed to load environment files: No such file or directory. Một unit từ chối khởi động dễ được phát hiện hơn nhiều so với một server âm thầm chấp nhận mật khẩu mặc định.

$MINIO_VOLUMES và $MINIO_OPTS được cố ý để không có dấu ngoặc kép, vì systemd tách các biến không có dấu ngoặc kép theo khoảng trắng thành các argument riêng. Nhờ đó, 4 từ trong MINIO_OPTS trở thành 4 argument của minio server. LimitNOFILE=65536 tăng giới hạn file descriptor, vì mỗi connection đang mở và mỗi file dữ liệu đang mở đều dùng 1 descriptor; giới hạn mặc định 1024 sẽ hết khi tải tăng cao.

sudo systemctl daemon-reload
sudo systemctl enable --now minio
systemctl is-active minio
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9000/minio/health/live

is-active phải in ra active, và health endpoint phải trả về 200. journalctl -u minio -n 20 --no-pager hiển thị địa chỉ API mà server đang listen. Nếu unit liên tục restart, systemd sẽ dừng thử và ghi log Start request repeated too quickly. Điều đó có nghĩa là MinIO thoát ở mỗi lần thử. Nguyên nhân được in trong các dòng phía trên thông báo đó, vì vậy hãy đọc ngược lên.

Để tăng mức cô lập, thêm ProtectSystem=full và ProtectHome=true vào section [Service]. Cả hai đều cần mount namespace từ kernel của host. Trên các môi trường container virtualization dùng chung kernel với host, chẳng hạn OpenVZ hoặc LXC, chúng có thể fail và unit sẽ báo status=226/NAMESPACE. Xóa 2 dòng đó thì unit sẽ khởi động. Bản thân unit là một unit thông thường; systemd service và timer trên VPS trình bày các directive còn lại.

Cài mc và kiểm tra toàn bộ vòng truyền dữ liệu

MinIO client là mc. Không cài nó bằng apt install mc. Gói đó là Midnight Commander, một trình quản lý tệp không liên quan đến MinIO.

dl.min.io vẫn cung cấp một binary mc, nhưng đó không phải bản community. Đường dẫn community cũ, https://dl.min.io/client/mc/release/linux-amd64/mc, trả về 410 Gone. Hiện MinIO cung cấp AIStor Client tại https://dl.min.io/aistor/mc/release/linux-amd64/mc; tài liệu tham chiếu AIStor CLI trỏ đến client này và mô tả nó có các chức năng độc quyền cho những triển khai AIStor Server có license. Tài liệu đó không nói gì về việc dùng client này với community server, nên hướng dẫn này vẫn dùng community client. Repository minio/mc đã được archive từ July 2026, vì vậy hãy build release cuối cùng của nó, RELEASE.2025-08-13T08-35-41Z, bằng cùng Go toolchain. Checksum database cũng bao phủ bản download này.

go install github.com/minio/mc@RELEASE.2025-08-13T08-35-41Z
sudo install -o root -g root -m 755 ~/go/bin/mc /usr/local/bin/mc

Đăng ký server dưới dạng alias, sau đó chuyển một object qua server.

MINIO_PASS=$(sudo sed -n 's/^MINIO_ROOT_PASSWORD=//p' /etc/default/minio)
mc alias set local http://127.0.0.1:9000 minio-root "$MINIO_PASS"
mc mb local/backups
echo "hello object storage" > /tmp/hello.txt
mc cp /tmp/hello.txt local/backups/hello.txt
mc ls local/backups
mc cat local/backups/hello.txt

mc ls phải liệt kê hello.txt cùng kích thước của object, còn mc cat phải in ra hello object storage. Vòng truyền dữ liệu này là bằng chứng thực tế cho thấy server hoạt động, vì nó tạo ra cùng các signed S3 request mà mọi client khác sẽ tạo. mc admin info local in trạng thái server nếu bạn muốn kiểm tra thêm.

Hãy chạy thêm một lần kiểm tra ngay bây giờ, khi máy vẫn chưa có dữ liệu.

mc alias set defaultcheck http://127.0.0.1:9000 minioadmin minioadmin

Lệnh này phải fail. Nếu lệnh thành công, file môi trường chưa được truyền vào process và server của bạn đang chạy bằng credential mặc định. Hãy sửa lỗi đó trước khi bất kỳ thứ gì khác truy cập vào máy.

mc lưu alias trong ~/.mc/config.json dưới dạng plain text, nên các credential đó nằm trong home directory của tài khoản đã chạy lệnh. Chạy mc dưới sudo sẽ đặt credential root vào /root/.mc/config.json. Chỉ giữ root alias trên một tài khoản administrator và cấp key riêng cho từng ứng dụng.

Cung cấp một object bằng presigned URL

Presigned URL là một đường dẫn HTTPS thông thường kèm theo chữ ký và thời hạn. Bất kỳ ai có đường dẫn này đều có thể tải object đó mà không cần tài khoản hay client.

mc share download --expire 12h local/backups/hello.txt

Kết quả trả về chứa X-Amz-Signature và X-Amz-Expires trong query string. Có hai điểm về nó khiến người dùng bất ngờ. Đường dẫn được tạo từ endpoint trong alias bạn sử dụng, vì vậy một alias trên 127.0.0.1 sẽ tạo ra đường dẫn mà chỉ máy này mới mở được: hãy tạo một alias thứ hai trên hostname công khai của bạn cho các đường dẫn dự định gửi đi. Ngoài ra, không có nút thu hồi cho từng đường dẫn. Chữ ký vẫn có hiệu lực cho đến khi hết hạn hoặc key dùng để ký bị xóa/thay đổi. Đối với đường dẫn được ký bằng root credentials, điều này đồng nghĩa với việc phải xoay vòng chúng, vì vậy đặt thời hạn ngắn là biện pháp kiểm soát thực tế. Bảy ngày là thời hạn tối đa mà định dạng chữ ký S3 cho phép.

Cấp key và bucket riêng cho restic

Thông tin xác thực của root có thể đọc và xóa mọi bucket, vì vậy backup job không được giữ chúng. Tạo một bucket, một policy chỉ áp dụng cho bucket đó và một user không có thêm quyền nào khác.

mc mb local/restic
cat > /tmp/restic-rw.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:GetBucketLocation"],
      "Resource": ["arn:aws:s3:::restic"]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": ["arn:aws:s3:::restic/*"]
    }
  ]
}
EOF
RESTIC_KEY=$(openssl rand -base64 24)
mc admin policy create local restic-rw /tmp/restic-rw.json
mc admin user add local restic-backup "$RESTIC_KEY"
mc admin policy attach local restic-rw --user restic-backup

MinIO có sẵn policy readwrite. Dùng policy này sẽ ngắn hơn một lệnh, nhưng nó cấp toàn quyền truy cập vào mọi bucket trên server. Policy trên cố ý ghi tên bucket hai lần: một lần là arn:aws:s3:::restic để thao tác liệt kê bucket hoạt động, và một lần là arn:aws:s3:::restic/* cho các object bên trong bucket. Trong S3, bucket và object là hai resource riêng biệt, nên policy chỉ ghi một trong hai sẽ thất bại theo cách dễ khiến bạn tưởng client bị lỗi.

Hãy kiểm tra giới hạn trước khi tin dùng.

mc alias set resticuser http://127.0.0.1:9000 restic-backup "$RESTIC_KEY"
mc ls resticuser/restic
mc ls resticuser/backups

Lệnh ls đầu tiên thành công và lệnh thứ hai thất bại với Access Denied. Một policy chưa được kiểm tra chỉ là phỏng đoán.

Bây giờ trỏ restic vào bucket. restic đọc thông tin xác thực S3 từ các biến môi trường AWS tiêu chuẩn, nên không có file thông tin xác thực riêng của restic.

sudo apt install -y restic
export AWS_ACCESS_KEY_ID=restic-backup
export AWS_SECRET_ACCESS_KEY="$RESTIC_KEY"
restic -r s3:http://127.0.0.1:9000/restic init
restic -r s3:http://127.0.0.1:9000/restic backup /etc
restic -r s3:http://127.0.0.1:9000/restic snapshots

restic init yêu cầu mật khẩu repository. Mật khẩu đó mã hóa repository, vì vậy MinIO chỉ lưu ciphertext; nếu mất mật khẩu thì cũng mất backup. Một tiến trình được systemd timer khởi chạy không có terminal để nhập mật khẩu, nên hãy đặt RESTIC_PASSWORD_FILE thành file mode 600 cho các backup theo lịch.

Có một quy tắc đặt repository quan trọng hơn mọi lệnh ở trên. Đặt repository restic trên cùng VPS với dữ liệu mà nó bảo vệ chỉ giúp bạn khôi phục sau một rm lỗi, chứ không bảo vệ trước vấn đề nào khác. MinIO node nên nằm trên một máy khác, tốt nhất là ở một region khác. backup restic trên VPS trình bày cách lập lịch và quản lý retention dựa trên cấu hình này.

Kết thúc TLS bằng nginx

MinIO chạy trên localhost, nên nginx là bề mặt public. Trước tiên, hãy cấp chứng chỉ như mô tả trong Cấp chứng chỉ Let's Encrypt bằng certbot và nginx, sau đó dùng server block này.

server {
    listen 443 ssl;
    server_name s3.example.com;

    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        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_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
        proxy_pass http://127.0.0.1:9000;
    }
}

Một số dòng trong đó rất quan trọng. client_max_body_size 0 xóa giới hạn body mặc định 1 MB; nếu không, mọi upload lớn hơn sẽ bị từ chối bằng 413 Request Entity Too Large trước khi MinIO nhận được request. proxy_request_buffering off truyền thẳng upload đến backend, vì mặc định nginx ghi toàn bộ request vào file tạm trước, khiến một object lớn cần gấp đôi dung lượng đĩa. proxy_set_header Host $http_host là dòng dễ bỏ sót: chữ ký S3 bao gồm header Host, nên proxy viết lại header này sẽ khiến mọi request thất bại với SignatureDoesNotMatch, trong khi access log vẫn hiển thị một request bình thường đã đến server.

Cũng phải khai báo tên public của MinIO để các liên kết do MinIO tạo trỏ đến proxy thay vì localhost.

echo 'MINIO_SERVER_URL=https://s3.example.com' | sudo tee -a /etc/default/minio
sudo systemctl restart minio

Firewall chỉ cần vài rule. Cho phép SSH và HTTPS, đồng thời không tạo rule nào cho cổng 9000 và 9001, vì địa chỉ bind vào 127.0.0.1 không thể truy cập từ máy khác, bất kể firewall được cấu hình thế nào. Kiến thức cơ bản về firewall ufw trên VPS có các lệnh cần dùng.

Khi nào MinIO một node là đủ và khi nào nên dùng S3 thực sự

Một node ở đây nghĩa là một ổ đĩa. Vì vậy deployment không có parity và cũng không có bản sao thứ hai. Độ bền của mỗi object phụ thuộc hoàn toàn vào độ bền của một ổ đĩa VPS. Tài liệu riêng của MinIO, hiện chỉ còn ở dạng source trong repository minio/docs kể từ khi tài liệu cộng đồng được host bị gỡ vào tháng 10 năm 2025, mô tả deployment standalone là phù hợp cho giai đoạn phát triển và đánh giá ban đầu, đồng thời nói rõ MinIO không khuyến nghị dùng trong production. Có thể bật object locking cho một bucket, nhưng trên một VPS, tính năng này chỉ ngăn việc xóa thông qua S3 API. Bất kỳ ai có quyền root trên máy vẫn có thể xóa các file trên disk. Vì vậy, không được cam kết chính sách lưu giữ bất biến trên mô hình này.

Mô hình này phù hợp làm target restic trên một VPS thứ hai ở region khác, cũng như làm S3 endpoint cho công việc phát triển và artifact của CI, trong đó việc mất một bucket chỉ khiến bạn phải build lại và không gây hậu quả nào khác. Mô hình này cũng hợp lý cho upload của người dùng trong một ứng dụng nhỏ, miễn là bạn sở hữu recovery plan và đã thực sự kiểm thử việc restore.

Hãy chọn managed S3 khi hợp đồng hoặc cơ quan quản lý yêu cầu object lock hay durability trên nhiều region, hoặc khi bạn không muốn là người nhận page lúc 03:00 vì disk đã đầy. Code bị đóng băng cũng là một lý do thực tế khác. Tính đến ngày 20 tháng 10 năm 2026, community edition đã được archive và không còn được maintain. Bản release cuối cùng là RELEASE.2025-10-15T17-29-55Z, cũng là bản guide này build. Sau bản đó sẽ không có lỗi nào được sửa. Vì vậy, chạy bản này đồng nghĩa với việc chấp nhận điều đó, hoặc chuyển sang dòng thương mại AIStor của MinIO hay một object store self-hosted khác. Bài các lựa chọn thay thế cho MinIO self-hosted so sánh các lựa chọn này.

Có một ranh giới cần nêu rõ vì vấn đề này thường được hỏi. Object storage không phải là database. Trong một bucket tiêu chuẩn, mỗi lần ghi sẽ thay thế toàn bộ object. Ngay cả lệnh append mà Amazon bổ sung cho S3 Express One Zone cũng chỉ thêm dữ liệu vào cuối object. Vì vậy, lưu file SQL đang hoạt động trên S3 bucket vừa chậm vừa không an toàn. Hãy giữ database trên local disk và backup nó vào bucket. Bài chạy SQLite trong production trên VPS mô tả cách tách này.

Các chế độ lỗi và thông báo bạn sẽ thấy

Unit bị lỗi ngay sau systemctl enable --now. Hãy đọc journalctl -u minio -n 30 --no-pager. Failed to load environment files: No such file or directory nghĩa là /etc/default/minio bị thiếu hoặc đường dẫn bị sai trong file unit. Một thông báo kết thúc bằng permission denied nghĩa là thư mục dữ liệu không được cấp quyền ghi cho tài khoản chạy dịch vụ, hãy kiểm tra xem stat -c '%U' /var/lib/minio/data có in ra minio-user hay không.

minioadmin:minioadmin vẫn đăng nhập được. File môi trường chưa được nạp vào tiến trình. Xác nhận unit có chứa EnvironmentFile=/etc/default/minio, chạy sudo systemctl daemon-reload, sau đó khởi động lại dịch vụ. MinIO chỉ đọc thông tin xác thực root một lần khi khởi động, vì vậy việc sửa file mà không khởi động lại sẽ không có tác dụng.

Address already in use khi khởi động. Một tiến trình khác đang chiếm cổng 9000. Tìm tiến trình đó bằng sudo ss -ltnp | grep :9000 trước khi bạn thay đổi cổng của MinIO.

Upload file trên 1 MB bị lỗi thông qua proxy. nginx trả về 413 Request Entity Too Large và MinIO không nhận được request. Hãy thiết lập client_max_body_size 0 trong block server.

SignatureDoesNotMatch. Hoặc secret key bị sai, hoặc một thành phần nào đó giữa client và MinIO đã ghi đè header Host, vốn là phần được bao gồm trong chữ ký.

RequestTimeTooSkewed. Đồng hồ trên client hoặc server bị sai. Mọi request S3 có chữ ký đều mang theo timestamp, và MinIO, giống như Amazon S3, sẽ từ chối các request có header chữ ký với timestamp chênh lệch quá 15 phút so với đồng hồ của hệ thống. Các link presigned sẽ được kiểm tra dựa trên thời hạn hết hiệu lực của chúng. Kiểm tra timedatectl và xác nhận rằng tính năng đồng bộ thời gian đang hoạt động.

Access Denied trên một bucket mà bạn biết là có tồn tại. Key bị giới hạn phạm vi ở một bucket khác. Hãy in ra những gì policy thực sự cho phép bằng mc admin policy info local restic-rw và so sánh tên bucket trong các dòng resource.

FAQ

MinIO chạy trên một node có đủ tốt cho backup thực tế không?

MinIO đủ tốt để làm đích restic trên một máy riêng với dữ liệu mà nó bảo vệ. Nhưng không đủ tốt nếu đó là bản sao duy nhất. Triển khai trên một ổ đĩa không có parity, nên không có bản sao thứ hai bên trong MinIO. Nếu ổ đĩa của VPS mất dữ liệu thì các object cũng mất. Hãy giữ thêm một đích backup ở nơi khác và khôi phục thử từ cả hai đích ít nhất một lần để xác nhận quy trình hoạt động.

Tại sao sha256sum -c không kiểm tra được file checksum trên MinIO?

Bạn chỉ gặp file đó trong một bản sao được lưu trước đây, vì khi kiểm tra vào ngày 20 October 2026, dl.min.io đã trả về 410 Gone cho mọi binary và file checksum của community. Nhãn sau chuỗi hash bên trong file đó cho biết release, chẳng hạn minio.RELEASE.2025-09-07T16-13-09Z, còn file đã tải xuống thường có tên minio. sha256sum -c tìm file có tên được ghi bên trong file checksum nhưng không thấy, nên báo No such file or directory và WARNING: 1 listed file could not be read. Bản tải xuống không bị lỗi. Hãy so sánh trực tiếp các chuỗi hash và bỏ qua nhãn, vì nhãn không có ý nghĩa bảo mật.

Console web quản trị MinIO đã đi đâu?

MinIO đã loại bỏ các tính năng quản trị khỏi console của community edition vào May 2025, chỉ giữ lại trình duyệt object trong giao diện web. Hiện nay, bạn quản lý bucket và user bằng client mc, sử dụng các lệnh như mc admin user add và mc admin policy attach. Đây là cách được thiết kế cho community edition, không phải workaround. Vì vậy, guide này thực hiện mọi thao tác từ command line.

Làm cách nào để trỏ restic đến MinIO làm S3 backend?

Đặt AWS_ACCESS_KEY_ID và AWS_SECRET_ACCESS_KEY thành access key và secret tương ứng của MinIO, rồi dùng repository string có dạng s3:https://s3.example.com/restic, trong đó phần tử cuối của path là tên bucket. Trước tiên hãy tạo bucket bằng mc mb, vì key chỉ có quyền trong một bucket không thể tạo bucket. restic mã hóa mọi dữ liệu bằng repository password riêng trước khi upload. Vì vậy, MinIO chỉ lưu ciphertext và không bao giờ thấy file của bạn.

Tôi có phải chạy MinIO phía sau nginx không?

Bạn cần TLS (transport layer security) bất cứ khi nào client không chạy trên cùng máy, vì nếu không có TLS thì mọi object đều đi qua network dưới dạng plain text, cùng với access key ID và request signature. Secret key không bao giờ rời khỏi client, vì S3 signing chỉ dùng key này cục bộ để tính signature. Tuy nhiên, bất kỳ ai trên đường truyền vẫn có thể đọc dữ liệu và gửi lại request đã bắt được trong thời gian timestamp còn hợp lệ. Dùng proxy trên port 443 với certificate từ certbot là cách đơn giản nhất để có TLS và giúp việc gia hạn certificate không liên quan đến MinIO. MinIO cũng có thể tự terminate TLS nếu bạn trỏ --certs-dir đến directory chứa public.crt và private.key. Nhưng khi đó service account cần quyền đọc private key đã được gia hạn, tức là phải làm thêm việc nhưng kết quả vẫn như nhau.

Bài viết này có hữu ích không?

#minio#s3#object-storage#self-hosted#vps