Ubuntu 24.04 VPS에 MinIO 설치하고 S3 구축하기
Ubuntu 24.04 VPS 하나에 MinIO를 설치해 소유한 S3 API를 구축합니다. 검증된 binary, systemd unit, mc 기본 사용법, presigned URL과 restic 백업 설정을 다룹니다.
자체 호스팅 객체 스토리지를 MinIO로 사용하면 얻는 것
MinIO는 Amazon S3 API를 지원하는 자체 호스팅 객체 스토리지입니다. restic 또는 S3 SDK를 자체 서버에 연결하고 endpoint 설정 하나만 변경하면 클라이언트는 차이를 인식하지 못합니다. 이 가이드에서는 Ubuntu 24.04에 단일 노드를 구축합니다. 검증된 바이너리, 전용 시스템 사용자, root 자격 증명을 unit 파일에서 분리하는 systemd unit, 그리고 restic이 백업을 저장할 bucket을 구성합니다.
S3 (simple storage service)는 파일 시스템이 아니라 HTTP API입니다. bucket의 key 아래에 객체를 PUT하고 다시 GET합니다. 부분 쓰기와 이름 변경은 지원되지 않습니다. 객체가 전체로 도착했거나 도착하지 않은 두 가지 상태만 있으므로 백업 도구는 이 모델을 사용하기에 적합합니다.
단일 노드에는 데이터 사본 하나만 저장됩니다. 이것이 선택에 따른 대가입니다. VPS 비용으로 직접 제어하는 S3 endpoint를 얻지만, 클라우드 제공업체가 수행하던 모든 작업도 직접 맡아야 합니다. 여기에는 고장 난 디스크 교체와 서버 소프트웨어 패치가 포함됩니다. 이 선택이 적합한 경우는 이 문서의 끝부분에서 명확히 설명합니다.
2026년 7월 MinIO community edition의 상태
이 내용을 기반으로 구축하기 전에 이 부분을 읽어야 합니다. 최근에 변경되었기 때문입니다. 2025년 5월 MinIO는 community edition의 웹 콘솔에서 관리 기능을 제거했습니다. 브라우저에 남은 기능은 object browser뿐입니다. 따라서 이제 버킷과 access key는 mc command line client로 관리합니다.
이후 2025년에 MinIO는 사전 컴파일된 community binary의 게시를 중단했습니다. 이제 프로젝트 README에는 community edition이 소스 코드로만 배포된다고 명시되어 있습니다. 이전 download URL은 여전히 작동합니다. 2026년 7월 기준으로 해당 URL은 server build RELEASE.2025-09-07T16-13-09Z와 client build RELEASE.2025-08-13T08-35-41Z을 제공하며, 더 최신인 community build는 없습니다. 따라서 아래 binary는 실제로 존재하고 실행되지만, 업데이트되지 않습니다. 2025년 9월 이후에 게시된 보안 수정 사항은 포함되어 있지 않습니다.
이 한 가지 사실이 이 가이드의 나머지 내용을 결정합니다. 따라서 여기서는 MinIO가 127.0.0.1에서 listening하고, 사용자가 제어하는 proxy를 통해서만 인터넷에 연결합니다. 수정 사항을 계속 반영하려면 소스 코드에서 빌드합니다. vendor README에는 단일 명령 go install github.com/minio/minio@latest이 제시되어 있습니다. 이 명령에는 Go toolchain이 필요하며 binary를 ~/go/bin/minio에 기록합니다. 해당 binary를 /usr/local/bin/minio에 설치하면 여기의 다른 모든 단계는 변경되지 않습니다.
MinIO 바이너리 설치 및 다운로드 확인
고정된 릴리스와 게시된 체크섬을 다운로드합니다. -f 플래그를 사용하면 HTTP 오류가 발생할 때 curl가 오류 페이지를 요청한 이름으로 저장하지 않고 실패합니다. 오류 페이지를 설치한 뒤 실행되지 않는 이유를 확인하려는 상황을 방지할 수 있습니다.
cd /tmp
REL=RELEASE.2025-09-07T16-13-09Z
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.$REL" -o minio
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.$REL.sha256sum" -o minio.sha256sum두 해시를 비교합니다. 해시만 비교합니다.
published=$(awk '{print $1}' minio.sha256sum)
downloaded=$(sha256sum minio | awk '{print $1}')
[ "$published" = "$downloaded" ] && echo "checksum ok"여기서는 sha256sum -c minio.sha256sum를 사용하지 마십시오. 해당 파일의 해시 뒤에 기록된 레이블은 minio.RELEASE.2025-09-07T16-13-09Z이고, 다운로드를 minio로 저장했으므로 -c는 존재하지 않는 파일을 찾습니다. No such file or directory를 보고한 다음 WARNING: 1 listed file could not be read을 보고합니다. 이 메시지는 다운로드가 손상된 것처럼 보이지만 실제로는 그렇지 않습니다. 레이블은 이름일 뿐입니다. 보증을 제공하는 부분은 해시입니다.
이 확인으로 무엇을 입증할 수 있는지 명확히 해야 합니다. 바이너리와 해시는 동일한 공급업체에서 동일한 연결을 통해 가져오므로, 일치하면 다운로드가 완전하고 전송 중 손상되거나 변경되지 않았음을 입증합니다. 공급업체를 신뢰할 수 있다는 뜻은 아닙니다. 이는 별개의 문제이며, 어떤 sha256sum 명령으로도 해결할 수 없습니다.
sudo install -o root -g root -m 755 minio /usr/local/bin/minio
minio --versionminio --version는 minio version RELEASE.2025-09-07T16-13-09Z을 출력한 다음 몇 개의 빌드 줄을 출력합니다. 여기서 Permission denied가 표시되면 모드가 잘못된 것입니다. command not found가 표시되면 /usr/local/bin이 사용자의 PATH에 없는 것입니다.
시스템 사용자 및 데이터 디렉터리 생성
MinIO는 네트워크에서 업로드를 받으므로 root로 실행하면 안 됩니다. 홈 디렉터리가 없고 로그인 셸을 사용하지 않는 계정을 할당합니다.
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은(는) UID가 1000 미만인 시스템 계정을 생성하므로 일반 사용자에게 사용되는 범위와 분리됩니다. -M은(는) 홈 디렉터리를 생성하지 않습니다. 로그인하지 않는 계정에는 홈 디렉터리에 보관할 항목이 없기 때문입니다. id minio-user으로 결과를 확인하고, stat -c '%U %a' /var/lib/minio도 실행합니다. 이 명령은 minio-user 750을(를) 출력해야 합니다.
데이터 디렉터리는 해당 사용자가 읽기만 할 수 있는 것이 아니라 쓰기도 할 수 있어야 합니다. 처음 시작할 때 MinIO는 볼륨 내부에 자체 구성을 저장할 .minio.sys 디렉터리를 생성합니다. 따라서 root가 소유한 디렉터리를 사용하면 시작 중 MinIO가 종료되고 메시지는 permission denied로 끝납니다. 이 방식으로 실행하는 모든 서비스에도 같은 규칙이 적용되며, VPS의 최소 권한 서비스 사용자에서 이 내용을 자세히 설명합니다.
root 자격 증명을 환경 파일에 넣기
root 자격 증명은 모든 bucket에 접근할 수 있으므로, 누구나 읽을 수 있는 unit 파일에 넣으면 안 됩니다. 먼저 올바른 mode로 파일을 만들고 그다음 파일에 기록합니다. 이렇게 하면 읽기 가능한 파일에 password가 잠시라도 남지 않습니다.
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/miniotee는 기존 파일을 다시 만들지 않고 내용을 비우므로 mode는 600으로 유지되고 소유자는 root로 유지됩니다. 이는 의도된 동작입니다. systemd는 권한을 User=로 낮추기 전에 root로 EnvironmentFile를 읽습니다. 따라서 service account는 자체 자격 증명을 읽을 필요가 없습니다. service가 실행되면 sudo -u minio-user cat /etc/default/minio로 이를 확인합니다. 이 command는 Permission denied를 출력해야 합니다.
MinIO를 시작하기 전에 두 가지 동작을 알아두어야 합니다. 환경에 MINIO_ROOT_USER도 MINIO_ROOT_PASSWORD도 없으면 MinIO는 시작을 거부하지 않습니다. 문서에 명시된 기본 자격 증명인 minioadmin:minioadmin로 시작합니다. 이는 모든 scanner가 가장 먼저 시도하는 자격 증명이며, 이 상태에서도 완전히 정상인 것처럼 보입니다. 대신 8자 미만의 password는 거부됩니다. MinIO는 startup 시 자격 증명이 유효하지 않다는 error를 출력하고 종료합니다. access key에는 3자 이상, secret key에는 8자 이상이 필요하기 때문입니다.
MINIO_VOLUMES는 data path이고 MINIO_OPTS에는 flag가 들어 있습니다. 127.0.0.1에 bind하면 아직 이 VPS 외부에서는 S3 API에 접근할 수 없습니다. 이것이 올바른 기본 설정입니다. 나중에 certificate를 보유한 proxy를 통해 의도적으로 외부에 공개합니다.
systemd unit 작성
/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.targetEnvironmentFile에 앞에 -이 없는 것은 오타가 아니라 의도적인 설정입니다. 대시가 있으면 systemd는 파일이 없어도 무시하고 MinIO를 시작합니다. 따라서 파일이 삭제되었거나 경로의 철자가 틀리면 서버가 minioadmin:minioadmin에서 조용히 실행됩니다. 대시가 없으면 파일이 없을 때 MinIO가 실행되기 전에 unit이 실패하고, journalctl -u minio에 Failed to load environment files: No such file or directory이 표시됩니다. 시작을 거부하는 unit이 기본 암호를 사용해 조용히 연결을 수락하는 서버보다 훨씬 쉽게 발견됩니다.
$MINIO_VOLUMES 및 $MINIO_OPTS은 의도적으로 따옴표로 묶지 않습니다. systemd는 따옴표로 묶지 않은 변수를 공백을 기준으로 여러 인수로 분할하기 때문입니다. 따라서 MINIO_OPTS의 4개 단어가 minio server에 전달되는 4개의 인수가 됩니다. LimitNOFILE=65536은 파일 디스크립터 제한을 늘립니다. 열려 있는 각 연결과 데이터 파일마다 디스크립터 1개가 필요하며, 기본값인 1024는 부하가 발생하면 부족해집니다.
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/liveis-active은 active을 출력해야 하며, health endpoint는 200에 응답해야 합니다. journalctl -u minio -n 20 --no-pager에는 서버가 수신 대기 중인 API 주소가 표시됩니다. unit이 계속 재시작되면 systemd는 실행을 포기하고 Start request repeated too quickly을 로그에 기록합니다. 이는 MinIO가 시도할 때마다 종료된다는 의미입니다. 원인은 해당 메시지 위의 줄에 표시되므로 위로 올라가서 확인합니다.
격리를 강화하려면 [Service] 섹션에 ProtectSystem=full 및 ProtectHome=true을 추가합니다. 두 설정 모두 호스트 커널의 mount namespace가 필요합니다. OpenVZ 또는 LXC처럼 호스트 커널을 공유하는 컨테이너 가상화 환경에서는 이 설정이 실패할 수 있으며, 이 경우 unit에 status=226/NAMESPACE이 표시됩니다. 이 2줄을 제거하면 시작됩니다. 이 unit 자체는 일반적인 unit이며, VPS의 systemd 서비스 및 타이머에서 나머지 지시어를 설명합니다.
mc 설치 및 왕복 작업 검증
MinIO 클라이언트는 mc입니다. apt install mc로 설치하지 마십시오. 해당 패키지는 MinIO와 관련 없는 파일 관리자 Midnight Commander입니다.
cd /tmp
curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc -o mc
curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc.sha256sum -o mc.sha256sum
[ "$(awk '{print $1}' mc.sha256sum)" = "$(sha256sum mc | awk '{print $1}')" ] && echo "checksum ok"
sudo install -o root -g root -m 755 mc /usr/local/bin/mc서버를 alias로 등록한 다음, 해당 서버를 통해 객체를 이동합니다.
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.txtmc ls는 크기와 함께 hello.txt를 나열해야 하며, mc cat는 hello object storage를 출력해야 합니다. 이 왕복 작업이 서버가 작동한다는 실제 증거입니다. 다른 모든 클라이언트가 수행할 동일한 서명된 S3 요청을 생성하기 때문입니다. 추가로 확인하려면 mc admin info local로 서버 상태를 출력할 수 있습니다.
이제 시스템이 아직 비어 있는 동안 검사를 한 번 더 실행합니다.
mc alias set defaultcheck http://127.0.0.1:9000 minioadmin minioadmin이 명령은 실패해야 합니다. 성공한다면 환경 파일이 프로세스에 전달되지 않았고 서버가 기본 자격 증명으로 실행 중인 것입니다. 다른 작업이 시스템에 접근하기 전에 이 문제를 해결하십시오.
mc는 alias를 ~/.mc/config.json에 일반 텍스트로 저장하므로, 해당 명령을 실행한 사용자의 홈 디렉터리에 자격 증명이 저장됩니다. sudo 아래에서 mc를 실행하면 root 자격 증명이 /root/.mc/config.json에 저장됩니다. root alias는 관리자 한 명의 계정에서만 유지하고, 각 애플리케이션에는 고유한 키를 할당하십시오.
presigned URL로 객체 1개 제공
presigned URL은 서명과 만료 시간이 포함된 일반 HTTPS 링크입니다. 이 링크를 가진 사람은 계정이나 클라이언트 없이 해당 객체 1개를 가져올 수 있습니다.
mc share download --expire 12h local/backups/hello.txt출력에는 쿼리 문자열에 X-Amz-Signature 및 X-Amz-Expires가 포함됩니다. 이와 관련해 사람들이 자주 놀라는 점이 2가지 있습니다. 링크는 사용한 alias의 endpoint를 기준으로 생성됩니다. 따라서 127.0.0.1의 alias로 생성한 링크는 이 컴퓨터에서만 열 수 있습니다. 전송할 링크에는 public hostname을 대상으로 두 번째 alias를 생성합니다. 또한 revoke 버튼은 없습니다. 서명은 만료될 때까지 유효하므로, 사용할 수 있는 유일한 제어 방법은 짧은 만료 시간을 설정하는 것입니다. S3 signature format에서 허용하는 최대 만료 기간은 7일입니다.
restic 전용 키와 버킷 만들기
root 자격 증명은 모든 버킷을 읽고 삭제할 수 있으므로 백업 작업에서 이 자격 증명을 사용해서는 안 됩니다. 버킷, 해당 버킷으로 범위를 제한한 정책, 다른 권한이 없는 사용자를 만듭니다.
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-backupMinIO에는 기본 제공되는 readwrite 정책이 있습니다. 이 정책을 사용하면 명령을 하나 줄일 수 있지만, 서버의 모든 버킷에 대한 전체 액세스 권한을 부여합니다. 위 정책에서 버킷 이름을 두 번 지정한 이유가 있습니다. arn:aws:s3:::restic는 버킷 목록을 표시할 때 사용하고, arn:aws:s3:::restic/*는 버킷 안의 객체에 사용합니다. S3에서 버킷과 객체는 서로 다른 리소스이므로 둘 중 하나만 지정한 정책은 클라이언트가 고장 난 것처럼 보이는 방식으로 실패합니다.
신뢰하기 전에 제한을 테스트합니다.
mc alias set resticuser http://127.0.0.1:9000 restic-backup "$RESTIC_KEY"
mc ls resticuser/restic
mc ls resticuser/backups첫 번째 ls는 성공하고 두 번째는 Access Denied와 함께 실패합니다. 테스트하지 않은 정책은 추측에 불과합니다.
이제 restic이 버킷을 사용하도록 설정합니다. restic은 표준 AWS 환경 변수에서 S3 자격 증명을 읽으므로 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 snapshotsrestic init은 리포지토리 암호를 요청합니다. 이 암호는 리포지토리를 암호화하므로 MinIO에는 암호문만 저장됩니다. 암호를 잃으면 백업도 잃게 됩니다. systemd 타이머로 시작된 실행에는 입력할 터미널이 없으므로 예약된 백업을 위해 RESTIC_PASSWORD_FILE을 mode 600 파일로 설정합니다.
위의 어떤 명령보다 중요한 배치 규칙이 하나 있습니다. 보호할 데이터와 같은 VPS에 restic 리포지토리를 두면 잘못된 rm으로부터만 복구할 수 있고, 그 외의 장애로부터는 보호할 수 없습니다. MinIO 노드는 다른 머신에 두어야 하며, 가능하면 다른 리전에 배치해야 합니다. VPS에서 restic 백업에서 이를 바탕으로 한 예약과 보존 설정을 설명합니다.
nginx로 TLS 종료
MinIO는 localhost에서 실행되므로 nginx가 외부에 노출되는 진입점입니다. 먼저 certbot과 nginx로 Let's Encrypt 인증서 발급에 설명된 방법으로 인증서를 발급한 다음, 다음 server block을 사용합니다.
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;
}
}이 설정의 일부 행은 필수입니다. client_max_body_size 0는 기본 1 MB 본문 제한을 제거합니다. 이 설정이 없으면 MinIO가 요청을 받기도 전에 413 Request Entity Too Large과 함께 1 MB를 초과하는 업로드가 거부됩니다. proxy_request_buffering off은 업로드를 바로 전달합니다. 기본 설정에서는 전체 요청을 먼저 임시 파일에 저장하므로 대용량 객체에 디스크 공간이 2배 필요합니다. proxy_set_header Host $http_host가 특히 중요합니다. S3 서명에는 Host 헤더가 포함되므로, proxy가 이 헤더를 다시 작성하면 모든 요청이 SignatureDoesNotMatch와 함께 실패합니다. 이때 access log에는 정상적인 요청이 도착한 것으로 표시됩니다.
MinIO에 public name도 지정해야 합니다. 그래야 MinIO가 생성하는 링크가 localhost가 아니라 proxy를 가리킵니다.
echo 'MINIO_SERVER_URL=https://s3.example.com' | sudo tee -a /etc/default/minio
sudo systemctl restart miniofirewall 설정은 간단하게 유지합니다. SSH와 HTTPS만 허용하고, 포트 9000과 9001에는 규칙을 전혀 추가하지 않습니다. 127.0.0.1에 바인딩된 address는 firewall 설정과 관계없이 다른 시스템에서 접근할 수 없기 때문입니다. 명령은 VPS에서 ufw firewall 기본 설정에 설명되어 있습니다.
단일 노드 MinIO로 충분한 경우와 실제 S3가 필요한 경우
여기서 단일 노드는 패리티가 전혀 없는 드라이브 1개를 의미합니다. MinIO 자체 문서에서는 이 구성을 테스트와 가용성이 필요하지 않은 소규모 워크로드에 적합한 구성으로 설명합니다. 배포 환경 내부에 두 번째 복사본이 없으므로 모든 객체의 내구성은 VPS 디스크 1개의 내구성과 같습니다. 버킷 복제와 객체 잠금을 비롯해 분산 삭제 코딩 백엔드를 전제로 하는 기능은 다중 드라이브 배포에 해당합니다. 따라서 이 구성에서 누구에게도 변경 불가능한 보존 정책을 제공한다고 약속해서는 안 됩니다.
다른 리전에 있는 두 번째 VPS를 restic 대상 저장소로 사용하기에 적합합니다. 버킷을 잃어도 다시 빌드하면 되고 그 이상의 문제가 발생하지 않는 개발 작업과 CI 아티팩트의 S3 엔드포인트로도 적합합니다. 소규모 애플리케이션의 사용자 업로드에도 사용할 수 있습니다. 단, 복구 계획을 직접 관리하고 실제로 복원을 테스트해야 합니다.
계약이나 규제 기관에서 객체 잠금 또는 다중 리전 내구성을 요구하는 경우에는 관리형 S3를 선택합니다. 디스크가 가득 찼다는 이유로 03:00에 호출되는 담당자가 되고 싶지 않은 경우에도 관리형 S3를 선택하는 편이 좋습니다. 동결된 빌드도 이를 선택해야 하는 정직한 이유입니다. 2026년 7월 기준으로 사전 컴파일된 커뮤니티 바이너리는 2025년 9월에 만들어졌으며 수정 사항을 받지 않습니다. 따라서 이를 실행하면 이러한 조건을 받아들여야 합니다. 또는 소스에서 직접 빌드하고 프로젝트 변경 사항을 스스로 계속 반영해야 합니다.
자주 언급되는 한 가지 경계가 있습니다. 객체 스토리지는 데이터베이스가 아닙니다. 모든 쓰기 작업은 전체 객체를 교체하므로 S3 버킷에 있는 활성 SQL 파일은 느리고 안전하지 않습니다. 데이터베이스는 로컬 디스크에 두고 대신 버킷에 백업합니다. VPS에서 SQLite를 운영 환경으로 실행하기에서 이러한 분리 방식을 설명합니다.
실패 유형과 표시되는 메시지
systemctl enable --now 직후에 장치가 실패합니다. journalctl -u minio -n 30 --no-pager을 읽습니다. Failed to load environment files: No such file or directory은(는) /etc/default/minio이(가) 누락되었거나 장치에서 해당 경로의 철자가 잘못되었다는 의미입니다. permission denied으로 끝나는 메시지는 데이터 디렉터리를 서비스 계정이 쓸 수 없다는 의미이므로, stat -c '%U' /var/lib/minio/data의 출력이 minio-user인지 확인합니다.
minioadmin:minioadmin이(가) 여전히 로그인됩니다. 환경 파일이 프로세스에 전달되지 않았습니다. 장치에 EnvironmentFile=/etc/default/minio이(가) 포함되어 있는지 확인하고, sudo systemctl daemon-reload을(를) 실행한 다음 서비스를 다시 시작합니다. MinIO는 시작할 때 root 자격 증명을 한 번만 읽으므로, 다시 시작하지 않고 해당 파일을 편집해도 변경되지 않습니다.
시작 시 Address already in use. 다른 프로세스가 port 9000을 사용하고 있습니다. MinIO의 port를 변경하기 전에 sudo ss -ltnp | grep :9000로 해당 프로세스를 찾습니다.
proxy를 통해 1 MB를 초과하는 업로드가 실패합니다. nginx가 413 Request Entity Too Large에 응답했으며 MinIO에는 요청이 전달되지 않았습니다. server block에 client_max_body_size 0을(를) 설정합니다.
SignatureDoesNotMatch. secret key가 잘못되었거나 client와 MinIO 사이의 무언가가 서명이 포함하는 Host header를 다시 작성했습니다.
RequestTimeTooSkewed. client 또는 server의 시간이 잘못되었습니다. 모든 S3 요청에는 timestamp가 포함되며 15분 범위를 벗어나면 거부됩니다. timedatectl을(를) 확인하고 time synchronisation이 활성 상태인지 확인합니다.
존재하는 것을 알고 있는 bucket에서 Access Denied. key의 범위가 다른 bucket으로 설정되어 있습니다. mc admin policy info local restic-rw로 policy가 실제로 허용하는 항목을 출력하고 resource 줄의 bucket 이름을 비교합니다.
FAQ
단일 노드 MinIO만으로 실제 백업에 충분합니까?
보호할 데이터와 다른 시스템에서 실행되는 restic 대상 저장소로는 충분합니다. 그러나 유일한 복사본으로 사용하기에는 충분하지 않습니다. 단일 드라이브 배포에는 패리티가 전혀 없으므로 MinIO 내부에 두 번째 복사본이 없습니다. VPS 디스크에서 데이터가 손실되면 객체도 사라집니다. 다른 위치에 두 번째 대상을 유지하고, 프로세스가 정상적으로 작동하는지 확인할 수 있도록 두 대상에서 각각 최소 1회 복원하십시오.
MinIO의 체크섬 파일에서 sha256sum -c이 실패하는 이유는 무엇입니까?
해당 파일에서 해시 뒤에 있는 레이블은 릴리스 이름인 minio.RELEASE.2025-09-07T16-13-09Z을 지정하지만, 다운로드한 파일의 일반적인 이름은 minio이기 때문입니다. sha256sum -c은 체크섬 파일에 적힌 이름의 파일을 찾지만 해당 파일을 찾지 못해 No such file or directory 및 WARNING: 1 listed file could not be read을 보고합니다. 다운로드 자체에는 문제가 없습니다. 해시 문자열을 직접 비교하고 레이블은 무시하십시오. 레이블에는 보안상 의미가 없습니다.
MinIO 관리자 웹 콘솔은 어디로 갔습니까?
MinIO는 2025년 5월 커뮤니티 에디션 콘솔에서 관리 기능을 제거하고 웹 인터페이스에 객체 브라우저만 남겼습니다. 이제 mc 클라이언트를 사용해 mc admin user add 및 mc admin policy attach와 같은 명령으로 버킷과 사용자를 관리합니다. 이는 우회 방법이 아니라 커뮤니티 에디션에서 지원되는 방식입니다. 따라서 이 가이드에서는 모든 작업을 명령줄에서 수행합니다.
restic이 MinIO를 S3 백엔드로 사용하도록 지정하려면 어떻게 합니까?
AWS_ACCESS_KEY_ID 및 AWS_SECRET_ACCESS_KEY을 MinIO 액세스 키와 해당 비밀 키로 설정한 다음, s3:https://s3.example.com/restic 형식의 저장소 문자열을 사용합니다. 여기서 마지막 경로 요소는 버킷 이름입니다. 키 하나의 버킷 범위에는 버킷 생성 권한이 없으므로 먼저 mc mb으로 버킷을 생성하십시오. restic은 업로드 전에 자체 저장소 암호로 모든 데이터를 암호화합니다. 따라서 MinIO에는 암호문만 저장되며 파일 내용은 전혀 노출되지 않습니다.
MinIO를 nginx 뒤에서 실행해야 합니까?
클라이언트가 같은 시스템에 있지 않다면 TLS (transport layer security)가 필요합니다. S3 자격 증명과 객체 데이터가 모두 요청 내부를 통해 전송되기 때문입니다. port 443에서 인증서를 사용하는 프록시를 실행하는 것이 이를 구현하는 가장 간단한 방법입니다. certbot에서 발급한 인증서를 사용하면 인증서 갱신을 MinIO와 분리할 수 있습니다. --certs-dir을 public.crt 및 private.key이 있는 디렉터리로 지정해 MinIO가 직접 TLS를 종료하도록 구성할 수도 있습니다. 그러나 이 경우 서비스 계정에 갱신된 private key에 대한 읽기 권한을 부여해야 하므로, 같은 결과를 얻기 위해 추가 작업이 필요합니다.