홈서버 구축기 A to Z

왜 홈서버를 운영하게 되었는지, 미니 PC 2대로 운용되고 있었던 홈서버를 한대로 합치면서 배운 내용들을 기록했다.

홈서버 구축기 A to Z
홈서버를 정비하며 배운 것들

계기 : 블로그 셀프 호스팅, 그리고 미니 PC

홈서버에 관심을 가지게 된 계기는 블로그 셀프 호스팅이었다. 정기적으로 글을 쓰는 것은 아니었지만, 글을 쓰는 것이 무형적/유형적 이득이 되었으면 좋겠다는 생각이 들었다. 그러던 중, "플랫폼에 글을 쓰는 것은 플랫폼의 배만 불려주는 것이다" 라는 의견을 보기도 하고, 티스토리 애드센스 사태(공지 링크) 같은 걸 보면서 외부에 종속되지 않는 환경을 지향하게 되었다.

만약, 플랫폼 정책이 맘에 안들어서 떠나고 싶다면? 사용 중인 플랫폼이 서비스를 종료한다면? 이런 질문들을 스스로 던지며, 약간의 리서치를 통해 초기 비용과 시간을 들여서 꽤 낮은 유지보수 비용으로 셀프 호스팅을 할 수 있을 것이라 판단했다.

셀프 호스팅을 하려고 찾아보니 편의성을 위해 저렴한 기본 AWS EC2 인스턴스를 사용하는 사례가 많았다. 프리 티어에 제공되는 무료 체험 시간으로 EC2를 사용해 구축해봤는데, 편하긴 하지만 월 유지비가 부담이 되었다.

또한, 개인 블로그, 수익형 블로그, AI가 작성하는 블로그(?) 등 여러 블로그를 운용하고자 했는데 기본 인스턴스 하나에 몇개를 굴릴 수 있을까 테스트해봤더니 2개도 버거워했다. 그러자고 블로그를 하나 추가할 때마다 인스턴스를 하나씩 더 파는 것은 합리적인 선택은 아니라고 생각이 들었다.

때 마침, 하드웨어 커뮤니티에 알리익스프레스 발 미니PC 열풍이 불었는데,

  • 저전력이지만 꽤 쓸만하다는 평을 듣는 Intel N100
  • 뻥스펙 아닌가 싶은 16GB 램
  • 컨테이너 용량들로 다 채우지 못할 것 같은 512GB SSD
  • 무엇보다 10W~15W 정도의 착한 소비 전력
  • 거실장이든 네트워크 단자함에 들어갈 수 있는 작은 크기
  • 포인트 및 카드 할인을 잘 하면 10만원
Firebat T8 Plus 미니 PC 구입기 및 팁 총정리
$80 정도 가격으로 구매할 수 있는 대표적인 미니 PC Firebat T8 Plus와 관련 설정 팁에 대해 알아보자.

이건 2번째 구입했을 때 작성한 구입기 링크. 미리 덕지 덕지 붙어있을 광고에 대한 사과를 드린다.

홈서버에 이보다 더 적합한 PC는 찾을 수 없을 것 같다는 생각이 들어 바로 주문했다.

사실 이런 저런 이유보다는 DIY를 좋아하는 편이라 그런 것 같다.

첫 성과 : 방구석 미니 PC에서 블로그 구동 하기

가장 먼저 한 일은, Ubuntu Server 24.04를 설치해준 것이다. 회사에서 이런 저런 기회로 리눅스를 다룰 일이 있었는데, 터미널로 소통하는데 막연한 두려움이 없는 정도의 익숙함을 가지고 있다. 뭔가 직접 개발하기 보다는 목적에 맞는 docker image를 찾고, docker-compose 파일을 작성하여 컨테이너를 관리하는 방향으로 운영하고자 했다.

도메인 구입 및 관리는 Cloudflare로 정했다. 보편적으로 많이 쓰이기도 하고, 도메인 구입 가격이 저렴하다는 생각이 들었다. Cloudflare에서 구입할 수 없는 도메인도 있었는데, 이는 Godaddy에서 구입하고 nameserver를 Cloudflare로 변경하여 관리포인트를 일원화했다.

다음으로 할 일은, 홈서버의 public ip 주소를 도메인과 연결하는 것인데 이를 대시보드에서 수동으로도 할 수 있었지만, 통신사가 부여하는 IP가 바뀔 수도 있다는 이야기를 들어서 자동으로 업데이트할 수 있는 수단을 찾아보았다. 같은 니즈를 가진 사람들이 많은지 cloudflare-ddns 라는 docker image를 발견했다. 5분마다 IP를 확인하고, 변경이 있을 시 Cloudflare API를 통해 DNS 레코드를 업데이트해준다.

