Files
obsidian/ops-agents/overview.md
kaffa d25dc3e52f obsidian 정합성 정정 — bouncer 단일화 잔존 stale 정리
- infra/compute/infra-hosts.md: jp1 default 20→19, cs-cf-worker-bouncer 컨테이너 라인에서 제거
- services/bunnycdn-security.md: Edge Script 64811 / bloom filter / 국가차단 / Turnstile inouter-bunny 폐기 반영. 현재 layer (Bunny Shield + Rate Limit + 대역폭 한도) 중심 재작성
- infra/network/apisix.md: Edge Script 64811 attach 라인 폐기 표시
- infra/security/cloudflare.md: Workers 인벤토리 + Worker 라우트 + CF proxy 패턴 + cfb-manager 절 모두 폐기 반영
- infra/security/crowdsec-safeline.md: cs-cf-worker-bouncer 운영 중 문장 폐기 표시
- ops-agents/overview.md: Syn 영역 정의에서 폐기 자산 명시
- history/_index.md: 누락된 2026-04-25-netbis-npm-vector-msg-rewrite, 2026-04-26-bouncer-consolidation 등록 + frontmatter updated
2026-04-26 10:33:48 +09:00

13 KiB

title, updated, tags
title updated tags
내부 운영 에이전트 (Ops Agents) 2026-04-10
agent
ops
claude-code

kappa가 혼자 쓰는 내부 인프라·운영 자동화 Claude Code 에이전트 집합. 고객 대상 OpenClaw 에이전트(jp1 agents 프로젝트, anvil/stamp/flux 등)와는 완전히 분리된 영역. 외부 클라우드 BM 프로비저닝(jp1 infra-tool 의 Tofu API)과도 무관.

명명 규칙: 북유럽 신화 (Heimdall = 파수꾼, Syn = 문지기, …). OpenClaw 쪽은 대장간/중세 기능 네이밍(anvil/forge/smelt/stamp/…)이라 자연스럽게 분리됨.

에이전트 목록

이름 호스트 Incus 프로젝트 IP 역할 비고
heimdall kr1 ops 10.100.3.108 인프라 전반 (K3s, Incus, Longhorn, 스토리지, 네트워크, 일반 서비스) tofu 관리 (kaffa/ops-agents-tofu/heimdall)
syn hp2 ops 10.100.2.173 엣지 레이어 전담 (BunnyCDN, SafeLine WAF, APISIX, Cloudflare 엣지) tofu 관리 (kaffa/ops-agents-tofu/syn)
skuld hp2 ops 10.100.2.45 플래너 (작업 분해, 우선순위, 일정 조율, 의사결정 지원) tofu 관리 (kaffa/ops-agents-tofu/skuld)

공통 원칙

통신 프로토콜 (ssh + tmux send-keys 체인)

모든 내부 에이전트는 한 줄 태그 포맷으로 서로와 kappa에 신호 전송:

태그 의미
[SYN DONE] ... 작업 완료
[SYN FAIL] ... 실패 (원인 한 줄)
[SYN ASK] ... 결정/입력 필요
[SYN PROGRESS] ... 중간 이정표 (드물게)
[SKULD DONE] ... 작업 완료
[SKULD FAIL] ... 실패 (원인 한 줄)
[SKULD ASK] ... 결정/입력 필요
[SYN→HEIMDALL] ... / [HEIMDALL→SYN] ... 피어 투 피어
[SKULD→HEIMDALL] ... / [SKULD→SYN] ... Skuld 피어 통신
[SYN CC] ... / [HEIMDALL CC] ... / [SKULD CC] ... 피어 대화를 kappa 에 CC

핵심 규칙: 한 줄만. 상세는 자기 tmux 창 또는 Outline agent-qna 문서에 남기고, 신호에는 포인터만.

