로컬 모델에 SSH 액세스를 안전하게 주는 방법은 절대 키를 주지 않는 것입니다. 대신 도구를 호출하게 하세요 — 커스터디언 역할을 하는 MCP 서버로, 키를 보관하고(또는 단기 인증서를 발급하고), 내가 목록에 올린 호스트에만 닿고, 호스트별 명령 허용 목록을 강제하며, 하나하나를 로그로 남깁니다. 그러면 탈취된 프롬프트는 커스터디언을 통해 동작을 요청할 수 있을 뿐, 내 신원을 가로채거나 목록에 없는 호스트에 닿을 수는 없습니다. 사람들이 가장 먼저 오해하는 것: 모델을 내 하드웨어에서 돌리면 프롬프트는 보호되지만 서버는 보호되지 않습니다 — “로컬이니까 안전하다”는 말은 사실이 아니며, 그 모델이 셸을 쥐었을 때 벌어지는 일에 대해서는 아무것도 하지 않습니다.
로컬 모델이 전성기를 맞고 있습니다. 워크스테이션의 Ollama, 내 엔드포인트 뒤의 오픈 웨이트 모델, 자체 호스팅 코딩 에이전트 — 그럴 만한 이유로 돌립니다. 프라이버시, 비용, 요청 제한 없음, 비행기에서도 동작. 그리고 모델이 이미 내 프롬프트를 다루고 있으면, 다음 수순은 뻔하게도 그것을 내 인프라로 겨누는 것입니다. 로그를 tail 하게 하고, 서비스를 재시작하게 하고, 마이그레이션을 돌리게 하는 것 — 바로 여기서 진짜 질문이 떨어집니다.
“로컬”이라고 서버 액세스가 안전해지지는 않는다
모델이 데이터센터에서 돌든 책상 밑 서버에서 돌든, 똑같이 위험한 것이 두 가지 있습니다.
키는 여전히 소지자 자격 증명입니다. id_ed25519를 에이전트 환경에 넣어 직접 ssh를 실행하게 하면, 그 바이트를 쥔 사람이든 무엇이든 그 키를 신뢰하는 모든 호스트에서 곧 나 자신입니다. 모델을 로컬에서 돌린다고 그 점이 바뀌지는 않습니다. 복사본을 마침 내가 소유한 머신으로 옮길 뿐입니다. 그리고 여전히 되돌릴 수 없습니다. 키가 모델의 컨텍스트를 한 번 거치고 나면 — 환경 변수, 마운트된 파일, 도구 호출, 트랜스크립트 — 그것이 있어서는 안 될 곳으로 흘러가지 않았음을 더는 증명할 수 없습니다. “모델이 내 키를 봤나?”에 대한 유일하게 정직한 답은 모든 호스트에서 키를 교체하는 것입니다.
로컬 모델도 여전히 혼란에 빠집니다. 프롬프트 주입에 클라우드 모델이 필요한 것은 아닙니다. 오염된 로그 한 줄, 악의적인 파일명, 함정이 심긴 도구 결과, 지나치게 적극적인 계획 — 로컬 모델은 이 모두에 호스팅 모델만큼이나 선뜻 반응합니다. 오히려 위험은 더 큽니다. 사람들이 로컬 구성을 더 믿고, 보호 난간을 덜 두르고, 더 넓은 액세스를 내주기 때문입니다 — 바로 “내 머신에 있으니까”라는 이유로요. 그것은 잘못된 직감입니다. 가중치가 로컬에 있다고 해서 모델의 판단이 더 나아지지는 않습니다.
그러니 목표는 어떤 에이전트에서든 같습니다 — 모델이 자격 증명을 쥐지 않고도 일을 하게 하고, 모든 동작을 범위가 정해지고, 보이고, 되돌릴 수 있게 만드는 것입니다.
잘못하는 세 가지 방법
원시 키를 붙여 넣기. 가장 직접적이고 가장 나쁜 방법입니다. 범위도, 만료도 없고, 앞서 말한 되돌릴 수 없음까지 더해집니다. 스테이징에 배포하는 키는 대개 두 홉 건너 프로덕션 데이터베이스에도 닿을 수 있습니다.
수명이 긴 토큰을 발급하기. 결코 만료되지 않는 배포 토큰이나 “자동화” 자격 증명. 키보다 깔끔해 보이지만, 단계만 더 붙은 같은 소지자 문제입니다. 무언가를 해지하는 일이 그것의 존재를 기억해 내는 일이라면, 그것은 자신을 만들어 낸 실험보다 더 오래 살아남습니다.
자체 root 로그인을 주고 손 떼기. 올바른 직감 — 별도의 신원 — 을 잘못된 방식으로 한 것입니다. 봇 사용자의 authorized_keys에 공개 키를 넣으면 감사 추적이 없는 액세스를 만든 셈입니다. 모델의 명령을 다른 누구의 것과도 구분할 수 없고, 새벽 2시에 뭔가 터지면 bash 기록과 감으로 그 세션을 재구성하게 됩니다.
공통점: 모델이 상주 자격 증명을 쥐고 있고, 관찰 가능성은 뒷전이라는 것입니다.
통하는 패턴: 복사본이 아니라 커스터디언
발상을 뒤집으세요. 모델은 자격 증명을 애초에 쥐어서는 안 됩니다.
- 모델은 요청하고, 커스터디언이 서명합니다. 브로커가 키를 보관하고(또는 단기 인증서를 발급하고) 모델을 대신해 인증합니다. 모델의 컨텍스트가 뚫려도 얻는 것은 브로커를 통해 동작을 요청하는 능력일 뿐, 어디서든 나를 사칭하는 능력이 아닙니다.
- 범위는 명시적입니다. 모델은 내가 목록에 올린 호스트에만 닿습니다. 새 호스트는 기본값이 아니라 새로운 결정입니다.
- 명령은 통제됩니다. 호스트별로 모델에게 완전한 셸을 줄지, 명령 허용 목록을 줄지, 아무것도 주지 않을지 정하세요 — 그래서 “nginx 재시작”은 웹 계층에서 허용되고, “뭐든 다”는 결코 허용되지 않습니다.
- 사람이 지켜볼 수 있습니다 — 실시간으로. 사후 분석에서만이 아니라, “모델이 이걸 했다”와 “내가 이걸 했다”를 구분하는 기록과 함께요.
- 해지는 교체가 아니라 토글입니다. 애초에 공유된 것이 없으므로, 액세스를 끄는 데 드는 비용이 없습니다.
이 중 어느 것도 유별나지 않습니다 — 진지한 인프라 팀에서 인증서 기반 SSH가 이미 대략 이렇게 돌아갑니다. 늘 걸리는 점은 이걸 직접 엮는 일이 하나의 프로젝트라는 것이고, 그래서 사람들은 위의 나쁜 선택지 중 하나로 건너뜁니다.
로컬 모델에 연결하기
MCP — Model Context Protocol — 가 이를 깔끔하게 해내는 방법이며, 클라이언트를 가리지 않습니다. MCP를 지원하는 클라이언트라면 무엇이든 구동할 수 있으므로, 내 모델이 Claude든, Ollama 뒤의 오픈 웨이트 모델이든, 직접 호스팅하는 것이든 상관없습니다.
- 로컬 모델을 MCP 지원 클라이언트로 실행하세요(MCP를 쓰는 코딩 에이전트나 채팅 클라이언트).
- SSH를 앞단에서 처리하는 MCP 서버를 가리키게 하세요 — 모델에게 키를 넘기는 대신 모델을 대신해 인증하는 서버로요.
- 원하는 호스트만 켜고, 각 호스트의 명령 정책(전체 / 허용 목록 / 차단)을 정하세요.
- 세션을 눈에 두고 감사 로그에 기록되게 하면, 모델이 실행하는 모든 명령을 추적하고 다시 재생할 수 있습니다.
모델은 도구를 얻고 — 세션 열기, 명령 실행, 파일 읽기·쓰기 — 인증은 커스터디언이 합니다. 내 키는 내 머신에서든 다른 어디서든 모델의 환경에 절대 들어가지 않습니다. 그리고 자격 증명을 모델이 아니라 커스터디언이 쥐고 있으므로, 대신 호스팅 에이전트로 손을 뻗는 순간에도 같은 구성이 그대로 이어집니다 — SSH로 쓰는 Claude Code와 SSH로 쓰는 OpenAI Codex가 반대편에 클라우드 모델을 두고 이 동일한 패턴을 앞단에서 씁니다.
Termalin은 이를 어떻게 하나
Termalin은 내장 MCP 서버를 갖춘 SSH 클라이언트이므로, 이 패턴이 프로젝트가 아니라 기본값입니다.
- 내 머신에서는 번들된 로컬 서버를 에이전트에 등록하세요(
claude mcp add termalin -- <path>/termalin-mcp, 또는 다른 MCP 클라이언트에 맞는 동등한 명령). 모델은 내가 켠 호스트에만 닿으며 — 에이전트 액세스는 기본적으로 꺼져 있습니다 — 인증은 Termalin의 키 커스터디언(사용자 대신 키를 보관하고 서명하는 구성 요소)을 거칩니다. 키를 한 번 잠금 해제하면 Termalin이 모델을 대신해 서명하고, 모델이 읽을 키 파일은 어디에도 없습니다. - 호스트별로 정책을 정합니다 — 전체 액세스, 명령 허용 목록, 또는 차단 — 그래서 혼란에 빠진 로컬 모델이 그 서버에서 내가 승인한 적 없는 것을 실행할 수 없습니다.
- 벌어지는 일을 지켜봅니다. 에이전트 세션은 실시간 터미널 탭으로 실행되고, 워치 그리드가 이를 미러링하며, 모델이 조작하는 타일이 빛납니다. 모든 명령은 세션 녹화에 표시되고 — 출력만, 키 입력은 절대 담지 않습니다 — 출처 기기와 IP와 함께 감사 로그에 기록됩니다.
- 앱이 실행 중이 아닌가요? 특정 서버로 범위가 제한되고, 만료 기간이 있고, 명령이 통제되며, 실행마다 단기 인증서로 인증하는 API 키로 모델을 Termalin의 호스팅 MCP 엔드포인트에 가리키게 하세요 — 그러면 유출된 키조차 목록에 없는 호스트에 닿거나 허용된 명령 밖으로 실행될 수 없습니다.
어느 쪽이든, 원하던 속성이 유지됩니다. 내 로컬 모델은 내 서버를 운용할 수 있고, 키는 한 번도 본 적이 없습니다.
심심한 호스트 하나로 시작하세요
프로덕션으로 시작하지 마세요. 위험이 낮은 서버 — 스테이징 서버나 장난감 VPS — 를 등록하고, 허용 목록으로 설정한 뒤, 모델에게 진짜 잡일을 주세요. 오류가 나타날 때까지 로그를 tail 하고, 설정을 고치고, 서비스를 재시작하는 일 말입니다. 작업하는 동안 그리드를 열어 두세요. 첫 한 시간 동안 알게 되는 것 — 어떻게 행동하는지, 어디서 머뭇거리는지, 모호함을 어떻게 다루는지 — 이 두 번째 호스트를 등록할지, 그리고 얼마만큼 풀어 줄지를 알려 줍니다.
그것이 커스터디언 모델의 조용한 보상입니다. 한 번에 호스트 하나씩 넓혀 가는데, 내딛는 어떤 걸음도 되돌릴 수 없는 것이 아니기 때문입니다 — 모델이 어디서 실행되든 말이죠.
Termalin은 내장 MCP 서버, 키 커스터디언, 호스트별 에이전트 정책을 갖춘 무료 크로스 플랫폼 SSH 클라이언트입니다 — 다운로드하거나, 키를 안전하게 다루는 방법을 읽어 보세요.