이제 도메인이 홈서버의 public ip 주소를 가르키게 되었는데, 마지막으로 공유기에서 포트 포워딩을 통해 80(http), 443(https)를 홈서버의 local ip로 넘겨주는 것으로 외부의 요청을 받을 준비가 되었다.

홈서버를 통해 블로그를 여러 개 구동하고 싶었기 때문에, 80/443 포트를 하나의 서비스에 물려줄 수 없었는데, 리버스 프록시를 통해 문제를 해결할 수 있었다. 검색을 하다보니 nginx-proxy-automation 이라는 오픈소스를 발견했는데, 내가 원하는 상황과 일치했다. 테스트 해보니 아래 그림과 같이 여러 로컬 서버에 요청을 넘길 수 있었다.

https://github.com/evertramos/nginx-proxy-automation
이 그림이 뭔가 이전 회사에서 개발 머신에 여러 개발 서버를 띄우고 내부망에서 접속할 수 있도록한 상황과 비슷하다고 느껴져서 기억을 되살려보니 frp(Fast Reverse Proxy)라는 것을 사용했었다.

마지막으로 블로깅 도구로는 Ghost를 선택했다.

일단, 내가 원했던 것은 일반적으로 익숙한 글쓰기 환경이었다. 가족과 함께 작성하는 블로그도 고려 중이었기에, 그들 입장에서 Markdown과 같이 새로 배워야하는 낯선 것들은 배제하였다. 가장 결정적이었던 것은 글쓰는 환경이 Medium이나 Notion과 별반 차이 없이 훌륭했다.

ghost 에디터. 마크다운 기반 글쓰기 환경과 더불어 첨부파일, 임베드 등 다양한 콘텐츠 삽입을 지원하여 글쓰기에 집중할 수 있다.
Ghost를 기술 블로그용 CMS로 선택한 이유
기술 블로그를 만들 때 가장 머리 아픈 고민 중 하나는 어떤 블로깅 도구를 사용할지 정하는 것이다. 이 글에서는 Ghost를 블로깅 도구로 선택한 이유와, 그 선택의 과정에서 고려한 다섯 가지 조건을 소개한다. 아울러 Ulysses와 결합된 Ghost 블로깅이 내게 어떤 사용자 경험을 안겨주었는지도 함께 소개한다.

Ghost를 기술 블로그용 CMS로 선택한 이유 - 전반적으로 Ghost를 선택한 이유가 많이 겹치는 글을 소개해본다.

Ghost는 몇가지 부가 기능을 더하여 자체 호스팅(유료)을 제공하는 동시에, 공식 docker image를 제공하고 있어서 아래와 같이 간단한 docker compose파일과 환경변수 설정만으로 블로그를 구동할 수 있다.

services:
  ghost:
    image: ghost:5
    depends_on:
      - db
    restart: unless-stopped
    ports:
      - "${EXTERNAL_PORT}:2368"
    environment:
      database__client: ${GHOST_DB_CLIENT}
      database__connection__host: ${GHOST_DB_HOST}
      database__connection__port: ${GHOST_DB_PORT}
      database__connection__user: ${MYSQL_USER}
      database__connection__password: ${MYSQL_PASSWORD}
      database__connection__database: ${MYSQL_DATABASE}
      url: ${GHOST_URL}
    volumes:
      - ghost-content:/content:/var/lib/ghost/content

  db:
    image: mysql:8
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
    volumes:
      - db-data:/var/lib/mysql


volumes:
  ghost-content:
  db-data:

ghost 셀프 호스팅을 위한 docker compose 구문

초기 세팅 이후에는 모든 것을 관리자 페이지를 통해 할 수 있다. 글쓰기, 테마 설정, 외부 서비스 연동(서치 콘솔, 애널리틱스 등) 등 일반적인 블로깅 플랫폼과 동일한, 혹은 그 이상 편리한 수준으로 실행할 수 있었다.

추가로 블로그를 개설하기 위해서는 같은 docker compose 파일을 이용하여 url, port 정도의 환경 변수만 변경하여 구동하면 되었다. 트래픽에 따른 리소스 사용률이 어떨지 모르겠지만, 초기 의도에 맞게 홈서버 운용 환경을 구성할 수 있었다.

