
RemotePower – 셀프 호스팅 방식의 원격 전원 관리
요약
RemotePower는 클라우드 의존성 없이 자체 인프라에서 장치의 전원을 관리할 수 있는 셀프 호스팅 방식의 도구입니다. 폴링 에이전트 방식을 사용하여 인바운드 방화벽 설정 없이도 NAT나 제한된 네트워크 환경에서 안전하게 원격 제어가 가능합니다.
핵심 포인트
- 클라우드 대시보드 의존 없는 완전한 셀프 호스팅 지원
- 폴링 에이전트 구조로 인바운드 방화벽 개방 불필요
- Python CGI와 JSON 파일을 활용한 단순하고 안정적인 백엔드
- NAT 및 제한된 네트워크 환경에서도 원격 제어 가능
제가 RemotePower를 만든 이유는 클라우드 서비스나 특정 업체의 '폰 홈(phone-home)' 대시보드에 의존하지 않고, 제 자체 인프라 전반에서 장치의 전원을 켜고 끄고 싶었기 때문입니다. 제가 운영하는 모든 것은 셀프 호스팅 (self-hosted) 방식이며, 원격 전원 관리는 SSH 스크립트와 cron 편법(hacks)으로 계속 임시방편을 찾아내야 했던 유일하고 짜증 나는 공백이었습니다. 그래서 이를 위한 제대로 된 도구를 직접 작성했습니다.
갈증 (The itch)
직접 하드웨어를 운영해 보셨다면 그 패턴을 잘 아실 겁니다. 박스를 재부팅해야 하거나 장치를 사이클링 (cycling) 해야 할 때, 직접 현장에 가거나 아니면 어떻게 사용하는지 절반쯤만 기억나는 일회성 SSH 스크립트를 짜서 겨우 해결하곤 하죠. 이에 대한 모든 상용 솔루션들은 여러분의 전원 관리를 그들의 클라우드를 통해 라우팅하고, 그들의 대시보드로 폰 홈 (phone home) 하는 그들의 에이전트 (agent)를 설치하게 하며, 내년에도 그 회사가 존재할 것이라고 믿으라고 합니다. "내 기기를 켜고 끄는 것"처럼 민감한 작업에 대해, 저는 그것이 결코 마음 편치 않았습니다.
저는 제가 완전히 소유하고, 제가 제어하는 인프라 위에서 전적으로 실행되며, 무언가 고장 났을 때 처음부터 끝까지 읽고 이해할 수 있는 무언가를 원했습니다.
작동 방식 (How it works)
RemotePower는 폴링 에이전트 (polling-agent) 설정입니다. 클라이언트가 작은 서버로 폰 홈 (phone home) 하기 때문에, 관리 중인 머신에 인바운드 (inbound) 연결을 노출할 필요가 없습니다. 에이전트가 먼저 요청을 보내고, 서버는 내부로 접속할 필요가 없습니다. 이는 관리 대상 박스에 인바운드 방화벽 구멍을 뚫을 필요가 없음을 의미하며, 제어하려는 대상이 전원 상태일 때는 이것이 핵심입니다.
흐름은 간단합니다:
- 각 관리 대상 장치에서 (또는 장치와 함께) 에이전트가 실행됩니다.
- 일정 간격으로 에이전트가 서버에 폴링 (poll) 합니다: "나에게 전달할 것이 있나요?"
- 서버는 대기 중인 명령어를 전달합니다.
- 에이전트가 명령을 실행하고 결과를 보고합니다.
에이전트가 모든 연결을 시작하기 때문에, 관리 대상 머신이 NAT 뒤에 있거나, 제한적인 방화벽 뒤에 있거나, 혹은 여러분이 완전히 제어할 수 없는 네트워크에 있더라도 여전히 작동합니다.
백엔드는 의도적으로 지루하게 설계되었습니다
이 부분은 제가 실제로 자랑스럽게 생각하는 부분입니다. 백엔드는 의도적으로, 그리고 공격적일 만큼 지루하게 설계되었습니다.
- nginx 뒤의 Python CGI — 각 요청은 수명이 짧은 프로세스입니다. 메모리를 누수하거나 멈춰버릴 수 있는 장기 실행 앱 서버(app server)가 없습니다.
- 저장용 플랫 JSON (Flat JSON) 파일 — 관리할 데이터베이스도, 마이그레이션(migrations)도, 커넥션 풀(connection pool)도, 계속 살려두어야 할 별도의 서비스도 없습니다.
- 인증을 위한 장치당 하나의 HMAC 토큰
덕분에 저렴한 VPS나 옷장에 있는 컴퓨터에 배포하기가 매우 간단하며, 무언가 고장 났을 때 원인을 파악하기 쉽습니다. 저장 계층이 cat packages.json인 경우, 디버깅(debugging)은 쿼리 플래너(query planner)를 추적하는 것과는 완전히 다른 경험이 됩니다.
서버 측 레이아웃의 대략적인 모습은 다음과 같습니다:
/var/www/remotepower/cgi-bin/ # CGI 핸들러 (api.py 및 기타)
/var/lib/remotepower/ # 플랫 JSON 상태 파일
/etc/remotepower/ # 설정(config)
플랫 파일(flat-file) 저장이 대규모 환경에서 "올바른" 선택일까요? 아닙니다. 하지만 대부분의 셀프 호스터(self-hosters)가 실제로 운영하는 규모 — 손에 꼽히는 수준에서 수십 대의 장치 — 에서는 운영상의 고통을 통째로 제거해 주며, 지금까지 그 트레이드오프(tradeoff)는 매번 가치가 있었습니다.
에이전트가 전원 관리 외에 수행하는 작업
어차피 에이전트가 홈(home)으로 연락(phoning home)하게 만들었다면, 몇 가지 유용한 기능을 더 추가하는 것은 자연스러운 일입니다. Linux 에이전트는 다음 작업도 수행합니다:
- 패키지 열거 (Package enumeration) —
dpkg-query/rpm/pacman/apk를 통해 설치된 패키지를 읽어오므로, 서버는 각 장치에 실제로 무엇이 있는지 인벤토리(inventory)를 보유하게 됩니다. - OSV.dev를 통한 CVE 스캔 — 설치된 패키지들을 알려진 취약점과 교차 참조하여 장치별로 발견 사항을 드러내며, 대시보드 뷰와 노이즈를 걸러내기 위한 무시 목록(ignore-list)을 제공합니다.
- Prometheus
/metrics엔드포인트 — 따라서 이미 Prometheus + Grafana를 실행 중이라면 (셀프 호스팅을 하고 있다면 아마 실행 중일 것입니다), 다른 모든 것과 함께 그래프로 시각화할 수 있습니다.
특히 CVE 관련 기능 덕분에 이 전원 관리 도구는 제가 예상했던 것보다 더 자주 확인하게 되는 도구가 되었습니다. 별도의 스캐너 (Scanner)를 구축하지 않고도 내 장비 중 어떤 것들이 취약한 패키지를 포함하고 있는지 알 수 있다는 점은 정말 유용합니다.
이 글을 게시하는 이유
이 프로젝트는 여전히 성장 중인 개인 프로젝트입니다. 아직 다듬어지지 않은 부분들이 있습니다. 제가 이미 알고 있는 몇 가지는 다음과 같습니다:
- Flat-JSON 저장 방식은 잘 작동하다가도 한계가 옵니다. 행 수준 잠금 (Row-level locking) 기능이 없기 때문에 매우 높은 동시성 (Concurrency)을 처리하는 데는 강점이 없습니다 (그렇게 설계된 것도 아닙니다).
- 요청당 CGI (CGI-per-request) 방식은 단순하지만, 과도한 폴링 (Polling) 상황에서 가장 빠른 모델은 아닙니다.
- 인증 모델 (장치별 HMAC)은 제가 설계한 위협 모델 (Threat model)에는 견고하지만, 더 많은 사람의 검토를 받고 싶습니다.
마지막 점이 바로 제가 이 글을 쓰는 진짜 이유입니다. 저보다 더 많은 규모의 시스템을 운영하는 분들이 보기에 설계 선택 중 잘못된 부분이 있다면 진심으로 듣고 싶습니다. 만약 여러분이 대규모 플릿 (Fleets)을 운영했거나, 대규모 전력을 관리했거나, 혹은 폴링 대 푸시 (Polling-vs-push) 또는 플랫 파일 대 데이터베이스 (Flat-files-vs-database)에 대해 확고한 의견을 가지고 있다면, 가감 없는 비판을 부탁드립니다.
사용해 보기 / 분석해 보기
저장소는 여기에 있습니다: github.com/tyxak/remotepower
아키텍처 결정, 에이전트 프로토콜 (Agent protocol), 왜 2026년에 CGI를 사용하는지 등 어떻게 구성되었는지에 대한 어떤 질문이든 기꺼이 답변하겠습니다. 그리고 제가 잘못한 부분을 발견하신다면, 그것이 바로 제가 이곳에서 기대하는 피드백입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
