headscale-tailscale-replace.../setup_doc/LXC_Caddysetup.md
PharmQ Admin 8d27461f76 Add pharmacy auto-registration and infrastructure improvements
- Auto-generate pharmacy_code (P001~P999) when creating new pharmacy
- Add new pharmacy fields: owner info, institution code/type, API port
- Change Headplane port mapping: 3000 → 3001 to avoid conflicts
- Add code-server setup script for development environment
- Add LXC Caddy setup documentation
- Update .gitignore to exclude farmq-admin submodule

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 07:54:47 +00:00

9.5 KiB

LXC Caddy에서 호스트 Tailscale 네트워크 연결 가이드

📅 작성일

2025년 9월 22일

🎯 개요

호스트에 Tailscale이 설치된 환경에서 LXC 컨테이너의 Caddy가 Tailscale 네트워크에 접근할 수 있도록 설정하는 완전한 가이드입니다.

🏗️ 시스템 구성

환경 정보

  • 호스트: Proxmox VE (Tailscale 설치됨)
  • LXC 컨테이너: Caddy 웹서버 (ID: 103)
  • 목표: LXC Caddy에서 Tailscale 네트워크의 서버들에 리버스 프록시

네트워크 구조

인터넷 → 도메인(*.pharmq.kr) → Caddy(LXC 103) → 호스트(라우팅) → Tailscale 네트워크

전제 조건

1. 호스트 Tailscale 설치 확인

# 호스트에서 Tailscale 상태 확인
tailscale status

# 출력 예시:
# 100.64.0.3      pve-p2               myuser       linux   -
# 100.64.0.6      pve-hp               myuser       linux   -
# 100.64.0.11     pve-p1               myuser       linux   -

2. LXC 컨테이너 정보 확인

# LXC 네트워크 정보 확인
pct exec 103 -- ip addr show eth0

# 출력 예시:
# inet 192.168.0.19/24 brd 192.168.0.255 scope global dynamic eth0

🔧 설정 단계

1단계: 호스트에서 IP 포워딩 활성화

# IP 포워딩 활성화 (임시)
echo 1 > /proc/sys/net/ipv4/ip_forward

# IP 포워딩 영구 활성화
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p

확인:

cat /proc/sys/net/ipv4/ip_forward
# 출력: 1

2단계: LXC에서 Tailscale 네트워크로 라우팅 추가

# LXC에 라우팅 규칙 추가 (임시)
pct exec 103 -- ip route add 100.64.0.0/10 via 192.168.0.200

# 라우팅 확인
pct exec 103 -- ip route | grep 100.64
# 출력: 100.64.0.0/10 via 192.168.0.200 dev eth0

영구 라우팅 설정:

# LXC 내부에서 설정
pct exec 103 -- bash -c 'echo "100.64.0.0/10 via 192.168.0.200" >> /etc/systemd/network/10-eth0.network'

# 또는 /etc/network/interfaces 사용 (Debian 기반)
pct exec 103 -- bash -c 'echo "up ip route add 100.64.0.0/10 via 192.168.0.200" >> /etc/network/interfaces'

3단계: iptables MASQUERADE 설정 (핵심!)

⚠️ 중요: 이 단계가 없으면 일부 Tailscale 노드 연결이 실패할 수 있습니다.

# LXC에서 Tailscale 네트워크로의 트래픽에 MASQUERADE 적용
iptables -t nat -A POSTROUTING -s 192.168.0.19 -d 100.64.0.0/10 -j MASQUERADE

# MASQUERADE 규칙 확인
iptables -t nat -L POSTROUTING -v -n | grep 100.64

영구 iptables 설정:

# iptables-persistent 설치 (Debian/Ubuntu)
apt-get install iptables-persistent

# 현재 규칙 저장
iptables-save > /etc/iptables/rules.v4

# 또는 systemd 서비스로 영구화
cat > /etc/systemd/system/lxc-tailscale-nat.service << 'EOF'
[Unit]
Description=LXC Tailscale NAT Rules
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 192.168.0.19 -d 100.64.0.0/10 -j MASQUERADE
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl enable lxc-tailscale-nat.service