하지만 이것이 편한가? 라는 질문을 했을 때 '완전히 편하지는 않다'라는 답을 할 수 밖에 없었다. 또한, 블로그 구동 외에도 다양한 셀프 호스팅 서비스들을 돌리고 싶었는데, 조금 번거로움이 느껴졌다. 이런 아쉬움을 어떻게 해결할 수 있을까 고민하던 차에 'Proxmox'와 Portainer라는 것을 알게 되었다.

개선 : Web UI를 통해 자유롭게 관리하는 홈서버

Proxmox Server Solutions
Proxmox develops powerful and efficient open-source server solutions like the Proxmox VE platform, Proxmox Backup Server, and Proxmox Mail Gateway.

Proxmox는 가상화 관리를 위한 오픈 소스 소프트웨어 서버로, Type 1 하이퍼바이저라고 한다. Type 1 하이퍼바이저가 무엇인지 찾아보니 중간에 OS가 껴있지 않고, 하드웨어와 바로 작동하여 성능이 더 좋다고 한다.

@https://jaycroos.com/installing-and-configuring-proxmox/

성능적인 부분보다 좋았던 것은 직관적인 시스템 관리 웹사이트이다. 공유기 설정 페이지 처럼 관리페이지에 접속하여 시스템 사용률을 한눈에 확인할 수 있고, 격리된 환경의 VM과 LXC 컨테이너를 생성/구동할 수 있다.

Proxmox 관리 페이지를 통한 리소스 사용률 확인
Proxmox 관리페이지를 통한 LXC Container 생성
Proxmox 관리페이지를 통한 LXC Container 리소스 수정

생성 시 컨테이너가 사용할 CPU 수, Memory, Disk 용량을 할당할 수 있는데, 컨테이너의 사용률을 모니터링하고 리소스가 부족하다 싶으면 UI를 통해 쉽게 리소스를 추가 할당할 수 있는 점이 좋았다. 편리하게 LXC Container를 생성하고 관리할 수 있으니, 독립적으로 구동되면 좋을 것 같은 것들을 분리하여 생성했다.

첫째로, wg-easy라는 docker image로 Wireguard VPN 서버를 구동시켰다. 뒤이어 소개할 Portainer에서 실행할 수도 있었지만, 어떤 문제가 발생해도 최소한 홈 네트워크에 접속할 수 있도록 독립적으로 구동하고자 했다.

wg-easy는 Web UI를 통한 vpn 프로필 관리 기능을 제공한다. 과거 회사에서는 ssh로 vpn 서버에 들어가서 스크립트 실행을 통해 프로필을 생성하고 이를 전달했었는데, 직관적인 인터페이스로 생성/관리할 수 있는 점이 매력적이었다.

wg-easy는 Web UI를 통해 VPN 프로필을 관리할 수 있게 해준다.

Openvpn만 알던 내게 Wireguard는 다소 생소해서 ChatGPT에게 차이점을 물어봤더니 아래와 같은 답을 들을 수 있었다.

특성 OpenVPN WireGuard
설계 오래된 기술, 복잡한 코드베이스 경량 설계, 최신 기술
성능 상대적으로 낮음 매우 빠르고 CPU 사용량 적음
보안 다양한 암호화 옵션, 설정에 따라 다름 기본적으로 안전한 최신 암호화
설정 복잡도 복잡함 간단함
호환성 높은 호환성, 다양한 환경에서 동작 신기술로 지원 범위가 점차 증가 중

호환성은 Android, iOS, Windows, 그리고 Mac OS 모두 전용 클라이언트가 제공되어 잘 동작했다.

둘째로는 NPM(nginx-proxy-manager)이다. 기존의 nginx-proxy-automation 과 같은 역할이지만, 차이가 있다면 NPM은 Web UI를 통해 프록시 대상을 관리할 수 있다는 것이다. 원래는 환경변수로 관리하던 프록시 설정을 아래와 같이 Web UI를 통해 관리할 수 있었다. 아래와 같이 도메인 이름과 포워딩할 IP, Port만 설정하면 된다.

NPM을 통한 프록시 추가 인터페이스 - IP 주소와 Port는 예시이다.

또한 프록시 설정을 하면서 https 제공을 위해 기존에 보유 중인 SSL 인증서를 사용할 수도 있고, 혹은 Let's Encrypt를 통한 원클릭 설정도 가능했다.

Let's Encrypt를 통한 원클릭 설정