통신 경로

  • kappa Mac → Syn: tmux send-keys -t 0:0 '...' Enter (window 0 이 syn-login, ssh 체인 유지)
  • kappa Mac → Heimdall: ssh kaffa@10.100.3.108 'tmux send-keys -t heimdall ...'
  • Syn → kappa Mac: ssh kaffa@100.106.245.27 '/opt/homebrew/bin/tmux send-keys -t 0:1 ...'
  • Syn → Heimdall: ssh kaffa@10.100.3.108 'tmux send-keys -t heimdall ...'
  • Heimdall → Syn: ssh kaffa@100.106.245.27 '/opt/homebrew/bin/tmux send-keys -t 0:0 ...' (경유 필요)
  • kappa Mac → Skuld: ssh kaffa@10.100.2.45 'tmux send-keys -t skuld ...'
  • Skuld → kappa Mac: ssh kaffa@100.106.245.27 '/opt/homebrew/bin/tmux send-keys -t 0:1 ...'
  • Skuld → Heimdall: ssh kaffa@10.100.3.108 'tmux send-keys -t heimdall ...'
  • Skuld → Syn: ssh kaffa@10.100.2.173 'tmux send-keys -t syn ...'

Syn, Skuld 컨테이너는 hp2 subnet routing 덕분에 Tailscale 설치 없이 tailnet의 다른 노드(kappa Mac 100.106.245.27, heimdall 10.100.3.108 등)에 직접 reachable. 호스트의 tailscale0 interface가 container bridge 로 투명하게 열려있음 — 2026-04-09 실측 확인. heimdall(kr1)의 incusbr0 역시 동일하게 tailnet 노출됨.

SSH identity

모든 ops 에이전트는 공유 ed25519 키 "ops-agents@kaffa" 를 사용 (Vault secret/apps/ops-agents-ssh · private_key / public_key). 이 키는:

  • /home/kaffa/.ssh/id_ed25519 에 각 컨테이너 cloud-init 시 자동 배치 (tofu ssh_private_key 변수 → base64encode → tftpl write_files)
  • authorized_keys 기본값에 포함되어 모든 에이전트가 피어로부터 inbound SSH 허용
  • kappa Mac ~/.ssh/authorized_keys 에도 추가되어 에이전트 → kappa CC 채널 지원

보안 tradeoff: 공유 키라서 1개 에이전트 compromise = 전체 ops-agents compromise. 이미 동일 blast radius (모두 kappa 사설 인프라, 상호 완전 신뢰) 라서 수용. 개별 키 관리 부담(신규 provisioning 마다 수동 pubkey 배포) 대비 운영 단순성이 우선.

fingerprint: SHA256:eBCIglGmK/FnDxJLqxT0CJvRGFEGaIKRWnZ3ZpTaugU

역할 분담 원칙

Heimdall 전담 (Syn 손대지 말 것):

  • K3s 클러스터 전반 (노드, Longhorn, 일반 워크로드)
  • Incus 호스트 관리
  • 스토리지, 네트워크 (Tailscale/OpenWrt/HAProxy)
  • 일반 서비스 파드 (Outline/Gitea/Vault 본체 등)
  • Obsidian 정본 전체 쓰기 권한

Syn 전담 (Heimdall 손대지 말 것):

  • BunnyCDN: 풀존, Shield/WAF, Rate Limit, MonthlyBandwidthLimit, 캐시 정책 (Edge Script 64811 crowdsec-bouncer-middleware는 2026-04-26 폐기)
  • SafeLine WAF: K3s safeline ns, Traefik middleware, 탐지 규칙, APISIX 통합
  • APISIX: 모든 인스턴스 (K3s 서울 / osaka-gw / sandbox-tokyo / zlambda), 라우트, 플러그인, Admin API
  • Cloudflare 엣지 관련: Turnstile 위젯, Worker 라우트 (cs-cf-worker-bouncer / cfb-manager는 2026-04-26 폐기)
  • Obsidian 중 엣지 범위 파일 쓰기: infra/network/apisix.md, infra/security/crowdsec-safeline.md 의 엣지 섹션, services/bunnycdn*.md

공동/협업:

  • CrowdSec 시나리오: Heimdall 소유, Syn은 APISIX/SafeLine용 시나리오 파라미터 튜닝 제안만
  • 두 에이전트 모두 OpenMemory·Outline 읽기·쓰기 OK (MCP 경유). Vault는 kappa 게이트웨이 ASK-only (아래 섹션).

Vault 접근 — kappa 게이트웨이 프로토콜

2026-04-09 도입. 에이전트는 Vault에 직접 접근할 수 없다. 중앙 집중 감사·블라스트 래디우스 제한이 목적.

