본문으로 건너뛰기

플랫폼 기반

Libre WebUI는 로컬 우선 solo 프로필과 공유 team 프로필을 지원합니다. Solo는 SQLite, 암호화된 로컬 blobs, 암호화된 임베디드 벡터, 로컬 조정 및 임베디드 영속 워커를 사용합니다. Team은 PostgreSQL, S3 호환 비공개 blobs, PGVector, Redis 조정 및 외부 영속 워커를 사용합니다. 시작 시 혼합 프로필을 거부하므로 상태가 로컬 백엔드와 공유 백엔드로 조용히 나뉘지 않습니다.

현재 이정표

영역구현된 기반남은 호출자 작업
영속성SQLite 및 PostgreSQL 저장소, 변경 불가능한 마이그레이션, 풀링된 트랜잭션새 도메인은 저장소 경계를 사용해야 함
Blobs암호화된 로컬 및 S3 호환 스트리밍 저장소, 범위, 체크섬, 영속 할당량채팅 첨부, 아바타 및 나머지 인라인 바이너리 필드 이동
벡터암호화된 임베디드 벡터, PGVector ACL 및 삭제에 안전한 문서 인덱스 재생성새 임베딩 호출자는 같은 권한과 수명 주기 계약을 보존해야 함
조정로컬 및 Redis 이벤트, 캐시, 임대, 속도 제한, 무효화 및 상태Redis를 비권위 상태로 유지
작업/이벤트SQLite/PostgreSQL 대기열, 트랜잭션 이벤트, 워커, 재시도, 취소, 관리모든 새 부작용에는 멱등성 또는 outbox 설계 필요
운영상태 게이트, 서명/암호화 백업 아카이브, 깨끗한 대상 복원, 검증각 배포 환경에서 복원 및 복제본 간 수용 테스트 수행

런타임 프로필

기본값은 LIBRE_PLATFORM_MODE=solo입니다. SQLite, 로컬 blobs, 임베디드 벡터, 로컬 조정 및 임베디드 영속 워커를 선택합니다. Solo 모드에서 Redis를 선택할 수는 있지만 그렇다고 SQLite나 로컬 파일을 복제본 간에 안전하게 공유할 수 있는 것은 아닙니다.

LIBRE_PLATFORM_MODE=team에는 모든 공유 종속성이 함께 필요합니다.

  • DATABASE_BACKEND=postgresDATABASE_URL
  • BLOB_STORE_BACKEND=s3
  • VECTOR_STORE_BACKEND=pgvector
  • COORDINATION_BACKEND=redisREDIS_URL
  • JOB_WORKER_MODE=external

이 선택자는 일관된 하나의 집합입니다. 공유 종속성이 하나라도 없거나 로컬 백엔드가 프로필에 섞이면 Team 시작이 실패합니다.

기존 solo 설치 마이그레이션

마이그레이션 전에 모든 Libre 애플리케이션과 워커를 중지하세요. 예시는 전역 npm 또는 Homebrew에서 설치한 libre-webui 명령을 사용합니다. 전역 설치 없이 사용하려면 npx --yes libre-webui@latest로 바꾸세요. 소스 체크아웃에서는 한 번 빌드하고 libre-webui migrate-postgresnpm run migrate:postgres --로 바꿉니다. 대상 team 배포와 정확히 같은 방식으로 대상 PostgreSQL, S3 및 버전 관리 암호화 키 환경을 설정한 다음 읽기 전용 분석부터 실행하세요.

libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode dry-run

보고서가 식별한 빈 대상에만 적용하세요. 실행이 실패하면 체크섬이 있는 가져오기 저널이 남습니다. 관련 없는 가져오기를 새로 시작하지 말고 동일한 원본과 대상을 다시 시작하세요.

libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode apply

# Only after an interrupted apply of this exact source and target:
libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode apply --resume

libre-webui migrate-postgres \
--source /absolute/path/to/data.sqlite \
--plugins /absolute/path/to/plugins \
--mode validate

관계형 행, 플러그인 정의, 로컬 암호화 blobs, 임베디드 벡터 및 기존 페르소나 벡터가 모두 PostgreSQL/S3/PGVector로 전송되고 인증될 때까지 완료 표식은 기록되지 않습니다. 명령은 원본 암호화 키를 만들어 내지 않습니다. ENCRYPTION_KEY는 원본 .encryption_key와 일치해야 하고 STORAGE_ENCRYPTION_KEYS에는 설정된 활성 키와 일치하는 legacy 항목이 있어야 합니다.

