Add Windows PowerShell one-click installation script
- Complete PowerShell script with colorful output and error handling
- Auto-detect existing Tailscale installations
- Smart handling of existing connections (like Linux version)
- Administrator privilege checking with clear instructions
- Automatic Tailscale download and silent installation
- Windows Defender firewall configuration
- Network connectivity testing and verification
- Comprehensive final status report
Features:
- One-line web execution support
- Force reinstall option (-Force parameter)
- Detailed system information display
- Graceful error handling and cleanup
- Windows-native user experience
🚀 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f69ee95443
commit
ea11f92070
455
WINDOWS_ONE_CLICK_INSTALLATION_PLAN.md
Normal file
455
WINDOWS_ONE_CLICK_INSTALLATION_PLAN.md
Normal file
@ -0,0 +1,455 @@
|
||||
# 🪟 Windows용 팜큐 Headscale 원클릭 설치 패키지 기획서
|
||||
|
||||
## 🎯 목표
|
||||
|
||||
Windows 클라이언트에서 **단 한 번의 실행**으로 Tailscale 설치부터 팜큐 Headscale 네트워크 연결까지 완전 자동화
|
||||
|
||||
## 🔍 현재 Windows 상황 분석
|
||||
|
||||
### 기존 연결된 Windows 클라이언트들
|
||||
```
|
||||
100.79.125.82 upharm-1 thug0bin@ windows offline
|
||||
100.76.226.63 upharm thug0bin@ windows offline
|
||||
100.93.4.146 prox-win10-kiosk thug0bin@ windows offline
|
||||
100.109.121.8 desktop-06t3j0m thug0bin@ windows offline
|
||||
100.70.5.37 desktop-9a1aurp thug0bin@ windows offline
|
||||
100.126.213.6 desktop-m445evd thug0bin@ windows offline
|
||||
```
|
||||
|
||||
### Windows 특성
|
||||
- **관리자 권한** 필요 (UAC)
|
||||
- **PowerShell** 스크립트 실행 정책
|
||||
- **GUI 설치 마법사** 선호
|
||||
- **레지스트리** 설정 관리
|
||||
- **서비스** 자동 시작 설정
|
||||
|
||||
## 💡 Windows 설치 패키지 방안 (5가지)
|
||||
|
||||
## 방안 1: PowerShell 원클릭 스크립트 (권장)
|
||||
|
||||
### 개념도
|
||||
```
|
||||
[사용자] → [PowerShell 스크립트] → [Tailscale MSI 설치] → [Headscale 등록] → [완료]
|
||||
우클릭 "관리자로 실행" 자동 다운로드/설치 자동 서버 설정
|
||||
```
|
||||
|
||||
### 구현 방법
|
||||
|
||||
#### 1.1 PowerShell 스크립트 생성
|
||||
```powershell
|
||||
# farmq-headscale-installer.ps1
|
||||
param(
|
||||
[switch]$Force,
|
||||
[string]$HeadscaleServer = "https://head.0bin.in",
|
||||
[string]$PreAuthKey = "8b3df41d37cb158ea39f41fc32c9af46e761de817ad06038"
|
||||
)
|
||||
|
||||
# 관리자 권한 확인
|
||||
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
Write-Host "❌ 관리자 권한이 필요합니다." -ForegroundColor Red
|
||||
Write-Host "우클릭 → '관리자로 실행'을 사용해주세요." -ForegroundColor Yellow
|
||||
pause
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "🚀 팜큐 Headscale Windows 설치 시작..." -ForegroundColor Green
|
||||
```
|
||||
|
||||
#### 1.2 웹 실행 방법
|
||||
```powershell
|
||||
# 관리자 PowerShell에서
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1'))
|
||||
|
||||
# 또는 강제 재등록
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1?force=1'))
|
||||
```
|
||||
|
||||
### 장점
|
||||
- ✅ 단일 명령어로 실행 가능
|
||||
- ✅ 기존 Linux 스크립트와 유사한 UX
|
||||
- ✅ 웹에서 바로 실행 가능
|
||||
- ✅ 버전 관리 용이
|
||||
|
||||
### 단점
|
||||
- ❌ PowerShell 실행 정책 문제
|
||||
- ❌ 일반 사용자에게 복잡함
|
||||
- ❌ UAC 프롬프트 필요
|
||||
|
||||
---
|
||||
|
||||
## 방안 2: MSI 설치 패키지 (GUI 방식)
|
||||
|
||||
### 개념도
|
||||
```
|
||||
[사용자] → [farmq-headscale-installer.msi 실행] → [설치 마법사] → [완료]
|
||||
더블클릭 GUI 단계별 진행
|
||||
```
|
||||
|
||||
### 구현 방법
|
||||
|
||||
#### 2.1 WiX Toolset으로 MSI 제작
|
||||
```xml
|
||||
<!-- farmq-installer.wxs -->
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Name="팜큐 Headscale 클라이언트" Language="1042"
|
||||
Version="1.0.0" Manufacturer="팜큐" UpgradeCode="...">
|
||||
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>
|
||||
|
||||
<!-- Tailscale MSI 번들링 -->
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFilesFolder">
|
||||
<Directory Id="INSTALLFOLDER" Name="FarmQ Headscale"/>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<!-- 사용자 정의 액션 -->
|
||||
<CustomAction Id="InstallTailscale"
|
||||
FileKey="TailscaleMSI"
|
||||
ExeCommand="msiexec /i tailscale-windows.msi /quiet"/>
|
||||
|
||||
<CustomAction Id="RegisterHeadscale"
|
||||
FileKey="RegisterScript"
|
||||
ExeCommand="powershell.exe -ExecutionPolicy Bypass -File register-headscale.ps1"/>
|
||||
</Product>
|
||||
</Wix>
|
||||
```
|
||||
|
||||
#### 2.2 설치 마법사 UI
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ 팜큐 Headscale 클라이언트 설치 │
|
||||
├─────────────────────────────────┤
|
||||
│ [ ] 기본 설치 (권장) │
|
||||
│ [ ] 기존 연결 해제 후 재설치 │
|
||||
│ │
|
||||
│ 서버: https://head.0bin.in │
|
||||
│ 네트워크: 100.64.0.0/10 │
|
||||
│ │
|
||||
│ [< 이전] [다음 >] [취소] │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 장점
|
||||
- ✅ Windows 사용자에게 친숙한 GUI
|
||||
- ✅ 제어판에서 제거 가능
|
||||
- ✅ 디지털 서명 가능
|
||||
- ✅ 그룹 정책 배포 가능
|
||||
|
||||
### 단점
|
||||
- ❌ 개발 복잡도 높음
|
||||
- ❌ 코드 서명 인증서 필요
|
||||
- ❌ 업데이트 배포 복잡
|
||||
|
||||
---
|
||||
|
||||
## 방안 3: 실행 파일 (EXE) + 내장 리소스
|
||||
|
||||
### 개념도
|
||||
```
|
||||
[사용자] → [farmq-installer.exe 실행] → [콘솔/GUI 선택] → [완료]
|
||||
단일 실행 파일 모든 리소스 내장
|
||||
```
|
||||
|
||||
### 구현 방법
|
||||
|
||||
#### 3.1 Go/C#으로 네이티브 실행파일
|
||||
```go
|
||||
// farmq-installer.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
//go:embed resources/tailscale-windows.msi
|
||||
//go:embed resources/register-script.ps1
|
||||
var resources embed.FS
|
||||
|
||||
func main() {
|
||||
fmt.Println("🚀 팜큐 Headscale Windows 설치")
|
||||
|
||||
// 관리자 권한 확인
|
||||
if !isAdmin() {
|
||||
fmt.Println("❌ 관리자 권한으로 다시 실행해주세요")
|
||||
return
|
||||
}
|
||||
|
||||
// Tailscale MSI 추출 및 설치
|
||||
installTailscale()
|
||||
|
||||
// Headscale 등록
|
||||
registerHeadscale()
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 배포 형태
|
||||
- **farmq-installer.exe** (단일 파일, ~50MB)
|
||||
- Tailscale MSI 포함
|
||||
- PowerShell 스크립트 포함
|
||||
- 모든 의존성 내장
|
||||
|
||||
### 장점
|
||||
- ✅ 단일 파일로 배포 간편
|
||||
- ✅ 오프라인 설치 가능
|
||||
- ✅ 의존성 문제 없음
|
||||
- ✅ 콘솔/GUI 하이브리드 가능
|
||||
|
||||
### 단점
|
||||
- ❌ 파일 크기 큼 (50MB+)
|
||||
- ❌ 네이티브 개발 필요
|
||||
- ❌ Tailscale 업데이트 시 재빌드
|
||||
|
||||
---
|
||||
|
||||
## 방안 4: 웹 기반 설치 (브라우저)
|
||||
|
||||
### 개념도
|
||||
```
|
||||
[사용자] → [웹페이지 방문] → [원클릭 다운로드] → [자동 실행] → [완료]
|
||||
설치 가이드 페이지 맞춤형 설치파일 브라우저 실행
|
||||
```
|
||||
|
||||
### 구현 방법
|
||||
|
||||
#### 4.1 웹 설치 페이지
|
||||
```html
|
||||
<!-- https://install.farmq.network -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>팜큐 Headscale Windows 설치</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🪟 Windows용 팜큐 네트워크 설치</h1>
|
||||
|
||||
<div class="install-options">
|
||||
<button onclick="downloadInstaller('basic')">
|
||||
🚀 기본 설치
|
||||
</button>
|
||||
<button onclick="downloadInstaller('force')">
|
||||
🔄 강제 재설치
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function downloadInstaller(type) {
|
||||
const url = `https://install.farmq.network/download?type=${type}`;
|
||||
window.location.href = url;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### 4.2 동적 설치파일 생성
|
||||
```python
|
||||
# Flask 서버에서 실시간 생성
|
||||
@app.route('/download')
|
||||
def download_installer():
|
||||
install_type = request.args.get('type', 'basic')
|
||||
|
||||
# 사용자 맞춤형 PowerShell 스크립트 생성
|
||||
script = generate_powershell_script(
|
||||
force=install_type=='force',
|
||||
preauth_key=get_current_preauth_key(),
|
||||
server_url="https://head.0bin.in"
|
||||
)
|
||||
|
||||
response = make_response(script)
|
||||
response.headers['Content-Type'] = 'application/octet-stream'
|
||||
response.headers['Content-Disposition'] = 'attachment; filename=farmq-install.ps1'
|
||||
return response
|
||||
```
|
||||
|
||||
### 장점
|
||||
- ✅ 최신 설정 항상 반영
|
||||
- ✅ 사용자별 맞춤 설치
|
||||
- ✅ 통계 수집 가능
|
||||
- ✅ 웹 기반으로 접근성 좋음
|
||||
|
||||
### 단점
|
||||
- ❌ 인터넷 연결 필수
|
||||
- ❌ 웹 서버 인프라 필요
|
||||
- ❌ 브라우저 보안 정책 제약
|
||||
|
||||
---
|
||||
|
||||
## 방안 5: 배치 파일 (BAT) 스크립트
|
||||
|
||||
### 개념도
|
||||
```
|
||||
[사용자] → [farmq-install.bat 실행] → [Windows CMD 명령] → [완료]
|
||||
우클릭 "관리자로 실행" 전통적인 배치 방식
|
||||
```
|
||||
|
||||
### 구현 방법
|
||||
|
||||
#### 5.1 배치 스크립트
|
||||
```batch
|
||||
@echo off
|
||||
:: farmq-install.bat
|
||||
title 팜큐 Headscale Windows 설치
|
||||
|
||||
:: 관리자 권한 확인
|
||||
net session >nul 2>&1
|
||||
if %errorLevel% neq 0 (
|
||||
echo ❌ 관리자 권한이 필요합니다.
|
||||
echo 우클릭으로 "관리자로 실행"해주세요.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo 🚀 팜큐 Headscale Windows 설치 시작...
|
||||
|
||||
:: Tailscale 다운로드 및 설치
|
||||
echo 📦 Tailscale 다운로드 중...
|
||||
powershell -Command "Invoke-WebRequest -Uri 'https://pkgs.tailscale.com/stable/tailscale-setup.exe' -OutFile 'tailscale-setup.exe'"
|
||||
|
||||
echo 🔧 Tailscale 설치 중...
|
||||
tailscale-setup.exe /S
|
||||
|
||||
:: Headscale 등록
|
||||
echo 🌐 Headscale 서버 등록 중...
|
||||
"C:\Program Files\Tailscale\tailscale.exe" up --login-server=https://head.0bin.in --authkey=8b3df41d37cb158ea39f41fc32c9af46e761de817ad06038
|
||||
|
||||
echo ✅ 설치 완료!
|
||||
pause
|
||||
```
|
||||
|
||||
### 장점
|
||||
- ✅ 개발 간단
|
||||
- ✅ Windows 네이티브 지원
|
||||
- ✅ 의존성 없음
|
||||
- ✅ 디버깅 용이
|
||||
|
||||
### 단점
|
||||
- ❌ 기능 제한적
|
||||
- ❌ 에러 처리 복잡
|
||||
- ❌ 사용자 경험 떨어짐
|
||||
|
||||
---
|
||||
|
||||
## 🎯 권장 구현 우선순위
|
||||
|
||||
### 1단계: PowerShell 스크립트 (즉시 구현 가능)
|
||||
**기간**: 1-2일
|
||||
**난이도**: 하
|
||||
|
||||
```powershell
|
||||
# 사용자 실행 방법
|
||||
# 1. 관리자 PowerShell 열기
|
||||
# 2. 다음 명령 실행
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1'))
|
||||
```
|
||||
|
||||
### 2단계: 실행 파일 (EXE) 방식
|
||||
**기간**: 3-5일
|
||||
**난이도**: 중
|
||||
|
||||
- Go언어로 크로스 컴파일
|
||||
- 단일 실행파일로 배포
|
||||
- GUI 옵션 포함
|
||||
|
||||
### 3단계: MSI 설치 패키지
|
||||
**기간**: 1주일
|
||||
**난이도**: 상
|
||||
|
||||
- 전문적인 설치 경험
|
||||
- 제어판 등록
|
||||
- 그룹 정책 배포 지원
|
||||
|
||||
## 📋 PowerShell 스크립트 구현 명세서
|
||||
|
||||
### 기본 기능
|
||||
```powershell
|
||||
# 1. 시스템 확인
|
||||
- Windows 버전 체크 (Windows 10/11 지원)
|
||||
- 관리자 권한 확인
|
||||
- 인터넷 연결 확인
|
||||
|
||||
# 2. Tailscale 설치
|
||||
- 기존 설치 확인
|
||||
- 최신 버전 다운로드
|
||||
- 자동 설치 (Silent Install)
|
||||
- 서비스 시작
|
||||
|
||||
# 3. Headscale 등록
|
||||
- 기존 연결 확인 및 해제
|
||||
- Pre-auth key로 자동 등록
|
||||
- 연결 상태 확인
|
||||
|
||||
# 4. 방화벽 설정
|
||||
- Windows Defender 예외 추가
|
||||
- 필요한 포트 허용
|
||||
|
||||
# 5. 완료 확인
|
||||
- IP 주소 할당 확인
|
||||
- 네트워크 연결 테스트
|
||||
- 상태 출력
|
||||
```
|
||||
|
||||
### 사용자 시나리오
|
||||
```
|
||||
1. 약국 직원이 새 PC 설정
|
||||
2. 관리자 PowerShell 실행
|
||||
3. 원클릭 명령어 붙여넣기
|
||||
4. 자동 설치 진행 (2-3분)
|
||||
5. 팜큐 네트워크 연결 완료
|
||||
```
|
||||
|
||||
## 🔧 즉시 구현 가능한 MVP
|
||||
|
||||
### 파일 구조
|
||||
```
|
||||
farmq-windows-installer/
|
||||
├── farmq-install.ps1 # 메인 설치 스크립트
|
||||
├── modules/
|
||||
│ ├── system-check.ps1 # 시스템 확인
|
||||
│ ├── tailscale-installer.ps1 # Tailscale 설치
|
||||
│ ├── headscale-register.ps1 # Headscale 등록
|
||||
│ └── network-verify.ps1 # 네트워크 확인
|
||||
├── resources/
|
||||
│ └── farmq-logo.ico # 아이콘
|
||||
└── README-windows.md # Windows 설치 가이드
|
||||
```
|
||||
|
||||
### 웹 실행 명령어
|
||||
```powershell
|
||||
# 기본 설치
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/thug0bin/headscale-tailscale-replacement/raw/branch/main/farmq-install.ps1'))
|
||||
|
||||
# 강제 재설치
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/thug0bin/headscale-tailscale-replacement/raw/branch/main/farmq-install.ps1?force=1'))
|
||||
```
|
||||
|
||||
## 📊 예상 사용 통계
|
||||
|
||||
### 대상 사용자
|
||||
- **팜큐 약국**: ~100개 약국 × 2-3대 PC = 200-300대
|
||||
- **신규 PC**: 월 10-20대 추가
|
||||
- **재설치**: 월 5-10건
|
||||
|
||||
### 성공 지표
|
||||
- ✅ **설치 성공률**: 95% 이상
|
||||
- ✅ **설치 시간**: 3분 이내
|
||||
- ✅ **사용자 만족도**: 5점 만점 4점 이상
|
||||
- ✅ **지원 요청**: 월 5건 이하
|
||||
|
||||
## 🚀 결론 및 추천
|
||||
|
||||
**즉시 구현 권장**: PowerShell 원클릭 스크립트
|
||||
|
||||
1. **개발 용이성** ⭐⭐⭐⭐⭐
|
||||
2. **사용자 편의성** ⭐⭐⭐⭐
|
||||
3. **유지보수성** ⭐⭐⭐⭐⭐
|
||||
4. **배포 편의성** ⭐⭐⭐⭐⭐
|
||||
|
||||
**다음 단계**: PowerShell 스크립트 구현 → EXE 파일 → MSI 패키지 순으로 단계적 발전
|
||||
|
||||
---
|
||||
|
||||
**목표**: "Linux처럼 Windows에서도 한 줄 명령어로 팜큐 네트워크 연결!" 🎯
|
||||
483
farmq-install.ps1
Normal file
483
farmq-install.ps1
Normal file
@ -0,0 +1,483 @@
|
||||
# 팜큐(FARMQ) Headscale Windows 원클릭 설치 스크립트
|
||||
# 사용법: 관리자 PowerShell에서 실행
|
||||
# iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1'))
|
||||
|
||||
param(
|
||||
[switch]$Force,
|
||||
[string]$HeadscaleServer = "https://head.0bin.in",
|
||||
[string]$PreAuthKey = "8b3df41d37cb158ea39f41fc32c9af46e761de817ad06038",
|
||||
[string]$FarmqNetwork = "100.64.0.0/10"
|
||||
)
|
||||
|
||||
# ================================
|
||||
# 색상 출력 함수
|
||||
# ================================
|
||||
function Write-ColorOutput {
|
||||
param(
|
||||
[string]$Message,
|
||||
[string]$ForegroundColor = "White"
|
||||
)
|
||||
Write-Host $Message -ForegroundColor $ForegroundColor
|
||||
}
|
||||
|
||||
function Write-Header {
|
||||
param([string]$Text)
|
||||
Write-Host ""
|
||||
Write-Host "============================================" -ForegroundColor Magenta
|
||||
Write-Host $Text -ForegroundColor White
|
||||
Write-Host "============================================" -ForegroundColor Magenta
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
function Write-Status {
|
||||
param([string]$Message)
|
||||
Write-Host ""
|
||||
Write-ColorOutput "🔧 $Message" "Blue"
|
||||
}
|
||||
|
||||
function Write-Success {
|
||||
param([string]$Message)
|
||||
Write-Host ""
|
||||
Write-ColorOutput "✅ $Message" "Green"
|
||||
}
|
||||
|
||||
function Write-Error {
|
||||
param([string]$Message)
|
||||
Write-Host ""
|
||||
Write-ColorOutput "❌ $Message" "Red"
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
param([string]$Message)
|
||||
Write-Host ""
|
||||
Write-ColorOutput "⚠️ $Message" "Yellow"
|
||||
}
|
||||
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host ""
|
||||
Write-ColorOutput "📋 $Message" "Cyan"
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 시스템 요구사항 확인
|
||||
# ================================
|
||||
function Test-Requirements {
|
||||
Write-Status "시스템 요구사항 확인 중..."
|
||||
|
||||
# 관리자 권한 확인
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||||
|
||||
if (-NOT $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
Write-Error "이 스크립트는 관리자 권한으로 실행해야 합니다."
|
||||
Write-Info "다음 방법으로 다시 실행해주세요:"
|
||||
Write-Info "1. Windows 키 + X → 'Windows PowerShell(관리자)' 클릭"
|
||||
Write-Info "2. 스크립트 명령어 다시 실행"
|
||||
Write-Host ""
|
||||
Read-Host "아무 키나 누르세요..."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Windows 버전 확인
|
||||
$osVersion = [System.Environment]::OSVersion.Version
|
||||
if ($osVersion.Major -lt 10) {
|
||||
Write-Warning "Windows 10 이상을 권장합니다. 현재: Windows $($osVersion.Major).$($osVersion.Minor)"
|
||||
}
|
||||
|
||||
# 인터넷 연결 확인
|
||||
try {
|
||||
Test-Connection "8.8.8.8" -Count 1 -Quiet | Out-Null
|
||||
}
|
||||
catch {
|
||||
Write-Warning "인터넷 연결을 확인해주세요."
|
||||
}
|
||||
|
||||
Write-Success "시스템 요구사항 확인 완료"
|
||||
}
|
||||
|
||||
# ================================
|
||||
# Tailscale 설치
|
||||
# ================================
|
||||
function Install-Tailscale {
|
||||
Write-Status "Tailscale 클라이언트 확인 중..."
|
||||
|
||||
# 기존 설치 확인
|
||||
$tailscalePath = Get-Command "tailscale" -ErrorAction SilentlyContinue
|
||||
if ($tailscalePath) {
|
||||
$version = & tailscale version 2>$null | Select-Object -First 1
|
||||
Write-Info "Tailscale이 이미 설치되어 있습니다."
|
||||
Write-Info "현재 버전: $version"
|
||||
return
|
||||
}
|
||||
|
||||
Write-Info "Windows용 Tailscale 설치 중..."
|
||||
|
||||
# 임시 다운로드 경로
|
||||
$tempPath = "$env:TEMP\tailscale-setup.exe"
|
||||
$downloadUrl = "https://pkgs.tailscale.com/stable/tailscale-setup.exe"
|
||||
|
||||
try {
|
||||
Write-Status "Tailscale 다운로드 중..."
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile $tempPath -UseBasicParsing
|
||||
|
||||
Write-Status "Tailscale 설치 중... (잠시 기다려주세요)"
|
||||
Start-Process -FilePath $tempPath -ArgumentList "/S" -Wait
|
||||
|
||||
# PATH 환경변수 새로고침
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
|
||||
# 설치 확인
|
||||
Start-Sleep -Seconds 3
|
||||
$tailscaleInstalled = Get-Command "tailscale" -ErrorAction SilentlyContinue
|
||||
if (-not $tailscaleInstalled) {
|
||||
# 직접 경로 시도
|
||||
$tailscaleExe = "C:\Program Files\Tailscale\tailscale.exe"
|
||||
if (Test-Path $tailscaleExe) {
|
||||
# PATH에 Tailscale 경로 추가
|
||||
$currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||
if ($currentPath -notlike "*Tailscale*") {
|
||||
[Environment]::SetEnvironmentVariable("Path", "$currentPath;C:\Program Files\Tailscale", "Machine")
|
||||
$env:Path = "$env:Path;C:\Program Files\Tailscale"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
|
||||
Write-Success "Tailscale 설치 완료"
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Error "Tailscale 설치 실패: $($_.Exception.Message)"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# Tailscale 서비스 시작
|
||||
# ================================
|
||||
function Start-TailscaleService {
|
||||
Write-Status "Tailscale 서비스 시작 중..."
|
||||
|
||||
try {
|
||||
# Tailscale 서비스 시작
|
||||
$service = Get-Service -Name "Tailscale" -ErrorAction SilentlyContinue
|
||||
if ($service) {
|
||||
if ($service.Status -ne "Running") {
|
||||
Start-Service -Name "Tailscale"
|
||||
Start-Sleep -Seconds 3
|
||||
}
|
||||
Write-Success "Tailscale 서비스가 실행 중입니다."
|
||||
} else {
|
||||
Write-Warning "Tailscale 서비스를 찾을 수 없습니다. 수동 시작을 시도합니다."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "서비스 시작에 실패했습니다: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# Headscale 등록
|
||||
# ================================
|
||||
function Register-Headscale {
|
||||
Write-Status "Headscale 서버에 등록 중..."
|
||||
|
||||
# Tailscale 실행파일 경로 확인
|
||||
$tailscaleCmd = Get-Command "tailscale" -ErrorAction SilentlyContinue
|
||||
if (-not $tailscaleCmd) {
|
||||
$tailscaleExe = "C:\Program Files\Tailscale\tailscale.exe"
|
||||
if (Test-Path $tailscaleExe) {
|
||||
$tailscaleCmd = @{Source = $tailscaleExe}
|
||||
} else {
|
||||
Write-Error "Tailscale 실행파일을 찾을 수 없습니다."
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
$tailscalePath = $tailscaleCmd.Source
|
||||
|
||||
# 기존 연결 확인
|
||||
try {
|
||||
$status = & $tailscalePath status 2>$null
|
||||
if ($LASTEXITCODE -eq 0 -and $status) {
|
||||
Write-Warning "이미 Tailscale/Headscale에 연결되어 있습니다."
|
||||
|
||||
# 현재 연결 상태 표시
|
||||
Write-Info "현재 연결 상태:"
|
||||
$status | Select-Object -First 5 | ForEach-Object { Write-Host " $_" }
|
||||
|
||||
# 강제 등록 옵션 확인
|
||||
if ($Force) {
|
||||
Write-Warning "강제 재등록 옵션이 활성화되었습니다."
|
||||
Write-Info "기존 연결을 해제하고 재등록합니다..."
|
||||
} else {
|
||||
$response = Read-Host "기존 연결을 해제하고 팜큐 Headscale로 등록하시겠습니까? (Y/n)"
|
||||
if ($response -eq "" -or $response -match "^[Yy]") {
|
||||
Write-Info "기존 연결을 해제합니다..."
|
||||
} else {
|
||||
Write-Info "등록을 건너뜁니다."
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
# 기존 연결 해제
|
||||
try {
|
||||
& $tailscalePath logout 2>$null
|
||||
Start-Sleep -Seconds 3
|
||||
Write-Success "기존 연결이 해제되었습니다."
|
||||
}
|
||||
catch {
|
||||
Write-Warning "연결 해제 중 오류가 발생했지만 계속 진행합니다."
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# 연결되어 있지 않음 (정상)
|
||||
}
|
||||
|
||||
Write-Info "Headscale 서버: $HeadscaleServer"
|
||||
Write-Info "Pre-auth Key: $($PreAuthKey.Substring(0,8))***************"
|
||||
|
||||
# Headscale 등록 시도
|
||||
Write-Status "등록 명령 실행 중..."
|
||||
|
||||
try {
|
||||
$arguments = @(
|
||||
"up",
|
||||
"--login-server=$HeadscaleServer",
|
||||
"--authkey=$PreAuthKey",
|
||||
"--accept-routes",
|
||||
"--accept-dns=false"
|
||||
)
|
||||
|
||||
& $tailscalePath $arguments
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Success "Headscale 등록 성공!"
|
||||
return $true
|
||||
} else {
|
||||
Write-Error "자동 등록에 실패했습니다."
|
||||
Write-Info "수동 등록 명령어:"
|
||||
Write-Host "tailscale up --login-server=`"$HeadscaleServer`" --authkey=`"$PreAuthKey`""
|
||||
return $false
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "등록 중 오류 발생: $($_.Exception.Message)"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 방화벽 설정
|
||||
# ================================
|
||||
function Configure-Firewall {
|
||||
Write-Status "방화벽 설정 확인 중..."
|
||||
|
||||
try {
|
||||
# Windows Defender 방화벽 예외 추가
|
||||
$ruleName = "Tailscale-FarmQ"
|
||||
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
||||
|
||||
if (-not $existingRule) {
|
||||
New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Protocol UDP -LocalPort 41641 -Action Allow -Profile Any | Out-Null
|
||||
New-NetFirewallRule -DisplayName "$ruleName-Outbound" -Direction Outbound -Protocol UDP -LocalPort 41641 -Action Allow -Profile Any | Out-Null
|
||||
Write-Info "Windows Defender 방화벽 예외를 추가했습니다."
|
||||
}
|
||||
|
||||
Write-Success "방화벽 설정 완료"
|
||||
}
|
||||
catch {
|
||||
Write-Warning "방화벽 설정 중 오류 발생: $($_.Exception.Message)"
|
||||
Write-Info "수동으로 방화벽에서 Tailscale을 허용해주세요."
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 연결 상태 확인
|
||||
# ================================
|
||||
function Test-Connection {
|
||||
Write-Status "연결 상태 확인 중..."
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
# Tailscale 실행파일 경로 확인
|
||||
$tailscaleCmd = Get-Command "tailscale" -ErrorAction SilentlyContinue
|
||||
if (-not $tailscaleCmd) {
|
||||
$tailscaleExe = "C:\Program Files\Tailscale\tailscale.exe"
|
||||
if (Test-Path $tailscaleExe) {
|
||||
$tailscaleCmd = @{Source = $tailscaleExe}
|
||||
} else {
|
||||
Write-Error "Tailscale 실행파일을 찾을 수 없습니다."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$tailscalePath = $tailscaleCmd.Source
|
||||
|
||||
try {
|
||||
$status = & $tailscalePath status 2>$null
|
||||
if ($LASTEXITCODE -ne 0 -or -not $status) {
|
||||
Write-Error "Tailscale 연결에 문제가 있습니다."
|
||||
return
|
||||
}
|
||||
|
||||
# IP 주소 확인
|
||||
$ipv4 = & $tailscalePath ip -4 2>$null
|
||||
$ipv6 = & $tailscalePath ip -6 2>$null
|
||||
|
||||
Write-Success "Headscale 네트워크 연결 완료!"
|
||||
Write-Info "할당된 IPv4: $(if($ipv4){$ipv4}else{'N/A'})"
|
||||
Write-Info "할당된 IPv6: $(if($ipv6){$ipv6}else{'N/A'})"
|
||||
|
||||
# 네트워크 테스트
|
||||
Write-Status "네트워크 연결 테스트 중..."
|
||||
|
||||
try {
|
||||
Test-Connection "100.64.0.1" -Count 2 -Quiet | Out-Null
|
||||
Write-Success "팜큐 네트워크($FarmqNetwork) 연결 정상!"
|
||||
}
|
||||
catch {
|
||||
Write-Warning "네트워크 테스트 실패. 방화벽을 확인해주세요."
|
||||
}
|
||||
|
||||
# 연결된 노드 확인
|
||||
Write-Info "네트워크 상태:"
|
||||
$status | Select-Object -First 10 | ForEach-Object {
|
||||
Write-Host " $_" -ForegroundColor Gray
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "연결 상태 확인 실패: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 정리 작업
|
||||
# ================================
|
||||
function Complete-Installation {
|
||||
Write-Status "설치 완료 작업 중..."
|
||||
|
||||
# 임시 파일 정리
|
||||
Get-ChildItem "$env:TEMP\tailscale*" -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Success "정리 작업 완료"
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 최종 정보 출력
|
||||
# ================================
|
||||
function Show-FinalInfo {
|
||||
Write-Header "팜큐 Headscale Windows 설치 완료!"
|
||||
|
||||
# 시스템 정보
|
||||
$computerName = $env:COMPUTERNAME
|
||||
$tailscaleCmd = Get-Command "tailscale" -ErrorAction SilentlyContinue
|
||||
if (-not $tailscaleCmd) {
|
||||
$tailscaleExe = "C:\Program Files\Tailscale\tailscale.exe"
|
||||
if (Test-Path $tailscaleExe) {
|
||||
$tailscaleCmd = @{Source = $tailscaleExe}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tailscaleCmd) {
|
||||
$tailscaleIP = & $tailscaleCmd.Source ip -4 2>$null
|
||||
}
|
||||
|
||||
$osVersion = [System.Environment]::OSVersion.Version
|
||||
|
||||
Write-ColorOutput "🎉 설치가 성공적으로 완료되었습니다!" "Green"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorOutput "📋 시스템 정보:" "Cyan"
|
||||
Write-Host " 컴퓨터명: $computerName"
|
||||
Write-Host " Tailscale IP: $(if($tailscaleIP){$tailscaleIP}else{'N/A'})"
|
||||
Write-Host " OS: Windows $($osVersion.Major).$($osVersion.Minor)"
|
||||
Write-Host " Headscale 서버: $HeadscaleServer"
|
||||
|
||||
Write-Host ""
|
||||
Write-ColorOutput "🔧 유용한 명령어:" "Yellow"
|
||||
Write-Host " tailscale status # 연결 상태 확인"
|
||||
Write-Host " tailscale ip # 할당된 IP 확인"
|
||||
Write-Host " tailscale ping <node> # 다른 노드와 연결 테스트"
|
||||
Write-Host " tailscale logout # 네트워크에서 해제"
|
||||
|
||||
Write-Host ""
|
||||
Write-ColorOutput "🌐 팜큐 관리자 페이지:" "Magenta"
|
||||
Write-Host " http://192.168.0.151:5002"
|
||||
Write-Host " http://192.168.0.151:5002/vms (VM 관리)"
|
||||
|
||||
Write-Host ""
|
||||
Write-ColorOutput "문제가 있을 경우 다음을 확인하세요:" "White"
|
||||
Write-Host " 1. Windows 방화벽 설정"
|
||||
Write-Host " 2. 바이러스 백신 프로그램 예외 설정"
|
||||
Write-Host " 3. 회사 네트워크 정책 확인"
|
||||
|
||||
Write-Header "설치 완료 - 팜큐 네트워크를 사용할 수 있습니다!"
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 메인 함수
|
||||
# ================================
|
||||
function Main {
|
||||
# 에러 발생 시 중단
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Header "팜큐(FARMQ) Headscale Windows 원클릭 설치"
|
||||
|
||||
try {
|
||||
# 설치 과정
|
||||
Test-Requirements
|
||||
Install-Tailscale
|
||||
Start-TailscaleService
|
||||
$registerSuccess = Register-Headscale
|
||||
|
||||
if ($registerSuccess) {
|
||||
Configure-Firewall
|
||||
Test-Connection
|
||||
Complete-Installation
|
||||
Show-FinalInfo
|
||||
} else {
|
||||
Write-Warning "등록에 실패했지만 Tailscale은 설치되었습니다."
|
||||
Write-Info "수동으로 등록을 완료해주세요."
|
||||
}
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Error "설치 중 오류가 발생했습니다: $($_.Exception.Message)"
|
||||
Write-Info "문제가 지속되면 관리자에게 문의하세요."
|
||||
Write-Host ""
|
||||
Read-Host "아무 키나 누르세요..."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 스크립트 실행
|
||||
# ================================
|
||||
|
||||
# 파라미터 처리
|
||||
if ($args -contains "--help" -or $args -contains "-h") {
|
||||
Write-Host "팜큐 Headscale Windows 설치 스크립트"
|
||||
Write-Host ""
|
||||
Write-Host "사용법:"
|
||||
Write-Host " iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1'))"
|
||||
Write-Host ""
|
||||
Write-Host "옵션:"
|
||||
Write-Host " -Force 기존 연결을 강제로 해제하고 재등록"
|
||||
Write-Host " -HeadscaleServer 서버 주소 (기본값: https://head.0bin.in)"
|
||||
Write-Host ""
|
||||
Write-Host "예시:"
|
||||
Write-Host " # 강제 재등록"
|
||||
Write-Host " iex ((New-Object System.Net.WebClient).DownloadString('https://git.0bin.in/.../farmq-install.ps1?force=1'))"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Force 파라미터 URL에서 처리
|
||||
if ($MyInvocation.MyCommand.Path -like "*force=1*") {
|
||||
$Force = $true
|
||||
}
|
||||
|
||||
# 메인 함수 실행
|
||||
Main
|
||||
Loading…
Reference in New Issue
Block a user