- 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>
250 lines
6.6 KiB
Markdown
250 lines
6.6 KiB
Markdown
# 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. 초기 설치
|
|
|
|
```bash
|
|
# 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. 인증 정보 설정
|
|
|
|
```bash
|
|
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를 등록해야 합니다.
|
|
|
|
```bash
|
|
# 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 스케줄 등록
|
|
|
|
```bash
|
|
# 심볼릭 링크 생성
|
|
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 서버 실행
|
|
|
|
```bash
|
|
# 개발 모드 (수동 실행)
|
|
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. 수동 테스트
|
|
|
|
```bash
|
|
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. 업데이트
|
|
|
|
```bash
|
|
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. 로그 확인
|
|
|
|
```bash
|
|
# 스크립트 로그
|
|
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. 일일 운영 점검
|
|
|
|
```bash
|
|
# 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'
|
|
```
|