번들 team 프로필 실행

안전하게 거부하도록 제공되는 템플릿에서 시작하세요. 완성한 환경 파일은 저장소 밖에 두고 운영자만 접근하도록 제한합니다.

cp deploy/team/.env.example /absolute/path/to/libre-team.env
chmod 600 /absolute/path/to/libre-team.env

시작 전에 모든 REPLACE_* 값을 바꾸세요. PostgreSQL 암호는 URL에 안전한 문자 집합(예: openssl rand -hex 32)으로 만드세요. 같은 리터럴이 서버 암호와 DATABASE_URL의 일부로 모두 사용되기 때문입니다. ENCRYPTION_KEYSTORAGE_ENCRYPTION_KEYS 안의 모든 값은 정확히 64자의 16진수여야 합니다. 새 설치에서는 legacy 항목이 ENCRYPTION_KEY와 같아야 하고 SQLite 마이그레이션에서는 둘 다 원본 키와 같아야 합니다. 새 blob 쓰기에는 다른 활성 키를 유지하고 객체 인벤토리에서 미사용이 증명될 때까지 이전 키를 보관하세요.

같은 파일에서 POSTGRES_MIGRATION_MODE, POSTGRES_POOL_MAX, 지원되는 PostgreSQL 제한 시간, REDIS_CONNECT_TIMEOUT_MS, OLLAMA_BASE_URL, OLLAMA_TIMEOUT, OLLAMA_LONG_OPERATION_TIMEOUT, OLLAMA_MAX_CONTEXT를 설정할 수 있습니다. 공유 Compose 환경은 각 값을 애플리케이션과 외부 워커에 동일하게 전달합니다. 제공자 제한 시간은 1,000-3,600,000밀리초, 최대 컨텍스트는 128-2,097,152토큰을 허용하며 긴 제한 시간은 표준 제한 시간보다 짧을 수 없습니다. 잘못된 값은 상태가 생성되기 전에 두 서버 진입점 모두를 실패시킵니다. 노드 로컬 Agent CLI 바이너리와 Codex OAuth 토큰 파일은 외부 영속 워커에서 지원되지 않으므로 team 프로필은 두 제공자 경로를 비활성으로 고정하고 활성화 시도를 시작 단계에서 거부합니다. 그런 다음 애플리케이션 복제본, 외부 영속 워커, PostgreSQL/PGVector, Redis, 버전 관리 MinIO 버킷 및 게이트웨이를 시작하세요.

docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml up --build --scale libre-webui=3 -d
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml ps

기본 team 프로필은 의도적으로 Docker 소켓을 마운트하지 않으므로 Docker 기반 Work를 사용할 수 없습니다. 모든 수명 주기 명령에 제공된 프로덕션 오버레이를 포함할 때만 활성화하세요.

docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml -f docker-compose.team.work.yml \
up --build --scale libre-webui=3 -d
docker compose --env-file /absolute/path/to/libre-team.env \
-f docker-compose.team.yml -f docker-compose.team.work.yml ps

이 오버레이는 애플리케이션과 워커 프로세스 모두를 내부 전용 네트워크의 필터링된 Docker 소켓 프록시 하나로 연결합니다. 어느 프로세스도 원시 소켓이나 소켓 그룹 멤버십을 받지 않으며 호스트 폴더 Work 워크스페이스는 계속 비활성화됩니다. 프록시는 info, images, containers, exec, volumes, networks 및 해당 수명 주기 호출에 필요한 쓰기 메서드만 제공합니다. API 표면을 줄이지만 Docker를 테넌트 경계로 만들지는 않습니다. 컨테이너 생성은 여전히 호스트 경로를 bind-mount할 수 있습니다. 호스트 격리가 중요하면 전용 VM 또는 rootless/별도 Work 데몬을 사용하세요.

Compose가 소유한 PostgreSQL, Redis 또는 MinIO 서비스를 직접 노출하지 마세요. 관리형 종속성에는 Helm team 프로필을 사용하고 검증된 TLS를 유지하세요. Compose 파일은 비공개 프로젝트 네트워크에서만 PostgreSQL TLS를 비활성화합니다. 외부 워커가 나타날 때까지 준비 상태는 실패로 유지됩니다.

영속성 및 마이그레이션 경계

