26년 홈서버 대청소: 주요 서비스 5개 한꺼번에 메이저 업데이트한 후기

미루고 미루던 홈서버 업데이트를 드디어 해치웠다. WireGuard, Nginx Proxy Manager, Portainer, Ghost, 그리고 Proxmox까지. 하나씩 하면 될 것을 한꺼번에 몰아서 했더니 반나절이 훌쩍 지나갔다. 각 서비스별로 어떤 변화가 있었고, 업그레이드 과정에서 뭘 주의해야 하는지 정리해본다.

26년 홈서버 대청소: 주요 서비스 5개 한꺼번에 메이저 업데이트한 후기
실제로는 더 복잡합니다😂
홈서버 업데이트 하면서 남긴 메모를 바탕으로 AI가 자동으로 작성한 내용임을 알립니다.

1. WireGuard Easy: v14 → v15 (완전 새로 짠 물건)

이번에 가장 손이 많이 갔던 녀석이다. v15는 단순 업데이트가 아니라 프로젝트 자체를 완전히 다시 작성한 버전이다. 기존 v14의 코드베이스를 갈아엎고 처음부터 새로 만들었기 때문에, 기존 설정 파일 구조와 환경 변수 체계가 전부 바뀌었다.

뭐가 달라졌나

가장 큰 변화는 설정 방식이다. 기존에는 Docker Compose의 environment 블록에 WireGuard 관련 설정값들을 죄다 넣어줬었다. DNS 서버, 허용 IP 대역, MTU 같은 것들을 전부 환경 변수로 관리했는데, v15부터는 이런 설정들이 대부분 Web UI 안의 Admin Panel로 옮겨갔다. 환경 변수에서 UI 기반 설정으로의 전환인 셈이다. 덕분에 docker-compose.yml 파일이 훨씬 깔끔해졌다.

Docker Compose 파일도 당연히 수정이 필요하다. 특히 주의할 점은, Web UI에 HTTP로 접속하는 경우 INSECURE 환경 변수를 true로 명시적으로 설정해줘야 한다는 것이다. Reverse proxy 뒤에서 돌리는 경우 대부분 해당되니 빼먹지 않도록 하자.

참고로 v15부터는 armv6/armv7 아키텍처를 더 이상 지원하지 않는다. 라즈베리파이 구형 모델을 사용하고 있다면 이 부분을 확인해야 한다.

마이그레이션 과정

공식 마이그레이션 가이드를 따라가면 되는데, 핵심은 이렇다:

  1. 기존 Web UI에서 Backup 버튼을 눌러 wg0.json 파일을 다운로드한다.
  2. 기존에 설정해뒀던 환경 변수들도 따로 메모해둔다 (자동 마이그레이션 안 됨).
  3. 기존 컨테이너를 docker compose down으로 내린다.
  4. 새 v15 컨테이너를 띄우고, Setup Wizard에서 기존 설정 파일을 업로드한다.
  5. 기존 환경 변수에 해당하는 설정들을 Admin Panel에서 다시 잡아준다.

다국어 지원

v15부터 다국어 지원이 들어갔는데, 아직 한국어는 없다. 기여 가이드를 보니 번역 PR을 올리면 되는 구조라서, 시간 나면 한번 해볼까 싶다.


2. Nginx Proxy Manager: 2.12.2 → 2.13.5 (난이도 최하)

이번 업데이트 중에서 가장 편했던 녀석. 그냥 이미지 태그 바꾸고 docker compose pull && docker compose up -d 한 방이면 끝이다. DB 스키마 변경도 없고, Nginx/OpenResty 쪽 변경도 없고, 템플릿 엔진 수정도 없어서 무중단에 가깝게 업그레이드할 수 있었다.

주요 변경사항

하지만 내부적으로는 꽤 많이 바뀌었다. 2.13 버전의 가장 큰 변화는 프론트엔드를 Vue에서 React로 완전히 교체한 것이다. 무려 5년 만에 이루어진 UI 전면 개편인데, Tabler UI를 기반으로 한 새 인터페이스가 확실히 더 깔끔하고 반응성도 좋아졌다. 모바일에서의 UI/UX도 개선되었다.

백엔드도 CommonJS에서 ESM 기반으로 리팩토링되었고, 전반적으로 async/await 패턴이 적용되었다. Certbot은 5.1로 업그레이드되면서 Hetzner Cloud DNS 통합이 추가되었고, 기본 MySQL TLS 지원도 들어갔다. 보안 측면에서는 악의적인 이메일 입력을 통한 원격 실행 취약점이 수정된 것이 눈에 띈다.