구현:

  • Heimdall ~/.mcp.json · Syn ~/syn/.mcp.json 에서 vault 항목 완전 제거
  • 두 에이전트 모두 mcp__vault__* 도구를 물리적으로 호출 불가
  • CLAUDE.md 에 규칙·포맷 명시

프로토콜:

단계 행위자 포맷
1 에이전트 [SYN ASK] vault:<path> <key> 필요 (용도: <한줄>) → kappa tmux 0:1 에 주입
2 kappa Vault 조회 (MCP mcp__vault__read_secret)
3a kappa [KAPPA->SYN] <path> <key> = <value> → 에이전트 tmux 에 주입 (성공)
3b kappa [KAPPA->SYN] DENIED: <사유/정정힌트> → 에이전트 tmux 에 주입 (거절)
4 에이전트 값 사용·즉시 폐기, 파일/OpenMemory/Obsidian 평문 저장 금지
5 에이전트 [SYN DONE] vault ... 수신 확인, 미저장 폐기 CC

규칙:

  • ASK 한 번에 여러 키를 동시 요청 가능 (같은 작업 범위 내)
  • 예외 없음 — bunnycdn/openmemory/nocodb 등 다른 MCP는 그대로 동작
  • 환경변수 잔존($VAULT_TOKEN, $VAULT_ADDR) 신뢰 금지
  • 검증: Syn + Heimdall 양쪽에서 e2e 테스트 완료 (DENIED 경로 포함)

이점:

  • 기술적 격리 (에이전트가 규칙을 잊거나 혼동해도 Vault 도달 불가)
  • 중앙 감사 로그 (kappa 세션 대화 히스토리에 모든 ASK/응답 기록)
  • 동기 승인 (kappa 부재 시 자동 차단)

한계:

  • kappa 세션 활성 상태 필요 (에이전트 자율 작업 중 kappa 부재 시 시크릿 요구 작업 blocking)
  • kappa 세션 대화 히스토리에 시크릿 평문 잔존 (/clear 또는 세션 종료 시 사라짐)
  • kappa 본인의 MCP 권한 남용 방지책은 별도 필요 (vault audit log on Vault 서버 사이드 병행 권장)

배포 관리

Heimdall

  • OpenTofu 관리: kaffa/ops-agents-tofu/heimdall (2026-04-09 재생성)
  • 변경 플로우: 로컬 clone → heimdall/ 에서 tofu plantofu apply
  • State: 로컬 terraform.tfstate (gitignore, 수동 백업)
  • Secrets (terraform.tfvars): Vault secret/apps/gitea 참조, 커밋 금지

Syn

  • OpenTofu 관리: kaffa/ops-agents-tofu (2026-04-09 신규)
  • 변경 플로우: 로컬 clone → syn/ 에서 tofu plantofu apply
  • State: 로컬 terraform.tfstate (gitignore, 수동 백업). 향후 R2 s3 backend 이주 검토.

Skuld

  • OpenTofu 관리: kaffa/ops-agents-tofu/skuld (2026-04-10 신규)
  • 변경 플로우: 로컬 clone → skuld/ 에서 tofu plantofu apply
  • State: 로컬 terraform.tfstate (gitignore, 수동 백업)
  • Secrets (terraform.tfvars): Vault 참조, 커밋 금지

런타임 설정 (heimdall · syn 공통)

