← Projects
Resume

PERSONAL PROJECT · 운영 중

junu.dev Home Infrastructure

Raspberry Pi에는 기술 위키를, Cloudflare Pages에는 웹 도구를 올려 서비스 특성에 맞게 배포 위치를 나눠 운영하고 있습니다.

PERIOD운영 중
TEAM개인 (1인)
ROLEDesign · Deploy · Operate
STACKRaspberry Pi · Docker Compose · Cloudflare Tunnel · Cloudflare Pages · GitHub Actions

실습용 VM을 만들고 지우는 대신, 실제로 매일 쓰는 서비스를 계속 운영하면서 배포 · 네트워크 · 데이터 문제를 직접 겪어 보기 위한 환경입니다.

Raspberry Pi Linux 서버에서 Wiki.js 기술 위키를 운영합니다. 위키는 Docker Compose로 Wiki.js와 PostgreSQL을 분리해 띄우고, 외부 접근은 Cloudflare Tunnel로만 받아 집 공유기의 포트를 열지 않았습니다. 웹 도구는 처음에 GitHub Actions에서 빌드해 Pi의 Self-hosted Runner가 Nginx 경로에 배포했고, 서버 처리가 필요 없는 정적 도구라 지금은 Cloudflare Pages로 옮겨 운영합니다.

GOAL실사용 서비스를 직접 운영

설치하고 끝나는 실습이 아니라, 바뀌고 고장 나는 서비스를 계속 유지합니다.

EDGEOrigin을 공개하지 않는 노출

Cloudflare Tunnel이 바깥으로 연결을 맺어, 인바운드 포트 없이 서브도메인별로 서비스를 연결합니다.

PLACEMENT서비스 특성에 맞춘 배포 위치

데이터베이스가 필요한 위키는 Pi에, 서버 처리가 필요 없는 웹 도구는 Cloudflare Pages에 둡니다.

DATA컨테이너와 데이터 분리

위키 데이터는 PostgreSQL 볼륨과 SQL Dump로 관리해 컨테이너를 다시 만들어도 유지됩니다.

이전 구조 · 웹 도구 Pi 직접 배포

GitHub Pushmaster 브랜치
→
Build Jobnpm ci · lint · build
→
Artifactdist 업로드
→
Pi RunnerSelf-hosted · Label 지정
→
Nginxrsync --delete 반영
→
Cloudflare Tunnel*.junu.dev 공개

현재: Cloudflare Pages로 이전

이전 구조 · 웹 도구를 Pi에 직접 배포하던 시기에 구성

CI/CDGitHub Actions 2단계 파이프라인

Build Job이 lint와 build를 통과한 결과물만 Artifact로 올리고, Deploy Job이 이를 받아 반영합니다. lint가 실패하면 배포까지 가지 않습니다.

RUNNERSelf-hosted Runner 라벨 라우팅

Pi에 Runner를 설치하고 raspberrypi · deploy · 서비스 이름 라벨을 붙여, 배포 Job이 정해진 장비에서만 실행되게 했습니다.

RELEASE동기화 방식의 정적 배포

rsync --delete로 서비스 디렉터리를 빌드 결과와 똑같이 맞춰 이전 파일이 남지 않게 하고, 배포 후 디렉터리 755 · 파일 644로 권한을 정리합니다.

CONCURRENCY중복 배포 방지

워크플로에 concurrency 그룹을 두어, 연속으로 push해도 마지막 변경만 배포되도록 이전 실행을 취소합니다.

현재 구조

MIGRATION웹 도구 Cloudflare Pages 이전

서버 처리가 필요 없는 웹 도구는 Cloudflare Pages로 이전하고, Pi에는 데이터베이스가 필요한 위키만 남겨 운영합니다.

EDGECloudflare Tunnel 공개

위키는 Cloudflare Tunnel로 인바운드 포트 없이 서브도메인으로 공개합니다.

CONTAINERDocker Compose 위키 구성

Wiki.js와 PostgreSQL을 컨테이너로 분리하고 볼륨으로 데이터를 유지하며, SQL Dump로 백업합니다.

HARDWAREmicroSD → NVMe 이전

계속 쓰고 지우는 서버 특성상 수명과 속도가 약한 microSD를 NVMe로 바꿔 저장장치를 안정화했습니다.

개인 작업에서 반복되던 일을 AI 에이전트와 함께 작은 웹 도구로 개발하고, Cloudflare Pages로 배포해 각자 서브도메인에서 운영합니다.

MASKLY · maskly.junu.dev웹 기반 이미지 편집기

React · Vite로 만든 레이어 기반 편집기입니다. 레이어 마스크, 브러시, 알파 편집, 실행 취소를 브라우저에서 처리합니다.

TRANSFORMER · transformer.junu.dev브라우저 파일 변환기

이미지 포맷 · 품질 · 크기 변환, 이미지/텍스트 → PDF, TXT · JSON · CSV · HTML · Markdown 변환을 서버 없이 브라우저에서 처리합니다.

데이터가 필요한 위키는 Pi에서, 정적 웹 도구는 Cloudflare Pages에서 운영하며 집 네트워크에 포트를 열지 않고 서비스를 공개합니다.

배포가 끝난 뒤에도 DNS, Tunnel 연결, 컨테이너 재시작, 데이터 백업처럼 서비스를 살려 두기 위해 확인해야 하는 일을 직접 반복하고 있습니다. 부트캠프에서 다룬 Self-hosted Runner, 빌드 · 배포 분리, 데이터 볼륨 분리를 작은 규모로 계속 써 보는 환경이기도 합니다.

PLACEMENT위키 Pi · 도구 Pages

서비스 특성에 맞게 배포 위치 분리

EDGE인바운드 포트 없이 공개

Cloudflare Tunnel · 서브도메인별 연결

SERVICES위키 + 웹 도구 2개

wiki · maskly · transformer

Tech Stack: Linux · Raspberry Pi · Docker Compose · Nginx · Cloudflare Tunnel · Cloudflare Pages · GitHub Actions · Self-hosted Runner · PostgreSQL · Wiki.js · React · Vite · AI Agent