ID와 권한 부여는 이제 비동기 저장소를 사용합니다. 저장소 트랜잭션 콜백은 같은 데이터베이스 연결에 바인딩된 작업 단위를 받으며 콜백 안에서 전역 저장소를 사용하면 거부됩니다. 이는 기존 SQLite 동작을 보존하면서 PostgreSQL 연결 풀이 사용하는 트랜잭션 경계입니다.

SQLite 마이그레이션 조정자는 필수 스키마를 검증한 뒤에만 기존 설치를 채택합니다. 번호가 있는 마이그레이션 이름과 체크섬을 기록하고 시작할 때마다 검증하며, 더 새롭거나 알 수 없거나 일치하지 않는 원장을 거부하고, 마이그레이션 또는 스키마 검증이 실패하면 시작을 실패시킵니다. 준비 상태와 복구 인벤토리는 동일한 표준 검사 계약을 사용합니다.

상태를 보유하는 애플리케이션 서비스를 가져오기 전에 시작 과정은 기존 SQLite 데이터베이스와 활성 WAL/SHM 파일을 비공개 임시 디렉터리에 복사해 검증합니다. PLATFORM_PREFLIGHT_TMP_DIR에는 데이터베이스와 WAL을 담을 충분한 여유 공간이 있어야 합니다. 제공된 Docker 및 Helm 배포는 여기에 전용 디스크 기반 임시 저장소를 마운트하며 제한된 /tmp tmpfs에 의존하지 않습니다. 기존 암호화 키가 없거나 과거의 중첩 데이터 디렉터리가 있으면 대체 키, 데이터베이스 또는 플러그인 상태를 만들기 전에 시작을 차단합니다.

스키마 v4는 암호화된 ID 이메일에 키 기반 동등성 토큰을 추가합니다. 복구는 모든 토큰이 존재하고 인증된 이메일과 일치해야 한다고 요구합니다. v4 커밋 직후의 좁은 충돌 창에서는 인증된 이메일 또는 봉투가 아닌 기존 값에 토큰이 없어도 시작을 허용하여 저장소 초기화가 암호화/토큰 backfill을 완료할 수 있게 합니다. 이전 릴리스는 임의 이메일 문자열을 허용하고 빈 값으로 필드를 지웠습니다. 채택 과정은 비어 있지 않은 값을 보존하고 빈 값을 NULL로 정규화합니다. 손상된 봉투 형태 값과 null이 아닌 불일치는 계속 사전 점검을 실패시킵니다.

애플리케이션 서비스는 비동기 dialect 저장소를 사용합니다. 네이티브 SQLite는 SQLite 어댑터, 마이그레이션/복구 검사 및 명시적으로 주입된 상태 검사로 제한됩니다. 런타임 저장소는 선택한 Persistence에서 초기화되며 PostgreSQL 활성화가 SQLite singleton이나 과거의 cwd 종속 JSON 파일로 대체되는 일은 없습니다.

공통 영속 작업 런타임도 드라이버에 종속되지 않습니다. 행위자 권한은 선택된 ID 저장소에서 읽고 네이티브 작업 저장소 생성은 하나의 어댑터 구성 경계로 제한됩니다. 트랜잭션 도메인 게시자는 SQLite에서는 불투명 동기 실행기를, PostgreSQL에서는 트랜잭션 바인딩 실행기를 받습니다. better-sqlite3 핸들을 받지 않습니다. 영속성 경계 테스트는 공통 작업, 리소스, ID, 채팅 및 Work 계약의 네이티브 드라이버 핸들을 거부합니다.

Blob 및 벡터 저장소 기반

생성된 갤러리 미디어와 문서 원본 파일은 BlobStore를 사용하고 문서 RAG와 페르소나 메모리는 VectorStore를 사용합니다. SQLite의 기존 갤러리 행은 이중 읽기되며 처음 접근할 때 blob 참조로 채택됩니다. 관계형 메타데이터와 영속 참조가 권위 상태입니다. 제공자 URL과 물리적 S3 키는 애플리케이션 콘텐츠로 저장되지 않습니다. 채팅 첨부, 아바타 및 남은 인라인 바이너리 필드는 아직 blob 저장소 호출자가 아니므로 마이그레이션되었다고 설명해서는 안 됩니다.