셋업 위자드도 새로 생겨서 기존의 기본 관리자 계정([email protected] / changeme) 방식이 사라졌다. 처음 접속할 때 직접 관리자 계정을 설정하게 된다. 물론 기존 사용자는 이미 계정이 있으니 영향 없다.

API도 손을 봤는데, 유효성 검증이 강화되었고 boolean 응답이 0/1에서 true/false로 바뀌었다. API를 직접 호출해서 자동화하고 있었다면 이 부분 확인이 필요하다.

다국어 지원

여기도 다국어 지원이 활발하게 진행 중이다. 2.13.5 기준으로 베트남어, 이탈리아어, 네덜란드어 등이 추가되었고, 2.13.6에서는 한국어도 추가된 것을 확인했다. 불가리아어, 인도네시아어, 아일랜드어 등도 계속 올라오고 있어서, 오픈소스 다국어 생태계가 점점 풍성해지는 느낌이다. 참고로 2.13.6에서는 TOTP 기반 2FA도 추가되었으니, 보안을 신경 쓴다면 함께 업그레이드하는 것도 좋겠다.


3. Portainer: 2.21.5 → 2.33.6 LTS (새 단장)

Portainer 업그레이드도 비교적 간단했다. Docker Compose 파일에서 이미지 태그를 lts로 수정한 뒤 docker compose pull && docker compose up -d 해주면 끝이다. Portainer는 자체적으로 DB 마이그레이션을 처리해주기 때문에 별도 작업이 필요 없다.

눈에 띄는 변화들

가장 먼저 체감되는 건 새 브랜딩이다. 거의 10년 만에 로고와 전반적인 UI 디자인이 새로워졌다. Docker 컨테이너 관리 도구로 시작했던 Portainer가 이제는 Kubernetes, Edge 환경까지 커버하는 플랫폼으로 성장하면서, 그에 걸맞은 현대적인 디자인으로 탈바꿈한 것이다. 로고, 파비콘, 전체적인 색감과 레이아웃이 달라져서 처음 접속하면 다른 서비스에 들어온 것 같은 기분이 든다.

기능적으로는 Observability 모듈이 눈에 띈다. 환경이 오프라인 상태가 되거나 백업이 실패하거나 리소스 사용량이 높아지는 등의 이벤트에 대해 알림을 설정할 수 있다. 기존에는 이런 모니터링을 하려면 Prometheus + Grafana 같은 별도 스택을 붙여야 했는데, Portainer 자체에서 해결할 수 있게 된 것이다.

Helm 지원도 대폭 개편되었다. 배포별 상세 페이지, 리비전 히스토리, 업그레이드/롤백 컨트롤, 릴리스 간 설정 비교 등이 추가되었다. 내부적으로는 Helm 바이너리 대신 SDK를 직접 사용하게 바뀌어 취약점도 줄고 성능도 좋아졌다. 쿠버네티스 사용자라면 꽤 반가울 변화다.

Docker Compose 웹 에디터에 코드 완성 및 유효성 검증 기능이 추가되어 배포 전에 오류를 잡아낼 수 있게 되었다. UI 쪽 React 마이그레이션도 계속 진행되면서 전반적인 로딩 속도도 개선되었다.

보안 측면에서는 mTLS 인증서 관리를 UI에서 직접 할 수 있게 되었고, Active Directory 인증에 Kerberos 지원이 추가되었다. 홈서버에서는 크게 체감하기 어려운 부분이긴 하지만, 기업 환경에서는 유용한 기능이다.


4. Ghost: 5.x → 6.0 (반쪽짜리 업그레이드)

Ghost 6.0은 이번 업데이트 중에서 가장 기대가 컸으면서도, 동시에 가장 아쉬움이 남는 업그레이드였다.

Ghost 6.0의 핵심 신기능

Ghost 6.0에는 두 가지 큰 기능이 추가되었다:

ActivityPub 통합 (소셜 웹) — Ghost 블로그가 이제 Fediverse의 일원이 될 수 있다. @[email protected] 형태의 프로필이 생기고, Mastodon, Threads, Bluesky(Bridgy 경유), Flipboard, WordPress 등에서 팔로우하고 상호작용할 수 있다. 긴 글 외에 짧은 형태의 Notes도 소셜 웹에 직접 발행할 수 있다. 별도의 써드파티 플러그인 없이 Ghost 코어에 ActivityPub이 내장된 것이다.

