sudo 권한, 현재 SSH 세션과 별도 콘솔 복구 경로
OBJECT STORAGE · 설치·설정 레시피
MinIO AIStor Free·SNMD·TLS 구성
현재 지원되는 MinIO AIStor Free를 Ubuntu에 설치하고 유효 라이선스·단일 노드 다중 드라이브(SNMD)·systemd·조직 CA TLS를 구성합니다. Free의 무고가용성·무복제 범위와 별도 장애 도메인 백업·복원 기준까지 검증합니다.BEFORE YOU START
시작 전에 준비하세요
AIStor Free Agreement 검토와 SUBNET에서 발급받은 유효한 Free 라이선스 파일
AIStor 전용으로 지속 마운트된 동일 용량 드라이브들과 검증된 /etc/fstab 매핑
내부 CA 또는 공인 CA가 발급한 서버 인증서·개인 키·CA 체인과 사설 DNS SAN
루트 자격 증명과 애플리케이션 키를 저장할 비밀 저장소, 별도 장애 도메인 객체 백업·복구 계획
권장 대상 내부 S3 호환 객체 저장소를 systemd 서비스로 구성하고 TLS·권한·복구 기준까지 운영하려는 개발자·운영자
FOLLOW THE RECIPE
8단계 구성·점검 레시피
배포 토폴로지와 호스트 자원 확인
AIStor Free는 단일 노드 단일 드라이브 또는 단일 노드 다중 드라이브(SNMD)만 허용합니다. 분산 다중 노드, site·bucket·batch replication, SLA·SLO가 필요한 업무는 이 레시피 대상이 아니며 Enterprise 설계 검토로 전환합니다.
cat /etc/os-release
uname -r
dpkg --print-architecturelscpu
free -hlsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS,MODEL,SERIALfindmnt --real --output TARGET,SOURCE,FSTYPE,OPTIONS- AIStor Free Agreement와 단일 노드·기능 제한을 검토하고 업무가 이를 수용한다.
- 모든 MinIO 드라이브가 같은 용량과 성능 등급이며 고유 UUID로 지속 마운트된다.
- 노드 장애에 대비해 제품 내 replication이 아닌 별도 실패 영역의 독립 백업과 복원 계획이 있다.
Free의 SNMD는 노드 장애·사이트 장애를 견디지 못하고 내장 replication 기능도 제공하지 않습니다. 여러 디렉터리를 같은 물리 디스크에 만들면 드라이브 장애 내성도 생기지 않습니다.
기존 데이터·마운트·포트와 인증서를 읽기 전용으로 점검합니다.
전용 마운트·기존 데이터·인증서 점검
지정 드라이브는 AIStor가 독점 관리해야 합니다. 기존 패키지·내용·배포 흔적이 있으면 신규 초기화를 중단하고 공식 업그레이드 또는 원래 토폴로지 복구 절차로 전환합니다. SUBNET 라이선스는 내용 출력 없이 존재와 접근 통제만 확인합니다.
sudo bash -euo pipefail -c 'targets=(/mnt/minio-1 /mnt/minio-2 /mnt/minio-3 /mnt/minio-4); physical_disks=(); for target in "${targets[@]}"; do runtime_source=$(findmnt --evaluate -n -o SOURCE --target "$target"); fstab_source=$(findmnt --fstab --evaluate -n -o SOURCE --target "$target"); case "$runtime_source:$fstab_source" in /dev/*:/dev/*) ;; *) exit 1;; esac; case "$runtime_source:$fstab_source" in *"["*) exit 1;; esac; runtime_real=$(readlink -f -- "$runtime_source"); fstab_real=$(readlink -f -- "$fstab_source"); test -b "$runtime_real"; test "$runtime_real" = "$fstab_real"; test "$(findmnt -n -o FSTYPE --target "$target")" = xfs; test "$(findmnt --fstab --evaluate -n -o FSTYPE --target "$target")" = xfs; fstab_options=$(findmnt --fstab --evaluate -n -o OPTIONS --target "$target"); case ",$fstab_options," in *,nofail,*) exit 1;; esac; target_disks=(); while read -r ancestor type; do if test "$type" = disk; then target_disks+=("$ancestor"); fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$runtime_real" | sort -u); test "${#target_disks[@]}" -eq 1; disk=${target_disks[0]}; leaf_devices=(); while read -r descendant; do descendant_real=$(readlink -f -- "$descendant"); test -b "$descendant_real"; if test "$(lsblk -r -n -p -o NAME -- "$descendant_real" | wc -l)" -eq 1; then leaf_devices+=("$descendant_real"); fi; done < <(lsblk -r -n -p -o NAME -- "$disk" | sort -u); test "${#leaf_devices[@]}" -eq 1; test "${leaf_devices[0]}" = "$runtime_real"; while read -r mounted_source mounted_target; do case "$mounted_source" in /dev/*) ;; *) continue;; esac; mounted_base=${mounted_source%%\[*}; mounted_real=$(readlink -f -- "$mounted_base"); belongs=false; while read -r ancestor type; do if test "$type" = disk && test "$ancestor" = "$disk"; then belongs=true; fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$mounted_real" | sort -u); if test "$belongs" = true; then test "$mounted_target" = "$target"; fi; done < <(findmnt --real -r -n -o SOURCE,TARGET); while read -r swap_source; do test -n "$swap_source" || continue; swap_real=$(readlink -f -- "$swap_source"); while read -r ancestor type; do if test "$type" = disk && test "$ancestor" = "$disk"; then exit 1; fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$swap_real" | sort -u); done < <(swapon --show=NAME --noheadings --raw); physical_disks+=("$disk"); done; test "$(printf "%s\n" "${physical_disks[@]}" | sort -u | wc -l)" -eq 4'네 대상이 모두 마운트되어 있고 runtime SOURCE와 fstab evaluated SOURCE가 같은 블록 장치이며 양쪽 모두 XFS여야 합니다. 각 LVM·DM·파티션의 전체 상위 계보를 따라 최하위 TYPE=disk가 정확히 하나인지 확인하고, 네 디스크가 서로 다르며 미마운트 sibling 파티션·LV, 다른 블록 마운트·swap이 없는 전용 장치이고 fstab에 nofail이 없을 때만 성공합니다. bind mount·RAID·multipath·같은 디스크의 여러 LV·원격 파일시스템은 이 SNMD 레시피에서 차단합니다.df -hT /mnt/minio-1 /mnt/minio-2 /mnt/minio-3 /mnt/minio-4sudo find /mnt/minio-1 /mnt/minio-2 /mnt/minio-3 /mnt/minio-4 -mindepth 1 -maxdepth 1 -print -quit출력이 있으면 신규 배포를 중단하고 기존 데이터의 소유 팀과 배포 구성을 확인합니다. 내용을 직접 수정하지 않습니다.sudo ss -ltnp | grep -E ':(9000|9001) '
if systemctl cat minio.service >/dev/null 2>&1; then systemctl status minio.service --no-pager; exit 1; fi
if dpkg-query -W -f='${Status} ${Version}\n' aistor; then exit 1; fi
if dpkg-query -W -f='${Status} ${Version}\n' minio; then exit 1; fiaistor와 minio 두 패키지 이름을 모두 검사합니다. 하나라도 설치되어 있거나 minio.service가 기존 배포로 존재하면 신규 설치를 중단합니다.test -s <MINIO_AISTOR_FREE_LICENSE_FROM_SUBNET>
stat -c '%a %U:%G %n' <MINIO_AISTOR_FREE_LICENSE_FROM_SUBNET>라이선스 토큰 자체를 터미널·티켓·명령 인자에 출력하지 않습니다. 발급 조직과 Free 플랜 여부는 SUBNET에서 확인합니다.openssl verify -CAfile <MINIO_CA_CERT> <MINIO_SERVER_CERT>
openssl x509 -in <MINIO_SERVER_CERT> -noout -subject -issuer -dates -ext subjectAltName
openssl x509 -in <MINIO_SERVER_CERT> -pubkey -noout | openssl sha256
openssl pkey -in <MINIO_SERVER_KEY_PEM> -pubout | openssl sha256
openssl pkey -in <MINIO_SERVER_KEY_PEM> -check -noout인증서와 개인 키의 공개키 SHA-256 출력 두 값이 같아야 합니다. 키 내용을 출력하지 않습니다.- 각 경로는 서로 다른 전용 물리 장치에 XFS로 마운트되고, 지속 fstab 항목이 있으며 로컬 nofail이 없다.
- 기존 내용이 있으면 신규 배포를 중단했다.
- 기존 minio 패키지·서비스가 있으면 신규 절차를 중단하고 배포 소유자와 버전을 확인했다.
- 9000·9001 포트가 비어 있다.
- SUBNET에서 받은 유효한 AIStor Free 라이선스 파일이 준비되어 있고 비밀로 취급된다.
- 인증서 SAN에 <MINIO_PRIVATE_DNS>가 있고 CA·개인 키 일치 검증이 성공한다.
마운트가 빠진 상태로 서비스를 시작하면 루트 파일시스템에 데이터가 쓰일 수 있습니다. 모든 findmnt 확인이 성공하기 전에는 시작하지 않습니다.
공식 다운로드 페이지에서 고정 버전 패키지와 체크섬을 확보합니다.
공식 AIStor Server·Client 체크섬 검증과 설치
AIStor 공식 릴리스 API와 Client 릴리스 인덱스가 제공하는 아키텍처별 버전 URL·SHA-256을 변경 승인에 고정합니다. 기존 Community Edition 경로가 아니라 /aistor/minio/release의 Server DEB와 /aistor/mc/release의 Client 바이너리인지 확인합니다.
sudo apt-get install ca-certificates curl gnupg jq unzipcurl --proto '=https' --tlsv1.2 --fail --location --output /tmp/aistor-release.json https://dl.min.io/api/releases/aistor/latest
jq '.[0] | {product, release_date, downloads}' /tmp/aistor-release.json검토자는 호스트 아키텍처의 versioned DEB URL과 같은 항목의 checksum을 변경 기록에 옮깁니다. API 응답을 셸 명령으로 직접 실행하지 않습니다.curl --proto '=https' --tlsv1.2 --fail --location --output /tmp/minio.deb '<APPROVED_VERSIONED_AISTOR_DEB_URL_FROM_RELEASE_API>'printf '%s %s
' '<MATCHING_AISTOR_DEB_SHA256_FROM_RELEASE_API>' /tmp/minio.deb | sha256sum --check -URL과 SHA-256은 같은 API 릴리스·아키텍처 항목에서 복사하고 변경 기록에 남깁니다.dpkg-deb --field /tmp/minio.deb Package Version Architecture
sudo test ! -e /root/aistor-change/<CHANGE_ID>
sudo install -d -o root -g root -m 0700 /root/aistor-change/<CHANGE_ID>
sudo bash -eu -c 'pkg=$(dpkg-deb --field /tmp/minio.deb Package); case "$pkg" in aistor|minio) ;; *) exit 1;; esac; if dpkg-query -W aistor >/dev/null 2>&1; then exit 1; fi; if dpkg-query -W minio >/dev/null 2>&1; then exit 1; fi; printf "aistor=absent\nminio=absent\n" > /root/aistor-change/<CHANGE_ID>/packages.before; printf "%s\n" "$pkg" > /root/aistor-change/<CHANGE_ID>/installed-package-name; dpkg-deb --field /tmp/minio.deb Version > /root/aistor-change/<CHANGE_ID>/installed-package-version; chmod 0600 /root/aistor-change/<CHANGE_ID>/*'DEB 내부의 실제 Package 필드가 승인된 aistor 또는 minio인지 강제 확인하고, 두 이름이 모두 사전 미설치임을 다시 확인합니다. 실제 패키지 이름·버전을 root 전용 변경 기록에 저장해야 다음 롤백이 정확한 신규 패키지만 대상으로 삼습니다.sudo dpkg -i /tmp/minio.debcurl --proto '=https' --tlsv1.2 --fail --location --output /tmp/aistor-mc '<APPROVED_VERSIONED_AISTOR_MC_URL_FROM_RELEASE_INDEX>'printf '%s %s
' '<MATCHING_AISTOR_MC_SHA256_FROM_RELEASE_INDEX>' /tmp/aistor-mc | sha256sum --check -서버 릴리스 날짜와 가까운 Client 버전을 선택하고, versioned mc URL과 같은 릴리스·아키텍처의 .sha256sum 값을 사용합니다.sudo install -o root -g root -m 0755 /tmp/aistor-mc /usr/local/bin/mcminio --version
mc --version
sudo sh -c 'pkg=$(cat /root/aistor-change/<CHANGE_ID>/installed-package-name); dpkg-query -W -f="\${Status} \${Package} \${Version}\n" "$pkg"'
systemctl cat minio.service
id minio-user- 고정 URL이 dl.min.io/aistor/minio/release의 AIStor DEB이고 SHA-256이 같은 릴리스에 속한다.
- sha256sum 검증이 OK다.
- dpkg-deb Package가 승인된 aistor 또는 minio이며 실제 신규 패키지 이름·버전과 사전 미설치 상태를 root 변경 기록에 남겼다.
- minio --version이 AIStor Free를 지원하는 RELEASE.2025-12-20 이상이다.
- mc --version이 Free 라이선스 표시를 지원하는 RELEASE.2025-12-19 이상이고 Server 릴리스 날짜와 가깝다.
- 패키지가 minio 서비스와 minio-user 실행 계정을 설치했다.
- 설치 직후 외부 포트를 열지 않았다.
체크섬이 다르면 설치하지 말고 릴리스 메타데이터와 공급망을 확인합니다. AIStor가 아닌 구형 Community Edition DEB나 버전 없는 파일을 운영에 섞지 않습니다.
전용 경로 권한, 환경 파일과 TLS 인증서를 구성합니다.
라이선스·전용 경로·systemd·TLS 구성
SUBNET 라이선스를 /opt/minio/minio.license에 배치하고, 공식 TLS 경로 /opt/minio/certs와 SNMD 볼륨을 구성합니다. 라이선스·개인 키·루트 자격 증명은 명령 인자나 로그에 노출하지 않습니다.
date -u +%Y%m%dT%H%M%SZsudo test ! -f /etc/default/minio || sudo cp --preserve=all --no-clobber /etc/default/minio /etc/default/minio.<BACKUP_SUFFIX>.baksudo install -d -o minio-user -g minio-user -m 0750 /mnt/minio-1/minio /mnt/minio-2/minio /mnt/minio-3/minio /mnt/minio-4/miniosudo install -d -o minio-user -g minio-user -m 0700 /opt/minio
sudo install -o minio-user -g minio-user -m 0600 <MINIO_AISTOR_FREE_LICENSE_FROM_SUBNET> /opt/minio/minio.license라이선스 내용은 출력하지 않습니다. 발급 파일 원본도 조직 비밀 저장소와 보존 정책에 따라 보호합니다.sudo install -d -o minio-user -g minio-user -m 0700 /opt/minio/certs /opt/minio/certs/CAssudo install -o minio-user -g minio-user -m 0644 <MINIO_PUBLIC_CERT_FULL_CHAIN_PEM> /opt/minio/certs/public.crt
sudo install -o minio-user -g minio-user -m 0600 <MINIO_SERVER_KEY_PEM> /opt/minio/certs/private.key
sudo install -o minio-user -g minio-user -m 0644 <MINIO_TRUSTED_REMOTE_CA_PEM> /opt/minio/certs/CAs/organization-ca.crtAIStor는 PEM 인증서·키만 지원합니다. 암호화된 키는 PKCS#1 추가 조건이 있으므로 이 기본 레시피에서는 승인된 비밀 전달 경로와 0600 권한의 평문 PEM 키를 사용합니다.sudoedit /etc/default/miniosudo chown root:root /etc/default/minio
sudo chmod 600 /etc/default/minioMINIO_LICENSE="/opt/minio/minio.license"
MINIO_ROOT_USER="<MINIO_ROOT_USER>"
MINIO_ROOT_PASSWORD="<MINIO_ROOT_PASSWORD_FROM_SECRET_MANAGER>"
MINIO_VOLUMES="https://<MINIO_PRIVATE_DNS>:9000/mnt/minio-{1...4}/minio"
MINIO_OPTS="--address <MINIO_PRIVATE_IP>:9000 --console-address <MINIO_PRIVATE_IP>:9001 --certs-dir /opt/minio/certs"자리표시자를 실제 값으로 교체합니다. 루트 비밀번호는 충분히 긴 고유 난수를 비밀 저장소에서 직접 붙여넣고 파일·화면·백업 접근 권한을 제한합니다.- MINIO_LICENSE가 root가 아닌 /opt/minio/minio.license를 가리키고 minio-user만 읽을 수 있다.
- 모든 SNMD 볼륨은 서로 다른 마운트의 /minio 하위 경로이며 minio-user만 관리한다.
- 환경 파일은 root만 읽을 수 있으며 Git·티켓·채팅에 복사하지 않는다.
- 기본 public.crt는 외부 클라이언트용 완전한 체인이며 private.key는 minio-user만 읽는다.
- API와 Console은 실제 사설 IP에만 바인딩된다.
볼륨 경로·순서·호스트 이름은 배포 정체성의 일부입니다. 라이선스가 없거나 유효하지 않으면 최신 AIStor는 관리 API·Console만 남고 모든 S3 작업을 차단하는 offline 모드로 시작할 수 있습니다.
마운트와 환경 파일을 다시 확인한 뒤 서비스를 시작합니다.
systemd 시작과 드라이브 온라인 확인
모든 마운트와 라이선스·TLS 파일 권한을 재확인한 뒤 서비스를 시작합니다. 드라이브가 오프라인이거나 license-readonly·offline 상태이면 운영 트래픽을 열지 않습니다.
sudo bash -euo pipefail -c 'targets=(/mnt/minio-1 /mnt/minio-2 /mnt/minio-3 /mnt/minio-4); physical_disks=(); for target in "${targets[@]}"; do runtime_source=$(findmnt --evaluate -n -o SOURCE --target "$target"); fstab_source=$(findmnt --fstab --evaluate -n -o SOURCE --target "$target"); case "$runtime_source:$fstab_source" in /dev/*:/dev/*) ;; *) exit 1;; esac; case "$runtime_source:$fstab_source" in *"["*) exit 1;; esac; runtime_real=$(readlink -f -- "$runtime_source"); fstab_real=$(readlink -f -- "$fstab_source"); test -b "$runtime_real"; test "$runtime_real" = "$fstab_real"; test "$(findmnt -n -o FSTYPE --target "$target")" = xfs; test "$(findmnt --fstab --evaluate -n -o FSTYPE --target "$target")" = xfs; fstab_options=$(findmnt --fstab --evaluate -n -o OPTIONS --target "$target"); case ",$fstab_options," in *,nofail,*) exit 1;; esac; target_disks=(); while read -r ancestor type; do if test "$type" = disk; then target_disks+=("$ancestor"); fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$runtime_real" | sort -u); test "${#target_disks[@]}" -eq 1; disk=${target_disks[0]}; leaf_devices=(); while read -r descendant; do descendant_real=$(readlink -f -- "$descendant"); test -b "$descendant_real"; if test "$(lsblk -r -n -p -o NAME -- "$descendant_real" | wc -l)" -eq 1; then leaf_devices+=("$descendant_real"); fi; done < <(lsblk -r -n -p -o NAME -- "$disk" | sort -u); test "${#leaf_devices[@]}" -eq 1; test "${leaf_devices[0]}" = "$runtime_real"; while read -r mounted_source mounted_target; do case "$mounted_source" in /dev/*) ;; *) continue;; esac; mounted_base=${mounted_source%%\[*}; mounted_real=$(readlink -f -- "$mounted_base"); belongs=false; while read -r ancestor type; do if test "$type" = disk && test "$ancestor" = "$disk"; then belongs=true; fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$mounted_real" | sort -u); if test "$belongs" = true; then test "$mounted_target" = "$target"; fi; done < <(findmnt --real -r -n -o SOURCE,TARGET); while read -r swap_source; do test -n "$swap_source" || continue; swap_real=$(readlink -f -- "$swap_source"); while read -r ancestor type; do if test "$type" = disk && test "$ancestor" = "$disk"; then exit 1; fi; done < <(lsblk -s -r -n -p -o NAME,TYPE -- "$swap_real" | sort -u); done < <(swapon --show=NAME --noheadings --raw); physical_disks+=("$disk"); done; test "$(printf "%s\n" "${physical_disks[@]}" | sort -u | wc -l)" -eq 4'사전 검사 뒤 마운트가 바뀔 수 있으므로 서비스 시작 직전에 동일한 하드 게이트를 다시 통과해야 합니다.sudo namei -l /opt/minio/minio.license /opt/minio/certs/private.key /opt/minio/certs/public.crtsudo systemctl enable --now minio.servicesystemctl status minio.service --no-pagersudo journalctl -u minio.service -n 120 --no-pagersudo ss -ltnp | grep -E ':(9000|9001) '- 서비스가 active와 enabled 상태다.
- 로그의 Online·Offline 드라이브 수가 설계와 일치한다.
- 로그에 license-readonly, offline, no valid license 경고가 없다.
- API와 Console이 지정한 사설 IP에서만 리슨한다.
- 기본 자격 증명 경고가 없다.
서비스가 active여도 유효 라이선스가 없으면 S3가 차단될 수 있습니다. 드라이브·라이선스 상태 중 하나라도 비정상이면 ACL을 열지 말고, 파일을 직접 수정하지 않은 채 원인을 복구합니다.
CA 검증 건강 확인 후 관리자와 S3 클라이언트 CIDR을 각각 허용합니다.
TLS·Free 라이선스·S3 읽기쓰기 검증
TLS 검증 뒤 AIStor Client로 드라이브와 Free 라이선스 상태를 확인하고 승인된 테스트 버킷에서 실제 S3 쓰기·읽기를 검증합니다. 모두 정상일 때만 API와 Console CIDR을 분리해 엽니다.
curl --fail --silent --show-error --cacert <MINIO_CA_CERT> https://<MINIO_PRIVATE_DNS>:9000/minio/health/liveinstall -d -m 0700 "$HOME/.mc/certs/CAs"
install -m 0644 <APPROVED_MINIO_CA_CERT> "$HOME/.mc/certs/CAs/organization-ca.crt"
cmp --silent <APPROVED_MINIO_CA_CERT> "$HOME/.mc/certs/CAs/organization-ca.crt"
openssl x509 -in <APPROVED_MINIO_CA_CERT> -noout -fingerprint -sha256
openssl x509 -in "$HOME/.mc/certs/CAs/organization-ca.crt" -noout -fingerprint -sha256
stat -c '%a %U:%G %n' "$HOME/.mc/certs" "$HOME/.mc/certs/CAs" "$HOME/.mc/certs/CAs/organization-ca.crt"mc를 실행할 전용 관리 계정으로 수행합니다. 오프라인 승인 경로의 public CA 인증서를 정확히 복사하고 fingerprint를 변경 기록과 대조합니다. 개인 키를 넣거나 peer 인증서를 즉석 승인하는 TOFU, --insecure를 사용하지 않습니다.read -rp 'One-time root access key: ' AISTOR_ROOT_ACCESS_KEY
read -rsp 'One-time root secret key: ' AISTOR_ROOT_SECRET_KEY
printf '
'
mc alias set root-bootstrap https://<MINIO_PRIVATE_DNS>:9000 "$AISTOR_ROOT_ACCESS_KEY" "$AISTOR_ROOT_SECRET_KEY"
unset AISTOR_ROOT_ACCESS_KEY AISTOR_ROOT_SECRET_KEY
mc admin info root-bootstrap신규 배포에는 아직 독립 관리자가 없으므로 보호된 단일 사용자 bootstrap 콘솔에서만 루트 자격을 한 번 사용합니다. alias set은 secret을 프로세스 인자로 전달하므로 다른 사용자의 process inspection과 셸 기록을 차단하고, 서버 측 root API를 끈 뒤 별칭을 제거합니다.read -rp 'Dedicated recovery admin access key: ' AISTOR_ADMIN_ACCESS_KEY
read -rsp 'Dedicated recovery admin secret key: ' AISTOR_ADMIN_SECRET_KEY
printf '
'
mc admin user add root-bootstrap "$AISTOR_ADMIN_ACCESS_KEY" "$AISTOR_ADMIN_SECRET_KEY"
mc admin policy attach root-bootstrap consoleAdmin --user "$AISTOR_ADMIN_ACCESS_KEY"
mc admin user info root-bootstrap "$AISTOR_ADMIN_ACCESS_KEY"
mc admin policy entities root-bootstrap --user "$AISTOR_ADMIN_ACCESS_KEY"
mc alias set aistor-admin https://<MINIO_PRIVATE_DNS>:9000 "$AISTOR_ADMIN_ACCESS_KEY" "$AISTOR_ADMIN_SECRET_KEY"
unset AISTOR_ADMIN_ACCESS_KEY AISTOR_ADMIN_SECRET_KEY
mc admin info aistor-adminconsoleAdmin은 root를 대체할 수 있는 최소 내장 전체 관리자 역할이지만 권한 자체는 광범위합니다. 복구 관리자를 앱과 분리하고, 일상 업무는 iamAdmin·infraAdmin·securityAuditAdmin 또는 버킷별 정책 계정으로 더 좁힙니다. root에서 파생한 secondary key는 root_access=off 때 함께 비활성화되므로 대체 관리자로 사용하지 않습니다.mc license info aistor-admin화면 캡처·리다이렉션·tee·원문 로그 저장을 금지한 보호 콘솔에서만 실행합니다. API Key·License ID·조직명은 기록하지 않거나 마스킹하고, 증적에는 Plan=Free·Expiry=N/A·상태(normal/read-only/offline)만 수기로 남깁니다.mc mb --ignore-existing aistor-admin/<APPROVED_TEST_BUCKET>
printf 'aistor-s3-verification
' | mc pipe aistor-admin/<APPROVED_TEST_BUCKET>/<CHANGE_ID>.txt
mc cat aistor-admin/<APPROVED_TEST_BUCKET>/<CHANGE_ID>.txt격리된 테스트 버킷과 고유 변경 ID를 사용합니다. 출력이 입력과 정확히 같아야 하며 증적·정리 정책에 따라 객체를 관리합니다.mc admin config set aistor-admin api root_access=off
mc admin service restart aistor-admin --wait
mc admin info aistor-admin
mc ready aistor-admin대체 관리자의 admin·S3 시험이 모두 성공한 뒤 실행합니다. MINIO_ROOT_USER·MINIO_ROOT_PASSWORD는 노드 내부 통신에 계속 필요할 수 있으므로 파일에서 삭제하지 않고 공개 API 인증만 끕니다.mc admin info root-bootstrap실패해야 통과입니다. 성공하면 해당 AIStor 릴리스에서 root_access 의미를 공급사 문서와 재확인하고 ACL을 열지 않습니다.mc ls root-bootstrap실패해야 통과입니다. root의 Admin·S3 호출이 모두 거부되고 aistor-admin은 성공해야 합니다.mc alias remove root-bootstrap
stat -c '%a %U:%G %n' "$HOME/.mc/config.json"서버 측 root API 거부와 대체 관리자 성공을 확인한 뒤에만 로컬 root 별칭을 삭제합니다. 루트 primary credential은 mc admin user/accesskey 명령으로 삭제할 수 있는 IAM 키가 아닙니다.sudo ufw allow from <S3_CLIENT_CIDR> to <MINIO_PRIVATE_IP> port 9000 proto tcpsudo ufw allow from <ADMIN_CIDR> to <MINIO_PRIVATE_IP> port 9001 proto tcp현재 SSH 세션·콘솔과 동일한 상위 ACL 제한을 유지한 채 적용합니다.sudo ufw status numbered- CA와 호스트 이름 검증을 유지한 health 요청이 성공한다.
- 승인 CA를 사전 배치하고 fingerprint를 대조했으며 TOFU나 --insecure를 사용하지 않았다.
- 라이선스 증적에는 Plan·Expiry·상태만 남고 API Key·License ID·조직명 원문이 없다.
- 독립 consoleAdmin 관리자가 Admin·S3 작업에 성공하고 root bootstrap은 Admin·S3 모두 거부되며 로컬 별칭이 삭제됐다.
- 승인 테스트 객체의 쓰기·읽기 내용이 정확히 일치한다.
- S3 API와 Console은 서로 다른 승인 CIDR만 접근한다.
- mc ready와 admin info에서 모든 드라이브가 온라인이다.
- 허용되지 않은 네트워크에서는 9000·9001에 접근할 수 없다.
health가 성공해도 라이선스가 offline이면 모든 S3 작업이 403으로 차단됩니다. mc license info와 실제 객체 시험 중 하나라도 실패하면 ACL을 열지 않고 라이선스·볼륨·권한을 복구합니다.
루트 계정 사용을 줄이고 Free 범위에 맞는 독립 백업·복원 운영을 마감합니다.
최소 권한·Free 제한·독립 백업 마감
root API는 비활성 상태로 유지하고 앱별 최소 정책·Access Key를 발급합니다. AIStor Free에는 site·bucket·batch replication이 없으므로 쓰기를 정지한 고유 복구점에 현재 객체를 독립 복사하고, 서버 설정·버킷·IAM을 별도 내보낸 뒤 빈 격리 대상에 실제 복원해 내용 SHA-256을 확인합니다.
mc admin user ls aistor-adminmc admin policy ls aistor-adminmc admin policy entities aistor-admin <APP_POLICY>mc admin info aistor-adminbash -euo pipefail -c 'install -d -m 0700 "$HOME/.mc/certs/CAs"; install -m 0644 <APPROVED_BACKUP_CA_CERT> "$HOME/.mc/certs/CAs/backup-ca.crt"; install -m 0644 <APPROVED_ISOLATED_CA_CERT> "$HOME/.mc/certs/CAs/isolated-ca.crt"; cmp --silent <APPROVED_BACKUP_CA_CERT> "$HOME/.mc/certs/CAs/backup-ca.crt"; cmp --silent <APPROVED_ISOLATED_CA_CERT> "$HOME/.mc/certs/CAs/isolated-ca.crt"; backup_ca_fpr=$(openssl x509 -in "$HOME/.mc/certs/CAs/backup-ca.crt" -noout -fingerprint -sha256 | cut -d= -f2 | tr -d :); isolated_ca_fpr=$(openssl x509 -in "$HOME/.mc/certs/CAs/isolated-ca.crt" -noout -fingerprint -sha256 | cut -d= -f2 | tr -d :); test "$backup_ca_fpr" = "<APPROVED_BACKUP_CA_SHA256_FINGERPRINT_WITHOUT_COLONS>"; test "$isolated_ca_fpr" = "<APPROVED_ISOLATED_CA_SHA256_FINGERPRINT_WITHOUT_COLONS>"; test "https://<MINIO_PRIVATE_DNS>:9000" != "https://<BACKUP_PRIVATE_DNS>:9000"; test "https://<MINIO_PRIVATE_DNS>:9000" != "https://<ISOLATED_PRIVATE_DNS>:9000"; test "https://<BACKUP_PRIVATE_DNS>:9000" != "https://<ISOLATED_PRIVATE_DNS>:9000"'원본·backup·isolated는 DNS URL뿐 아니라 다음 단계에서 확인하는 실제 해석 IP 집합과 승인 leaf 인증서 지문도 모두 달라야 하며, 서로 다른 계정·노드·장애 도메인이어야 합니다.bash -euo pipefail -c 'resolve_ips() { getent ahosts "$1" | while read -r ip remainder; do printf "%s\n" "$ip"; done | sort -u; }; primary_ips=$(resolve_ips <MINIO_PRIVATE_DNS>); backup_ips=$(resolve_ips <BACKUP_PRIVATE_DNS>); isolated_ips=$(resolve_ips <ISOLATED_PRIVATE_DNS>); test -n "$primary_ips"; test -n "$backup_ips"; test -n "$isolated_ips"; test -z "$(comm -12 <(printf "%s\n" "$primary_ips") <(printf "%s\n" "$backup_ips"))"; test -z "$(comm -12 <(printf "%s\n" "$primary_ips") <(printf "%s\n" "$isolated_ips"))"; test -z "$(comm -12 <(printf "%s\n" "$backup_ips") <(printf "%s\n" "$isolated_ips"))"; live_fpr() { host=$1; ca=$2; openssl s_client -connect "$host:9000" -servername "$host" -verify_hostname "$host" -verify_return_error -CAfile "$ca" </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256 | cut -d= -f2 | tr -d :; }; primary_fpr=$(live_fpr <MINIO_PRIVATE_DNS> <APPROVED_MINIO_CA_CERT>); backup_fpr=$(live_fpr <BACKUP_PRIVATE_DNS> <APPROVED_BACKUP_CA_CERT>); isolated_fpr=$(live_fpr <ISOLATED_PRIVATE_DNS> <APPROVED_ISOLATED_CA_CERT>); test "$primary_fpr" = "<APPROVED_PRIMARY_LEAF_SHA256_FINGERPRINT_WITHOUT_COLONS>"; test "$backup_fpr" = "<APPROVED_BACKUP_LEAF_SHA256_FINGERPRINT_WITHOUT_COLONS>"; test "$isolated_fpr" = "<APPROVED_ISOLATED_LEAF_SHA256_FINGERPRINT_WITHOUT_COLONS>"; test "$primary_fpr" != "$backup_fpr"; test "$primary_fpr" != "$isolated_fpr"; test "$backup_fpr" != "$isolated_fpr"'s_client는 CA 체인과 hostname 검증을 모두 유지합니다. 같은 IP 집합 또는 같은 승인 leaf 지문이면 별칭을 만들지 말고 실제 독립 장애 도메인을 다시 준비합니다.read -rp 'Backup access key: ' AISTOR_BACKUP_ACCESS_KEY
read -rsp 'Backup secret key: ' AISTOR_BACKUP_SECRET_KEY
printf '\n'
mc alias set backup https://<BACKUP_PRIVATE_DNS>:9000 "$AISTOR_BACKUP_ACCESS_KEY" "$AISTOR_BACKUP_SECRET_KEY"
unset AISTOR_BACKUP_ACCESS_KEY AISTOR_BACKUP_SECRET_KEY
read -rp 'Isolated restore access key: ' AISTOR_ISOLATED_ACCESS_KEY
read -rsp 'Isolated restore secret key: ' AISTOR_ISOLATED_SECRET_KEY
printf '\n'
mc alias set isolated https://<ISOLATED_PRIVATE_DNS>:9000 "$AISTOR_ISOLATED_ACCESS_KEY" "$AISTOR_ISOLATED_SECRET_KEY"
unset AISTOR_ISOLATED_ACCESS_KEY AISTOR_ISOLATED_SECRET_KEY
mc ready backup
mc ready isolated
mc stat backup/<APPROVED_BACKUP_SENTINEL_OBJECT>
mc stat isolated/<APPROVED_ISOLATED_SENTINEL_OBJECT>
! mc stat backup/<FORBIDDEN_SENTINEL_OBJECT>
! mc stat isolated/<FORBIDDEN_SENTINEL_OBJECT>두 Access Key는 원본 aistor-admin과 다른 계정·비밀 저장소에서 발급하고 recovery bucket 생성·객체 read/write/list에 필요한 범위만 허용합니다. 승인 sentinel은 성공하고 명시한 금지 sentinel은 AccessDenied여야 합니다. secret이 프로세스 인자에 잠시 나타나므로 보호된 단일 사용자 관리 호스트에서만 수행합니다.bash -euo pipefail -c 'umask 077; destination=<SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>; test ! -e "$destination"; install -d -m 0700 "$destination"; test "$(findmnt -n -o FSTYPE --target /dev/shm)" = tmpfs; plaintext_dir=$(mktemp -d /dev/shm/aistor-control-plane.XXXXXX); gnupg_home=$(mktemp -d /dev/shm/aistor-gnupg.XXXXXX); case "$plaintext_dir:$gnupg_home" in /dev/shm/aistor-control-plane.*:/dev/shm/aistor-gnupg.*) ;; *) exit 1;; esac; cleanup() { test "${plaintext_dir#/dev/shm/aistor-control-plane.}" != "$plaintext_dir"; test "${gnupg_home#/dev/shm/aistor-gnupg.}" != "$gnupg_home"; rm -r -- "$plaintext_dir" "$gnupg_home"; }; trap cleanup EXIT HUP INT TERM; recipient_fpr=$(gpg --batch --with-colons --show-keys --fingerprint <APPROVED_RECOVERY_RECIPIENT_PUBLIC_KEY> | grep "^fpr:" | cut -d: -f10 | head -n 1); test "$recipient_fpr" = "<APPROVED_RECOVERY_RECIPIENT_FULL_FINGERPRINT>"; gpg --batch --homedir "$gnupg_home" --import <APPROVED_RECOVERY_RECIPIENT_PUBLIC_KEY>; gpg --batch --homedir "$gnupg_home" --with-colons --list-keys "$recipient_fpr" | grep -q "^pub:"; mc admin config export aistor-admin > "$plaintext_dir/server-config.txt"; (cd "$plaintext_dir" && mc admin cluster bucket export aistor-admin); mc admin cluster iam export aistor-admin --output "$plaintext_dir/admin-iam-info.zip"; test -s "$plaintext_dir/server-config.txt"; unzip -t "$plaintext_dir/cluster-metadata.zip"; unzip -t "$plaintext_dir/admin-iam-info.zip"; (cd "$plaintext_dir" && sha256sum -- server-config.txt cluster-metadata.zip admin-iam-info.zip > "$destination/control-plane-plaintext.SHA256SUMS"); for name in server-config.txt cluster-metadata.zip admin-iam-info.zip; do gpg --batch --yes --homedir "$gnupg_home" --trust-model always --recipient "$recipient_fpr" --output "$destination/$name.gpg" --encrypt "$plaintext_dir/$name"; test -s "$destination/$name.gpg"; done; chmod 0600 "$destination"/*; (cd "$destination" && sha256sum -- *.gpg > control-plane-ciphertext.SHA256SUMS); cleanup; trap - EXIT HUP INT TERM; test ! -e "$plaintext_dir"; test ! -e "$gnupg_home"'세 평문은 검증된 tmpfs에만 만들고 EXIT trap으로 제거합니다. 승인 수신자 공개키의 전체 fingerprint가 변경 기록과 정확히 같아야 암호화하며, 영구 경로에는 GPG 암호문과 평문·암호문 SHA-256 증적만 남깁니다. 서버 환경 root 자격·라이선스 파일·TLS private key는 이 export에 없으므로 별도 승인 공개키 암호화 백업이 필요합니다.bash -euo pipefail -c 'source_dir=<ENCRYPTED_RECOVERY_SET>/<RECOVERY_POINT_UTC>; test "$(findmnt -n -o FSTYPE --target /dev/shm)" = tmpfs; secret_fpr=$(gpg --batch --with-colons --list-secret-keys --fingerprint "<APPROVED_RECOVERY_RECIPIENT_FULL_FINGERPRINT>" | grep "^fpr:" | cut -d: -f10 | head -n 1); test "$secret_fpr" = "<APPROVED_RECOVERY_RECIPIENT_FULL_FINGERPRINT>"; (cd "$source_dir" && sha256sum --check control-plane-ciphertext.SHA256SUMS); restore_dir=$(mktemp -d /dev/shm/aistor-control-restore.XXXXXX); case "$restore_dir" in /dev/shm/aistor-control-restore.*) ;; *) exit 1;; esac; cleanup() { test "${restore_dir#/dev/shm/aistor-control-restore.}" != "$restore_dir"; rm -r -- "$restore_dir"; }; trap cleanup EXIT HUP INT TERM; for name in server-config.txt cluster-metadata.zip admin-iam-info.zip; do gpg --batch --output "$restore_dir/$name" --decrypt "$source_dir/$name.gpg"; done; (cd "$restore_dir" && sha256sum --check "$source_dir/control-plane-plaintext.SHA256SUMS"); unzip -t "$restore_dir/cluster-metadata.zip"; unzip -t "$restore_dir/admin-iam-info.zip"; cleanup; trap - EXIT HUP INT TERM; test ! -e "$restore_dir"'개인 키는 원본 AIStor 관리 호스트가 아니라 승인된 격리 복구 호스트에만 둡니다. 암호문 checksum, 수신자 비밀키 전체 fingerprint, 복호화 평문 checksum, ZIP 구조 검사가 모두 성공해야 복구 가능한 제어면 백업으로 승인합니다. 실제 import는 별도 변경 승인과 빈 격리 환경에서 수행합니다.mc mb backup/recovery-<RECOVERY_POINT_UTC>
mc mirror --dry-run aistor-admin/<APPROVED_SOURCE_BUCKET>/ backup/recovery-<RECOVERY_POINT_UTC>/
mc mirror --overwrite --checksum SHA256 aistor-admin/<APPROVED_SOURCE_BUCKET>/ backup/recovery-<RECOVERY_POINT_UTC>/
mc diff aistor-admin/<APPROVED_SOURCE_BUCKET>/ backup/recovery-<RECOVERY_POINT_UTC>/애플리케이션 쓰기를 먼저 정지하고 고유한 새 bucket 생성이 성공해야 합니다. --remove는 사용하지 않습니다. mc mirror는 원자적 스냅샷이 아니며 최신 객체 상태만 복사합니다. version history는 보존하지 않고 tags 외 메타데이터도 완전히 복사하지 않으며, mc diff는 이름·크기만 비교하므로 다음 SHA-256 검증을 생략할 수 없습니다.test ! -e <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects
install -d -m 0700 <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects
mc mirror --overwrite aistor-admin/<APPROVED_SOURCE_BUCKET>/ <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects/
( cd <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects && find . -type f -print0 | sort -z | xargs -0 -r sha256sum ) > <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects.SHA256SUMS쓰기 정지 상태에서 객체 키별 현재 내용을 로컬 보호 작업 공간으로 내려받아 전수 manifest를 만듭니다. 용량 때문에 전수 검증이 불가능하면 이 복구점을 완전 검증으로 표시하지 말고 승인된 SDK manifest 작업으로 대체합니다.mc mb isolated/restore-<RECOVERY_POINT_UTC>
bash -o pipefail -c 'mc ls --recursive --json isolated/restore-<RECOVERY_POINT_UTC> | jq -e -s "length == 0"'
mc mirror --dry-run backup/recovery-<RECOVERY_POINT_UTC>/ isolated/restore-<RECOVERY_POINT_UTC>/
mc mirror --overwrite --checksum SHA256 backup/recovery-<RECOVERY_POINT_UTC>/ isolated/restore-<RECOVERY_POINT_UTC>/
mc diff backup/recovery-<RECOVERY_POINT_UTC>/ isolated/restore-<RECOVERY_POINT_UTC>/isolated 별칭은 운영과 다른 계정·노드·장애 도메인입니다. 고유 restore bucket 생성이 실패하거나 실제 재귀 객체 목록이 0건이 아니면 덮어쓰지 말고 새 이름으로 다시 시작합니다. pipefail은 mc 목록 실패가 빈 결과로 오인되는 것을 막습니다.test ! -e <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects
install -d -m 0700 <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects
mc mirror --overwrite isolated/restore-<RECOVERY_POINT_UTC>/ <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects/
( cd <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects && find . -type f -print0 | sort -z | xargs -0 -r sha256sum ) > <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects.SHA256SUMS
diff -u <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/source-objects.SHA256SUMS <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restored-objects.SHA256SUMS
bash -o pipefail -c 'mc cat backup/recovery-<RECOVERY_POINT_UTC>/<KNOWN_OBJECT_KEY> | sha256sum > <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/backup-known-object.sha256'
bash -o pipefail -c 'mc cat isolated/restore-<RECOVERY_POINT_UTC>/<KNOWN_OBJECT_KEY> | sha256sum > <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restore-known-object.sha256'
diff -u <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/backup-known-object.sha256 <SECURE_RECOVERY_WORKDIR>/<RECOVERY_POINT_UTC>/restore-known-object.sha256manifest diff는 출력 없이 종료 코드 0이어야 하고, 대표 객체는 두 S3 대상에서 실제 mc cat 읽기와 SHA-256이 같아야 합니다. 복구 증적에는 고유 RECOVERY_POINT_UTC와 control-plane export checksum도 연결합니다.openssl x509 -checkend 2592000 -noout -in /opt/minio/certs/public.crtstat -c '%a %U:%G %n' "$HOME/.mc/config.json"aistor-admin은 root 대체용 비상 관리자이며 보호된 관리 계정에서만 유지합니다. 앱과 백업 자동화는 별도 최소 권한 별칭을 사용합니다.- 애플리케이션은 루트 자격 증명을 사용하지 않는다.
- 각 앱 정책은 필요한 버킷·접두사·S3 작업만 허용한다.
- Access Key·Secret Key를 앱별로 분리하고 비밀 저장소에서 교체한다.
- 서버 설정·버킷 메타데이터·IAM export를 서로 구분해 암호화 보관하고 ZIP·SHA-256 무결성을 검증했다.
- 쓰기 정지와 고유 복구점을 사용했고 mirror가 latest-state-only이며 버전 이력·전체 메타데이터를 보존하지 않는 한계를 기록했다.
- 빈 격리 대상 역복원 뒤 전수 SHA-256 manifest와 실제 S3 read 검증이 일치했다.
- Console은 관리자 CIDR에만 열리고 감사·서버 로그 접근을 제한한다.
- Free에 분산 배포·site/bucket/batch replication·mc support 기능이 없음을 운영 문서에 명시했다.
- 별도 실패 영역의 독립 백업, 정기 객체 복원 시험, 인증서·라이선스·패키지 갱신 절차가 있다.
SNMD의 여러 드라이브는 백업이나 HA가 아닙니다. Free에서 제공하지 않는 replication 명령으로 우회하지 말고, 독립 계정·장애 도메인·보존 정책을 갖춘 별도 객체 백업과 복원 증적을 유지합니다.
환경 파일·인증서·방화벽을 되돌리되 객체 데이터는 보존하는 롤백을 준비합니다.
신규 AIStor 중단·설정 복원·데이터 보존
이 레시피는 신규 AIStor Free 설치 전용입니다. 클라이언트 쓰기와 상위 ACL을 먼저 닫고 서비스를 중지·비활성화한 뒤 라이선스·TLS·환경·객체 데이터를 그대로 보존합니다. 패키지 기본 환경 파일 복원은 오프라인 증적용이며 자동 재시작하지 않습니다.
sudo systemctl stop minio.service
sudo systemctl disable minio.service
systemctl status minio.service --no-pagersudo find /etc/default -maxdepth 1 -type f -name 'minio.*.bak' -printf '%TY-%Tm-%Td %TH:%TM:%TS %p\n' | sortsudo test -f /etc/default/minio.<BACKUP_SUFFIX>.bak변경 기록과 대조해 구성 단계에서 만든 패키지 기본 환경 파일 백업인지 확인합니다.sudo cp --preserve=all --no-clobber /etc/default/minio /etc/default/minio.failed.<ROLLBACK_SUFFIX>sudo cp --preserve=all /etc/default/minio.<BACKUP_SUFFIX>.bak /etc/default/minio파일만 복원합니다. 이전 운영 배포가 아니므로 이 상태로 서비스를 시작하지 않습니다.sudo namei -l /opt/minio/minio.license /opt/minio/certs/private.key /mnt/minio-1/minio /mnt/minio-2/minio /mnt/minio-3/minio /mnt/minio-4/minio라이선스·인증서·객체 경로는 삭제하거나 이동하지 않습니다. 보존 기간과 인수인계 책임자를 기록합니다.sudo ufw delete allow from <S3_CLIENT_CIDR> to <MINIO_PRIVATE_IP> port 9000 proto tcpsudo ufw delete allow from <ADMIN_CIDR> to <MINIO_PRIVATE_IP> port 9001 proto tcpsudo bash -eu -c 'state=/root/aistor-change/<CHANGE_ID>; grep -qx "aistor=absent" "$state/packages.before"; grep -qx "minio=absent" "$state/packages.before"; pkg=$(cat "$state/installed-package-name"); case "$pkg" in aistor|minio) ;; *) exit 1;; esac; dpkg-query -W "$pkg" >/dev/null; apt-get remove -- "$pkg"'배포를 완전히 철회할 때만 실행합니다. 사전 기록에서 두 후보가 모두 없었고 DEB에서 기록한 실제 신규 Package 값이 aistor 또는 minio일 때 그 하나만 제거합니다. 전용 드라이브의 객체 데이터·환경 파일 백업·인증서는 자동 삭제하지 않습니다.- 클라이언트 쓰기 중단과 상위 ACL 차단을 확인했다.
- 변경 기록과 내용으로 복원할 <BACKUP_SUFFIX>를 선택했다.
- 현재 실패 설정도 별도로 보존했다.
- 서비스는 중지·비활성 상태이고 이번 UFW 규칙을 제거했다.
- 라이선스·TLS·볼륨과 독립 백업을 보존했다.
- 변경 기록의 실제 Package 필드와 사전 미설치 상태를 검증해 이번 신규 패키지 하나만 제거했다.
- MinIO 데이터 파일을 셸에서 직접 삭제·이동·수정하지 않았다.
환경 파일 복원만으로 객체나 배포 상태가 되돌아가지는 않습니다. 재개가 필요하면 원래 볼륨 순서·DNS·TLS·라이선스와 독립 백업을 검토한 별도 변경 승인으로 시작합니다.
서비스 실패·디스크·메모리·TLS 장애 대응 가이드로 이어갑니다.
SECURITY CHECK
운영 전 마지막 보안 점검
- AIStor Free Agreement와 단일 노드·기능 제한을 승인하고 유효 라이선스 상태를 감시한다.
- 9000과 9001은 사설 IP와 승인 CIDR에만 노출하고 Console 범위를 더 좁힌다.
- CA 검증 TLS를 사용하고 개인 키와 환경 파일을 최소 계정만 읽게 한다.
- 루트 자격 증명을 앱에 주지 않고 버킷·작업별 최소 권한 정책을 사용한다.
- 전용 드라이브의 MinIO 관리 파일을 다른 프로세스나 스크립트가 직접 만지지 않는다.
- Free에 없는 내장 replication을 백업으로 가정하지 않고 독립 객체 백업·복원 시험을 운영한다.
COMMON ERRORS
자주 막히는 지점
마운트 누락으로 서비스 시작 실패
- 증상
- MinIO 로그에 볼륨 접근 오류가 표시되거나 예상과 다른 루트 디스크 용량이 보입니다.
- 가능한 원인
- 부팅 후 전용 드라이브가 마운트되지 않았거나 경로·소유권이 달라졌습니다.
- 확인 순서
- 서비스를 멈추고 findmnt·UUID·fstab·소유권을 확인한 뒤 모든 마운트가 복구된 후 시작합니다.
TLS 인증서 이름 불일치
- 증상
- 브라우저·mc·S3 SDK가 인증서의 호스트 이름이 맞지 않는다고 거부합니다.
- 가능한 원인
- 접속 DNS가 인증서 SAN에 없거나 다른 인증서 파일이 배치되었습니다.
- 확인 순서
- 검증 우회 없이 SAN이 정확한 인증서를 재발급하고 CA 체인을 클라이언트에 배포합니다.
라이선스 offline·read-only로 S3 403 발생
- 증상
- 서비스와 Console은 열리지만 객체 읽기·쓰기에서 403 AccessDenied가 발생합니다.
- 가능한 원인
- AIStor 라이선스가 없거나 유효하지 않아 offline 상태이거나, 만료·용량 조건으로 read-only 상태입니다.
- 확인 순서
- mc license info와 서버 로그로 상태를 확인하고 SUBNET의 유효 라이선스를 공식 절차로 적용합니다. 우회하지 말고 정상 상태와 S3 회귀 테스트를 확인한 뒤 ACL을 엽니다.
Access Denied 또는 정책 범위 오류
- 증상
- 로그인은 되지만 특정 버킷이나 객체 작업이 거부됩니다.
- 가능한 원인
- 사용자에 연결된 정책의 작업·리소스 ARN 또는 버킷 이름이 실제 사용 범위와 다릅니다.
- 확인 순서
- policy entities와 앱 요청을 비교해 필요한 최소 작업만 추가하고 루트 키로 우회하지 않습니다.
PRIMARY REFERENCES
공식 문서
- MinIO AIStor Ubuntu Server 설치
- MinIO AIStor TLS 네트워크 암호화
- MinIO AIStor 라이선스와 Free 기능 범위
- MinIO AIStor mc license info
- MinIO AIStor 릴리스 아티팩트
- MinIO AIStor Client 설치와 사용
- MinIO AIStor 소프트웨어 요구 사항
- MinIO AIStor 스토리지 요구 사항
- MinIO AIStor 루트 자격 증명과 API 접근
- MinIO Client 별칭과 사설 CA
- MinIO AIStor 관리자 사용자와 Access Key
- MinIO Client mc mirror
- MinIO AIStor 서버 설정 내보내기
- MinIO AIStor 버킷 메타데이터 내보내기
- MinIO AIStor IAM 메타데이터 내보내기
설치 저장소와 지원 버전은 바뀔 수 있습니다. 검토일 이후에는 링크된 공식 문서와 현재 서버의 패키지 후보 버전을 함께 확인하세요.