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

388 lines
9.5 KiB
Markdown

# 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 설치 확인
```bash
# 호스트에서 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 컨테이너 정보 확인
```bash
# 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 포워딩 활성화
```bash
# IP 포워딩 활성화 (임시)
echo 1 > /proc/sys/net/ipv4/ip_forward
# IP 포워딩 영구 활성화
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
```
**확인:**
```bash
cat /proc/sys/net/ipv4/ip_forward
# 출력: 1
```
### 2단계: LXC에서 Tailscale 네트워크로 라우팅 추가
```bash
# 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
```
**영구 라우팅 설정:**
```bash
# 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 노드 연결이 실패할 수 있습니다.**
```bash
# 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 설정:**
```bash
# 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단계: 연결 테스트
```bash
# 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 매핑 확인:**
```bash
# 호스트에서 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 설정 예시:**
```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 설정 적용
```bash
# 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단계: 최종 테스트
```bash
# 외부에서 도메인 접근 테스트
curl -I https://p2.pharmq.kr
# 성공 예시 응답:
# HTTP/2 501
# server: pve-api-daemon/3.0
# via: 1.1 Caddy
```
## 🔍 문제 해결
### 문제 1: LXC에서 Tailscale IP 접근 불가
**증상:**
```bash
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
```
**해결책:**
```bash
# 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
**증상:**
```bash
curl -I https://p2.pharmq.kr
# HTTP/2 502
```
**해결책:**
```bash
# 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
}
```
**해결책:**
```caddyfile
# 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. 네트워크 라우팅이 핵심
```bash
# 이 명령어가 모든 것을 해결합니다
pct exec 103 -- ip route add 100.64.0.0/10 via 192.168.0.200
```
### 3. 호스트 기준 IP 사용
- LXC 내부 Tailscale 상태가 아닌 **호스트 Tailscale 상태** 기준으로 IP 설정
### 4. HTTPS 백엔드 처리
```caddyfile
# PVE와 같은 HTTPS 백엔드의 경우 필수
transport http {
tls_insecure_skip_verify
}
```
## 🚀 확장 가능성
### 다른 서비스 추가
```caddyfile
# 새로운 Tailscale 노드 추가 예시
newservice.pharmq.kr {
reverse_proxy http://100.64.0.X:PORT
tls {
dns cloudflare YOUR_TOKEN
}
}
```
### 자동화 스크립트
```bash
#!/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`
### 재부팅 후 복구
```bash
# 호스트 재부팅 후 실행할 명령어들 (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일