4단계: 연결 테스트

# LXC에서 Tailscale 네트워크 ping 테스트
pct exec 103 -- ping -c 2 100.64.0.3

# 출력 예시:
# PING 100.64.0.3 (100.64.0.3) 56(84) bytes of data.
# 64 bytes from 100.64.0.3: icmp_seq=1 ttl=64 time=0.038 ms
# 64 bytes from 100.64.0.3: icmp_seq=2 ttl=64 time=0.047 ms

5단계: Caddyfile 설정

호스트 기준 Tailscale IP 매핑 확인:

# 호스트에서 Tailscale 노드 목록 확인
tailscale status

# 예시 출력:
# 100.64.0.3      pve-p2               myuser       linux   -
# 100.64.0.6      pve-hp               myuser       linux   -
# 100.64.0.11     pve-p1               myuser       linux   -
# 100.64.0.12     pve7                 myuser       linux   -

Caddyfile 설정 예시:

{
    email admin@pharmq.kr
    acme_dns cloudflare YOUR_CLOUDFLARE_TOKEN
}

# 와일드카드 인증서
*.pharmq.kr {
    tls {
        dns cloudflare YOUR_CLOUDFLARE_TOKEN
    }
    respond "Wildcard domain: {host} - SSL ready!" 200
}

# PVE 노드들 (호스트 기준 Tailscale 네트워크)
p2.pharmq.kr {
    reverse_proxy https://100.64.0.3:8006 {
        transport http {
            tls_insecure_skip_verify
        }
    }
    tls {
        dns cloudflare YOUR_CLOUDFLARE_TOKEN
    }
}

hp.pharmq.kr {
    reverse_proxy https://100.64.0.6:8006 {
        transport http {
            tls_insecure_skip_verify
        }
    }
    tls {
        dns cloudflare YOUR_CLOUDFLARE_TOKEN
    }
}

p1.pharmq.kr {
    reverse_proxy https://100.64.0.11:8006 {
        transport http {
            tls_insecure_skip_verify
        }
    }
    tls {
        dns cloudflare YOUR_CLOUDFLARE_TOKEN
    }
}

6단계: Caddy 설정 적용

# Caddyfile 문법 검증
pct exec 103 -- caddy validate --config /etc/caddy/Caddyfile

# Caddy 설정 다시 로드
pct exec 103 -- systemctl reload caddy

# Caddy 상태 확인
pct exec 103 -- systemctl status caddy

7단계: 최종 테스트

# 외부에서 도메인 접근 테스트
curl -I https://p2.pharmq.kr

# 성공 예시 응답:
# HTTP/2 501
# server: pve-api-daemon/3.0
# via: 1.1 Caddy

🔍 문제 해결

문제 1: LXC에서 Tailscale IP 접근 불가

증상:

pct exec 103 -- ping 100.64.0.3
# PING 100.64.0.3 (100.64.0.3) 56(84) bytes of data.
# --- 100.64.0.3 ping statistics ---
# 2 packets transmitted, 0 received, 100% packet loss

해결책:

# 1. 호스트 IP 포워딩 확인
cat /proc/sys/net/ipv4/ip_forward
# 0이면 활성화 필요

# 2. LXC 라우팅 규칙 확인
pct exec 103 -- ip route | grep 100.64
# 없으면 라우팅 규칙 추가 필요

# 3. 호스트 Tailscale 상태 확인
tailscale status
# 대상 노드가 활성 상태인지 확인

문제 2: Caddy에서 502 Bad Gateway

증상:

curl -I https://p2.pharmq.kr
# HTTP/2 502

해결책:

# 1. LXC에서 직접 연결 테스트
pct exec 103 -- curl -I --connect-timeout 5 https://100.64.0.3:8006

# 2. Caddy 로그 확인
pct exec 103 -- journalctl -u caddy --since "1 minute ago"

# 3. 대상 서버 응답 확인
curl -I --connect-timeout 5 https://100.64.0.3:8006

