📋 기획 및 설계: - PharmQ SaaS 서비스 기획서 작성 - 구독 서비스 라인업 정의 (클라우드PC, AI CCTV, CRM) - DB 스키마 설계 및 API 아키텍처 설계 🗄️ 데이터베이스 구조: - service_products: 서비스 상품 마스터 테이블 - pharmacy_subscriptions: 약국별 구독 현황 테이블 - subscription_usage_logs: 서비스 이용 로그 테이블 - billing_history: 결제 이력 테이블 - 샘플 데이터 자동 생성 (21개 구독, 월 118만원 매출) 🔧 백엔드 API 구현: - 구독 현황 통계 API (/api/subscriptions/stats) - 약국별 구독 조회 API (/api/pharmacies/subscriptions) - 구독 상세 정보 API (/api/pharmacy/{id}/subscriptions) - 구독 생성/해지 API (/api/subscriptions) 🖥️ 프론트엔드 UI 구현: - 대시보드 구독 현황 카드 (월 매출, 구독 수, 구독률 등) - 약국 목록에 구독 상태 아이콘 및 월 구독료 표시 - 약국 상세 페이지 구독 서비스 섹션 추가 - 실시간 구독 생성/해지 기능 구현 ✨ 주요 특징: - 서비스별 색상 코딩 및 이모지 아이콘 시스템 - 실시간 업데이트 (구독 생성/해지 즉시 반영) - 반응형 디자인 (모바일/태블릿 최적화) - 툴팁 기반 상세 정보 표시 📊 현재 구독 현황: - 총 월 매출: ₩1,180,000 - 구독 약국: 10/14개 (71.4%) - AI CCTV: 6개 약국, CRM: 10개 약국, 클라우드PC: 5개 약국 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
424 lines
13 KiB
Markdown
424 lines
13 KiB
Markdown
# 🌐 FARMQ Headscale 완전 가이드
|
|
|
|
## 📚 목차
|
|
1. [개념 정리](#개념-정리)
|
|
2. [아키텍처 개요](#아키텍처-개요)
|
|
3. [포트 구성](#포트-구성)
|
|
4. [설치 및 구성](#설치-및-구성)
|
|
5. [클라이언트 연결 워크플로우](#클라이언트-연결-워크플로우)
|
|
6. [실제 사용 시나리오](#실제-사용-시나리오)
|
|
7. [문제 해결](#문제-해결)
|
|
|
|
---
|
|
|
|
## 🧠 개념 정리
|
|
|
|
### Tailscale vs Headscale vs Headplane
|
|
|
|
#### 1. **Tailscale** (원본 서비스)
|
|
- **정의**: 상용 VPN 서비스 (SaaS)
|
|
- **특징**:
|
|
- 클라우드 기반 coordination server 사용
|
|
- 구독 기반 유료 서비스
|
|
- 자동화된 관리
|
|
- **단점**:
|
|
- 데이터가 외부 서버를 거침
|
|
- 비용 발생
|
|
- 프라이버시 우려
|
|
|
|
#### 2. **Headscale** (오픈소스 서버)
|
|
- **정의**: Tailscale의 coordination server를 대체하는 오픈소스 구현
|
|
- **특징**:
|
|
- 자체 호스팅 가능
|
|
- 완전한 프라이버시 제어
|
|
- 무료 사용
|
|
- REST API 제공
|
|
- **역할**:
|
|
- 클라이언트 인증 및 등록
|
|
- IP 주소 할당
|
|
- 라우팅 테이블 관리
|
|
- 키 교환 coordination
|
|
|
|
#### 3. **Headplane** (웹 UI)
|
|
- **정의**: Headscale을 관리하기 위한 웹 인터페이스
|
|
- **특징**:
|
|
- 브라우저에서 노드 관리
|
|
- 시각적 네트워크 상태 확인
|
|
- 사용자 및 키 관리
|
|
|
|
#### 4. **클라이언트 (Tailscale 클라이언트)**
|
|
- **정의**: 실제 VPN 연결을 담당하는 클라이언트 프로그램
|
|
- **중요**: Tailscale의 **클라이언트 소프트웨어**를 그대로 사용
|
|
- **변경점**: 서버 주소만 Headscale 서버로 지정
|
|
|
|
---
|
|
|
|
## 🏗️ 아키텍처 개요
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ 클라이언트 PC │ │ Headscale │ │ 클라이언트 PC │
|
|
│ │ │ 서버 │ │ │
|
|
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
|
|
│ │ Tailscale │◄────┼─┤ Headscale │─┼────┤ │ Tailscale │ │
|
|
│ │ Client │ │ │ │ Server │ │ │ │ Client │ │
|
|
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
|
|
│ │ │ ┌─────────────┐ │ │ │
|
|
│ │ │ │ Headplane │ │ │ │
|
|
│ │ │ │ Web UI │ │ │ │
|
|
│ │ │ └─────────────┘ │ │ │
|
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
│ │ │
|
|
└────────────────────────┼────────────────────────┘
|
|
│
|
|
┌─────────────────┐
|
|
│ FARMQ Flask │
|
|
│ Admin Panel │
|
|
└─────────────────┘
|
|
```
|
|
|
|
### 데이터 흐름
|
|
1. **등록**: 클라이언트 → Headscale 서버 (인증)
|
|
2. **키 교환**: Headscale 서버 → 클라이언트들 (P2P 키 정보)
|
|
3. **실제 통신**: 클라이언트 ↔ 클라이언트 (직접 P2P)
|
|
4. **관리**: Headplane/Flask UI → Headscale API
|
|
|
|
---
|
|
|
|
## 🔌 포트 구성
|
|
|
|
### 현재 FARMQ 설정
|
|
|
|
| 서비스 | 포트 | 프로토콜 | 용도 | 접근 |
|
|
|--------|------|----------|------|------|
|
|
| **Headscale Server** | `8070` | HTTP | 클라이언트 등록/관리 | 클라이언트 ← → 서버 |
|
|
| **Headplane UI** | `3000` | HTTP | 웹 관리 인터페이스 | 관리자 → 웹브라우저 |
|
|
| **FARMQ Admin** | `5001` | HTTP | 한국어 관리 페이지 | 관리자 → 웹브라우저 |
|
|
|
|
### 중요한 포인트
|
|
- **클라이언트가 사용하는 포트**: `8070` (Headscale 서버)
|
|
- **관리자가 사용하는 포트**: `3000` (Headplane), `5001` (FARMQ Admin)
|
|
- **내부 컨테이너 포트**: `8080` (Docker 내부에서만 사용)
|
|
|
|
---
|
|
|
|
## 🛠️ 설치 및 구성
|
|
|
|
### 1. 서버 구성 (이미 완료)
|
|
|
|
```bash
|
|
# 서버 시작
|
|
cd /srv/headscale-setup
|
|
docker-compose up -d
|
|
|
|
# 서비스 확인
|
|
docker-compose ps
|
|
```
|
|
|
|
### 2. 클라이언트 설치 과정
|
|
|
|
#### Step 1: Tailscale 클라이언트 설치
|
|
|
|
```bash
|
|
# Ubuntu/Debian
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
|
|
# 또는 수동 설치
|
|
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
|
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
|
|
sudo apt update
|
|
sudo apt install tailscale
|
|
```
|
|
|
|
#### Step 2: Headscale 서버에 등록
|
|
|
|
```bash
|
|
# 기본 명령어 형식
|
|
sudo tailscale up --login-server=http://[서버IP]:8070 --authkey=[PreAuth키]
|
|
|
|
# FARMQ 실제 명령어 예시
|
|
sudo tailscale up \
|
|
--login-server=http://192.168.0.151:8070 \
|
|
--authkey=YOUR_PREAUTH_KEY_HERE \
|
|
--hostname=pharmacy-busan-pc1 \
|
|
--accept-dns=false
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 클라이언트 연결 워크플로우
|
|
|
|
### 전체 프로세스
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Admin as 관리자
|
|
participant Server as Headscale 서버
|
|
participant Client as 클라이언트 PC
|
|
participant Network as VPN 네트워크
|
|
|
|
Admin->>Server: 1. 사용자 생성
|
|
Admin->>Server: 2. PreAuth 키 생성
|
|
Admin->>Client: 3. PreAuth 키 전달
|
|
Client->>Client: 4. Tailscale 클라이언트 설치
|
|
Client->>Server: 5. 등록 요청 (PreAuth 키 포함)
|
|
Server->>Client: 6. 인증 완료 및 설정 전달
|
|
Client->>Network: 7. VPN 네트워크 참여
|
|
Network->>Client: 8. 다른 노드들과 P2P 연결
|
|
```
|
|
|
|
### 상세 단계별 설명
|
|
|
|
#### 1. 서버 측 작업 (관리자)
|
|
|
|
```bash
|
|
# 1-1. 사용자 생성 (한 번만)
|
|
docker exec headscale headscale users create pharmacy-busan
|
|
|
|
# 1-2. 사용자 목록 확인
|
|
docker exec headscale headscale users list
|
|
|
|
# 1-3. PreAuth 키 생성
|
|
docker exec headscale headscale preauthkeys create --user 1 --expiration 1h
|
|
|
|
# 출력 예시:
|
|
# f8d9c7e4b2a6c8f4d9e7b3a5c8f4d9e7b3a5c8f4d9e7b3a5c8f4d9e7b3a5c8f4
|
|
```
|
|
|
|
#### 2. 클라이언트 측 작업
|
|
|
|
```bash
|
|
# 2-1. 기존 연결 해제 (있다면)
|
|
sudo tailscale logout
|
|
sudo tailscale down
|
|
|
|
# 2-2. Headscale 서버에 등록
|
|
sudo tailscale up \
|
|
--login-server=http://192.168.0.151:8070 \
|
|
--authkey=f8d9c7e4b2a6c8f4d9e7b3a5c8f4d9e7b3a5c8f4d9e7b3a5c8f4d9e7b3a5c8f4 \
|
|
--hostname=pharmacy-busan-pc1 \
|
|
--accept-dns=false
|
|
|
|
# 2-3. 연결 상태 확인
|
|
tailscale status
|
|
|
|
# 2-4. IP 주소 확인
|
|
tailscale ip -4
|
|
```
|
|
|
|
#### 3. 결과 확인
|
|
|
|
```bash
|
|
# 서버에서 노드 목록 확인
|
|
docker exec headscale headscale nodes list
|
|
|
|
# 웹 UI에서 확인
|
|
# - Headplane: http://192.168.0.151:3000
|
|
# - FARMQ Admin: http://192.168.0.151:5001
|
|
```
|
|
|
|
---
|
|
|
|
## 🏥 실제 사용 시나리오
|
|
|
|
### 시나리오 1: 새 약국 등록
|
|
|
|
```bash
|
|
# 서버 작업 (관리자)
|
|
docker exec headscale headscale users create pharmacy-seoul
|
|
docker exec headscale headscale preauthkeys create --user [USER_ID] --expiration 2h
|
|
|
|
# 클라이언트 작업 (약국 PC)
|
|
curl -O http://192.168.0.151:8000/add-client.sh
|
|
chmod +x add-client.sh
|
|
./add-client.sh pharmacy-seoul pos-terminal-1
|
|
# PreAuth 키 입력 시 위에서 생성한 키 사용
|
|
```
|
|
|
|
### 시나리오 2: 여러 PC가 있는 약국
|
|
|
|
```bash
|
|
# 같은 사용자로 여러 머신 등록 가능
|
|
sudo tailscale up --login-server=http://192.168.0.151:8070 --authkey=[KEY] --hostname=busan-pos1
|
|
sudo tailscale up --login-server=http://192.168.0.151:8070 --authkey=[KEY] --hostname=busan-pos2
|
|
sudo tailscale up --login-server=http://192.168.0.151:8070 --authkey=[KEY] --hostname=busan-office
|
|
```
|
|
|
|
### 시나리오 3: 임시 접속 (노트북)
|
|
|
|
```bash
|
|
# 짧은 만료시간으로 키 생성
|
|
docker exec headscale headscale preauthkeys create --user [USER_ID] --expiration 30m
|
|
|
|
# 노트북에서 임시 연결
|
|
sudo tailscale up --login-server=http://192.168.0.151:8070 --authkey=[TEMP_KEY] --hostname=manager-laptop
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 상태 확인 및 관리
|
|
|
|
### 명령어 모음
|
|
|
|
```bash
|
|
# === 서버 측 (Headscale) ===
|
|
|
|
# 사용자 관리
|
|
docker exec headscale headscale users list
|
|
docker exec headscale headscale users create [username]
|
|
|
|
# 노드 관리
|
|
docker exec headscale headscale nodes list
|
|
docker exec headscale headscale nodes expire [node_id]
|
|
|
|
# PreAuth 키 관리
|
|
docker exec headscale headscale preauthkeys list --user [user_id]
|
|
docker exec headscale headscale preauthkeys create --user [user_id] --expiration [time]
|
|
|
|
# === 클라이언트 측 (Tailscale) ===
|
|
|
|
# 상태 확인
|
|
tailscale status # 네트워크 상태 및 연결된 노드들
|
|
tailscale ip # 내 IP 주소들
|
|
tailscale netcheck # 네트워크 연결성 테스트
|
|
tailscale ping [node] # 특정 노드 ping
|
|
|
|
# 연결 관리
|
|
tailscale up # 연결 시작
|
|
tailscale down # 연결 중단
|
|
tailscale logout # 로그아웃
|
|
|
|
# 로그 확인
|
|
sudo journalctl -u tailscaled -f
|
|
```
|
|
|
|
### 웹 UI 접근
|
|
|
|
```bash
|
|
# Headplane (기본 관리 UI)
|
|
http://192.168.0.151:3000
|
|
# API 키: 8qRr1IB.tV95CmA0fLaCiGGIgBfeoN9daHceFkzI
|
|
|
|
# FARMQ 관리자 페이지 (한국어)
|
|
http://192.168.0.151:5001
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ 중요한 주의사항
|
|
|
|
### 1. 포트 혼동 방지
|
|
- **클라이언트 등록**: `8070` 포트 사용
|
|
- **웹 관리**: `3000`, `5001` 포트 사용
|
|
- **Docker 내부**: `8080` 포트 (외부에서 직접 접근 불가)
|
|
|
|
### 2. PreAuth 키 보안
|
|
- 키는 일회용 또는 제한된 횟수만 사용 가능
|
|
- 짧은 만료시간 설정 권장 (1h ~ 24h)
|
|
- 키 노출 시 즉시 새 키 생성
|
|
|
|
### 3. 네트워크 구성
|
|
- 모든 클라이언트는 `100.64.0.0/10` 대역 IP 할당
|
|
- 첫 번째 클라이언트: `100.64.0.1` (서버 역할도 함)
|
|
- 이후 클라이언트들: `100.64.0.2`, `100.64.0.3`, ...
|
|
|
|
### 4. 방화벽 설정
|
|
```bash
|
|
# 서버 측 방화벽 (필요시)
|
|
sudo ufw allow 8070/tcp # Headscale
|
|
sudo ufw allow 3000/tcp # Headplane
|
|
sudo ufw allow 5001/tcp # FARMQ Admin
|
|
|
|
# 클라이언트 측 (Tailscale이 자동 처리)
|
|
sudo ufw allow in on tailscale0
|
|
```
|
|
|
|
---
|
|
|
|
## 🚨 문제 해결
|
|
|
|
### 일반적인 문제들
|
|
|
|
#### 1. "connection refused" 오류
|
|
```bash
|
|
# 원인: 서버 포트 접근 불가
|
|
# 해결:
|
|
docker-compose ps # 서버 실행 확인
|
|
sudo ufw status # 방화벽 확인
|
|
ping 192.168.0.151 # 서버 연결 확인
|
|
```
|
|
|
|
#### 2. "invalid auth key" 오류
|
|
```bash
|
|
# 원인: PreAuth 키 만료 또는 잘못된 키
|
|
# 해결:
|
|
docker exec headscale headscale preauthkeys create --user [user_id] --expiration 1h
|
|
```
|
|
|
|
#### 3. "user not found" 오류
|
|
```bash
|
|
# 원인: 존재하지 않는 사용자
|
|
# 해결:
|
|
docker exec headscale headscale users list # 사용자 확인
|
|
docker exec headscale headscale users create [username] # 사용자 생성
|
|
```
|
|
|
|
#### 4. IP 할당되지 않음
|
|
```bash
|
|
# 진단:
|
|
tailscale status # 연결 상태 확인
|
|
tailscale netcheck # 네트워크 테스트
|
|
sudo journalctl -u tailscaled -f # 로그 확인
|
|
|
|
# 해결:
|
|
sudo systemctl restart tailscaled # 서비스 재시작
|
|
```
|
|
|
|
### 로그 위치
|
|
```bash
|
|
# Headscale 서버 로그
|
|
docker logs headscale
|
|
|
|
# Headplane 로그
|
|
docker logs headplane
|
|
|
|
# Tailscale 클라이언트 로그
|
|
sudo journalctl -u tailscaled -f
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 체크리스트
|
|
|
|
### 서버 설치 완료 확인
|
|
- [ ] Docker 및 Docker Compose 설치됨
|
|
- [ ] Headscale 컨테이너 실행 중 (포트 8070)
|
|
- [ ] Headplane 컨테이너 실행 중 (포트 3000)
|
|
- [ ] FARMQ Admin 실행 중 (포트 5001)
|
|
- [ ] 방화벽에서 필요 포트 열림
|
|
|
|
### 클라이언트 연결 확인
|
|
- [ ] Tailscale 클라이언트 설치됨
|
|
- [ ] 서버에 사용자 생성됨
|
|
- [ ] PreAuth 키 생성됨 (유효한 만료시간)
|
|
- [ ] `tailscale up` 명령어 성공
|
|
- [ ] `tailscale status`에서 다른 노드들 보임
|
|
- [ ] VPN IP 주소 할당됨 (`100.64.0.x`)
|
|
|
|
### 네트워크 연결 확인
|
|
- [ ] 서버 ping 성공 (`ping 100.64.0.1`)
|
|
- [ ] 다른 클라이언트와 ping 성공
|
|
- [ ] 웹 UI 접근 가능
|
|
|
|
---
|
|
|
|
## 🎯 다음 단계
|
|
|
|
1. **자동화 스크립트 활용**: `add-client.sh`, `create-preauth-key.sh` 사용
|
|
2. **모니터링 설정**: FARMQ Admin에서 실시간 상태 확인
|
|
3. **백업 전략**: Headscale 설정 및 데이터베이스 백업
|
|
4. **확장**: 새로운 약국 및 지점 추가
|
|
|
|
---
|
|
|
|
**🎊 이제 완전한 프라이빗 VPN 네트워크를 운영할 수 있습니다!** |