공유기에서 이 컨테이너의 IP로 80, 443 포트포워딩 설정을 해주는 것으로 NPM이 http/https 요청을 처리할 수 있도록 했다.

마지막으로 Portainer를 구동하기 위한 컨테이너를 생성했다. Portainer는 Docker 관리를 용이하게 도와주는 도구로, Web UI를 통해 Docker를 구동하고, 컨테이너, 볼륨, 네트워크 등 리소스를 관리할 수 있는 인터페이스를 제공한다.

앞서 소개했던 cloudflare-ddns 마이그레이션 예시. 공식 docker-compose 설정 구문과 환경변수를 설정하는 것으로 끝이었다.

관심사가 이렇다보니 우연히 Awesome-Selfhosted 라는 페이지를 발견했는데, 여기에 소개된 대부분의 서비스들은 docker를 통한 설치 가이드를 제공한다. 이것 저것 가볍게 테스트 해보고 싶은데, 기존 환경에서 새로운 서비스를 구동하기 위한 번거로움이 컸었다. 그런데 이제는 Portainer의 Web UI를 통해 서비스를 생성 및 구동하고, Portainer의 IP와 포트 번호로 NPM에서 포워딩을 설정 해주면 순식간에 어디서든 접속할 수 있는 서비스가 만들어진다.

구동하는 컨테이너가 많아지니 일시적으로 램과 디스크 사용률이 높아졌는데, Proxmox에서 쉽게 시스템 리소스를 더 할당할 수 있어서 문제를 해소할 수 있었다. (초기 RAM 4GB -> 8GB, 저장용량 20GB -> 100GB)

현재 Proxmox 위에서 총 3개의 LXC 컨테이너가 구동되고 있고, Portainer를 통해 8개의 docker가 구동되고 있다. (이 블로그도 그 중 하나이다.) 블로그를 셀프 호스팅 해보겠다는 1차적인 목표를 넘어 다양한 소프트웨어를 구동해볼 수 있는 환경을 구축했기에 앞으로 다양한 시도를 해볼 수 있을 것 같다.

마치며

커피한잔으로 유명하신 1인 개발자 분의 블로그에는 6년간 홈서버로 서비스를 운영하신 이야기가 공유되어있다. 월 5천원 남짓한 전기료만 내셨다고 하는데, 클라우드 대비 정말 저렴한 가격에 적절한 컴퓨팅 리소스를 운용할 수 있다. 2번째 첨부한 링크와 같이 비용보다는 가정 내 전기, 침수 등 운용 이슈가 리스크로 작용할 때라면 충분히 돈을 벌고 있다는 뜻이니 기분 좋게 클라우드로 이전하면 될 것이다.

집에서 서버를 운영하는 게 가능한가요?
집에서도 서버를 운영할 수 있을까? 생각은 하지만 실제로 실행하는 사람은 별로 없는 것 같습니다.
커피한잔 서버 장애 썰
집에서 서버를 6년 동안 운영했다는 것이 많은 분들에게 신기하게 들렸나 봅니다. 이해합니다. 옛 개발자 동료들도 이야기를 들으면 대부분 놀랐으니까.

얼마 전, 필자의 블로그도 건물 시스템 점검 3시간동안 셧다운 되었었지만, 문제될 일은 없었다😅

요즘은 서비스를 만들어서 배포를 하려면 무조건 클라우드를 쓰는게 기본 전제가 되는데, 정말 큰 트래픽을 요구하지 않는 서비스라면 이렇게 비용 부담없이 홈서버로 시작해보는 것도 좋을 것 같다.

또한, 이전에 스타트업에 다닐 때는 내부 시스템을 구축하고 손길이 곳곳에 닿아있었는데 지금 회사에서는 이런 것들과 멀어졌다는 게 아쉬웠다. 이번 기회에 나만의 시스템, 인프라를 구축하며 아쉬움이 조금 달래졌다.

홈서버라는 것이 시작은 블로그 셀프 호스팅이었지만, 어느덧 나만의 작은 인프라를 구축하고 이것저것 실험하는 재미로 이어졌다. 클라우드 대비 장/단점이 있지만, 비용 부담 없이 내가 원하는 대로 환경을 꾸릴 수 있다는 점이 정말 매력적이었다. 앞으로도 이 홈서버를 기반으로 다양한 시도를 해볼 계획이다.

이 글을 읽고 만약 호기심이 생긴다면, 작은 도전부터 시작해보는 것을 제안해본다.