추가된 문서:
- SCRIPT_IMPROVEMENT_PLAN.md: 스크립트 개선 계획
- FARMQ_ADMIN_INTEGRATION_ANALYSIS.md: farmq-admin API 분석
- HEADSCALE_AUTO_REGISTER_PLAN.md: 초기 계획
주요 내용:
- Headscale VPN 등록 시 자동 DB 생성
- API 엔드포인트: demo.pharmq.kr, gateway.pharmq.kr
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
8.0 KiB
8.0 KiB
headscale-quick-install.sh 개선 계획
목표
Headscale VPN 등록 시 farmq.db와 gateway.db에 자동으로 약국 및 관리자 계정 생성하여 스크립트 실행만으로 즉시 프론트엔드 로그인 가능하게 만들기
자동 생성 플로우
1. Headscale VPN 등록 → VPN IP 부여 (예: 100.64.0.25)
2. farmq-admin API 호출 → farmq.db에 약국 생성
- pharmacy_code: P0005 (자동 증가)
- pharmacy_name: 사용자 입력
- tailscale_ip: 100.64.0.25 (VPN IP)
- hira_code: 사용자 입력 (선택)
- api_port: 8082 (기본값)
3. gateway API 호출 → gateway.db에 admin 계정 생성
- username: p0005 (pharmacy_code 소문자)
- password: 1234 (기본 비밀번호)
- email: p0005@pharmq.internal
- name: {pharmacy_name} 관리자
- role: admin
- primary_pharmacy_code: P0005
- pharmacy_members에도 자동 매핑됨
4. 로그인 정보 출력
추가할 함수들
1. collect_pharmacy_info()
약국 기본 정보를 사용자로부터 입력받음
collect_pharmacy_info() {
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${WHITE}약국 정보 입력${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
# 약국명 입력 (필수)
while [ -z "$PHARMACY_NAME" ]; do
read -p "약국명을 입력하세요: " PHARMACY_NAME
done
# 요양기관부호 입력 (선택)
read -p "요양기관부호 (선택, Enter로 건너뛰기): " HIRA_CODE
# 약국 주소 입력 (선택)
read -p "약국 주소 (선택): " PHARMACY_ADDRESS
# 약국장 이름 입력 (선택)
read -p "약국장 이름 (선택): " OWNER_NAME
# 연락처 입력 (선택)
read -p "약국 연락처 (선택): " PHARMACY_PHONE
echo -e "${GREEN}✓ 약국 정보 입력 완료${NC}"
}
2. get_assigned_vpn_ip()
Headscale에서 부여받은 VPN IP 가져오기
get_assigned_vpn_ip() {
echo -e "${BLUE}VPN IP 확인 중...${NC}"
# tailscale status로 IP 추출
VPN_IP=$(tailscale status --json 2>/dev/null | grep -oP '"TailscaleIPs":\["(\d+\.\d+\.\d+\.\d+)"' | grep -oP '\d+\.\d+\.\d+\.\d+' | head -1)
if [ -z "$VPN_IP" ]; then
echo -e "${RED}✗ VPN IP를 가져올 수 없습니다${NC}"
return 1
fi
echo -e "${GREEN}✓ VPN IP: $VPN_IP${NC}"
return 0
}
3. create_pharmacy_via_api()
farmq-admin API를 호출하여 약국 생성
create_pharmacy_via_api() {
echo -e "${BLUE}약국 등록 중 (farmq.db)...${NC}"
# JSON 데이터 구성
JSON_DATA=$(cat <<EOF
{
"pharmacy_name": "$PHARMACY_NAME",
"vpn_ip": "$VPN_IP",
"hira_code": "$HIRA_CODE",
"address": "$PHARMACY_ADDRESS",
"owner_name": "$OWNER_NAME",
"phone": "$PHARMACY_PHONE",
"api_port": 8082
}
EOF
)
# API 호출 (외부 도메인)
RESPONSE=$(curl -s -X POST https://demo.pharmq.kr/api/pharmacy \
-H "Content-Type: application/json" \
-d "$JSON_DATA")
# pharmacy_code 추출
PHARMACY_CODE=$(echo "$RESPONSE" | grep -oP '"pharmacy_code":"[^"]*"' | cut -d'"' -f4)
if [ -z "$PHARMACY_CODE" ]; then
echo -e "${RED}✗ 약국 생성 실패${NC}"
echo "$RESPONSE"
return 1
fi
echo -e "${GREEN}✓ 약국 생성 완료: $PHARMACY_CODE${NC}"
return 0
}
4. create_gateway_user_via_api()
gateway API를 호출하여 관리자 계정 생성
create_gateway_user_via_api() {
echo -e "${BLUE}관리자 계정 생성 중 (gateway.db)...${NC}"
# username: pharmacy_code 소문자 (P0005 → p0005)
USERNAME=$(echo "$PHARMACY_CODE" | tr '[:upper:]' '[:lower:]')
PASSWORD="1234" # 기본 비밀번호
EMAIL="${USERNAME}@pharmq.internal"
# JSON 데이터 구성
JSON_DATA=$(cat <<EOF
{
"username": "$USERNAME",
"email": "$EMAIL",
"password": "$PASSWORD",
"name": "${PHARMACY_NAME} 관리자",
"phone": "$PHARMACY_PHONE",
"primary_pharmacy_code": "$PHARMACY_CODE",
"role": "admin"
}
EOF
)
# API 호출 (외부 도메인)
RESPONSE=$(curl -s -X POST https://gateway.pharmq.kr/api/auth/register \
-H "Content-Type: application/json" \
-d "$JSON_DATA")
# 성공 여부 확인
if echo "$RESPONSE" | grep -q '"success":true'; then
echo -e "${GREEN}✓ 관리자 계정 생성 완료${NC}"
return 0
else
echo -e "${RED}✗ 관리자 계정 생성 실패${NC}"
echo "$RESPONSE"
return 1
fi
}
5. display_login_credentials()
생성된 로그인 정보 출력
display_login_credentials() {
echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${WHITE}🎉 설치 및 등록 완료!${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "\n${GREEN}약국 정보:${NC}"
echo -e " 약국 코드: ${WHITE}$PHARMACY_CODE${NC}"
echo -e " 약국명: ${WHITE}$PHARMACY_NAME${NC}"
echo -e " VPN IP: ${WHITE}$VPN_IP${NC}"
echo -e "\n${GREEN}프론트엔드 로그인 정보:${NC}"
echo -e " URL: ${WHITE}https://pharmq.kr${NC}"
echo -e " 아이디: ${WHITE}$(echo "$PHARMACY_CODE" | tr '[:upper:]' '[:lower:]')${NC}"
echo -e " 비밀번호: ${WHITE}1234${NC}"
echo -e " ${YELLOW}⚠ 최초 로그인 후 비밀번호를 변경하세요!${NC}"
echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
main() 함수 수정
main() {
print_header "팜큐(FARMQ) Headscale 원클릭 설치"
# 사전 체크
detect_os
check_requirements
# 설치 과정
install_tailscale
start_tailscale
register_headscale
# VPN IP 확인
sleep 3 # Headscale에서 IP 할당 대기
get_assigned_vpn_ip || exit 1
# 약국 정보 수집
collect_pharmacy_info
# 약국 및 계정 생성
create_pharmacy_via_api || exit 1
create_gateway_user_via_api || exit 1
# 사후 설정
configure_firewall
verify_connection
# 정리 및 완료
cleanup
display_login_credentials
}
API 엔드포인트
| API | URL | 용도 | 접근 방식 |
|---|---|---|---|
| farmq-admin | https://demo.pharmq.kr/api/pharmacy | 약국 생성 | 외부 도메인 (HTTPS) |
| gateway | https://gateway.pharmq.kr/api/auth/register | 사용자 생성 | 외부 도메인 (HTTPS) |
장점:
- ✅ 모든 API가 외부 도메인으로 통일되어 있음
- ✅ HTTPS로 보안 통신
- ✅ 내부 네트워크 접근 불필요
- ✅ VPN 망 내부/외부 어디서든 실행 가능
보안 고려사항
- 기본 비밀번호 1234: 간단하지만 프론트엔드에서 강제 변경 유도 필요
- API 키 인증: 현재는 public API지만 나중에 인증 토큰 추가 고려
- HTTPS: 현재 HTTP이지만 production에서는 HTTPS 사용 권장
에러 처리
- VPN IP 할당 실패 시 스크립트 중단
- 약국 생성 실패 시 스크립트 중단
- 사용자 생성 실패 시 경고만 출력 (약국은 이미 생성됨)
테스트 시나리오
- ✅ 정상 플로우: 모든 정보 입력 → 약국 및 계정 생성 → 로그인 성공
- ✅ 선택 정보 생략: 약국명만 입력 → 약국 및 계정 생성 → 로그인 성공
- ✅ VPN IP 할당 실패: 에러 메시지 출력 후 종료
- ✅ 약국 생성 실패: 에러 메시지 출력 후 종료
- ✅ 사용자 생성 실패: 경고 출력, 수동 생성 안내
다음 단계
- ✅ farmq-admin API 개선 (VPN IP, hira_code 지원) - 완료
- ✅ gateway API 개선 (pharmacy 검증, pharmacy_members 자동 추가) - 완료
- ⏳ headscale-quick-install.sh 수정 - 진행 중
- ⏳ 통합 테스트