복구 게이트는 명시적 집계 제한 아래에서 모든 영속 객체와 임베디드 벡터 봉투를 순차 인증합니다. 인식 가능한 기존 텍스트 봉투와 저장된 모든 음성 바이너리 봉투도 애플리케이션 ENCRYPTION_KEY로 엄격히 인증하며 런타임의 복호화 후 원본 반환 호환성 대체를 절대 사용하지 않습니다. 원본 저장소를 초기화, 복구, 다시 쓰기 또는 삭제하지 않습니다. 손상된 암호문, 알 수 없거나 잘못된 키, 표준이 아닌 blob 레이아웃 및 검증 한도 초과는 스냅샷을 차단합니다.

기본 복구 한도는 로컬 객체 250,000개, 암호화 및 평문 blob 바이트 64 GiB, 벡터 행 250,000개, 직렬화된 벡터 암호문 4 GiB, 벡터 구성 요소 5억 개입니다. 테스트와 임베디드 호출자는 RecoveryInventoryOptions를 통해 실행별 한도를 재정의할 수 있지만 CLI는 초과 상태를 조용히 샘플링하거나 건너뛰지 않습니다.

기존 암호문 검증의 기본 한도는 값이 채워진 후보 필드 100만 개와 저장 및 인증 평문 각각의 집계 바이트 16 GiB입니다. 기존 텍스트 봉투에는 영속 표식이 없으므로 이전 스키마 세대의 평문 행은 계속 호환됩니다. 보고서는 인증된 봉투만 셉니다. 저장 음성 봉투는 모호하지 않으며 프로필/소유자/필드 ID를 추가 데이터로 항상 인증합니다.

암호화된 로컬 blobs

BlobStore는 소유자 범위이며 스트리밍 put/read, 메타데이터/stat, 포괄적 바이트 범위 및 멱등 삭제를 제공합니다. LocalEncryptedBlobStore는 애플리케이션이 제공한 루트 아래에 불투명 UUID 키 객체를 씁니다. 통합 대상은 ${DATA_DIR}/blobs입니다. 배타적 준비 파일, fsync 및 동일 파일 시스템 내 원자적 rename을 사용하며 디렉터리는 0700, 파일은 0600입니다.

모든 객체에는 무작위 256비트 데이터 키가 있습니다. AES-256-GCM은 비공개 메타데이터를 암호화하고 제한된 본문 청크를 독립적으로 인증합니다. 추가 인증 데이터는 blob ID, 소유자, 용도, 청크 인덱스 및 평문 길이를 바인딩합니다. 버전 관리 저장소 keyring이 각 데이터 키를 감쌉니다. 설명자는 평문 크기, SHA-256, 콘텐츠 유형, 생성 시각, 형식 버전 및 암호화 키 ID를 기록합니다. 전체 읽기는 SHA-256을 검증하고 범위 읽기는 접근한 모든 청크를 인증합니다.

할당량 계약은 스트리밍 전에 용량을 예약하고 실제 바이트를 소비하며 원자적으로 보이게 된 뒤에만 커밋하고 실패한 예약을 해제합니다. SQLite는 BEGIN IMMEDIATE, PostgreSQL은 직렬화 가능 트랜잭션과 행 잠금을 사용합니다. S3 객체 메타데이터와 할당량 사용량은 하나의 데이터베이스 트랜잭션에서 함께 커밋되거나 롤백됩니다. 시작 시 만료된 예약과 물리적 blob이 없는 할당량 객체를 조정합니다. BLOB_QUOTA_BYTES_PER_USER는 소유자별 영속 한도를 설정하고 BLOB_QUOTA_RESERVATION_TTL_MS는 버려진 예약의 수명을 제한합니다.

BLOB_STORE_BACKEND=s3는 비공개 S3 호환 버킷을 사용합니다. Libre는 불투명 객체 키와 애플리케이션 암호화 청크 스트림을 업로드하고, 암호화된 설명자를 PostgreSQL에 보관하며, 포괄적 HTTP 범위를 지원하고, 평문과 암호문의 SHA-256 다이제스트를 검증하고, 멱등 삭제를 수행합니다. 삭제 중인 행은 물리적 삭제와 원자적 메타데이터/할당량 제거가 성공할 때까지 유지됩니다. 조정은 중단된 삭제를 재시도하고 오래된 물리적 고아 객체를 제거합니다. Docker 게이트 MinIO 스위트는 복제본 간 읽기/삭제, 테넌트 격리, 할당량 경합, 소비되지 않은 스트림 및 커밋/삭제 경계에 주입된 데이터베이스 실패를 다룹니다.

암호화된 임베디드 벡터