네이티브 애널리틱스 — 기존에는 페이지 뷰, 트래픽 소스, 방문자 행동 같은 데이터를 보려면 Google Analytics나 Umami 같은 외부 도구를 붙여야 했다. Ghost 6.0부터는 자체 대시보드에서 실시간 방문자, 인기 콘텐츠, 유입 경로, 뉴스레터 성과, 멤버 성장 추이를 쿠키 없이 확인할 수 있다. 백엔드로는 Tinybird라는 ClickHouse 기반 분석 플랫폼을 사용한다.

셀프호스팅의 현실

문제는 이 두 가지 핵심 기능이 셀프호스팅 환경에서 바로 쓸 수 있는 상태가 아니라는 점이다.

애널리틱스: Ghost-CLI 기반 설치에서는 사용 불가. 새로운 Docker Compose 기반 설치 방식(현재 프리뷰 상태)을 사용해야 하고, 별도로 Tinybird 계정을 만들어 연동해야 한다. Tinybird에 무료 플랜이 있긴 하지만, 사용량 제한이 있다. 다행히 관리자 대시보드에서 차트를 로딩할 때만 요청이 카운트되므로, 방문자 트래픽 자체는 영향을 받지 않는다.

ActivityPub: 기본적으로 Ghost에서 제공하는 호스팅 서비스(ap.ghost.org)를 통해 사용할 수 있지만, 일일 100회 인터랙션, 1만 팔로워 같은 제한이 있다. 완전한 셀프호스팅을 하려면 역시 Docker Compose 프리뷰 방식이 필요하다. 아직 독립적인 Docker 이미지가 아니라 Git 레포를 클론해서 올려야 하는 구조다. nginx 설정에 ActivityPub 프록시 블록을 추가하는 작업도 필요하다.

Ghost 팀은 Ghost 7.0부터 Docker Compose를 공식 기본 설치 방식으로 전환할 예정이라고 밝히고 있다.

그 외 변경사항

개발 스택도 업데이트되었다. Node.js v22만 지원하고 (v18, v20 지원 종료), MySQL 8이 유일한 프로덕션 DB, API에서 ?limit=all 파라미터가 제거되어 최대 100건까지만 반환되도록 바뀌었다. API를 사용하는 커스텀 통합이 있다면 페이지네이션 처리가 필요하다.

결론

일단 Ghost 5 → 6 업그레이드 자체는 공식 가이드를 따르면 큰 문제 없이 진행된다. 블로그 기본 기능에는 문제가 없고, 테마 호환성도 괜찮았다. 다만 ActivityPub과 Analytics 같은 핵심 신기능을 셀프호스팅에서 제대로 활용하려면 Docker Compose 기반으로 전환해야 하는데, 이건 좀 더 시간을 두고 작업할 예정이다. 당장 블로그 운영에 지장은 없으니, 일단 이대로 시마이.


5. Proxmox: 8.3.0 → 9.1 (이번 업데이트의 보스)

이번 업데이트 중 단연 가장 긴장됐던 녀석이다. 하이퍼바이저 업그레이드는 실패하면 VM 전체가 날아갈 수 있기 때문에, 제대로 준비하고 진행해야 한다. Debian Bookworm에서 Trixie로의 대규모 전환이기도 하다.

사전 준비: 8.4.1로 먼저 올리기

Proxmox 9로 바로 점프할 수 없다. 반드시 먼저 8.4.1 이상으로 올려놓아야 한다. 내 경우 8.3.0에서 시작했기 때문에:

apt update
apt dist-upgrade
pveversion  # 8.4.1 이상인지 확인

이 과정에서 별 이슈 없이 8.4 대로 올라갔다.

pve8to9 체크 스크립트

Proxmox는 pve8to9라는 업그레이드 전 체크리스트 스크립트를 제공한다. pve8to9 --full로 전체 검사를 돌릴 수 있고, 반드시 한 번 이상은 full 옵션으로 돌려봐야 한다. 이 스크립트는 문제를 확인만 해줄 뿐, 알아서 고쳐주지는 않는다.

내 N100 미니PC에서 나온 주요 이슈는 두 가지였다:

systemd-boot 패키지 문제: Debian Trixie에서 systemd-boot 패키지가 systemd-boot-efi, systemd-boot-tools, systemd-boot 메타패키지로 분리되었다. PVE 8.1~8.4 ISO로 설치한 시스템에는 systemd-boot 메타패키지가 불필요하게 남아있는데, 이게 부팅 관련 패키지 업그레이드 시 충돌을 일으킨다. 실제로 GRUB으로 부팅하는 시스템이라면 apt remove systemd-boot으로 안전하게 제거할 수 있다. N100 미니PC 사용자들 사이에서 공통적으로 보고되는 이슈다.

intel-microcode 패키지 누락: N100 같은 인텔 CPU를 사용하는 경우, CPU 마이크로코드 패키지가 설치되어 있지 않다는 경고가 뜬다. apt 소스에 non-free-firmware 컴포넌트를 추가한 후 apt install intel-microcode로 설치하면 된다. 여기서 non-free는 유료가 아니라 오픈소스 라이선스가 아닌 펌웨어라는 뜻이다.

업그레이드 실행

공식 가이드를 따라 진행했다:

  1. /etc/apt/sources.list에서 bookwormtrixie로 변경
  2. Proxmox VE 9 패키지 레포지토리 추가 (deb822 형식 권장)
  3. apt update로 패키지 인덱스 갱신
  4. apt dist-upgrade 실행

apt dist-upgrade 과정에서 설정 파일 변경에 대한 선택지가 여러 번 나온다:

  • /etc/issue → 부팅 시 자동 생성되는 파일이라 기본값(No) 선택해도 무방
  • /etc/lvm/lvm.conf → 직접 수정한 적 없다면 새 버전(Yes) 선택 권장
  • /etc/ssh/sshd_config → deprecated된 옵션 교체 정도라 새 버전 권장
  • /etc/default/grub → 커널 파라미터를 직접 수정한 적 있다면 주의, 잘 모르겠으면 기본값(No)

나는 대부분 기본값(엔터키)으로 선택했고, 별 문제 없이 넘어갔다.

시스템 성능에 따라 소요 시간이 크게 다른데, SSD 기반이면 5분 내외, HDD면 60분 이상 걸릴 수 있다. 내 N100 미니PC(SSD)에서는 체감상 10분 정도 걸렸다.

주의사항

  • 업그레이드는 반드시 콘솔이나 SSH(tmux/screen 사용 권장)에서 진행할 것. Web UI의 가상 콘솔에서 하면 도중에 연결이 끊긴다.
  • 완료 후 리부트하면 새 커널(6.14 기반)로 부팅된다.
  • 웹 UI 접속 시 브라우저 캐시를 반드시 비우거나 강제 새로고침(Ctrl+Shift+R)을 할 것.
  • 루트 마운트 포인트에 최소 5GB, 이상적으로는 10GB 이상의 여유 공간이 필요하다.
  • 업그레이드 실패의 가장 흔한 원인은 메모리 부족이니, RAM이나 swap 설정을 미리 확인하자.

마무리

반나절에 걸쳐 5개 서비스를 한꺼번에 업데이트했다. 체감 난이도를 정리하면:

서비스 버전 변경 난이도 한줄 요약
NPM 2.12.2 → 2.13.5 ★☆☆☆☆ pull & up, 끝
Portainer 2.21.5 → 2.33.6 ★☆☆☆☆ 태그 lts로 바꾸고 pull & up
Ghost 5 → 6 ★★☆☆☆ 업그레이드는 쉬운데 신기능 활성화가 숙제
WireGuard v14 → v15 ★★★☆☆ 완전 재작성, 마이그레이션 필요
Proxmox 8.3.0 → 9.1 ★★★★☆ 하이퍼바이저라 긴장감 최고, N100 이슈 있음

하나 아쉬운 건 WireGuard Easy와 Nginx Proxy Manager 모두 다국어 지원이 활발한데, WireGuard Easy에는 아직 한국어 번역이 없다는 점이다. NPM은 2.13.6에서 한국어가 추가된 걸 확인했지만, wg-easy는 아직. 둘 다 오픈소스 프로젝트이고 번역 기여 구조가 잘 되어 있으니, 시간 나면 한국어 번역 PR을 올려볼 생각이다.

홈서버 운영은 이렇게 가끔씩 몰아서 업데이트하는 날이 온다. 귀찮지만, 끝나고 나면 은근 뿌듯하다. 혹시 비슷한 환경에서 업데이트를 고민하고 있다면, 이 글이 참고가 되었으면 한다.

⬇️ 미니PC를 활용한 홈서버 구축기 ⬇️

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