SSH 키를 넘겨주지 않고도 AI 에이전트가 서버에 배포하게 하는 방법
요약
AI 에이전트가 서버 배포 시 SSH 키와 같은 민감한 자격 증명을 직접 보유할 때 발생하는 보안 위협과 가역성 문제를 다룹니다. 기존의 잘못된 방식들을 분석하고, 에이전트에게 권한을 직접 부여하는 대신 안전하게 관리하는 구조적 접근의 필요성을 강조합니다.
핵심 포인트
- SSH 키를 에이전트에게 직접 제공하는 것은 보안상 매우 위험함
- 자격 증명 노출 시 키 교체(Rotation)가 필수적인 가역성 문제 발생
- 단순 토큰 생성이나 별도 root 계정 부여 방식의 한계 지적
- 에이전트가 자격 증명의 소유자가 아닌 관리자(Custodian) 역할을 수행해야 함
코딩 부분은 대부분 해결되었습니다. 에이전트는 브랜치를 생성하고, 패치를 적용하며, 테스트를 작성하고, PR(Pull Request)을 열 수 있습니다. 그다음 변경 사항이 실제 서버에 반영되어야 합니다. 서비스가 재시작되거나, 마이그레이션(migration)이 실행되거나, nginx 설정이 편집되어야 하는데, 여기서 자율성(autonomy)이 완전히 멈춰버립니다. 배포에는 SSH가 필요하고, SSH에는 자격 증명(credentials)이 필요한데, 제정신인 사람이라면 누구도 에이전트의 환경에 개인 키(private key)를 붙여넣고 싶어 하지 않을 것입니다.
그러한 망설임은 옳으며, 그 이유를 정확히 짚고 넘어갈 가치가 있습니다. SSH 개인 키는 소지자 자격 증명(bearer credential)입니다. 즉, 그 바이트를 가진 사람이 바로 당신입니다. 에이전트와 키를 공유하는 것은 동료와 공유하는 것과는 다릅니다. 왜냐하면 다시 되돌릴 수 없기 때문입니다. 일단 키가 에이전트의 컨텍스트(context) — 환경 변수(env var), 마운트된 파일, 설정 블록(config blob) — 를 통과하고 나면, 그 키가 로그, 트랜스크립트(transcript), 또는 당신이 읽지 않은 도구 호출(tool call)에 남지 않았다고 더 이상 증명할 수 없습니다. "모델이 내 키를 보았는가?"라는 질문에 대한 유일하고 정직한 답변은, 해당 키를 신뢰하는 모든 호스트에서 키를 교체(rotate)하는 것입니다. 이것이 가역성(irreversibility) 문제이며, 위협 모델(threat model)을 명확히 설명하지 못하는 사람들조차 "그냥 에이전트에게 키를 주라"는 말이 잘못되었다고 느끼는 이유입니다.
잘못된 세 가지 방법
원시 키를 붙여넣기. 가장 직접적인 경로입니다. id_ed25519를 에이전트의 설정이나 환경에 넣고 에이전트가 직접 ssh를 실행하게 하는 것입니다. 앞서 언급한 가역성 문제 외에도, SSH 키는 범위(scope)가 없고 만료 기간도 없습니다. 스테이징(staging)에 배포하는 키가 보통 두 단계 떨어진 운영(production) 데이터베이스 자격 증명까지 읽을 수 있는 것과 같습니다. 그리고 권한 취소(revocation)는 키 교체(rotation)를 의미하며, 이는 모든 서버의 authorized_keys를 수정해야 함을 의미하고, 결국 당신은 이를 미루게 될 것입니다.
수명이 긴 토큰 생성하기. 배포 토큰(deploy token), PAT(Personal Access Token), 또는 절대 만료되지 않는 "자동화" 자격 증명을 만드는 것입니다. 키보다는 더 위생적으로 느껴질 수 있지만, 추가적인 단계만 더해졌을 뿐 동일한 소지자 자격 증명(bearer) 문제입니다. 경험 법칙은 다음과 같습니다: 만약 자격 증명을 취소하기 위해 그것이 존재한다는 사실을 기억해야 한다면, 그 자격 증명은 그것이 생성된 목적이었던 실험보다 더 오래 살아남을 것입니다.
에이전트에게 자체적인 root 계정을 부여하십시오. 이 방법은 적어도 올바른 본능을 보여줍니다. 즉, 별도로 취소할 수 있는 별개의 ID를 갖는 것입니다. 하지만 일반적인 방식( deploy-bot 사용자의 authorized_keys에 공개 키를 넣고 그대로 두는 방식)으로 수행하면, 감사 추적(audit trail)이 전혀 남지 않습니다. 에이전트의 명령과 다른 사람의 명령을 구분할 수 있는 것이 아무것도 없으며, 에이전트가 실제로 무엇을 했는지 기록하는 것도 없습니다. 새벽 2시에 무언가 고장 났을 때, 여러분은 bash 히스토리와 직감에 의존해 에이전트의 세션을 재구성해야만 합니다.
공통점은 이렇습니다. 세 가지 방식 모두 에이전트가 상시 자격 증명(standing credential)을 보유하고 있으며, 관찰 가능성(observability)은 뒷전이라는 점입니다.
이상적인 모습: 복사본이 아닌 관리자(custodian)
모델을 뒤집으십시오. 에이전트는 자격 증명을 아예 보유해서는 안 됩니다.
- 에이전트는 요청하고, 관리자가 서명합니다. 중개 프로세스(broker process)가 키를 보유하거나 수명이 짧은 인증서(short-lived certificates)를 발행하며, 에이전트를 대신하여 인증을 수행합니다. 에이전트의 환경에는 훔칠 만한 가치가 있는 것이 아무것도 없습니다. 컨텍스트가 침해되더라도 브로커를 통해 작업을 _요청_할 수 있는 권한만 얻을 뿐, 인터넷 어디에서든 당신을 사칭할 수 있는 권한을 얻지는 못합니다.
- 범위(Scope)가 명시적입니다. 관리자는 당신이 목록에 기재한 호스트에만 접근할 수 있습니다. 새로운 호스트는 기본 설정이 아니라 새로운 결정의 대상입니다.
- 사람이 지켜볼 수 있습니다. 사후 분석(post-mortem) 시점에만 보는 것이 아니라, 일이 일어나는 동안 실시간으로 확인할 수 있습니다. 그리고 기록은 "에이전트가 이것을 했다"와 "내가 이것을 했다"를 반드시 구분해야 합니다.
- 취소는 회전(rotation)이 아닌 토글(toggle)입니다. 아무것도 공유된 적이 없기 때문에, 액세스를 차단하는 데 드는 비용은 아무것도 없습니다.
이 중 어느 것도 생소한 것이 아닙니다. 이는 실제 인프라 팀을 갖춘 기업에서 이미 인증서 기반 SSH가 작동하는 방식과 거의 유사합니다. 문제는 이를 직접 구축하는 것이 하나의 프로젝트가 된다는 점이었고, 그래서 대부분의 사람들은 위에서 언급한 나쁜 옵션 중 하나로 바로 건너뛰곤 했습니다.
Termalin이 이를 구현하는 방법
Termalin은 MCP 서버가 내장된 SSH 클라이언트입니다. Claude나 Model Context Protocol (MCP)을 지원하는 무엇이든 당신의 에이전트가 될 수 있으며, hosts_list, ssh_exec, SFTP 읽기 및 쓰기, 그리고 지속적인 세션 (persistent sessions)과 같은 도구들을 사용할 수 있게 됩니다. 인증은 Termalin이 수행합니다.
당신의 로컬 머신에서. 번들로 제공되는 로컬 서버를 에이전트에 등록하세요:
claude mcp add termalin -- <path>/termalin-mcp
에이전트는 Settings → MCP에서 당신이 활성화한 호스트에만 접근할 수 있습니다. 에이전트의 접근 권한은 기본적으로 비활성화되어 있으며, 호스트 인벤토리는 에이전트 전용 인증(agent-only auth)으로 작성되므로 비밀번호가 디스크에 저장되지 않습니다. 인증은 Termalin의 **키 관리자 (key custodian)**를 통해 이루어집니다. 당신이 키를 한 번 잠금 해제하면, Termalin이 에이전트를 대신하여 서명합니다. ssh-add도 필요 없고, 에이전트가 읽을 키 파일도 필요 없으며, 키가 디스크에 닿는 일조차 전혀 없습니다.
그리고 실제로 지켜볼 수도 있습니다. 에이전트 세션은 라이브 터미널 탭으로 실행되며, **워치 그리드 (watch grid)**는 모든 열린 세션을 나란히 미러링하여 보여주고, 에이전트가 제어 중인 타일은 빛이 납니다. 당신이 이미 열어둔 세션에 에이전트가 타이핑하도록 허용하는 것은 별도의 동의 토글(consent toggle)이며, 기본 설정이 아닙니다. 모든 에이전트 명령은 세션 기록(session recording)에 표시되며 — 이 기록은 출력값만 캡처하고 당신의 키 입력(keystrokes)은 절대 캡처하지 않습니다 — 해당 명령이 발생한 장치 및 IP와 함께 감사 로그(audit log)에 기록됩니다.
앱을 실행하지 않는 경우. 만약 에이전트가 데스크톱이 없는 곳(CI, 클라우드 샌드박스 등)에 있다면, 웹 캐비닛 (web cabinet)에서 API 키를 생성하고 이를 호스팅된 MCP 엔드포인트로 지정하세요:
{
"mcpServers": {
"termalin": {
...
호스팅된 엔드포인트는 터널 에이전트(tunnel agent)에 등록된 서버에만 접근하며, 각 실행을 **단기 인증서 (short-lived certificate)**로 인증합니다. 이 역시 상시 사용 가능한 키(standing key)를 전달하지 않습니다. API 키 자체는 특정 서버로 범위가 제한(scoped)되어 있고, 만료 기간(30일, 90일 또는 365일)을 가지며, 언제든지 취소할 수 있습니다. 호스팅된 실행은 키당 속도 제한(rate-limited) 및 시간 제한(time-boxed)이 적용됩니다.
어떤 방식이든 당신이 원했던 속성은 유지됩니다. 에이전트는 배포를 수행할 수 있지만, 키를 본 적은 단 한 번도 없습니다.
평범한 호스트 하나로 시작하기
운영 환경(production)부터 시작하지 마세요. 스테이징 서버나 연습용 VPS와 같이 리스크가 낮은 박스(box) 하나를 먼저 등록하세요. 에이전트에게 실제 업무를 부여하십시오. 브랜치를 배포하고, 에러가 나타날 때까지 로그를 추적(tail)하며, 설정을 수정하고, 서비스를 재시작하게 하세요. 에이전트가 작업하는 동안 모니터링 그리드(watch grid)를 열어두십시오. 첫 한 시간 동안 배우게 되는 것들—에이전트가 어떻게 행동하는지, 어디에서 주저하는지, 모호한 상황에서 어떻게 대처하는지—이 두 번째 호스트를 등록할지 여부를 결정해 줄 것입니다.
이것이 관리자 모델(custodian model)이 주는 조용한 보상입니다. 당신이 취하는 그 어떤 단계도 되돌릴 수 없기에, 한 번에 하나의 호스트씩 확장해 나갈 수 있습니다.
Termalin의 무료 티어는 전체 데스크톱 앱을 제공하며, 모든 신규 계정은 14일간의 Pro 체험판으로 시작합니다 — 다운로드하거나 MCP 문서부터 시작해 보세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기