VectorStore는 모든 쿼리와 변경에 행위자를 요구합니다. 레코드는 네임스페이스, 불투명 테넌트 범위 ID, 소유자, 리소스 ID, 임베딩 모델, 차원, 버전, 원본 리비전, 동등성 속성 및 선택적 사용자/그룹 권한 부여를 포함합니다.

SQLite는 암호화된 임베딩이 데이터베이스를 떠나기 전에 네임스페이스/모델/차원/버전, 소유자 또는 권한 부여, 리소스 및 속성 조건자를 적용합니다. 제한되고 승인된 후보 집합만 복호화하여 코사인 점수를 계산합니다. 같은 불투명 벡터 ID는 다른 테넌트의 존재를 드러내지 않고 소유자별로 격리됩니다. Upsert는 임베딩, ACL 및 속성을 원자적으로 교체하고 삭제는 소유자 범위이며 관련 행을 연쇄 삭제합니다.

임베딩은 ID와 모델 메타데이터를 추가 인증 데이터로 바인딩한 AES-256-GCM을 사용합니다. 쿼리 가능한 ID, 권한 부여, 모델, 버전, 리비전 및 필터 메타데이터는 평문으로 남으므로 호출자는 필터 속성에 비밀을 넣으면 안 됩니다. 임베딩 자체는 민감한 파생 데이터입니다.

VECTOR_STORE_BACKEND=pgvector는 거리 정렬 및 LIMIT과 같은 SQL 문 안에서 네임스페이스, 모델, 차원, 버전, 리소스, 속성, 소유자 및 권한 부여 조건자를 적용합니다. 전역 최근접 이웃을 사후 필터링하는 것은 금지됩니다. 모든 쿼리에서 신뢰할 수 있는 현재 멤버십 확인자가 그룹 권한을 해석하며 호출자가 제공한 groupIds는 무시됩니다. 따라서 철회가 즉시 적용되고 위조한 그룹 클레임으로 후보를 검색할 수 없습니다.

문서 수집과 임베딩 재생성 유지 관리 엔드포인트는 작업 시작 전에 하나의 변경 불가능한 실행 사양을 캡처합니다. 활성 상태, 모델, 벡터 버전, 청커 버전, 청크 크기, 겹침 및 유사도 임계값이 포함됩니다. 같은 사양이 청크 생성, 관계형 게시, 벡터 upsert 및 시맨틱 쿼리를 제어하므로 실행 중 환경설정 변경이 모델이 섞인 청크를 만들거나 다른 임계값으로 벡터를 쿼리하지 못합니다. 게시된 문서 메타데이터는 집계 청크 리비전과 이 사양을 기록하여 SQL을 권위 있는 인덱스 매니페스트로 유지합니다.

재생성은 문서별 자동 갱신 조정자 임대를 유지하고 관계형 게시 전과 벡터 변경 전후에 소유자 범위 행과 영구 삭제 tombstone을 다시 확인합니다. Upsert 진행 중 삭제가 커밋될 수 있으며 사후 upsert 권한 확인이 다시 생성된 벡터를 제거합니다. PostgreSQL/team 시맨틱 읽기는 PGVector를 변경하지 않습니다. SQLite는 저장 매니페스트가 정확히 현재 모델과 청크 설정을 증명할 때만 관계형 임베딩을 지연 재게시할 수 있습니다. 선택적 변경은 같은 문서 임대를 유지하며 행과 청크를 다시 로드합니다. 사용 중이거나 대체된 리비전은 건너뛰며 키워드 대체 또는 명시적 재생성 대상 상태를 유지합니다.

문서 인덱스는 최대 1,000개 벡터의 보상 가능한 배치로 교체되고 정확한 인덱스 검사는 하나의 변경 배치가 문서 전체라고 가정하지 않고 전체 리소스 매니페스트를 페이지로 나누어 확인합니다. 한 문서가 게시할 수 있는 청크는 최대 100,000개이므로 어떤 단일 문서도 이식 가능한 아카이브의 전체 문서 청크 한도를 넘지 않습니다. 수집은 100,001번째 청크를 임베딩이나 관계형/벡터 게시 전에 거부하고 해당 영속 작업을 재시도 없이 데드 레터 처리합니다. 다시 업로드하기 전에 임베딩 청크 크기를 늘리거나 과도한 단락 나눔을 제거하세요.

