Pi의 SSH 확장 프로그램을 사용하여 VPS를 관리하는 방법
요약
AI 에이전트형 터미널인 Pi의 SSH 확장 프로그램을 사용하여 VPS를 관리하는 방법을 소개합니다. 자연어로 명령을 내리면 원격 서버에 명령을 라우팅하여 시스템 설정, Docker 배포 등을 자동화할 수 있습니다.
핵심 포인트
- Pi는 LLM을 파일 편집 및 쉘 명령 실행 도구와 결합한 에이전트형 하네스입니다.
- SSH 확장 프로그램을 통해 로컬이 아닌 원격 서버에 명령을 안전하게 실행할 수 있습니다.
- 에이전트의 안전성은 연결된 언어 모델의 성능과 직결되므로 주의가 필요합니다.
- TypeScript 확장 프로그램을 통해 필요한 기능을 모듈식으로 추가할 수 있습니다.
먼저 제 Linux 숙련도에 대해 솔직하게 말씀드리겠습니다. 이 글의 전체 내용은 이 부분에 달려 있기 때문입니다.
저는 IDE(통합 개발 환경) 안에서 생활합니다. 요즘은 에이전트형 데스크톱(agentic desktop) 안에서 살고 있죠. 프롬프트를 작성하고, diff(차이점)를 검토하며, PR(Pull Request)을 보냅니다. 서버에 SSH로 접속하는 일은 거의 없으며, 접속하더라도 제 지식은 apt update, docker compose up, 그리고 nginx가 제대로 작동하지 않을 때 재시작하는 수준에 머물러 있습니다. 그 이상의 작업(ufw 규칙, PostgreSQL 허용 목록, Caddy 설정 등)은 모두 메모 파일에 저장되어 있었습니다. 모든 서버 작업은 그 파일을 열고 명령어를 하나씩 복사하여 붙여넣는 과정을 의미했습니다.
지난달, 저는 Pi를 사용하여 완전히 새로운 VPS를 처음부터 설정했습니다. Pi는 단 6줄의 코드로 시스템 업데이트, Docker, 방화벽, 앱 배포, 그리고 제 도메인을 사용한 HTTPS 설정을 수행합니다.
여기 설정 방법과 실행된 정확한 명령어, 그리고 제가 고생하며 배운 한 가지 교훈이 있습니다. 그것은 바로 에이전트형 하네스(agentic harness)의 안전성은 연결된 모델의 안전성과 동일하다는 점입니다. 어떤 모델을 선택하느냐에 따라 이 도구가 당신의 시간을 한 시간 아껴줄 수도 있고, 혹은 당신을 자신의 서버에서 차단시켜 버릴 수도 있습니다.
Pi란 무엇인가?
Pi는 최소한의 오픈 소스 에이전트형 하네스(agentic harness)입니다. Claude Code나 OpenCode와 같은 기존의 AI 터미널과 유사하게, 언어 모델(language model)을 파일 읽기, 코드 편집, 쉘 명령 실행에 필요한 도구들과 결합하여 감싸는 터미널 프로그램입니다. 차이점은 SSH 확장 프로그램이 해당 쉘 명령을 로컬 머신이 아닌 원격 서버로 라우팅한다는 것입니다. 따라서 각 명령어를 실행하기 전에 검토하면서 자연어로 VPS를 관리할 수 있습니다.
“에이전트형 하네스(Agentic harness)”라는 말이 전문 용어처럼 들리겠지만, 개념은 이렇습니다. 모델은 두뇌이고, 하네스는 그 두뇌를 장착하는 몸체입니다. Claude Code, OpenCode, Codex CLI, 그리고 Pi는 모두 하네스입니다. Pi의 핵심 가치(그들의 슬로건은 말 그대로 “많은 에이전트 하네스가 있지만, 이 하네스는 당신의 것입니다”입니다)는 의도적으로 매우 작게 제작되었다는 점입니다. 플랜 모드(plan mode), 하위 에이전트(sub-agents), 권한 팝업 등이 없습니다. 추가적인 기능이 필요하다면 TypeScript 확장 프로그램으로 추가하거나 패키지로 설치하면 됩니다.
SSH 지원은 바로 그런 종류의 패키지입니다. 제가 사용하는 pi-ssh-tools는 /ssh 명령어를 추가할 뿐만 아니라, 로컬 도구들은 로컬에 그대로 유지하면서 별도의 원격 도구 세트(ssh_read, ssh_write, ssh_edit, ssh_bash)를 제공합니다. SSH 모드는 기본적으로 꺼져 있으며 세션 간에 유지되지 않고, 활성화된 원격 호스트를 시스템 프롬프트 (system prompt)에 주입하여 에이전트 (agent)가 자신이 어디에서 작업하고 있는지 알 수 있게 합니다. 솔직히 말해서 꽤 우아한 방식입니다.
저 같은 사람에게 가치는 타이핑 속도가 아닙니다. 하네스 (harness)와 좋은 모델 (model)이 결합되어 제가 모르는 명령어를 알고 있다는 점입니다. 저는 제가 무엇을 원하는지는 압니다. 하지만 그것이 ufw allow인지 ufw enable인지, 혹은 어떤 순서로 실행해야 하는지는 전혀 기억나지 않습니다. 알고 보니 그 순서가 매우 중요하더군요. 잠시 후에 더 자세히 다루겠지만, 순서를 틀리는 바람에 제 서버에 대한 SSH 접속 권한을 거의 잃을 뻔했습니다.
SSH 확장 프로그램을 사용한 Pi 설정
세 가지가 필요합니다. 로컬에 설치된 Pi, 확장 프로그램 폴더에 있는 SSH 확장 프로그램, 그리고 VPS에 대한 키 기반 (key-based) SSH 접속 권한입니다. 확장 프로그램은 단순히 시스템의 ssh를 호출하는 방식이므로, 터미널에서 ssh root@your-ip가 작동한다면 Pi에서도 동일하게 작동합니다.
1단계: Pi 설치
한 줄이면 됩니다:
npm install -g @earendil-works/pi-coding-agent
2단계: SSH 확장 프로그램 설치
마찬가지로 Pi 자체 패키지 관리자를 사용하여 한 줄이면 됩니다:
pi install npm:@ogulcancelik/pi-ssh-tools
끝입니다. 예제 파일을 클론 (cloning)하거나 설정을 수동으로 편집할 필요가 없습니다. 패키지가 매니페스트 (manifest)에 자신의 확장 프로그램을 선언하면 Pi가 자동으로 로드합니다. (Pi의 공식 패키지 페이지에 있는 표준 주의 사항: 확장 프로그램은 코드를 실행하고 에이전트를 제어할 수 있으므로, 설치 전에 서드파티 (third-party) 패키지의 소스 코드를 훑어보세요. 이 패키지는 의존성 (dependencies)이 전혀 없는 20 KB 크기이므로 금방 확인할 수 있습니다.)
3단계: 모델 설정 (이 부분이 중요합니다)
저는 Pi에서 기본 모델로 DeepSeek를 사용합니다. 여기서 여러분의 오후 시간을 아껴드리겠습니다. Flash 모델이 아닌 Pro 모델을 사용하세요.
왜일까요? 터미널 작업을 처리하기 위해 프런티어 모델 (Frontier model)까지 필요하지는 않습니다. 충분히 괜찮은 (good enough) 모델이면 충분합니다. 터미널 명령을 수행하는 데 Claude Token이나 GPT 비용을 지불하고 싶지 않습니다. 로컬 모델 (Local model)도 한번 시도해봐야겠습니다.
4단계: 연결하기
Pi를 시작한 다음, 다음을 수행하세요:
/ssh <your-vps-ip>
또는 인자 없이 /ssh만 입력하면 ~/.ssh/config에 있는 호스트 목록을 제공합니다. /ssh status는 현재 어디에 연결되어 있는지 보여주며, /ssh off는 로컬로 돌아갑니다. SSH 모드는 세션 간에 유지되지 않는데, 저는 이 점이 마음에 듭니다. 내일 실수로 Pi를 다시 열었다가, 여전히 연결되어 있다는 사실을 잊은 채 운영 서버 (Production server)를 편집하기 시작하는 사고를 방지할 수 있기 때문입니다.
SSH 모드가 켜져 있는 동안, 에이전트 (Agent)가 제안하는 모든 작업은 여러분의 노트북이 아닌 원격 서버 (Remote box)에서 실행됩니다. 이것이 바로 아래의 안전 섹션이 존재하는 이유입니다.
단 한 번의 프롬프트로 새로운 VPS 프로비저닝하기
제 앱들을 위해 방금 새 VPS를 구매했습니다. 예전의 저라면 메모장 파일을 열었을 것입니다. 대신 저는 Pi를 열고, /ssh를 실행한 뒤, 다음과 같은 간단한 프롬프트를 보냈습니다:
update and upgrade
install docker, fzf
set ufw for port 8080 and 5173 only
...
단 여섯 줄입니다. 문법은 전혀 필요 없습니다. 기본적으로 리눅스 (Linux)를 잘 아는 동료에게 업무를 지시하는 방식과 같습니다.
Pi가 생성한 명령어 체인
에이전트가 제 프롬프트를 처리하며 제안하고 실행한 내용은 다음과 같으며, 작업 순서에 따라 그룹화되었습니다.
시스템 업데이트:
apt-get update && apt-get upgrade -y
Docker 및 fzf:
curl -fsSL https://get.docker.com | sh
apt-get install -y fzf
systemctl enable --now docker
방화벽 (Firewall). 제가 매의 눈으로 지켜본 단계입니다:
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
...
세 번째 줄을 보세요. 방화벽을 활성화하기 전에 ufw allow OpenSSH (22/tcp와 유사)가 포함되어 있습니다. 저는 그런 요청을 한 적이 없습니다. 제 프롬프트는 말 그대로 "port 8080 and 5173 only"라고 했고, 이를 문자 그대로 받아들였다면 그 지시는 SSH를 차단했을 것입니다. 즉, 세션 도중에 저와 에이전트 자신을 모두 차단해 버린다는 의미입니다. Pro 모델은 스스로 SSH 규칙을 추가하고 그 이유를 설명했습니다.
그 한 줄의 차이가 "AI 지원 서버 관리"와 저녁 시간을 복구 콘솔(rescue console)에서 VPS를 재구축하며 보내는 것 사이의 차이를 만듭니다.
클론 및 빌드 (Clone and build):
git clone https://github.com/<user>/<repo>.git /opt/app
cd /opt/app
docker build -t app .
...
내 도메인을 사용한 Caddy:
apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
...
그 다음 /etc/caddy/Caddyfile을 작성했습니다:
api.ekky.dev {
reverse_proxy localhost:8080
}
...
그리고 systemctl reload caddy로 다시 로드했습니다. Caddy는 스스로 TLS 인증서를 가져왔는데, 이것이 바로 제가 nginx가 아닌 Caddy를 요청한 핵심 이유입니다. 제 nginx-plus-certbot 관련 메모는 화면 두 개 분량이나 되지만, 이것은 단 네 줄뿐입니다.
최종 상태: 패치된 시스템, 실행 중인 컨테이너 (container), 제가 요청한 정확한 구멍들(그리고 제가 요청하는 것을 잊어버린 SSH 구멍까지)을 가진 방화벽, 그리고 제 도메인에 적용된 HTTPS. 완전히 빈 서버 상태에서 말이죠. 저는 그저 앉아서 승인만 했을 뿐입니다.
나의 Ask-to-Verify 워크플로우
이 방식이 별도의 설정 없이 바로 사용하기에 안전하다고 거짓말하지는 않겠습니다. 안전하지 않습니다. Pi에는 내장된 가드레일 (guardrails)이 없습니다. 모델이 무엇을 제안하든 Pi는 실행할 것입니다. 직접 구축하지 않는 한 "정말 확실합니까?"라고 묻는 계층이 없습니다. 또한 pi-mono 문서에서는 더 엄격한 경계를 원한다면 Pi를 컨테이너화 (containerizing)하거나 샌드박싱 (sandboxing)할 것을 공개적으로 제안하고 있습니다.
따라서 저의 완화 방법은 설정이 아니라 습관입니다:
- 명령어가 실행되기 전에 모든 명령어를 읽습니다. 대충 훑어보는 것이 아니라, 읽어야 합니다. 저의 Linux 지식은 기초적이지만, 목적지 경로,
-y플래그, 그리고rm,dd, 또는 제가 아끼는 파일로의 리다이렉트(redirect)를 포함하는 모든 것을 식별할 수 있습니다. 명령어를 전혀 알 수 없을 때는, 먼저 Pi에게 설명을 요청합니다. 메시지 한 번의 비용이 들 뿐이며, 명령어를 설명하는 것은 이 모델들이 진정으로 잘하는 일입니다. - 제 손은 항상
Esc근처에 둡니다. 이를 누르면 명령 체인(chain) 중간이라도 즉시 실행을 중단합니다. 방화벽(firewall)이나 디스크를 건드리는 작업을 할 때는 왼손을 키보드 그 구석에서 떼지 않습니다. 상황이 이상해지면Ctrl+C를 눌러 세션 자체를 종료합니다. - 방화벽과 데이터베이스(database) 단계에는 두 배로 주의를 기울입니다. 이 두 곳은 잘못된 명령어가 요란하게 실패하지 않는 두 지점입니다. 잘못된 대상에 대해 조용히 성공해 버립니다.
- 재구축 가능한 서버만 사용합니다. 제가 Pi가 건드리도록 허용하는 모든 것은 리포지토리(repo)와 Docker 빌드를 통해 오후 시간 내에 다시 생성할 수 있는 것들입니다. 저는 데이터를 잃으면 안 되는 서버에는 한 번도 이 방식을 적용한 적이 없습니다. 앞으로도 그럴 계획이 없습니다.
Pro 모델을 사용하며 여러 세션에 걸쳐 확인해 본 결과, 해로운 행동을 하는 것을 본 적이 없습니다. 하지만 표현을 주의 깊게 보십시오. "본 적이 없다"는 것이 "절대 없을 것이다"라는 뜻은 아닙니다. 위험이 사라지는 것이 아니라, 중요한 순간에 당신이 직접 관여하고 있는지 확인하는 것입니다.
이것이 실제로 절약해 주는 것
새로운 VPS를 설정하던 저의 예전 루틴은 다음과 같았습니다. 수동으로 SSH 접속. 메모 파일 열기. 아마도 20개 정도의 명령어를 하나씩 복사해서 붙여넣기. 작년 이후 패키지 이름이 바뀌어 에러가 발생하는 두 개의 명령어를 구글링하기. 몇 달 동안 제 메모에 들어있던 오타 수정하기. ufw SSH 규칙을 한 번 까먹기(어떻게 알았냐고요?). 한 시간의 대부분을 허비하기.
Pi를 사용하면: 프롬프트 한 번, 약 10분간의 관찰 및 승인, 끝. 전체 프로비저닝(provisioning) 실행에 사용된 DeepSeek Pro 토큰 비용은 실제 비용으로 약 $0.03(또는 그보다 적음) 정도였습니다.
솔직히 말해서, 더 큰 절약은 심리적인 부분입니다. 예전에는 방화벽 규칙을 강화하거나 PostgreSQL 허용 목록(allow-list)에 IP를 추가하는 것과 같은 사소한 서버 작업들을 미루곤 했습니다. 왜냐하면 작업 하나하나가 이미 두 번이나 배웠던 내용을 다시 배우는 데 20분을 소모한다는 것을 의미했기 때문입니다. 하지만 이제 서버 작업은 단 한 문장이면 충분합니다. 그래서 저는 그냥 생각이 날 때 바로 처리합니다. 제 서버들은 그 어느 때보다 상태가 좋으며, 저는 이렇게 깔끔하게 서버를 유지하는 대부분의 사람들보다 Linux를 더 모릅니다. 어떻게 받아들이든 여러분의 자유입니다.
누가 이것을 해야 하는가 (그리고 정말로 하지 말아야 할 사람)
다음과 같은 경우라면 이 방식이 마음에 드실 것입니다: 한 달에 몇 번 개인 VPS를 만지는 개발자이고, 명령어를 검증할 정도의 Linux 지식은 있지만 암기해서 작성할 정도는 아니며, 앱을 리포지토리(repo)로부터 다시 빌드할 수 있는 경우입니다. 만약 여러분의 메모 파일이 시스템 관리자(sysadmin) 역할을 해왔다면, 이 방식은 그 메모 파일을 대화가 가능한 무언가로 대체해 줄 것입니다.
다음과 같은 경우에는 피하십시오: 운영(production) 인프라이거나, 서버가 고객 데이터를 보유하고 있거나, 컴플라이언스(compliance)가 관련되어 있거나, 오늘 오후에 서버를 즉시 재구축할 여력이 없는 경우입니다. 또한, 관리자 없이(unattended) 실행할 계획이라면 피하십시오. Pi는 여러분이 커피를 만들러 간 사이에 아주 즐겁게 파괴적인 명령어를 실행할 것입니다. 이 루프(loop) 안에 있는 인간은 장식용이 아닙니다. 인간이 바로 그 루프 자체입니다.
이 글을 읽으셨다면, 실용적인 AI, Python 프로그래밍, 그리고 기타 기술 관련 콘텐츠에 대한 향후 게시물을 위해 Medium 또는 Substack에서 저를 팔로우하는 것을 잊지 마세요. 제품 구축을 도와줄 AI 네이티브 엔지니어가 필요하시다면, 개발 서비스도 제공하고 있습니다. 대화를 나누거나 me@ekky.dev로 이메일을 보내주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기