임대 원격 Mac에서 Ollama 배치 추론과 OpenClaw 에이전트를 함께 두는 재현 절차입니다. 루프백·프록시로 API를 나누고, 서버와 큐에서 동시성을 캡한 뒤 재시도·폴백으로 야간 작업을 안정화합니다. 홈 · 노트 · 도움말.
목표와 권장 토폴로지
동시 요청 과다는 VRAM 스왑·타임아웃 연쇄로 이어집니다. 임대 Mac에서는 역할을 층으로 나눕니다.
- Ollama —
127.0.0.1:11434에서만 로컬 모델 런타임으로 동작. - OpenClaw 게이트웨이 —
127.0.0.1:18789, 컨트롤 플레인·에이전트·도구(공식 Docker·CLI 문서 참고). - 선택적 에지 — 내부 VPN 클라이언트가 HTTPS 단일 호스트명을 써야 할 때만 동일 호스트에 Caddy나 Nginx. 그렇지 않으면 노트북에서 SSH 로컬 포워딩으로 충분합니다.
- 큐 워커 — 한 줄 한 작업 형식의 프롬프트를 읽고,
-P병렬 상한과 백오프를 강제하는 셸 또는 소규모 Python 드라이버.
심화 하드닝은 OpenClaw Docker·프로덕션·원격 Mac 글을 참고하세요.
macOS(원격 Mac)에 Ollama 설치
공식 스크립트로 설치 후 모델을 미리 pull합니다. OLLAMA_NUM_PARALLEL 등은 프로필이나 launchd에 고정하세요.
curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3.2
스모크 테스트:
curl -fsS http://127.0.0.1:11434/api/tags
OpenAI 호환은 /v1/chat/completions로 같은 리스너에 매핑합니다.
OpenClaw 게이트웨이: Ollama와 공존할 때의 설치 포인트
문서상 1급 경로는 전역 CLI(Node 24·22.16+)와 저장소의 ./scripts/docker/setup.sh입니다.
- CLI + 데몬 —
npm install -g openclaw@latest후openclaw onboard --install-daemon, 반복 실험 시openclaw gateway --port 18789 --verbose. - Docker — 설정·워크스페이스를 데이터 볼륨에 마운트해 재프로비저닝 후에도 로그와 에이전트 상태가 남도록 구성.
Ollama는 Metal 네이티브로 단독 두고, OpenClaw는 127.0.0.1:11434를 호출하게 합니다. 헬스:
curl -fsS http://127.0.0.1:18789/healthz
API 라우팅: 하나의 호스트명, 두 업스트림
TLS는 한 번 종료하고 경로로 분기합니다. Caddy 예시:
inference.internal.example.com {
route /v1/* {
reverse_proxy 127.0.0.1:11434
}
route /openclaw/* {
reverse_proxy 127.0.0.1:18789
}
}
엣지에 속도 제한을 겹치고, 사내망이 아니면 ssh -L로 두 포트만 터널링합니다.
라우팅 결정 요약
| 트래픽 | 대상 | 이유 |
|---|---|---|
배치 /api/generate 또는 OpenAI 호환 |
127.0.0.1:11434 |
지연 최소, 루프백 또는 인증된 프록시 뒤에 둠. |
| 게이트웨이 UI·WS 컨트롤 | 127.0.0.1:18789 |
/healthz로 상태 확인, 디버깅 시 SSH 터널. |
| 신뢰할 수 없는 인터넷 | 기본적으로 없음 | VPN·SSH·상호 TLS 등으로 보호 전에는 공개하지 않음. |
큐 스크립트: 동시성 캡과 JSON 안전 페이로드
한 줄 한 작업 prompts.txt. JSON은 python3, 병렬은 GNU xargs -P(macOS는 gxargs 또는 ThreadPoolExecutor).
#!/usr/bin/env bash
set -euo pipefail
OLLAMA_URL="${OLLAMA_URL:-http://127.0.0.1:11434}"
MODEL="${MODEL:-llama3.2}"
MAX_JOBS="${MAX_JOBS:-2}"
PROMPTS="${1:?path to prompts.txt}"
mkdir -p out failed
run_one() {
local i="$1" line="$2"
local body try=0 delay=1
body="$(python3 -c 'import json,sys; print(json.dumps({"model":sys.argv[1],"prompt":sys.argv[2],"stream":False}))' "$MODEL" "$line")"
while (( try < 4 )); do
if curl -fsS --max-time 600 -H 'Content-Type: application/json' \
-d "$body" "$OLLAMA_URL/api/generate" -o "out/resp-$i.json"; then
return 0
fi
sleep "$delay"
delay=$(( delay * 2 ))
try=$(( try + 1 ))
done
printf '%s\n' "$line" >> failed/prompts-$i.txt
return 1
}
export -f run_one
export OLLAMA_URL MODEL
nl -ba "$PROMPTS" | while read -r num line; do
printf '%s\0' "$num|$line"
done | xargs -0 -n1 -P"$MAX_JOBS" bash -c 'IFS="|" read -r num line <<<"$1"; run_one "$num" "$line"' _
MAX_JOBS는 VRAM·OLLAMA_NUM_PARALLEL 이하로; 16GB·7B급은 1부터 점진 증가.
리소스 한도: Ollama·macOS·배치 드라이버
아래를 겹쳐 캡합니다.
- Ollama —
OLLAMA_NUM_PARALLEL·필요 시OLLAMA_MAX_LOADED_MODELS. - 큐 —
MAX_JOBS≤ 서버 병렬 + 다른 작업 여유. - macOS —
launchd·선택SoftResourceLimits/HardResourceLimits. - OpenClaw — cron 피크가 Ollama 배치와 겹치지 않게.
디그레이션과 재시도
HTTP 실패는 예제처럼 지수 백오프. 모델 단계 폴백 순서:
- 1차 모델 — 풀 컨텍스트·품질 우선.
- 폴백 모델 — OOM 유사 오류나 연속 500일 때 더 작은 양자화나 레이어 수.
- 절단 — 프롬프트 길이 클램프·ID 로그.
- 데드 레터 —
failed/후 재큐.
총 시도 상한(예: 네 번)으로 독 프롬프트가 큐 전체를 막지 않게 합니다.
FAQ
모든 인터페이스 바인드? 비권장. 루프백+SSH/VPN·프록시 인증이 기본입니다.
동시성 상한 위치? Ollama·프록시·큐 세 층.
역할 분리? OpenClaw=게이트웨이, Ollama=추론 HTTP, 프로세스 분리.
타임아웃 다발? --max-time·백오프·작은 모델·데드 레터, 무한 재시도 금지.
검증? /api/tags·/healthz curl, 외부는 SSH 터널.