매니페스트 이전 solo 데이터베이스에는 어떤 모델이나 청커로 만들었는지 기록 없이 인증된 인라인 문서 벡터가 있을 수 있습니다. 첫 시맨틱 사용은 그 존재만 업그레이드 신호로 취급합니다. 문서 임대를 유지한 채 권위 있는 문서 텍스트를 다시 청크하고 현재 캡처된 사양으로 모든 벡터를 다시 생성합니다. 기존 페이로드를 복사하거나 오늘의 환경설정으로 레이블하지 않습니다. 제공자 실패나 사용 중인 임대는 기존 행을 변경하지 않고 키워드 검색 가능하게 유지합니다.

이러한 기존 문서에 인증된 현재 매니페스트 메타데이터와 정확한 암호화 플랫폼 벡터 인덱스가 완전히 갖춰지지 않으면 SQLite에서 team으로의 마이그레이션은 안전하게 거부됩니다. 현재 환경설정은 과거 벡터의 모델을 증명하지 않습니다. Dry-run에서 이 차단 요인을 보고하면 같은 DATA_DIRENCRYPTION_KEY를 사용해 현재 릴리스를 solo/SQLite 모드로 시작하고 원하는 임베딩 모델을 활성화해 선택한 뒤 각 해당 소유자에 대해 설정 -> 문서 -> 임베딩 재생성을 사용하고 마이그레이션 dry-run을 다시 실행하세요. 그래야만 proven 벡터가 PGVector로 이동하는 동안 team 저장소 읽기가 보존된 인라인 암호문을 무시할 수 있습니다.

기밀성은 백엔드마다 다릅니다. 임베디드 SQLite는 메타데이터 ACL 조건자를 적용한 뒤 애플리케이션 AES-256-GCM으로 임베딩을 암호화합니다. PGVector는 수치 임베딩을 연산해야 하므로 해당 열을 애플리케이션 수준에서 암호화하지 않습니다. 임베딩을 민감한 파생 데이터로 취급하세요. TLS, 암호화된 PostgreSQL 볼륨과 백업, 최소 권한 애플리케이션 역할, 제한된 데이터베이스 관리, 벡터나 원본 내용을 절대 포함하지 않는 SQL 로그가 필요합니다. 원본 텍스트, 페르소나 메모리 내용, 갤러리 메타데이터 및 blob 설명자는 계속 봉투 암호화됩니다. 벡터 속성은 쿼리 가능한 평문이므로 비밀을 절대 포함하면 안 됩니다.

저장소 암호화 키

현재 호출자 마이그레이션 기간에 버전 관리 keyring을 활성화하는 배포는 안정적인 64자 ENCRYPTION_KEY를 설정하고, 정확한 legacy 항목으로 같은 키를 STORAGE_ENCRYPTION_KEYS에 포함하고, STORAGE_ENCRYPTION_ACTIVE_KEY_ID를 항목 하나로 설정해야 합니다. 쓰기는 활성 키를 사용하고 읽기는 단계적 회전을 지원하도록 설정된 모든 키 ID를 허용합니다. 이 임시 legacy 요구 사항은 기존 암호화 서비스가 독립적으로 다른 키를 만들지 못하게 합니다. 모든 객체와 벡터를 다시 쓰거나 rewrap하고 검증할 때까지 이전 키를 보관하세요.

맵이 없으면 어댑터는 기존 64자 ENCRYPTION_KEY를 키 ID legacy로 허용하거나 환경 키가 없을 때 기존 ${DATA_DIR}/.encryption_key 파일을 읽습니다. 저장소 팩터리는 비공개 권한을 가진 일반 비심볼릭 링크 키 파일만 허용하며 파일을 만들거나 다시 쓰거나 교체하지 않습니다. 명시적 환경 설정이 영속 키와 충돌하면 시작을 안전하게 실패시킵니다. 회전 중 감지된 기존 환경/파일 키는 이전 봉투를 다시 쓰고 검증할 때까지 정확한 키 ID legacy로 버전 관리 맵에 남아야 합니다. 누락, 형식 오류, 불일치 및 알 수 없는 키는 안전하게 거부됩니다.

임베디드 벡터 쿼리는 SQLite에서 ACL과 메타데이터 조건자를 적용한 뒤 후보 수, 암호화 바이트 및 차원별 점수 계산 작업을 집계하고 나서야 암호문을 Node로 반환해 복호화합니다. 예산을 초과하는 쿼리는 안전하게 거부되며 리소스나 메타데이터 범위를 좁혀야 합니다.

조정

