루팅한 갤럭시 S9 한 대가 내 홈 서버다. 처음엔 카카오톡 봇 하나 돌리려고 시작했는데, 어느새 블로그와 자동화 루틴, 데이터 수집기까지 전부 이 폰 위에 올라가 있다. 지난 한 달 동안 이 폰에서 겪은 장애와 수정 기록을 시리즈로 남기기 전에, 먼저 “지금 이 폰에서 무엇이 어디서 돌아가는가"를 한 장의 지도로 정리해 둔다. 이 글은 이어질 시리즈들의 서문이자 색인이다.

두 겹의 리눅스

폰 안에는 리눅스가 두 겹으로 있다. 바깥은 Termux다. 안드로이드 위에 리눅스 유저랜드를 올려주는 앱이고, tmux 서버와 cloudflared 터널, 그리고 카카오톡 봇처럼 안드로이드와 직접 닿아야 하는 것들이 여기서 돈다. 안쪽은 proot-distro로 올린 Ubuntu 컨테이너다. 블로그 관리 서버, 데이터 수집기, 자동화 루틴, 그리고 이 모든 것을 관리하는 Claude Code 원격 세션이 여기서 돈다.

이 구조에서 가장 많이 헷갈린 건 경로였다. Ubuntu 안의 /root와 바깥 Termux 홈은 완전히 다른 디렉터리다. 부팅 스크립트를 Ubuntu 안의 ~/.termux/boot/에 두고 “왜 안 실행되지” 하며 한참을 헤맨 적이 있다. Termux:Boot가 감시하는 진짜 경로는 바깥 Termux 홈 아래다. 이 교훈은 재해복구 문서 맨 앞에 “경로 혼동 주의"로 박아 두었다.

tmux 세션 10개

서비스는 전부 tmux 소켓 하나 아래 이름 붙은 세션으로 산다. 세션 이름이 곧 서비스 지도다.

세션역할
iris카카오톡 DB 브리지(Iris 데몬, 창 0)와 Python 봇 irispy(창 1)
claude전체 인프라를 관리하는 Claude Code 원격 세션
remoteGemini 원격 코딩 채팅 서버
hts체결 데이터 기록기 웹앱 정적 서버
cloudflare봇·Gemini·기록기 쪽 외부 터널(메인 터널)
blogtunnel블로그 쪽 두 번째 터널
blogadmin블로그 관리 서버(Node)
blogcaddyCaddy 정적 서빙·리버스 프록시
phoneserver코인 시세·AI 폴백 FastAPI
rummycube보드게임 서버

Iris는 루팅된 안드로이드에서 app_process로 실행되는 데몬인데, 카카오톡의 로컬 SQLite DB를 읽어 HTTP와 WebSocket API로 열어 준다. irispy 봇은 그 API에 붙는 순수 Python이다. 블로그는 Hugo 정적 빌드 결과를 Caddy가 서빙하고, 글 작성·예약 발행·통계는 별도 Node 관리 서버가 맡는다(2026년 10월 중순부터 본문 서빙은 Cloudflare Workers로 옮겼고 폰에는 서버 상태 화면만 남았다). 체결 기록기는 pm2 아래에서 돌고, 매일 아침 채점 스크립트가 cron으로 돈다. 코인추천과 미국 시황 글은 Claude Code 세션의 예약 루틴이 하루 세 번 발행한다.

부팅과 감시

재부팅 뒤 이 모든 것을 올리는 건 Termux:Boot가 실행하는 start-iris.sh 한 개다. 이름은 Iris지만 실제로는 위 세션 전부를 순서대로 띄운다. 각 세션은 tmux has-session 가드로 중복 기동을 막고, Ubuntu 안의 cron 데몬과 pm2 복구는 별도 줄에서 처리한다. Termux 앱 자체가 죽으면 MacroDroid가 3분 안에 다시 실행시키고, 그러면 Termux:Boot가 다시 스크립트를 돈다.

살아 있는지 보는 건 Ubuntu 안 cron이 5분마다 돌리는 watchdog.sh다. 서비스별로 HTTP 응답 또는 프로세스 존재를 확인하고, 죽었으면 부팅 스크립트와 똑같은 명령을 tmux send-keys로 해당 창에 다시 쏜다.

여기에 구조적인 약점이 하나 있다. cron과 pm2를 올리는 줄이 부팅 초기에 가끔 멈춘다. 그 줄이 동기로 실행되던 시절엔 뒤의 세션이 하나도 안 올라왔고, 백그라운드로 뺀 뒤에도 “그날은 cron이 안 뜬 채로” 시작하는 날이 있다. cron이 없으면 watchdog도 없으니, 감시자가 감시자를 못 고치는 셈이다. 이 문제를 어떻게 줄여 왔는지가 다음 시리즈의 큰 줄기다.

git 밖의 것들

코드는 전부 GitHub에 있다. 하지만 부팅 스크립트, crontab, Caddy 설정, 터널 토큰 파일의 위치, MacroDroid 매크로는 git 밖에 있다. 그래서 별도 저장소에 재해복구 문서와 설정 사본을 두고, 인프라를 바꿀 때마다 같은 커밋에서 갱신하는 규칙을 세웠다. 이 문서 덕분에 “폰이 벽돌이 되면 어디서부터 다시 하나"에 답이 있다.

이어질 시리즈

  • 폰 서버 안정화 일지: 부팅 스크립트 한 줄, 좀비 26개, 터널 오탐, DNS가 속인 두 번, 내 손으로 만든 7시간 장애, 재해복구 문서, 저장공간 감사, 공개 면적 축소.
  • 카톡 봇 이미지 전송기: Iris가 보낼 수 있는 것과 없는 것, 카카오톡 업데이트가 전송을 멈춘 날, 전송 계측과 간격 설계, Worker 보관함.
  • 카톡 봇 운영 기록: 게임 경제, 자기교착, 메시지 캐시, 코드 리뷰, PIN 위생.
  • 블로그 운영기: 예약 발행, 썸네일 생성, 댓글, 타임존 버그, SEO, Workers 이전.
  • 자동화 루틴 기록: 시황·코인 루틴의 데이터 오류, 교차검증, 알림 정책, 권한 분류기, 스케줄러.

다음 글부터는 이 폰이 어떻게 자주 넘어졌고, 어떻게 덜 넘어지게 만들었는지 적는다.

🤖 이 포스팅은 AI의 도움을 받아 작성되었습니다.