13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] self-hosting

  • Proxmox LXC 안에서 Docker 돌리기 — nesting·keyctl과 함정들

    Proxmox에서 어떤 서비스를 올릴 때, 무거운 VM을 통째로 띄우는 대신 가벼운 LXC 컨테이너 안에서 Docker를 돌리는 방법이 있습니다. 저는 사진 서버(Immich)도, 이 블로그 자동화 봇도 이 방식으로 운영합니다. 실제 설정과 반드시 알아야 할 함정을 정리합니다.

    1. 왜 VM이 아니라 LXC + Docker인가

    • 가볍다: LXC는 호스트 커널을 공유해서 VM보다 메모리·오버헤드가 훨씬 적습니다.
    • 빠르다: 부팅이 거의 즉시고, 자원 낭비가 적습니다.
    • Docker 생태계 그대로: compose 파일과 이미지를 그대로 씁니다.

    단, “다른 커널이 필요하다”거나 “강한 격리가 필수”라면 그땐 VM이 맞습니다. 일반적인 웹서비스·봇·셀프호스팅 앱이라면 LXC + Docker가 가성비 최고입니다.

    2. 핵심 — 두 개의 기능 플래그

    기본 LXC에 Docker를 깔면 안 돌아갑니다. 두 가지 features를 켜야 합니다.

    # 컨테이너(예: 113)에 nesting + keyctl 활성화
    pct set 113 --features nesting=1,keyctl=1
    플래그 역할
    nesting=1 컨테이너 안에서 또 컨테이너(Docker) 실행 허용
    keyctl=1 Docker가 쓰는 커널 키링 접근 허용

    실제로 제 컨테이너들은 이렇게 잡혀 있습니다 — 봇 컨테이너는 nesting=1,keyctl=1, Immich 컨테이너는 nesting=1. 그리고 둘 다 unprivileged(비특권) 컨테이너입니다. 보안상 가능하면 unprivileged로 두는 걸 권합니다.

    3. Docker 설치

    플래그를 켜고 컨테이너를 재시작한 뒤, 안에서 평범하게 Docker를 설치하면 됩니다.

    # LXC 내부에서 (공식 스크립트)
    curl -fsSL https://get.docker.com | sh
    docker --version   # 예: Docker version 29.4.0
    docker compose version

    4. 반드시 밟는 함정 — 좀비 프로세스

    여기서 많은 분이 당합니다. 컨테이너 안에서 자식 프로세스를 반복 생성하는 앱(브라우저 자동화, 이미지 변환 등)을 Docker로 돌리면, 죽은 자식이 좀비로 쌓입니다. 컨테이너의 PID 1이 이를 거두지 않기 때문입니다(저는 이걸로 좀비 307개를 만든 적이 있습니다 — 관련 글).

    # docker-compose.yml — tini를 PID 1로 넣어 좀비 자동 수거
    services:
      app:
        image: my-app:latest
        init: true

    5. 그 외 실전 주의점

    • rootfs 용량: Docker 이미지·빌드 캐시가 금방 쌓입니다. LXC rootfs를 넉넉히(무거운 이미지는 16GB+) 잡고, docker builder prune을 주기적으로.
    • 데이터는 볼륨으로: 컨테이너를 갈아엎어도 데이터가 남게, 영구 데이터는 호스트 경로/NAS 볼륨에 마운트.
    • 백업: LXC 자체를 Proxmox 스냅샷/백업하면 Docker 스택까지 통째로 보존됩니다.

    6. 정리

    LXC + Docker는 홈랩에서 VM의 무게 없이 Docker 생태계를 쓰는 최적의 절충안입니다. 핵심은 딱 두 가지 — nesting=1과 keyctl=1을 켜는 것, 그리고 서브프로세스 앱엔 init: true를 잊지 않는 것. 이 두 개만 챙기면 미니 PC 한 대에 서비스를 훨씬 많이 얹을 수 있습니다.

  • 포트 개방 없이 홈랩 서비스 외부 공개하기 — Cloudflare Tunnel 실전

    홈랩에 올린 서비스를 밖에서 접속하려면 보통 공유기 포트포워딩 + DDNS를 씁니다. 그런데 저는 공유기에 포트를 단 하나도 열지 않고 이 블로그(blog.pswq.net)를 외부에 공개하고 있습니다. 방법은 Cloudflare Tunnel입니다. 실제로 제 홈랩을 이걸로 운영하면서 겪은 구성과 장단점을 그대로 공개합니다.

    1. 왜 포트포워딩을 버렸나

    전통적인 방식(포트포워딩 + DDNS)은 홈랩에서 문제가 많습니다.

    • 고정 IP가 없다 — 가정용 회선은 IP가 바뀌어서 DDNS에 의존해야 함
    • 포트를 여는 순간 공격 표면 — 열린 80/443은 전 세계 스캐너의 표적
    • 내 공인 IP가 노출 — 위치·회선이 드러남
    • 일부 ISP는 80/443 인바운드를 아예 막음

    Cloudflare Tunnel은 이걸 근본적으로 뒤집습니다. 홈랩에서 Cloudflare로 바깥으로 나가는(outbound) 연결만 맺고, 외부 요청은 그 연결을 타고 들어옵니다. 즉 공유기에 열 포트가 0개입니다.

    2. 동작 원리 한 장 요약

    방문자 → Cloudflare 엣지(HTTPS) → [터널] → cloudflared(홈랩) → 내부 서비스
                                        ↑ 홈랩이 먼저 outbound로 연결해 둠

    핵심은 인바운드 포트가 필요 없다는 점입니다. 홈랩의 cloudflared 데몬이 Cloudflare에 먼저 붙어 있고, 외부 트래픽은 그 통로로만 들어옵니다. HTTPS 인증서도 Cloudflare가 자동으로 처리해서 내가 인증서를 관리할 필요가 없습니다.

    3. 실제 구성 — 토큰(원격 관리형) 방식

    Cloudflare Tunnel은 두 가지로 설정할 수 있습니다. 저는 토큰 방식을 씁니다.

    방식 설정 위치 특징
    토큰(원격 관리형) Cloudflare Zero Trust 대시보드 웹에서 라우팅 관리, 서버엔 토큰만
    로컬 config.yml 서버의 설정 파일 파일로 버전관리, GitOps에 유리

    홈랩 서버에서 데몬을 이렇게 띄웁니다(토큰은 절대 공개 금지, 여기선 가림).

    cloudflared --no-autoupdate tunnel run --token <터널토큰>

    --no-autoupdate는 데몬이 멋대로 자동 업데이트해서 예기치 않게 재시작하는 걸 막으려고 붙였습니다(홈랩은 안정성이 우선). 서버 쪽 설정은 이게 전부고, 나머지 라우팅은 전부 대시보드에서 합니다.

    4. 공개 호스트네임 연결

    Zero Trust 대시보드 → 터널 → Public Hostname에서 도메인과 내부 서비스를 매핑합니다.

    항목 값(예)
    Subdomain / Domain blog . (내 도메인)
    Service Type HTTP
    URL http://192.168.x.x:<내부포트>

    여기서 URL은 홈랩 내부에서 본 서비스 주소입니다. 즉 방문자는 HTTPS로 blog.내도메인에 접속하지만, 터널 반대편에선 평범한 사내 HTTP 서비스로 전달됩니다. 내부 서비스는 HTTPS를 몰라도 되고, 공인 IP도 드러나지 않습니다. 저는 이 방식으로 WordPress 블로그를 외부에 공개하고 있습니다.

    5. 직접 써 보고 느낀 장단점

    좋은 점

    • 포트 개방 0 — 공유기 설정을 건드릴 필요가 없고 공격 표면이 사라짐
    • 공인 IP 숨김 — 방문자는 Cloudflare만 봄
    • HTTPS 자동 — 인증서 갱신을 신경 쓸 필요 없음
    • 무료 — 개인 홈랩 규모에선 비용이 들지 않음

    주의할 점

    • 토큰 유출은 치명적 — 토큰이 곧 터널 권한이라, 프로세스 인자·로그·스크린샷에 노출되지 않게 관리해야 함
    • Cloudflare 의존 — 트래픽이 Cloudflare를 경유하므로 서비스 장애의 영향을 받음
    • 관리자 페이지는 반드시 보호 — 외부 공개 시 Cloudflare Access로 접근 제어를 걸어 두는 걸 권장(로그인/관리 경로)

    6. 결론

    홈랩 서비스를 밖에 내놓을 때, 저는 이제 포트포워딩으로 돌아갈 이유를 못 느낍니다. 포트 0개, IP 숨김, 무료 HTTPS라는 조합은 개인 홈랩에 특히 잘 맞습니다. 단, 토큰 관리와 관리자 경로 보호만 확실히 하면 됩니다. 홈랩 서비스를 외부에 공개할 계획이라면 Cloudflare Tunnel부터 검토해 보시길 권합니다.