조정자 계약은 이벤트, 만료 캐시 항목, 펜싱된 임대 및 고정 창 속도 제한 소비를 제공합니다. 로컬 구현은 단일 복제본 solo 프로필 전용입니다. Redis 구현은 분리된 명령/구독 클라이언트, 제한된 페이로드, 상태 검사, 키 네임스페이스, 원자적 스크립트, 고유 소유자 토큰, 임대 만료 및 펜싱 토큰을 사용합니다. Redis 오류 후 로컬 조정으로 대체하지 않습니다.

Redis는 권위 있는 원본이 아닙니다. 권한 부여, 영속 작업 및 재생 가능한 이벤트는 데이터베이스에 남아야 하며 Redis는 깨우기, 캐시 무효화, 접속 상태, 할당량 및 조정 계층입니다. 중요한 작업은 부작용을 커밋하기 전에 데이터베이스 임대나 펜싱 토큰도 검증해야 합니다.

애플리케이션 티켓팅, 캐시, 공유 무효화, 연결 제한, Work 이벤트 및 분산 런타임 잠금이 이 경계를 사용합니다. Redis 선택만으로는 로컬 영속성을 공유할 수 없습니다. Team 모드에는 전체 공유 프로필이 필요합니다.

영속 작업 및 이벤트

SQLite 마이그레이션 v3은 영속 작업, 시도, 이벤트 스트림 헤드 및 순서 있는 이벤트 테이블을 제공합니다. 서비스 계약은 멱등 enqueue, 제한된 재시도, 취소, 진행 상황, 임대 heartbeat/reclaim, 데드 레터 상태 및 전역 커서별 재생을 지원합니다. 암호화 JSON 페이로드는 작업/이벤트 ID를 인증 데이터로 사용하는 플랫폼 keyring을 사용하고 페이로드 참조는 제한된 불투명 식별자입니다.

SQLite 마이그레이션 v13과 PostgreSQL 마이그레이션 v12는 생성 범위 채팅 재생에 사용하는 일치하는 (stream_id, subject_id, global_cursor) 인덱스를 추가합니다. 스트림과 주체 필터는 따라잡기 한도 전에 적용되므로 긴 세션의 이전 생성이 현재 생성의 재생 예산을 소비하거나 전체 이벤트 스트림 스캔을 강제하지 않습니다.

애플리케이션과 독립 워커 bootstrap은 문서 수집, 미디어 계속 처리 및 재시도 가능한 리소스 정리를 위한 감사된 처리기를 등록합니다. 관리자 경계는 제한된 검사와 취소를 제공합니다. Enqueue는 멱등이며 관계형 생성/삭제 경로는 같은 SQLite/PostgreSQL 트랜잭션에 영속 작업을 삽입합니다. 리소스 정리는 재시도에 안전한 작업으로 벡터, 비공개 blobs, 영속 참조, 캐시 항목 및 리소스 대상 대기 작업을 제거합니다.

복구 인벤토리는 모든 작업 상태와 시도 결과를 세고 이벤트 스트림과 마지막 커서를 기록하며 안전하지 않은 실행 중 작업을 차단하고 집계 제한 아래에서 암호화 페이로드를 인증합니다. 스트림 헤드 불일치와 스트림별 비연속 시퀀스도 거부합니다.

단조 증가 임대 토큰은 오래된 워커의 후속 데이터베이스 커밋을 차단합니다. 펜싱은 정확히 한 번 실행을 보장하지 않습니다. 워커가 외부 부작용을 완료한 뒤 성공 기록 전에 실패할 수 있습니다. 따라서 처리기 채택에는 제공자 멱등성 키 또는 트랜잭션 outbox/inbox 프로토콜과 각 부작용 직전의 행위자 권한 재검증이 필요합니다.

SQLite 마이그레이션 v4는 무작위 ID 암호문 옆에 고유한 키 기반 이메일 조회 토큰을 추가합니다. 토큰은 애플리케이션 암호화 키를 사용하는 HMAC입니다. 평문 저장이나 결정론적 암호화 없이 원자적 중복 이메일 강제를 복원합니다. 시작 시 트래픽을 허용하기 전에 모든 기존 ID 이메일을 인증하고 backfill합니다.

상태 및 복구

