From 3db351002c7e8832f2509d43f071e9fbf8269143 Mon Sep 17 00:00:00 2001 From: hyungi Date: Sat, 20 Jun 2026 05:54:09 +0000 Subject: [PATCH] =?UTF-8?q?ops(hygiene):=20jwt=5Fsecret=20fail-loud=20+=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=ED=9A=8C=EC=A0=84=20+=20sqlite=20gitignor?= =?UTF-8?q?e=20+=20eval=20override=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JWT_SECRET 빈값이면 부팅 RuntimeError (구: 빈 키로 전 토큰 서명하며 침묵 부팅 = 인증붕괴). core.utils setup_logger FileHandler→RotatingFileHandler(10MB×3) — logs 무한증가 차단. .gitignore *.sqlite3 + 0바이트 db.sqlite3 제거. Phase 2A/2B closed eval override 2파일 git rm (참조 0, history 보존). lockfile 은 제외(별도). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 3 + app/core/utils.py | 5 +- app/main.py | 7 ++ docker-compose.override.cand.yml | 135 ------------------------ docker-compose.override.rerank-cand.yml | 101 ------------------ 5 files changed, 14 insertions(+), 237 deletions(-) delete mode 100644 docker-compose.override.cand.yml delete mode 100644 docker-compose.override.rerank-cand.yml diff --git a/.gitignore b/.gitignore index 1c8be9c..15d3003 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,6 @@ caddy_data/ *.bak_* *.pre-* .pre-*/ + +# SQLite 로컬 아티팩트 (Django/툴링 잔재) +*.sqlite3 diff --git a/app/core/utils.py b/app/core/utils.py index d7349f3..f64599b 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -2,6 +2,7 @@ import hashlib import logging +from logging.handlers import RotatingFileHandler from pathlib import Path @@ -13,7 +14,9 @@ def setup_logger(name: str, log_dir: str = "logs") -> logging.Logger: if not logger.handlers: # 파일 핸들러 - fh = logging.FileHandler(f"{log_dir}/{name}.log", encoding="utf-8") + fh = RotatingFileHandler( + f"{log_dir}/{name}.log", maxBytes=10 * 1024 * 1024, backupCount=3, encoding="utf-8" + ) fh.setFormatter(logging.Formatter( "%(asctime)s [%(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S" diff --git a/app/main.py b/app/main.py index 5ff002b..27197e9 100644 --- a/app/main.py +++ b/app/main.py @@ -84,6 +84,13 @@ async def lifespan(app: FastAPI): # 시작: DB 연결 확인 await init_db() + # 2026-06-20: JWT_SECRET 빈값 fail-loud — credentials.env 미로드/누락 시 빈 키로 전 토큰 + # 서명하며 부팅하던 침묵 인증붕괴 차단 (totp_secret 은 per-user 라 미가드). + if not settings.jwt_secret: + raise RuntimeError( + "JWT_SECRET 미설정 — 빈 키 서명 방지. credentials.env / 환경변수 확인." + ) + # NAS 마운트 확인 (NFS 미마운트 시 로컬 빈 디렉토리에 쓰는 것 방지) from pathlib import Path nas_check = Path(settings.nas_mount_path) / "PKM" diff --git a/docker-compose.override.cand.yml b/docker-compose.override.cand.yml deleted file mode 100644 index 59602c2..0000000 --- a/docker-compose.override.cand.yml +++ /dev/null @@ -1,135 +0,0 @@ -# Phase 2A — Embedding candidate compose override (Diagnose only) -# -# Profile-isolated: `--profile embed-cand` 명시 opt-in. default up 시 미기동. -# production fastapi/postgres/reranker 에 영향 0. -# 본 PR 종료 시 별 chore (PR-2A-Chunks-Cand-Cleanup-1) 에서 제거. -# -# 후보 상태 (2026-05-23): -# - me5_large_inst : ✅ smoke PASS (dim 1024) -# - bge_mgemma2 : ❌ Phase 2A-Extended 별 PR 이관 (9B FP16 → VRAM OOM risk + 다운로드 cost) -# - me5_ko : ❌ 폐기 (401 Unauthorized, gated/모델명 부정확) -# - snowflake_l_v2 : 신규 추가 (Snowflake/snowflake-arctic-embed-l-v2.0, 2024-12, multilingual 강화) -# -# 사용: -# docker compose -f docker-compose.yml -f docker-compose.override.cand.yml \ -# --profile embed-cand up -d embedding-cand-me5-inst -# -# 호출 (DS network 내부): -# http://embedding-cand-me5-inst:80/embed -# http://embedding-cand-snowflake-l-v2:80/embed - -services: - embedding-cand-me5-inst: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - restart: unless-stopped - container_name: hyungi_document_server-embedding-cand-me5-inst-1 - expose: - - "80" - environment: - - MODEL_ID=intfloat/multilingual-e5-large-instruct - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - embedding_cand_me5_inst_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - profiles: ["embed-cand"] - - embedding-cand-snowflake-l-v2: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - restart: unless-stopped - container_name: hyungi_document_server-embedding-cand-snowflake-l-v2-1 - expose: - - "80" - environment: - - MODEL_ID=Snowflake/snowflake-arctic-embed-l-v2.0 - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - embedding_cand_snowflake_l_v2_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - profiles: ["embed-cand"] - - # ===== 비활성 후보 (Phase 2A-Extended 별 PR 이관 또는 폐기) ===== - # 진단 박제만 보존. 본 PR scope 외. - - embedding-cand-bge-mgemma2: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - container_name: hyungi_document_server-embedding-cand-bge-mgemma2-1 - expose: - - "80" - environment: - - MODEL_ID=BAAI/bge-multilingual-gemma2 - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - embedding_cand_bge_mgemma2_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 300s - profiles: ["embed-cand-extended"] # 본 PR 미사용. extended 별 profile. - - embedding-cand-me5-ko: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - container_name: hyungi_document_server-embedding-cand-me5-ko-1 - expose: - - "80" - environment: - - MODEL_ID=dragonkue/multilingual-e5-large-ko - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - embedding_cand_me5_ko_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - profiles: ["embed-cand-disabled"] # 401 fail. 사용 X. - -volumes: - embedding_cand_me5_inst_cache: - embedding_cand_snowflake_l_v2_cache: - embedding_cand_bge_mgemma2_cache: - embedding_cand_me5_ko_cache: diff --git a/docker-compose.override.rerank-cand.yml b/docker-compose.override.rerank-cand.yml deleted file mode 100644 index 6ffe16e..0000000 --- a/docker-compose.override.rerank-cand.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Phase 2B — Reranker candidate compose override (Diagnose only) -# -# Profile-isolated: `--profile rerank-cand` 명시 opt-in. default up 시 미기동. -# production fastapi/postgres/reranker(bge-reranker-v2-m3) 에 영향 0. -# 본 PR 종료 후 별 chore (PR-2B-Rerank-Cand-Cleanup-1) 에서 제거. -# -# 후보 상태 (2026-05-23): -# - gte_ml_base : Apache 2.0, 305M, smoke 대기 -# - mxbai_large : Apache 2.0, ~435M, safetensors 부재 — TEI smoke risk -# - bge_v2_gemma_2b : Gemma 라이센스, 2.5B FP16 ~5GB, smoke 대기 -# -# 사용: -# docker compose -f docker-compose.yml -f docker-compose.override.rerank-cand.yml \ -# --profile rerank-cand up -d rerank-cand-gte-ml-base - -services: - rerank-cand-gte-ml-base: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - restart: unless-stopped - container_name: hyungi_document_server-rerank-cand-gte-ml-base-1 - expose: - - "80" - environment: - - MODEL_ID=Alibaba-NLP/gte-multilingual-reranker-base - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - rerank_cand_gte_ml_base_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - profiles: ["rerank-cand"] - - rerank-cand-mxbai-large: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - restart: unless-stopped - container_name: hyungi_document_server-rerank-cand-mxbai-large-1 - expose: - - "80" - environment: - - MODEL_ID=mixedbread-ai/mxbai-rerank-large-v1 - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=4 - volumes: - - rerank_cand_mxbai_large_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 60s - profiles: ["rerank-cand"] - - rerank-cand-bge-v2-gemma-2b: - image: ghcr.io/huggingface/text-embeddings-inference:1.7 - restart: unless-stopped - container_name: hyungi_document_server-rerank-cand-bge-v2-gemma-2b-1 - expose: - - "80" - environment: - - MODEL_ID=BAAI/bge-reranker-v2-gemma - - MAX_BATCH_TOKENS=8192 - - MAX_CONCURRENT_REQUESTS=2 - volumes: - - rerank_cand_bge_v2_gemma_2b_cache:/data - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 120s - profiles: ["rerank-cand"] - -volumes: - rerank_cand_gte_ml_base_cache: - rerank_cand_mxbai_large_cache: - rerank_cand_bge_v2_gemma_2b_cache: