Files
hyungi_document_server/docs/deploy.md
hyungi 45cabc9aea refactor: GPU 서버 재구성 + ChromaDB→Qdrant 마이그레이션
- embed_to_chroma.py → embed_to_qdrant.py 리라이트 (bge-m3 + Qdrant REST API)
- auto_classify.scpt: embed_to_qdrant.py 경로 변경 + sourceChannel 덮어쓰기 버그 수정
- requirements.txt: chromadb/schedule 제거, qdrant-client/flask/gunicorn 추가
- credentials.env.example: GPU_SERVER_IP 항목 추가
- GPU 서버 재구성 계획서 (docs/gpu-restructure.md) + dev-roadmap/commands 통합
- CLAUDE.md, README.md, deploy.md 현행화

GPU 서버 변경사항 (이미 적용됨):
  - Ollama: qwen3.5:9b, id-9b 제거 → bge-m3 + bge-reranker-v2-m3
  - Surya OCR 서비스 (:8400, systemd)
  - Docker + NFS + Komga 이전 (:25600)
  - tk-ai-service: Ollama API → OpenAI API 전환 (MLX 35B)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 13:19:31 +09:00

6.6 KiB

Mac mini 배포 가이드

마지막 업데이트: 2026-03-29 대상: Mac mini M4 Pro (macOS, Python 3.11+)

요구사항

  • macOS 14+ (Sonoma 이상)
  • Python 3.11+ (Homebrew 설치 권장)
  • DEVONthink 4 — 실행 중이어야 AppleScript 동작
  • OmniFocus 4 — 실행 중이어야 AppleScript 동작
  • MLX 서버 — Qwen3.5-35B-A3B, localhost:8800에서 실행 중
  • Tailscale — NAS 및 GPU 서버 접근용

1. 초기 설치

# Mac mini에서
cd ~/Documents/code/
git clone https://git.hyungi.net/hyungi/devonthink_home.git "DEVONThink_my server"
cd "DEVONThink_my server"

# Python 가상환경
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

2. 인증 정보 설정

mkdir -p ~/.config/pkm
nano ~/.config/pkm/credentials.env
chmod 600 ~/.config/pkm/credentials.env

credentials.env.example을 참고하여 실제 값 입력:

# 필수
LAW_OC=<법령API키>
MAILPLUS_HOST=mailplus.hyungi.net
MAILPLUS_PORT=993
MAILPLUS_USER=hyungi
MAILPLUS_PASS=<비밀번호>
NAS_DOMAIN=ds1525.hyungi.net
NAS_TAILSCALE_IP=100.101.79.37
NAS_PORT=15001

# 선택 (향후)
CLAUDE_API_KEY=<키>
#CHAT_WEBHOOK_URL=<Synology Chat 웹훅>
#GPU_SERVER_IP=<Tailscale IP>

3. 한국 법령 API IP 등록

법령 API 호출 전에 Mac mini의 공인 IP를 등록해야 합니다.

# Mac mini에서 공인 IP 확인
curl -s ifconfig.me

# open.law.go.kr → 로그인 → 마이페이지 → 인증키 관리
# 위에서 확인한 IP를 서버 IP로 등록
# ※ Tailscale IP(100.x.x.x)가 아니라 실제 공인 IP

# 등록 후 테스트
source venv/bin/activate
python scripts/law_monitor.py
# → "법령 API 에러" 없이 정상 동작 확인

4. launchd 스케줄 등록

# 심볼릭 링크 생성
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.law-monitor.plist ~/Library/LaunchAgents/
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.mailplus.plist ~/Library/LaunchAgents/
ln -sf ~/Documents/code/DEVONThink_my\ server/launchd/net.hyungi.pkm.daily-digest.plist ~/Library/LaunchAgents/

# 등록
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.mailplus.plist
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.daily-digest.plist

# 확인
launchctl list | grep pkm

5. PKM API 서버 실행

# 개발 모드 (수동 실행)
cd ~/Documents/code/DEVONThink_my\ server/
source venv/bin/activate
python scripts/pkm_api_server.py

# 프로덕션 모드 (gunicorn, Phase 3 이후)
# gunicorn -w 2 -b 127.0.0.1:9900 scripts.pkm_api_server:app

# 동작 확인
curl http://localhost:9900/health
curl http://localhost:9900/devonthink/inbox-count

API 서버는 GUI 세션에서 실행해야 합니다 (AppleScript가 DEVONthink/OmniFocus GUI에 접근).

6. DEVONthink Smart Rule 설정

  1. DEVONthink → Preferences → Smart Rules
  2. 새 Rule: "AI Auto Classify"
    • Event: On Import
    • Database: Inbox
    • Condition: Tags is empty
    • Action: Execute Script → External → applescript/auto_classify.scpt
  3. 새 Rule: "OmniFocus Sync"
    • Event: On Import
    • Database: Projects
    • Action: Execute Script → External → applescript/omnifocus_sync.scpt

7. 수동 테스트

cd ~/Documents/code/DEVONThink_my\ server/
source venv/bin/activate

# 각 스크립트 수동 실행
python3 scripts/law_monitor.py
python3 scripts/mailplus_archive.py
python3 scripts/pkm_daily_digest.py

# AI 분류 테스트
python3 tests/test_classify.py

8. 업데이트

cd ~/Documents/code/DEVONThink_my\ server/
git pull
source venv/bin/activate
pip install -r requirements.txt

# launchd 재로드 (plist가 변경된 경우만)
launchctl unload ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
launchctl load ~/Library/LaunchAgents/net.hyungi.pkm.law-monitor.plist
# (나머지도 동일)

9. 로그 확인

# 스크립트 로그
tail -f logs/law_monitor.log
tail -f logs/mailplus.log
tail -f logs/digest.log

# API 서버 로그
tail -f logs/pkm-api.log
tail -f logs/pkm-api.error.log

# launchd 시스템 로그
log show --predicate 'process == "python3"' --last 1h

10. 일일 운영 점검

# 1. launchd 작업 상태
launchctl list | grep pkm

# 2. 오늘의 로그 에러 확인
grep -c ERROR logs/law_monitor.log
grep -c ERROR logs/mailplus.log

# 3. 법령 마지막 확인 시간
cat data/law_last_check.json | python3 -m json.tool

# 4. DEVONthink Inbox 미처리 건수 (API 서버 실행 중이면)
curl -s http://localhost:9900/devonthink/inbox-count

# 5. MLX 서버 상태
curl -s http://localhost:8800/v1/models | python3 -m json.tool

실행 스케줄

스크립트 시간 용도
law_monitor.py 매일 07:00 법령 변경 모니터링 (한국+US/JP/EU)
mailplus_archive.py 매일 07:00, 18:00 MailPlus 이메일 수집
pkm_daily_digest.py 매일 20:00 일일 다이제스트 생성
pkm_api_server.py 상시 (수동/launchd) REST API (포트 9900)

트러블슈팅

법령 API "사용자 정보 검증 실패"

원인: Mac mini 공인 IP가 open.law.go.kr에 등록되지 않음
해결:
1. curl -s ifconfig.me 로 현재 공인 IP 확인
2. open.law.go.kr → 마이페이지 → 인증키 관리 → IP 등록
3. IP가 변경되면 다시 등록 필요 (고정 IP 아닌 경우)

MailPlus IMAP Connection refused

확인 순서:
1. Synology DSM → MailPlus Server → 서비스 상태 확인
2. IMAP 활성화: DSM → MailPlus Server → 메일 전송 → IMAP 탭
3. 포트: 993(SSL) vs 143(STARTTLS)
4. 방화벽: Synology 방화벽에서 993 포트 확인
5. Tailscale 직접:
   python3 -c "import imaplib; m=imaplib.IMAP4_SSL('100.101.79.37', 993); print('OK')"

AppleScript 실행 오류

확인:
1. DEVONthink, OmniFocus가 GUI로 실행 중인지 확인
2. 접근성 권한: 시스템 설정 → 개인정보 보호 → 접근성 → python/osascript 허용
3. 수동 테스트:
   osascript -e 'tell application "DEVONthink 3" to get name of databases'

MLX 서버 응답 없음

확인:
1. MLX 서버 프로세스 확인: ps aux | grep mlx
2. 포트 확인: lsof -i :8800
3. 모델 로드 확인: curl http://localhost:8800/v1/models
4. 재시작 필요 시: (MLX 서버 시작 명령어 실행)

Daily Digest에 데이터가 비어있음

확인:
1. DEVONthink이 실행 중인지 확인
2. OmniFocus가 실행 중인지 확인
3. 로그 확인: tail -20 logs/digest.log
4. AppleScript 직접 테스트:
   osascript -e 'tell application "DEVONthink 3" to get count of databases'