문제 3: SSL 인증서 오류

증상:

transport http {
    dial_timeout 10s
}

해결책:

# HTTPS 백엔드의 경우 SSL 검증 무시 추가
reverse_proxy https://100.64.0.3:8006 {
    transport http {
        tls_insecure_skip_verify
    }
}

📋 체크리스트

설정 전 확인사항

  • 호스트에 Tailscale 설치 및 활성화됨
  • LXC 컨테이너 네트워크 설정 확인
  • 대상 Tailscale 노드들이 활성 상태

설정 단계 체크리스트

  • 호스트 IP 포워딩 활성화
  • LXC에서 Tailscale 네트워크 라우팅 추가
  • LXC에서 Tailscale IP로 ping 성공
  • Caddyfile에 올바른 Tailscale IP 설정
  • HTTPS 백엔드에 tls_insecure_skip_verify 추가
  • Caddy 설정 검증 및 리로드
  • 외부에서 도메인 접근 테스트 성공

🎯 핵심 포인트

1. LXC에 Tailscale 설치 불필요

  • 잘못된 접근: LXC에 Tailscale 직접 설치
  • 올바른 접근: 호스트 Tailscale을 통한 라우팅

2. 네트워크 라우팅이 핵심

# 이 명령어가 모든 것을 해결합니다
pct exec 103 -- ip route add 100.64.0.0/10 via 192.168.0.200

3. 호스트 기준 IP 사용

  • LXC 내부 Tailscale 상태가 아닌 호스트 Tailscale 상태 기준으로 IP 설정

4. HTTPS 백엔드 처리

# PVE와 같은 HTTPS 백엔드의 경우 필수
transport http {
    tls_insecure_skip_verify
}

🚀 확장 가능성

다른 서비스 추가

# 새로운 Tailscale 노드 추가 예시
newservice.pharmq.kr {
    reverse_proxy http://100.64.0.X:PORT
    tls {
        dns cloudflare YOUR_TOKEN
    }
}

자동화 스크립트

#!/bin/bash
# setup-lxc-tailscale-routing.sh

LXC_ID="103"
HOST_IP="192.168.0.200"
TAILSCALE_NETWORK="100.64.0.0/10"

# IP 포워딩 활성화
echo 1 > /proc/sys/net/ipv4/ip_forward

# LXC 라우팅 추가
pct exec $LXC_ID -- ip route add $TAILSCALE_NETWORK via $HOST_IP

echo "✅ LXC Tailscale 라우팅 설정 완료"

📝 유지보수

정기 점검 항목

  1. Tailscale 연결 상태: tailscale status
  2. LXC 라우팅 상태: pct exec 103 -- ip route | grep 100.64
  3. Caddy 도메인 목록: pct exec 103 -- journalctl -u caddy | grep domains

재부팅 후 복구

# 호스트 재부팅 후 실행할 명령어들 (3단계 모두 필수!)
echo 1 > /proc/sys/net/ipv4/ip_forward
pct exec 103 -- ip route add 100.64.0.0/10 via 192.168.0.200
iptables -t nat -A POSTROUTING -s 192.168.0.19 -d 100.64.0.0/10 -j MASQUERADE

🎉 결론

이 방법을 사용하면:

  • LXC에 Tailscale 설치 불필요
  • 간단한 네트워크 라우팅으로 해결
  • 호스트 Tailscale 리소스 효율적 활용
  • SSL 인증서 자동 관리
  • 확장성 및 유지보수성 우수

핵심 원리: 호스트가 이미 Tailscale 네트워크에 연결되어 있다면, LXC는 라우팅 + MASQUERADE를 통해 호스트를 경유하여 접근할 수 있습니다!

⚠️ 중요 교훈: MASQUERADE 없이는 일부 Tailscale 노드 연결이 실패할 수 있습니다. 반드시 3단계 모두 필요합니다!


작성자: Claude Code Assistant 파일 위치: /srv/pq_setup/LXC_Caddy_with_Host_Tailscale_Setup_Guide.md 최종 업데이트: 2025년 9월 22일