복구 준비 상태
Libre WebUI는 백업 및 복원의 첫 번째 안전 게이트로 읽기 전용 복구 인벤토리를 제공합니다. 알려진 상태가 무엇인지, 감지된 어떤 조건이 스냅샷을 차단하는지 보고합니다. 유지 관리 잠금을 획득하거나 데이터를 복사, 암호화, 업로드, 삭제, 복구 또는 복원하지 않습니다.
libre-webui recovery-check --json > recovery-inventory.json
소스 체크아웃에서는 npm run build:backend를 한 번 실행하고 libre-webui recovery-check를 npm run recovery:check --로 바꾸세요. 패키지형 npx 및 Homebrew 설치는 기본적으로 ~/.libre-webui를 검사하며 DATA_DIR과 명시적 경로 옵션이 이 위치를 재정의합니다.
차단 요인이 없으면 명령은 상태 0, 보고서는 완성되었지만 복구 차단 요인이 있으면 1, 잘못된 인수나 예기치 않은 수집 실패에는 2로 종료합니다. 기본값이 아닌 위치를 검사하려면 --data-dir PATH 또는 --database PATH를 사용하세요. 기본 또는 --data-dir 볼륨 인벤토리는 표준 DATA_DIR/data.sqlite 파일만 허용하며 하드 링크, 심볼릭 링크 또는 일반 파일이 아닌 데이터베이스/WAL/SHM 항목을 거부합니다. 명시적인 --database 경로는 DATA_DIR 밖에 있을 수 있지만 선택한 데이터베이스와 보조 파일은 여전히 일반 파일이어야 하고 심볼릭 링크일 수 없습니다. --data-dir 없이 --database를 사용하면 일치하는 키, blobs 및 플러그인 정의를 함께 조사하도록 데이터베이스의 부모를 데이터 루트로 취급합니다.
런타임은 결정론적인 백엔드 패키지 plugins 디렉터리와, 상대 PLUGINS_DIR인 경우 과거의 백엔드 상대 위치에서도 기존 플러그인 정의를 읽습니다. 복구는 활성 기존 경로를 조사하고 사용자 지정 정의가 있으면 볼륨 전용 스냅샷을 차단합니다. 이미지 레이아웃에서 이러한 호환성 디렉터리를 옮기는 패키지형 배포는 --legacy-plugins-dir PATH를 여러 번 전달할 수 있습니다.
비공개 Compose 배포에서는 컨테이너의 마운트 볼륨, 코드 및 비밀을 보고하도록 배포된 컨테이너 안에서 실행하세요.
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
인벤토리 검사 항목
버전이 지정된 JSON 보고서에는 다음이 기록됩니다.
- 애플리케이션, Node.js, 운영 체제 및 아키텍처 버전
- 비공개 검사 스냅샷을 만들기 전 SQLite 파일과 WAL/SHM 크기,
quick_check, 외래 키 검증, 스키마 지문, 사용자 버전, 누락된 필수 테이블 및 no-follow 원본 파일 검증 - 데이터 디렉터리의 읽기/쓰기 가능 여부, 파일 수 및 바이트 수
- 선택된 암호화 키 출처와 단방향 16자 지문
- 영속
.encryption_key파일의 no-follow 및 단일 링크 검증 - 사용자 지정 플러그인 정의의 존재 여부, 개수, 크기 및 데이터 디렉터리 포함 여부와 함께 암호화된 로컬 blob 루트, 임베디드 미디어, 음성 참조, 문서 텍스트, 기존 문서 벡터, ACL/필터 행을 포함한 플랫폼 벡터
- 표준 로컬 blob 객체와 임베디드 플랫폼 벡터 봉투 전부에 대한 제한된 읽기 전용 인증(전체 blob 청크/체크섬 검증 및 설정된 키 가용성 포함)
- 채팅, 노트, 문서, 환경설정, 플러그인 비밀, 갤러리/미디어 상태, 계정 이메일의 인식 가능한 기존 텍스트 AES-GCM 봉투 전부와 AAD에 바인딩된 저장 음성 이름, 녹음 및 텍스트 기록 봉투 전부에 대한 제한된 읽기 전용 인증
- Work 작업/실행/미리보기 수와 예상 Docker 볼륨, Kubernetes PVC 또는 해시된 호스트 경로 ID. Docker 볼륨에는 관리 레이블과 정확한 소유 작업 ID가 모두 있어야 함
- 기존 미디어 생성 작업 상태와 상태별 영속 작업, 결과별 시도, 이벤트 스트림/이벤트 수 및 마지막 전역 이벤트 커서
- 모든 암호화된 영속 작업 및 이벤트 페이로드의 제한된 읽기 전용 인증과 모든 불투명 참조 페이로드의 제한된 구문 검증
- 명시적 차단 요인, 경고 및 애플리케이션 데이터 디렉터리 밖에 있는 데이터
보고서에는 암호화 키, JWT/세션 비밀, 제공자 자격 증명, 플러그인 내용, 사용자 콘텐츠 또는 호스트 워크스페이스의 실제 경로가 포함되지 않습니다. 비밀 존재 여부 불리언과 되돌릴 수 없는 암호화 키 지문만 출력합니다.
읽기 전용 데이터 마운트는 복구 검사에 유효하며 차단 요인이 아닌 경고를 생성합니다. 애플리케이션 준비 상태에는 여전히 쓰기 가능한 저장소가 필요합니다. 백업 도우미가 사용하는 읽기 전용 스냅샷을 대상으로 Libre WebUI를 시작하지 마세요.
차단 요인
차단 요인이 하나라도 있으면 복구 게이트 실패로 취급하세요. 일반적인 차단 요인에는 누락되거나 손상된 데이터베이스, 불완전한 스키마, 없거나 충돌하는 키, 손상되거나 인증되지 않은 기존/플랫폼 암호문, 검증 한도 초과, 읽을 수 없는 데이터 디렉터리, 링크되었거나 일반 파일이 아닌 SQLite 원본, 활성 Work 실행/미리보기·미디어 작업·영속 작업, 없거나 잘못 레이블된 Work 워크스페이스, 영속 이벤트 헤드 불일치나 시퀀스 간격, 데이터 디렉터리 밖의 사용자 지정 플러그인 정의, 외부 워크스페이스를 검증할 수 없는 런타임 제어 영역이 있습니다. 스냅샷 전에 활성 작업을 정지하고 누락된 종속성을 해결하세요. 차단 요인을 숨기려고 보고서를 편집하지 마세요.
암호화된 영속 페이로드는 작업/이벤트 ID에 대해 인증되고 표준 제한 JSON인지 검증됩니다. 불투명 참조 페이로드는 제한 및 구문 검사만 수행합니다. 현재 기반에는 대상 존재나 접근을 복구가 증명할 수 있는 권위 있는 blob 참조 저장소가 없습니다. 이러한 참조가 있으면 보고서는 referenceTargetsVerified를 false로 표시하고 경고하며 페이로드나 참조 값을 노출하지 않습니다.
기존 텍스트 필드는 필수 봉투 표식보다 먼저 존재했으므로 이전 스키마 세대의 실제 평문 행은 계속 읽을 수 있고 인증된 암호문으로 보고되지 않습니다. 표준 봉투는 항상 인증합니다. 봉투 너비 IV 또는 인증 태그가 있는 세 부분 값은 잘못된 경우 안전하게 거부됩니다. 저장된 음성 필드는 모호하지 않은 바이너리 봉투를 사용하며 프로필, 소유자 및 필드 ID에 대해 반드시 인증되어야 합니다. JSON encryption.legacyCiphertext 섹션은 평문을 노출하지 않고 인증된 텍스트/바이너리 레코드 및 바이트 합계를 보고합니다.
스키마 v4의 users.email_lookup 열이 있으면 복구는 null이 아닌 모든 이메일도 인증하고 도메인 분리된 키 기반 조회 토큰을 다시 계산합니다. 누락되거나 일치하지 않는 토큰 또는 null 이메일에 연결된 토큰은 스냅샷을 차단합니다. v4 이전 데이터베이스에는 이 파생 조회 열이 없어 계속 호환됩니다.
현재 백업 경계
비공개 배포 도우미는 애플리케이션이 실행 중이면 중지한 뒤 해당 컨테이너의 변경 불가능한 이미지, 마운트 데이터 볼륨 및 환경을 사용해 통합 solo 아카이브를 만듭니다. 매니페스트는 Ed25519로 서명되고 전체 페이로드는 운영자가 보유한 AES-256-GCM 백업 키로 암호화됩니다. SQLite, 로컬 blobs와 임베디드 벡터, 런타임 선택자 및 복원 상태를 복호화하는 데 필요한 보호 설정을 포함합니다. 도우미는 아카이브와 메타데이터 보고서를 게시하기 전에 서명, 암호문 체크섬 및 복호화된 페이로드를 검증합니다. libre-webui-restore는 새 Docker 볼륨만 허용하고 데이터를 복사하기 전에 복호화된 복구 인벤토리를 검증하며 복구된 설정을 새 대상 디렉터리의 비공개 파일로 게시합니다.
보호되는 런타임 설정에는 PostgreSQL 풀, 연결, 유휴, 명령문 및 마이그레이션 잠금 제한 시간, Redis 연결 제한 시간, 두 영속 blob 할당량 설정, 플랫폼 선택자, S3 접두사와 주소 지정 모드가 포함됩니다. 이 값은 평문 매니페스트가 아니라 서명되고 암호화된 페이로드 안에 있으며 적용된 복원에서 모드 0600 설정으로 다시 게시됩니다.
Solo 아카이브에는 Docker Work 볼륨, Kubernetes PVC, 호스트 바인딩 워크스페이스 폴더, Ollama 모델 또는 외부 제공자 상태가 포함되지 않습니다. 서명된 매니페스트의 제외 항목을 계속 확인할 수 있게 유지하고 외부 Work 저장소를 별도로 스냅샷하세요. Team 프로필은 별도의 오프라인 team 워크플로를 사용합니다. PostgreSQL 내보내기 스냅샷, 정확한 버전 관리 S3 암호문 객체, PGVector 인벤토리, 런타임 설정 및 키 ID를 같은 서명/암호화 아카이브 형식으로 봉인하고 복원 중 깨끗한 PostgreSQL/S3 대상을 기준으로 검증합니다. Redis 캐시, 접속 상태, 깨우기 및 임대는 표준 SQL 상태에서 다시 만듭니다.
Team 백업은 정확히 내보낸 PostgreSQL 스냅샷 안의 제한된 암호화 영속 작업과 이벤트 페이로드도 모두 인증합니다. 보호된 서명 인벤토리는 작업, 이벤트, 스트림, 커서, 봉투, 참조 및 인증된 평문 합계를 기록합니다. 모든 이벤트 스트림은 정확히 연속 시퀀스 1..last_sequence를 포함해야 하며 PostgreSQL의 전역 커서 시퀀스가 저장된 최대 커서보다 뒤처져서는 안 됩니다. 복원은 깨끗한 대상에서 이 검사를 반복하고 성공을 보고하기 전에 전체 결과가 서명된 원본 인벤토리와 일치해야 합니다. PostgreSQL ID 할당은 트랜잭션 방식이 아니므로 서로 다른 전역 커서 값 사이의 간격은 유효합니다. 스트림별 시퀀스가 연속 순서 계약입니다.
PLUGINS_DIR이 DATA_DIR 밖을 가리키면 복구는 정확히 그 디렉터리를 조사하고 애플리케이션 볼륨 아카이브의 제외 항목으로 표시합니다. 정의가 하나라도 있으면 운영자가 일치하는 플러그인 디렉터리 스냅샷을 준비할 때까지 볼륨 전용 스냅샷을 차단합니다. 활성 기존 플러그인 디렉터리에도 같은 규칙이 적용됩니다. 심볼릭 링크이거나 일반 파일이 아니거나 읽을 수 없는 JSON 정의는 항상 차단 요인이며 따라가거나 조용히 생략하지 않습니다.
영속 작업과 순서 있는 이벤트는 두 프로필 모두에서 활성화됩니다. 복구는 작업 시도나 Work 실행이 활성 상태이면 차단하고, 작업/이벤트 페이로드와 연속 스트림 헤드를 검증하며, 표준 SQL 상태를 보존합니다. Solo는 제한된 임베디드 워커를 실행하고 team은 같은 등록 처리기를 외부 워커에서 실행하며 Redis는 깨우기와 fan-out에만 사용합니다.
프로덕션에서는 암호화 및 JWT 비밀을 보호된 비밀 관리자에 저장하고, 백업 아카이브를 암호화하여 호스트 외부에 보관하고, 깨끗하고 호환되는 환경에서 복원을 테스트하세요. 인벤토리는 알려진 상태의 사전 점검 스냅샷일 뿐 유지 관리 잠금이나 모든 외부 리소스가 복원 가능하다는 독립적인 증거가 아닙니다.
서명 및 암호화 백업 명령
아래 예시는 전역 npm 또는 Homebrew에서 설치한 libre-webui 명령을 사용합니다. 전역으로 설치하지 않았다면 libre-webui를 npx --yes libre-webui@latest로 바꾸세요. 소스 체크아웃에서는 백엔드를 한 번 빌드하고 libre-webui backup을 npm run recovery:backup --로 바꿉니다. 프로덕션 Docker 이미지는 /usr/local/bin/libre-webui에서 같은 명령을 제공합니다. Team 백업 및 복원에는 PostgreSQL 16 pg_dump와 pg_restore도 필요합니다. 프로덕션 이미지와 Homebrew formula의 명령 경로에 포함되어 있습니다. 일반 npm/npx에서 이 명령을 사용하기 전에 호환되는 PostgreSQL 클라이언트를 명시적으로 설치하세요.
비공개 디렉터리에서 운영자가 보유할 AES-256-GCM 아카이브 키와 Ed25519 서명 키 쌍을 생성한 다음 개인 키를 보호된 호스트 외부 저장소로 옮기세요.
install -d -m 0700 /absolute/private/libre-backup-keys
libre-webui backup keygen \
--directory /absolute/private/libre-backup-keys
정지된 solo 데이터 디렉터리의 아카이브를 만들고 독립적으로 검증합니다.
libre-webui backup create \
--offline \
--data-dir /absolute/path/to/libre-data \
--output /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
libre-webui backup verify \
--archive /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
먼저 사전 점검으로 복원한 다음 새롭고 빈 대상 디렉터리에만 적용합니다.
libre-webui backup restore-preflight \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-apply \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-verify \
--target /absolute/restore/libre-data
Team 모드에서는 모든 애플리케이션 복제본과 워커를 중지하고 원본 PostgreSQL/S3/keyring 환경을 로드한 상태로 조정된 아카이브를 만드세요.
libre-webui backup create-team \
--offline \
--output /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
복원 전에 별개의 빈 PostgreSQL 데이터베이스와 비어 있는 버전 관리 S3 버킷의 환경 변수를 로드하세요. 사전 점검은 서명과 암호화 아카이브를 검증하고 보호된 인벤토리를 확인하며 선택한 대상 데이터베이스와 버킷 접두사가 비어 있음을 데이터를 게시하지 않고 증명합니다. 적용은 깨끗한 대상에 복원하고 결과 PostgreSQL 스키마, 정확한 S3 객체 및 PGVector 레코드를 검증하며 보호된 런타임 설정을 새 비공개 디렉터리에 기록합니다.
libre-webui backup restore-team-preflight \
--archive /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-team-apply \
--archive /absolute/backups/libre-team.lwbackup \
--configuration-output /absolute/restore/libre-team-config \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
복원 대상을 원본 데이터베이스, 원본 버킷, 기존 데이터 디렉터리 또는 파일이 있는 설정 디렉터리로 지정하지 마세요. 공개 서명 키는 복원 실행서와 함께 보관하세요. 아카이브와 공개 키만 가지고는 페이로드를 복호화할 수 없습니다.
Team 복원에서 롤백이 불완전하다고 보고되면 선택한 두 대상을 모두 오염된 것으로 취급하고 즉시 다시 시도하지 마세요. 대상 PostgreSQL 데이터베이스를 검사하고 정리한 다음 정확한 대상 S3 접두사 아래의 모든 객체 버전과 삭제 마커를 열거해 제거하세요. restore-team-preflight를 다시 실행합니다. 깨끗한 대상 사전 점검이 성공한 뒤에만 적용을 안전하게 다시 시도할 수 있습니다.
예약 검증 복구 훈련
복원해 보지 않은 백업은 복구가 아니라 희망에 불과합니다. 훈련은 가동 중단이나 운영자 없이 위의 정확한 파이프라인을 처음부터 끝까지 실행하여 인스턴스를 실제로 복구할 수 있음을 증명합니다.
- 데이터 디렉터리의 정지 상태 스냅샷을 준비합니다. SQLite 데이터베이스는 온라인 백업 API로, blobs와 파일은 물리적으로 복사합니다. 훈련은 조용한 시점을 기다리며 영속 작업이 진행 중이면 실행을 거부합니다.
recovery-check와 같은 규칙입니다. - 준비된 사본을 임시 훈련 키를 사용한 서명된 AES-256-GCM 암호화 아카이브로 만들고 전체 복구 인벤토리를 실행합니다.
- 아카이브를 검증하고 격리된 임시 대상에 복원한 뒤 복원 환경을 다시 검증합니다.
- 측정한 내용을 기록합니다. 복원 시간은 입증된 RTO이고 성공 훈련 간격은 현재 일정으로 달성 가능한 RPO의 상한입니다. 그런 다음 모든 artifact를 삭제합니다. 훈련은 검증이지 백업이 아니므로 아카이브나 키를 보관하지 않습니다.
RECOVERY_DRILL_INTERVAL_HOURS(예: 24)로 일정을 활성화하세요. 훈련은 조정자 임대 아래 공유 스케줄러에서 실행되어 복제본이나 겹치는 틱이 중복 실행하지 못합니다. 시스템 페이지에는 훈련 기록과 관리자용 "지금 훈련 실행" 버튼이 표시되며 GET /api/recovery/drills와 POST /api/recovery/drills/run이 이를 지원합니다. 무인 훈련 실패는 알림 받은편지함과 구독한 웹훅 대상으로 모든 관리자에게 알리고, 수동 실행은 거부 사유를 직접 보고합니다. RECOVERY_DRILL_HISTORY는 보관 기록을 제한하며 기본값은 60개입니다.
훈련은 파일 시스템 아카이브가 권위 있는 백업 경로인 solo(SQLite) 프로필을 대상으로 합니다. Team 프로필은 조정된 backup create-team 흐름을 유지하며 복원 리허설은 현재 운영자 실행서 단계로 남아 있습니다.