SSH Operator
SSH/SFTP를 통해 원격 Linux 서버를 운영하여 애플리케이션 배포, Docker 컨테이너 관리, 런타임 상태 점검을 수행합니다. 다중 파일/다중 폴더 프로젝트를 지원하며 Baota(宝塔) 패널 환경에 최적화되어 있습니다.
호출 시점
- 사용자가 서버에 코드를 배포, 게시, 릴리스하도록 요청할 때
- 사용자가 원격 서비스를 재시작, 재빌드, 업데이트하도록 요청할 때
- 사용자가 원격 호스트에 파일이나 전체 폴더를 업로드하도록 요청할 때
- 사용자가 원격 로그를 보거나 서비스 상태를 확인하도록 요청할 때
- 사용자가 원격 서버에서 명령을 실행하거나 문제를 진단하도록 요청할 때
- 사용자가 원격 웹사이트/블로그 소스 파일을 편집하도록 요청할 때
- 사용자가 블로그 포스트를 게시하거나 블로그 플랫폼의 게시 API를 탐지하도록 요청할 때
- 사용자가 Baota / 宝塔 패널,
/www/wwwroot/, 또는 중국 클라우드 VPS 호스팅을 언급할 때
기능
- SSH를 통한 원격 호스트 연결 (비밀번호 또는 키 기반 인증)
- SFTP를 통한 파일 업로드/다운로드 및 폴더 재귀 업로드
- 셸 명령 실행 및 출력 스트리밍
- Docker 및 docker-compose 워크로드 관리
- 서비스 상태, 로그, 디스크 사용량, 프로세스 상태 점검
- 배포 변경 사항 활성화 확인 (체크섬, 프로세스 재시작, HTTP 헬스 체크)
- Baota 패널 디렉터리 구조 및 Nginx 리버스 프록시 설정에 맞춘 명령 자동 조정
- SSH를 통한 원격 웹사이트/블로그 소스 파일 직접 편집
- 블로그 게시 API(WordPress, Ghost, Halo) 탐지 및 Python 스크립트를 통한 Markdown 포스트 게시
필수 입력 값
작업을 수행하기 전에 사용자 또는 환경으로부터 다음 정보를 수집합니다:
HOST— 서버 IP 또는 호스트명PORT— SSH 포트 (기본값 22)USER— SSH 사용자 이름AUTH— 비밀번호 또는 개인 키 경로. 키를 선호하며, 커밋된 파일에 비밀 정보를 절대 하드코딩하지 마십시오.REMOTE_ROOT— 서버의 기본 프로젝트 경로 (예:/www/wwwroot/ai-interviewer)FILES_TO_UPLOAD—local_path -> remote_relative_path쌍 목록 (전체 폴더 포함)COMMANDS— 실행할 배포 또는 진단 명령
다중 파일 / 다중 폴더 배포
실제 프로젝트는 단일 파일이 아닙니다. 다음 방법 중 하나를 사용하세요:
옵션 1: 제공된 스크립트 템플릿 사용
scripts/deploy-folder.py를 프로젝트 저장소에 복사하고 FILES_TO_UPLOAD 목록을 구성한 후 실행하세요. 재귀적 폴더 업로드를 처리하고 상대 경로를 유지합니다.
Unix 계열 로컬 환경에서는 scripts/deploy-rsync.sh가 적절한 제외 항목과 함께 증분 rsync 기반 대안을 제공합니다.
옵션 2: 에이전트 기반 SFTP
에이전트가 SFTP/SSH 도구를 갖춘 경우:
- SSH 세션을 설정합니다.
- 변경된 각 폴더에 대해 내용을 탐색하고 원격 디렉터리 트리를 재생성하면서 개별적으로 파일을 업로드합니다.
- 변경된 각 파일을 일치하는 원격 상대 경로에 업로드합니다.
- 배포 명령을 실행하고 확인합니다.
옵션 3: 원샷 tarball
대규모 프로젝트의 경우 로컬에서 패킹하고 원격에서 추출하는 것이 좋습니다:
# 로컬
tar czf deploy.tar.gz backend/app frontend/.next docker-compose.yml .env.production
scp deploy.tar.gz user@host:/tmp/
# 원격
ssh user@host "cd /www/wwwroot/project && tar xzf /tmp/deploy.tar.gz && docker-compose up -d --build"
스크립트 라이브러리
바로 사용 가능한 자동화 스크립트입니다. Python 스크립트는 scripts/_ssh.py를 공유하여 연결/설정 로딩을 처리하고 .env 파일(.env.example 참조)에서 자격 증명을 읽습니다. 스크립트를 _ssh.py와 함께 프로젝트에 복사하세요.
| 스크립트 | 목적 |
|---|---|
scripts/_ssh.py | 공유 헬퍼: .env 설정 로드 및 SSH/SFTP 연결 열기 |
scripts/deploy-folder.py | 파일 및 폴더의 재귀적 SFTP 업로드 후 배포 후 명령 실행 |
scripts/deploy-rsync.sh | 일반적인 제외 항목이 포함된 증분 rsync 배포 |
scripts/blog_api_probe.py | 일반적인 블로그 게시 API(WordPress, Ghost, Halo) 탐지 |
scripts/publish_post.py | REST API를 통해 WordPress 또는 Ghost에 Markdown 파일 게시 |
scripts/backup_before_deploy.py | 배포 전 코드, Nginx 설정, Docker 볼륨, SQLite 백업 |
scripts/server_health.py | CPU, 메모리, 디스크, Docker, Nginx, HTTP 상태 수집 |
scripts/log_collector.py | Docker, Nginx, Baota 로그를 로컬 파일로 가져와 분석 |
scripts/nginx_manager.py | Baota Nginx 사이트 설정 읽기/백업/편집 및 안전하게 리로드 |
scripts/bt_panel.py | Baota 설치, 패널 정보 보기, Nginx 리로드, SSH를 통한 Docker 상태 확인 |
Python 종속성은 requirements.txt에 나열되어 있습니다.
표준 배포 워크플로우
- SSH 세션 설정 — 제공된 자격 증명과 적절한 타임아웃(≥20초) 사용
- 변경 전 백업 —
scripts/backup_before_deploy.py또는 동등한 명령 실행 REMOTE_ROOT가 존재하는지 확인 (mkdir -p)- 파일/폴더 업로드 —
REMOTE_ROOT아래에 상대 경로 유지 - 명령 실행 — 순서대로 실행하며, 종속 명령은
&&로 연결하는 것이 좋음 - 서비스 시작 대기 (
sleep+docker-compose ps또는 헬스 엔드포인트 사용) - 확인 — 새 코드가 활성화되었는지 확인 (컨테이너 내 grep,
/health호출, 로그 확인) - 결과 보고 — 변경 사항, 서비스 상태, 오류를 간결하게 보고
일반적인 명령 패턴
# 서비스 중지, 재빌드, 재시작
cd ${REMOTE_ROOT} && docker-compose stop backend \
&& docker-compose rm -f backend \
&& docker-compose build backend \
&& docker-compose up -d backend
# 서비스 상태 확인
cd ${REMOTE_ROOT} && docker-compose ps
# 최근 로그 보기
cd ${REMOTE_ROOT} && docker-compose logs --tail=50 backend
# 실행 중인 컨테이너 내부 코드 확인
docker exec ${CONTAINER_NAME} grep -n "await db.flush()" app/api/v1/interview.py
# 디스크 정리
docker system prune -a -f
Baota / 宝塔 패널 적응
전체 운영 가이드는 references/baota.md를, bt CLI 치트 시트는 references/bt-commands.md를 참조하세요. 주요 사항:
- 공식 사이트: https://www.bt.cn; 설치 스크립트: https://www.bt.cn/new/download.html
- 기본 프로젝트 루트:
/www/wwwroot/<site-name> scripts/bt_panel.py를 사용하여 Baota 설치, 패널 정보 보기, SSH를 통한 Nginx 리로드- 프로젝트 디렉터리 내에서 Docker Compose 사용; CLI 또는 Baota Docker 플러그인을 통해 컨테이너 관리
- Node/Python 프론트엔드의 경우 Baota 사이트를 추가하고
scripts/nginx_manager.py를 사용하여127.0.0.1:3000에 Nginx 리버스 프록시 위치를 추가 - Nginx에서
/api/를 백엔드 컨테이너(예:127.0.0.1:8000)로 라우팅 - Baota 방화벽과 클라우드 제공업체 보안 그룹 모두에서 포트 개방
- 높은 번호의 포트를 인터넷에 직접 노출하지 말고 80/443에서 Nginx 사용
문제가 발생하면 references/troubleshooting.md를 참조하세요.
안전 규칙
- 비밀 정보를 커밋하지 마십시오.
PASS또는 키 경로는 환경 변수,.env파일(git에서 제외), 또는 비밀 관리자에 저장하세요. - 명시적 파일 목록을 선호하여 광범위한 업로드로 예상치 못한 파일을 덮어쓰는 것을 방지하세요.
- 서비스를 재시작하기 전에 비파괴적 검사(로그, ps, df)를 먼저 실행하세요.
- **
git push --force또는 파괴적인rm -rf는 사용자가 명시적으로 요청하지 않는 한 피하세요. - 위험한 작업(데이터베이스 마이그레이션, 서비스 전체 재시작, 파괴적 삭제)은 가능한 경우 사용자에게 확인하세요.
- 임시 파일(예:
/tmp/deploy.tar.gz)은 배포 후 정리하세요.
크로스 플랫폼 참고 사항
- 이 스킬은 Linux 원격 호스트와 SSH 클라이언트 또는
paramiko와 같은 Python 라이브러리가 있는 로컬 환경을 가정합니다. - Windows 로컬 호스트에서는 경로를 정규화해야 할 수 있습니다. 명령에서 원격 경로는 항상 따옴표로 묶으세요.
- 직접적인 SSH 도구가 없는 에이전트의 경우 다음 대안 사용: (1) 사용자가 실행할 배포 스크립트 생성, 또는 (2) 플랫폼에서 제공하는 터미널/원격 실행 도구 사용
- Claude Code, Codex, TRAE, Cursor에서 최대 이식성을 유지하려면 메인
SKILL.md를 500줄 미만으로 유지하고 상세 참조는references/로 이동하세요.
예시
사용자: "최신 백엔드 수정 사항을 내 Baota 서버에 배포해줘."
에이전트:
HOST,PORT,USER, 인증 정보,REMOTE_ROOT를 묻거나 로드합니다.- 어떤 파일이 변경되었는지 묻거나 최근 편집 내용을 추론합니다.
- 변경된 파일/폴더를
REMOTE_ROOT아래의 원격 경로에 업로드합니다. - 영향을 받는 Docker 서비스를 재빌드하고 재시작합니다.
docker-compose ps를 확인하고 로그를 확인하여 상태를 확인합니다.- 업로드 및 서비스 상태에 대한 간단한 요약으로 응답합니다.