배포 프로브는 이제 프로세스 생존 상태와 종속성 준비 상태를 구분합니다.

  • /health/health/live는 프로세스만 확인합니다.
  • /health/ready는 데이터베이스, 표준 스키마 원장, 쓰기 가능한 데이터 저장소 및 등록된 필수 종속성을 검사하면서 세부 정보를 가립니다. 선택적 제공자를 기다리지 않습니다.
  • /health/deep은 현재 관리자를 요구하고 HTTP 이벤트 루프 밖의 제한된 워커에서 SQLite 무결성과 외래 키 검사를 실행합니다. Ollama 같은 선택적 서버 수준 제공자 프로브도 핵심 준비 상태를 바꾸지 않는 경고로 집계합니다.

libre-webui recovery-check --json을 실행하세요. 소스 체크아웃에서는 백엔드를 한 번 빌드하고 npm run recovery:check -- --json을 사용합니다. 인벤토리는 읽기 전용이며 스키마/키 ID, 로컬 blob 루트, 기존 및 플랫폼 벡터 수를 보고하고 로컬 플랫폼 blob/벡터 암호문, 기존 애플리케이션과 저장 음성 암호문, 암호화된 영속 작업/이벤트 페이로드를 인증합니다. 데이터 크기, 플러그인 정의와 백업 루트 포함 여부, 임베디드 미디어, Work 리소스와 정확한 소유권 레이블, 작업/시도/이벤트 체크포인트, 활성 Work 실행/미리보기와 작업, 차단 요인 및 알려진 제외 항목도 보고합니다. 완전한 백업이 아니라 백업 전 게이트입니다. 복구 준비 상태를 참조하세요.

인증된 다중 복제본 운영

Team 프로필은 모든 공유 종속성을 함께 설정한다는 조건으로 애플리케이션 복제본 3개 이상과 외부 영속 워커 1개 이상의 구성을 인증합니다. PostgreSQL, PGVector, Redis, S3 호환 blobs, 안정적인 공유 비밀 및 JOB_WORKER_MODE=external이 필요합니다. Helm 차트는 렌더링 시 이 사전 요구 사항을 강제합니다. 완전한 team 프로필 없이 복제본 수가 1을 넘으면 안전하지 않은 토폴로지를 배포하지 않고 렌더링이 실패합니다. 스키마 마이그레이션은 PostgreSQL advisory lock으로 단일 리더를 선출하므로 서로 다른 버전의 복제본이 원장을 두고 경쟁하지 않습니다.

인증은 희망 사항이 아니라 실행 가능합니다. 릴리스 파이프라인은 실제 이미지를 빌드하고 복제본 간 스트림 재개, 쓰기 중 워커 사망과 결정론적 재생, 권위 있는 SQL로 대체하는 Redis 중단, 조정자 손실 중 철회 강제, 공유 속도 제한 일관성, S3 삭제 재시도 및 부하 상태의 테넌트 격리를 시험하는 3복제본 훈련(npm run test:team-platform)을 실행합니다. 운영자는 secrets.existingSecret(차트 값을 Secret으로 렌더링하는 대신 운영자 관리 Secret 참조)과 networkPolicy.enabled(애플리케이션 포트 외 인바운드를 기본 거부하며 영속 워커는 인바운드를 허용하지 않음)로 pod를 더 강화할 수 있습니다. 어느 쪽이든 pod 보안 기본값은 엄격합니다. non-root, 읽기 전용 루트 파일 시스템, capability 제거, seccomp RuntimeDefault, 권한 상승 금지를 적용합니다.

남아 있는 전환 작업

기반이 마련되었다고 해서 모든 바이너리 필드가 이미 blob인 것은 아닙니다. 저장 음성 오디오, 채팅 첨부, 아바타 및 향후 플러그인 정의 바이너리 리소스는 이동 전에 명시적 참조 메타데이터, 이중 읽기/backfill, 보존 및 삭제 테스트가 필요합니다. 마찬가지로 향후 모든 임베딩 호출자는 모델, 차원, 버전, 원본 리비전, 소유자, 리소스 범위 및 신뢰할 수 있는 권한 부여를 VectorStore를 통해 전달해야 합니다. 벡터 테이블 직접 접근은 허용되는 지름길이 아닙니다.

장시간 실행되거나 외부에 보이는 새 부작용은 영속 리소스 대상을 등록하고 취소와 재시도를 지원하며 소유 관계형 변경과 함께 트랜잭션 enqueue/outbox 경계를 사용해야 합니다. Team 배포에서 활성화하기 전에 새 리소스를 복제본 간 업로드/읽기/검색/삭제 및 백업/복원 수용 게이트에 추가하세요.