diff --git a/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md b/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md
new file mode 100644
index 0000000..b2392af
--- /dev/null
+++ b/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md
@@ -0,0 +1,289 @@
+# FarmQ Admin 머신 이름 표시 문제 해결 계획
+
+## 📋 문제 상황
+
+현재 FarmQ Admin의 머신 관리 페이지에서 **머신 이름이 hostname으로만 표시**되고 있어, Magic DNS에서 사용되는 실제 노드 이름(`given_name`)과 일치하지 않는 문제가 발생하고 있습니다.
+
+## 🔍 문제 분석
+
+### 1. 현재 상황
+
+**Headscale CLI API 실제 데이터:**
+```json
+{
+ "id": 1,
+ "name": "0bin-Ubuntu-VM", // ❌ 실제 Magic DNS에서 사용되는 이름
+ "given_name": "0bin-ubuntu-vm", // ✅ Magic DNS 접두어 (pev.headscale.local)
+ "ip_addresses": ["100.64.0.1"],
+ "user": {"name": "myuser"},
+ "online": true
+}
+```
+
+**FarmQ Admin 현재 표시:**
+```html
+{{ machine_data.machine_name or machine_data.hostname }}
+
{{ machine_data.hostname }}
+```
+
+### 2. 문제의 근본 원인
+
+#### A. 데이터베이스 스키마 불일치
+
+**Headscale 모델:**
+```python
+# models/headscale_models.py
+class Node:
+ hostname = Column(String) # 시스템 호스트명 (0bin-Ubuntu-VM)
+ given_name = Column(String) # 사용자 지정 이름 (0bin-ubuntu-vm) - Magic DNS용
+```
+
+**FarmQ 모델:**
+```python
+# models/farmq_models.py
+class MachineProfile:
+ hostname = Column(String) # hostname으로 복사됨
+ machine_name = Column(String) # hostname으로 중복 저장됨 ❌
+```
+
+#### B. 동기화 로직 문제
+
+```python
+# utils/database_new.py (line 343)
+machine_data = {
+ 'hostname': node.hostname, # "0bin-Ubuntu-VM"
+ 'machine_name': node.hostname, # ❌ hostname 중복! given_name이어야 함
+ 'tailscale_ip': node.ipv4,
+}
+```
+
+#### C. 템플릿 표시 문제
+
+```html
+
+{{ machine_data.machine_name or machine_data.hostname }}
+
+
+```
+
+## ✅ 해결 방안
+
+### 1. 즉시 수정 (Quick Fix)
+
+#### A. 데이터베이스 동기화 로직 수정
+```python
+# farmq-admin/utils/database_new.py
+def get_all_machines_with_details():
+ machine_data = {
+ 'hostname': node.hostname, # 시스템 호스트명
+ 'machine_name': node.given_name, # ✅ Magic DNS 이름으로 변경
+ 'display_name': node.given_name or node.hostname, # 표시용 이름
+ 'tailscale_ip': node.ipv4,
+ }
+```
+
+#### B. FarmQ 모델 동기화 수정
+```python
+# models/farmq_models.py - sync_machine_from_headscale
+machine = MachineProfile(
+ hostname=headscale_node_data.get('hostname'),
+ machine_name=headscale_node_data.get('given_name'), # ✅ given_name 사용
+ tailscale_ip=headscale_node_data.get('ipv4'),
+)
+```
+
+#### C. 템플릿 표시 개선
+```html
+
+{{ machine_data.machine_name or machine_data.hostname }}
+
+```
+
+### 2. 근본적 개선 (Long-term)
+
+#### A. 필드 명칭 명확화
+```python
+class MachineProfile:
+ system_hostname = Column(String) # 시스템 호스트명 (0bin-Ubuntu-VM)
+ headscale_name = Column(String) # Headscale given_name (0bin-ubuntu-vm)
+ magic_dns_name = Column(String) # Magic DNS 전체 이름 (0bin-ubuntu-vm.headscale.local)
+ display_name = Column(String) # 사용자 표시용 이름
+```
+
+#### B. Magic DNS 정보 표시 강화
+```html
+
+
{{ machine.display_name }}
+
+ {{ machine.magic_dns_name }}
+
+
+
+ 시스템: {{ machine.system_hostname }}
+
+
+```
+
+## 🚀 구현 단계
+
+### Phase 1: 긴급 수정 (1-2시간)
+
+1. **데이터 동기화 로직 수정**
+ ```bash
+ # 파일: farmq-admin/utils/database_new.py
+ # 라인: 343
+ 'machine_name': node.given_name, # hostname → given_name
+ ```
+
+2. **템플릿 표시 개선**
+ ```bash
+ # 파일: farmq-admin/templates/machines/list.html
+ # Magic DNS 정보 추가 표시
+ ```
+
+3. **동기화 함수 수정**
+ ```bash
+ # 파일: farmq-admin/models/farmq_models.py
+ # sync_machine_from_headscale 함수 수정
+ ```
+
+### Phase 2: 표시 개선 (2-3시간)
+
+1. **Magic DNS 정보 강화 표시**
+ - `.headscale.local` 접미사 자동 표시
+ - 클립보드 복사 기능
+ - 연결 테스트 기능
+
+2. **필터링 기능 추가**
+ - Magic DNS 이름으로 검색
+ - 온라인/오프라인 필터
+ - 사용자별 필터
+
+### Phase 3: 구조적 개선 (4-6시간)
+
+1. **데이터베이스 스키마 개선**
+ - 필드명 명확화
+ - Magic DNS 전용 필드 추가
+ - 인덱스 최적화
+
+2. **API 통합 개선**
+ - Headscale CLI 응답 캐싱
+ - 실시간 상태 업데이트
+ - WebSocket을 통한 실시간 알림
+
+## 📊 예상 결과
+
+### Before (현재)
+```
+머신 이름: 0bin-Ubuntu-VM # hostname (시스템명)
+호스트명: 0bin-Ubuntu-VM # 중복 정보
+Magic DNS: 사용불가 ❌ # given_name 정보 부족
+```
+
+### After (수정 후)
+```
+머신 이름: 0bin-ubuntu-vm # given_name (Magic DNS용)
+Magic DNS: 0bin-ubuntu-vm.headscale.local ✅
+시스템명: 0bin-Ubuntu-VM # hostname (참고 정보)
+IP 주소: 100.64.0.1 # 현재와 동일
+```
+
+## 🧪 테스트 계획
+
+### 1. 데이터 검증
+```python
+# 테스트 스크립트
+def test_machine_name_mapping():
+ nodes = headscale_session.query(Node).all()
+ for node in nodes:
+ print(f"ID: {node.id}")
+ print(f"Hostname: {node.hostname}") # 0bin-Ubuntu-VM
+ print(f"Given Name: {node.given_name}") # 0bin-ubuntu-vm
+ print(f"Magic DNS: {node.given_name}.headscale.local")
+ print("---")
+```
+
+### 2. Magic DNS 연결 테스트
+```bash
+# 각 노드별 Magic DNS 테스트
+ping 0bin-ubuntu-vm.headscale.local
+ping pev.headscale.local
+ping pqserver.headscale.local
+```
+
+### 3. UI 표시 확인
+- 머신 목록에서 올바른 이름 표시
+- Magic DNS 주소 복사 기능
+- 연결 상태와 일치성 확인
+
+## 📝 체크리스트
+
+### 코드 수정
+- [ ] `farmq-admin/utils/database_new.py` - 동기화 로직 수정
+- [ ] `farmq-admin/models/farmq_models.py` - 모델 동기화 수정
+- [ ] `farmq-admin/templates/machines/list.html` - 표시 개선
+- [ ] `farmq-admin/templates/machines/detail.html` - 상세 페이지 수정
+
+### 테스트
+- [ ] 데이터베이스 동기화 테스트
+- [ ] Magic DNS 이름 표시 확인
+- [ ] UI 표시 정상성 확인
+- [ ] 기존 기능 호환성 테스트
+
+### 문서화
+- [ ] 변경사항 README 업데이트
+- [ ] API 문서 갱신
+- [ ] 사용자 가이드 수정
+
+## 🔧 구현 파일 목록
+
+### 수정할 파일들
+1. **`farmq-admin/utils/database_new.py`** (라인 343)
+ - `machine_name` 필드를 `given_name`으로 변경
+
+2. **`farmq-admin/models/farmq_models.py`** (라인 445)
+ - 동기화 시 `given_name` 사용
+
+3. **`farmq-admin/templates/machines/list.html`** (라인 115-119)
+ - Magic DNS 정보 추가 표시
+
+4. **`farmq-admin/templates/machines/detail.html`**
+ - 상세 페이지 Magic DNS 정보 개선
+
+### 새로 추가할 기능
+- Magic DNS 주소 클립보드 복사
+- 연결 테스트 버튼
+- 실시간 온라인 상태 표시
+
+## 💡 장기적 개선사항
+
+### 1. Headscale API 직접 통합
+현재 CLI 기반 → REST API 직접 호출로 전환하여 성능 개선
+
+### 2. 실시간 모니터링
+WebSocket을 통한 실시간 노드 상태 업데이트
+
+### 3. Magic DNS 관리 기능
+- 노드 이름 변경
+- Magic DNS 도메인 설정
+- DNS 해석 테스트 도구
+
+## 📅 구현 일정
+
+| 단계 | 작업 | 소요시간 | 완료일 |
+|------|------|---------|---------|
+| Phase 1 | 긴급 수정 | 2시간 | 당일 |
+| Phase 2 | 표시 개선 | 3시간 | 1일 |
+| Phase 3 | 구조 개선 | 6시간 | 2-3일 |
+
+---
+
+**작성일:** 2025년 9월 13일
+**업데이트:** FarmQ Admin 머신 이름 표시 문제 분석 및 해결 계획 수립 완료
\ No newline at end of file
diff --git a/farmq-admin/models/farmq_models.py b/farmq-admin/models/farmq_models.py
index ccdcbfc..54b2c99 100644
--- a/farmq-admin/models/farmq_models.py
+++ b/farmq-admin/models/farmq_models.py
@@ -432,6 +432,7 @@ class FarmqDatabaseManager:
if machine:
# 기존 머신 업데이트
machine.hostname = headscale_node_data.get('hostname')
+ machine.machine_name = headscale_node_data.get('given_name') or headscale_node_data.get('hostname')
machine.tailscale_ip = headscale_node_data.get('ipv4')
machine.tailscale_status = 'online' if headscale_node_data.get('is_online') else 'offline'
machine.last_seen = datetime.now()
@@ -442,7 +443,7 @@ class FarmqDatabaseManager:
headscale_node_id=headscale_node_data.get('id'),
headscale_machine_key=headscale_node_data.get('machine_key'),
hostname=headscale_node_data.get('hostname'),
- machine_name=headscale_node_data.get('hostname'),
+ machine_name=headscale_node_data.get('given_name') or headscale_node_data.get('hostname'),
tailscale_ip=headscale_node_data.get('ipv4'),
tailscale_status='online' if headscale_node_data.get('is_online') else 'offline',
last_seen=datetime.now()
diff --git a/farmq-admin/templates/machines/list.html b/farmq-admin/templates/machines/list.html
index e64c4aa..41f5d7a 100644
--- a/farmq-admin/templates/machines/list.html
+++ b/farmq-admin/templates/machines/list.html
@@ -113,7 +113,17 @@
{{ machine_data.machine_name or machine_data.hostname }}
-
{{ machine_data.hostname }}
+
+ {{ machine_data.machine_name or machine_data.hostname }}.headscale.local
+
+
+ {% if machine_data.hostname != (machine_data.machine_name or machine_data.hostname) %}
+
+ OS: {{ machine_data.hostname }}
+
+ {% endif %}
{{ machine_data.headscale_user_name or '미지정' }}
@@ -440,6 +450,16 @@ function deleteNode(nodeId, nodeName) {
});
}
+// Magic DNS 주소 클립보드 복사 기능
+function copyToClipboard(text) {
+ navigator.clipboard.writeText(text).then(() => {
+ showToast(`Magic DNS 주소가 복사되었습니다: ${text}`, 'success');
+ }).catch(err => {
+ console.error('복사 실패:', err);
+ showToast('복사에 실패했습니다.', 'danger');
+ });
+}
+
// 초기 카운터 설정
document.addEventListener('DOMContentLoaded', function() {
filterMachines();
diff --git a/farmq-admin/utils/database_new.py b/farmq-admin/utils/database_new.py
index 0d72ad6..e9c8e4e 100644
--- a/farmq-admin/utils/database_new.py
+++ b/farmq-admin/utils/database_new.py
@@ -340,7 +340,7 @@ def get_all_machines_with_details() -> List[Dict[str, Any]]:
machine_data = {
'id': node.id,
'hostname': node.hostname,
- 'machine_name': node.hostname, # 표시용 이름
+ 'machine_name': node.given_name or node.hostname, # Magic DNS용 이름 (given_name 우선)
'tailscale_ip': node.ipv4,
'ipv6': node.ipv6,
'headscale_user_name': node.user.name if node.user else '미지정',