두 에이전트 모두 동일한 워크스페이스 패턴:

  • 베이스 이미지: Debian 13 cloud (incus images:debian/13/cloud)
  • 유저: kaffa (uid 1000, NOPASSWD sudo)
  • 셸: fish
  • Claude Code 공식 인스톨러 (curl -fsSL https://claude.ai/install.sh | bash), npm 미사용
  • uv / uvx (MCP 서버·Python 실행)
  • 리소스 limit: heimdall 8 GiB / 4 vCPU · syn 4 GiB / 4 vCPU · skuld 4 GiB / 4 vCPU

파일 레이아웃 (컨테이너 내부)

경로 레벨 내용
/home/kaffa/<agent>/CLAUDE.md workspace 에이전트 persona / 범위 / 프로토콜
/home/kaffa/<agent>/.mcp.json workspace 프로젝트 MCP 서버 목록
/home/kaffa/<agent>/{runbooks 하위} workspace 레이어별 운영 런북 (syn: bunnycdn/cloudflare/safeline/apisix)
/home/kaffa/.claude/settings.json user-global allowlist, enabledPlugins
/home/kaffa/.claude/.credentials.json user-global Claude Code OAuth
/home/kaffa/.claude/plugins/ user-global 플러그인 marketplace
/home/kaffa/.claude.json user-global 프로젝트 상태, trust 플래그
/home/kaffa/obsidian/ user-global Obsidian vault clone (별도 git)
/home/kaffa/.ssh/id_ed25519 user-global 공유 ops-agents@kaffa

systemd 서비스

에이전트 서비스 WorkingDirectory ExecStart
heimdall heimdall-tmux.service /home/kaffa/heimdall tmux new-session -d -s heimdall "claude"
syn syn-tmux.service /home/kaffa/syn tmux new-session -d -s syn "claude --dangerously-skip-permissions"
skuld skuld-tmux.service /home/kaffa/skuld tmux new-session -d -s skuld "claude --dangerously-skip-permissions"

heimdall 은 --dangerously-skip-permissions 플래그를 사용하지 않음settings.json allowlist 로 대체. syn, skuld 는 플래그 유지.

tofu repo 워크스페이스 정본

변경 시 kaffa/ops-agents-tofu 하위 워크스페이스 디렉토리에서 작업 → commit/push:

  • heimdall-workspace/{CLAUDE.md, mcp.json, runbooks/{k3s,incus,longhorn,network,patroni,storage}}/home/kaffa/heimdall/{CLAUDE.md, .mcp.json, runbooks/}
  • syn-workspace/{CLAUDE.md, mcp.json, runbooks/{bunnycdn,cloudflare,safeline,apisix}}/home/kaffa/syn/{CLAUDE.md, .mcp.json, <런북들 top-level>}
  • skuld-workspace/{CLAUDE.md, mcp.json}/home/kaffa/skuld/{CLAUDE.md, .mcp.json}

자동 전개: cloud-init runcmd 가 부팅 시 ops-agents-tofu repo 를 git clone --depth=1 로 가져와 위 매핑대로 /home/kaffa/<agent>/ 에 복사 + clone 정리. 신규 컨테이너 provisioning 시 manual scp 단계 0.

라이브 컨테이너에 워크스페이스 변경 반영 시:

  • 직접 수정 + repo 에 commit/push (정합성)
  • 또는 repo 변경 후 scp 로 sync

시크릿 환경변수 (heimdall)

heimdall 은 .mcp.json 안에 토큰을 평문으로 두지 않는다. 패턴:

  1. Vault secret/apps/<service> 에 토큰 저장
  2. tofu 변수 <service>_mcp_token (sensitive) 에 주입 (terraform.tfvars 는 gitignore)
  3. cloud-init 이 /etc/heimdall/env (root:kaffa 0640) 에 KEY=value 형식으로 작성
  4. systemd heimdall-tmux.serviceEnvironmentFile=/etc/heimdall/env 로 로드
  5. .mcp.json 의 stdio 서버는 command: "sh", args: ["-c", "exec npx ... --header \"X: $KEY\""] 로 expansion

현재 적용 대상:

  • NOCODB_MCP_TOKEN (Vault secret/apps/nocodb.mcp_token)
  • NOCODB_MCP_URL (Vault secret/apps/nocodb.mcp_url)

syn 은 현재 토큰 필요한 MCP 가 없어 env file 미사용 (필요 시 동일 패턴 적용 가능).

  • systemd syn-tmux.service (enabled, 첫 로그인 후 수동 start)

향후 확장 후보

내부 에이전트를 더 찍어낸다면 (Tofu 템플릿화 완료 후):

이름 (북유럽) 역할 후보
Mimir 지식·메모리 관리 (Obsidian 정합성, OpenMemory 큐레이션)
Forseti 분쟁 조정 — CI/CD, PR 리뷰, 코드 품질
Bragi 프론트엔드·UX·카피
Eir 헬스체크·복구·장애 대응
Vör 관찰성 (VictoriaMetrics/Logs/Grafana)

이름 예약만. 실제 생성은 필요 시점에.

참조