Phase 8(RDP), Phase 9(noVNC) 통합 — 총 10단계로 확장
- Phase 8: RDP 자동 연결 (xorg+openbox+freerdp+toggle API) - VM 201(192.168.0.201) 자동 감지, rdpuser 자동 로그인 - RDP Toggle API (포트 8090) 설치 - 이미 설치돼있으면 스킵 - Phase 9: noVNC 웹 서비스 (기존 스크립트 호출) - 이미 설치돼있으면 스킵 - Phase 10: 검증 + 결과 출력 (기존 Phase 8) - RDP API 정보 출력 추가 - 모든 Phase 번호 /8 → /10으로 변경 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
192
pharmq-setup.sh
192
pharmq-setup.sh
@@ -127,7 +127,7 @@ print_info() { echo -e "${CYAN} $1${NC}"; }
|
|||||||
# Phase 1: PVE Repository Fix
|
# Phase 1: PVE Repository Fix
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase1_repo_fix() {
|
phase1_repo_fix() {
|
||||||
print_phase "Phase 1/8: PVE Repository Fix"
|
print_phase "Phase 1/10: PVE Repository Fix"
|
||||||
|
|
||||||
# Proxmox 환경 확인
|
# Proxmox 환경 확인
|
||||||
if [ ! -f /etc/pve/storage.cfg ]; then
|
if [ ! -f /etc/pve/storage.cfg ]; then
|
||||||
@@ -207,7 +207,7 @@ EOF
|
|||||||
# Phase 2: PVE Host Tailscale → Headscale 등록
|
# Phase 2: PVE Host Tailscale → Headscale 등록
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase2_tailscale_pve() {
|
phase2_tailscale_pve() {
|
||||||
print_phase "Phase 2/8: PVE Host Tailscale 등록"
|
print_phase "Phase 2/10: PVE Host Tailscale 등록"
|
||||||
|
|
||||||
# Headscale 서버 주소 자동 감지 (LAN vs 외부)
|
# Headscale 서버 주소 자동 감지 (LAN vs 외부)
|
||||||
# ping만으로는 부정확 (외부 약국에 192.168.0.100 장비가 있을 수 있음)
|
# ping만으로는 부정확 (외부 약국에 192.168.0.100 장비가 있을 수 있음)
|
||||||
@@ -283,7 +283,7 @@ phase2_tailscale_pve() {
|
|||||||
# Phase 3: 약국 정보 수집
|
# Phase 3: 약국 정보 수집
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase3_collect_info() {
|
phase3_collect_info() {
|
||||||
print_phase "Phase 3/8: 약국 정보 수집"
|
print_phase "Phase 3/10: 약국 정보 수집"
|
||||||
|
|
||||||
# 명령행 인자가 있으면 사용, 없으면 대화형 입력
|
# 명령행 인자가 있으면 사용, 없으면 대화형 입력
|
||||||
if [ -n "$ARGS_NAME" ]; then
|
if [ -n "$ARGS_NAME" ]; then
|
||||||
@@ -334,7 +334,7 @@ phase3_collect_info() {
|
|||||||
# Phase 4: PBS 등록 + Windows VM 복원
|
# Phase 4: PBS 등록 + Windows VM 복원
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase4_pbs_restore() {
|
phase4_pbs_restore() {
|
||||||
print_phase "Phase 4/8: PBS 등록 + Windows VM 복원"
|
print_phase "Phase 4/10: PBS 등록 + Windows VM 복원"
|
||||||
|
|
||||||
# 이미 VM이 존재하면 스킵
|
# 이미 VM이 존재하면 스킵
|
||||||
local TARGET_CHECK="${ARGS_VM_VMID:-201}"
|
local TARGET_CHECK="${ARGS_VM_VMID:-201}"
|
||||||
@@ -587,7 +587,7 @@ PYEOF
|
|||||||
# Phase 5: Ubuntu CT 생성
|
# Phase 5: Ubuntu CT 생성
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase5_create_ct() {
|
phase5_create_ct() {
|
||||||
print_phase "Phase 5/8: Ubuntu CT 생성"
|
print_phase "Phase 5/10: Ubuntu CT 생성"
|
||||||
|
|
||||||
# 이미 ubuntu-api CT가 존재하면 스킵
|
# 이미 ubuntu-api CT가 존재하면 스킵
|
||||||
for vmid in $(seq 200 299); do
|
for vmid in $(seq 200 299); do
|
||||||
@@ -685,7 +685,7 @@ phase5_create_ct() {
|
|||||||
# Phase 6: CT 내부 환경 구축
|
# Phase 6: CT 내부 환경 구축
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase6_setup_ct() {
|
phase6_setup_ct() {
|
||||||
print_phase "Phase 6/8: CT 내부 환경 구축"
|
print_phase "Phase 6/10: CT 내부 환경 구축"
|
||||||
|
|
||||||
# 헬퍼: CT 내부에서 명령 실행
|
# 헬퍼: CT 내부에서 명령 실행
|
||||||
ct_exec() {
|
ct_exec() {
|
||||||
@@ -780,7 +780,7 @@ SVCEOF"
|
|||||||
# Phase 7: 약국 + 장비 + 계정 등록
|
# Phase 7: 약국 + 장비 + 계정 등록
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase7_register() {
|
phase7_register() {
|
||||||
print_phase "Phase 7/8: 약국 + 장비 + 계정 등록"
|
print_phase "Phase 7/10: 약국 + 장비 + 계정 등록"
|
||||||
|
|
||||||
# 7-1. 약국 생성 (CT를 primary 장비로)
|
# 7-1. 약국 생성 (CT를 primary 장비로)
|
||||||
print_step "약국 생성 중... (farmq.db)"
|
print_step "약국 생성 중... (farmq.db)"
|
||||||
@@ -888,10 +888,161 @@ JSONEOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Phase 8: 검증 + 결과 출력
|
# Phase 8: RDP 자동 연결 설정
|
||||||
# ============================================================
|
# ============================================================
|
||||||
phase8_verify() {
|
phase8_rdp_setup() {
|
||||||
print_phase "Phase 8/8: 검증 + 결과 출력"
|
print_phase "Phase 8/10: RDP 자동 연결 설정"
|
||||||
|
|
||||||
|
# 이미 설치되어있으면 스킵
|
||||||
|
if systemctl is-active --quiet rdp-toggle-api.service 2>/dev/null && \
|
||||||
|
[ -f "/opt/rdp-toggle-api/rdp-toggle-api.py" ]; then
|
||||||
|
print_ok "RDP 자동 연결 이미 설치됨 — 스킵"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# RDP 서버 주소 (Phase 4의 VM에서 자동 설정)
|
||||||
|
local RDP_SERVER="${MSSQL_SERVER%%\\*}" # 192.168.0.201\PM2014 → 192.168.0.201
|
||||||
|
local RDP_USERNAME="administrator"
|
||||||
|
local RDP_PASSWORD="pharmq119"
|
||||||
|
local LOCAL_USER="rdpuser"
|
||||||
|
|
||||||
|
print_info "RDP 서버: $RDP_SERVER"
|
||||||
|
print_info "RDP 사용자: $RDP_USERNAME"
|
||||||
|
|
||||||
|
# 패키지 설치
|
||||||
|
print_step "RDP 패키지 설치 중 (xorg, openbox, freerdp)..."
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y xorg openbox unclutter freerdp3-x11 python3 python3-venv >/dev/null 2>&1 || \
|
||||||
|
apt-get install -y xorg openbox unclutter freerdp2-x11 python3 python3-venv >/dev/null 2>&1
|
||||||
|
print_ok "RDP 패키지 설치 완료"
|
||||||
|
|
||||||
|
# 사용자 생성
|
||||||
|
if ! id "$LOCAL_USER" &>/dev/null; then
|
||||||
|
useradd -m -s /bin/bash "$LOCAL_USER"
|
||||||
|
fi
|
||||||
|
chown -R "$LOCAL_USER:$LOCAL_USER" "/home/$LOCAL_USER"
|
||||||
|
|
||||||
|
# 자동 로그인 설정
|
||||||
|
print_step "자동 로그인 + X 자동 시작 설정 중..."
|
||||||
|
mkdir -p /etc/systemd/system/getty@tty1.service.d
|
||||||
|
cat > /etc/systemd/system/getty@tty1.service.d/override.conf << EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=-/sbin/agetty --autologin $LOCAL_USER --noclear %I \$TERM
|
||||||
|
Type=idle
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# .bash_profile — tty1에서 X 자동 시작
|
||||||
|
cat > "/home/$LOCAL_USER/.bash_profile" << 'BPEOF'
|
||||||
|
if [[ -z $DISPLAY ]] && [[ $(tty) == /dev/tty1 ]]; then
|
||||||
|
startx
|
||||||
|
logout
|
||||||
|
fi
|
||||||
|
BPEOF
|
||||||
|
chown "$LOCAL_USER:$LOCAL_USER" "/home/$LOCAL_USER/.bash_profile"
|
||||||
|
|
||||||
|
# .xinitrc — RDP 자동 연결
|
||||||
|
local XFREERDP_CMD="xfreerdp3"
|
||||||
|
command -v xfreerdp3 >/dev/null 2>&1 || XFREERDP_CMD="xfreerdp"
|
||||||
|
|
||||||
|
cat > "/home/$LOCAL_USER/.xinitrc" << EOF
|
||||||
|
#!/bin/bash
|
||||||
|
xset -dpms && xset s off && xset s noblank
|
||||||
|
unclutter -idle 0.1 -root &
|
||||||
|
openbox-session &
|
||||||
|
sleep 2
|
||||||
|
$XFREERDP_CMD /v:$RDP_SERVER /u:$RDP_USERNAME /p:"$RDP_PASSWORD" +f /cert:ignore +dynamic-resolution /sound:sys:alsa +clipboard
|
||||||
|
pkill -SIGTERM Xorg
|
||||||
|
EOF
|
||||||
|
chmod +x "/home/$LOCAL_USER/.xinitrc"
|
||||||
|
chown "$LOCAL_USER:$LOCAL_USER" "/home/$LOCAL_USER/.xinitrc"
|
||||||
|
|
||||||
|
# Openbox 설정
|
||||||
|
mkdir -p "/home/$LOCAL_USER/.config/openbox"
|
||||||
|
cat > "/home/$LOCAL_USER/.config/openbox/rc.xml" << 'OBEOF'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<openbox_config xmlns="http://openbox.org/3.4/rc">
|
||||||
|
<applications>
|
||||||
|
<application class="*">
|
||||||
|
<decor>no</decor>
|
||||||
|
<maximized>yes</maximized>
|
||||||
|
</application>
|
||||||
|
</applications>
|
||||||
|
</openbox_config>
|
||||||
|
OBEOF
|
||||||
|
chown -R "$LOCAL_USER:$LOCAL_USER" "/home/$LOCAL_USER/.config"
|
||||||
|
|
||||||
|
# RDP Toggle API 설치
|
||||||
|
print_step "RDP Toggle API 설치 중..."
|
||||||
|
local INSTALL_DIR="/opt/rdp-toggle-api"
|
||||||
|
local VENV_DIR="$INSTALL_DIR/venv"
|
||||||
|
local GITEA_BASE_URL="https://git.0bin.in/thug0bin/pve9-repo-fix/raw/branch/main/RDP"
|
||||||
|
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
python3 -m venv "$VENV_DIR"
|
||||||
|
"$VENV_DIR/bin/pip" install --upgrade pip -q >/dev/null 2>&1
|
||||||
|
"$VENV_DIR/bin/pip" install fastapi==0.115.5 uvicorn==0.32.1 python-multipart==0.0.20 pydantic==2.10.3 -q >/dev/null 2>&1
|
||||||
|
curl -fsSL "$GITEA_BASE_URL/rdp-toggle-api.py" -o "$INSTALL_DIR/rdp-toggle-api.py"
|
||||||
|
chmod +x "$INSTALL_DIR/rdp-toggle-api.py"
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/rdp-toggle-api.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=RDP Toggle API Service
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=$INSTALL_DIR
|
||||||
|
ExecStart=$VENV_DIR/bin/python $INSTALL_DIR/rdp-toggle-api.py
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir -p /var/lib/rdp-toggle
|
||||||
|
cat > /var/lib/rdp-toggle/config.json << EOF
|
||||||
|
{
|
||||||
|
"rdp_server": "$RDP_SERVER",
|
||||||
|
"rdp_username": "$RDP_USERNAME",
|
||||||
|
"rdp_password": "$RDP_PASSWORD",
|
||||||
|
"local_user": "$LOCAL_USER"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now rdp-toggle-api.service >/dev/null 2>&1
|
||||||
|
|
||||||
|
print_ok "Phase 8 완료: RDP 자동 연결 설정됨 (API: 포트 8090)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Phase 9: noVNC 웹 서비스 설치
|
||||||
|
# ============================================================
|
||||||
|
phase9_novnc_setup() {
|
||||||
|
print_phase "Phase 9/10: noVNC 웹 서비스 설치"
|
||||||
|
|
||||||
|
# 이미 설치되어있으면 스킵
|
||||||
|
if [ -d "/srv/pharmq-novnc" ] && systemctl is-active --quiet pharmq-vnc-app.service 2>/dev/null; then
|
||||||
|
print_ok "noVNC 이미 설치됨 — 스킵"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# noVNC 설치 스크립트를 별도로 실행 (대화형 요소가 많아서)
|
||||||
|
print_step "noVNC 설치 스크립트 다운로드 및 실행 중..."
|
||||||
|
curl -fsSL https://git.0bin.in/thug0bin/pve9-repo-fix/raw/branch/main/VNC/pharmq-novnc-setup.sh -o /tmp/pharmq-novnc-setup.sh
|
||||||
|
chmod +x /tmp/pharmq-novnc-setup.sh
|
||||||
|
bash /tmp/pharmq-novnc-setup.sh || true
|
||||||
|
rm -f /tmp/pharmq-novnc-setup.sh
|
||||||
|
|
||||||
|
print_ok "Phase 9 완료: noVNC 설치"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Phase 10: 검증 + 결과 출력
|
||||||
|
# ============================================================
|
||||||
|
phase10_verify() {
|
||||||
|
print_phase "Phase 10/10: 검증 + 결과 출력"
|
||||||
|
|
||||||
# API 헬스체크
|
# API 헬스체크
|
||||||
print_step "API 서버 헬스체크 중..."
|
print_step "API 서버 헬스체크 중..."
|
||||||
@@ -953,9 +1104,16 @@ phase8_verify() {
|
|||||||
echo -e " API: http://${CT_VPN_IP}:8082"
|
echo -e " API: http://${CT_VPN_IP}:8082"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
if systemctl is-active --quiet rdp-toggle-api.service 2>/dev/null; then
|
||||||
|
echo -e "${WHITE}[RDP 자동 연결]${NC}"
|
||||||
|
echo -e " RDP API: http://${PVE_VPN_IP:-localhost}:8090"
|
||||||
|
echo -e " RDP 서버: ${MSSQL_SERVER%%\\*}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e "${WHITE}[로그인 정보]${NC}"
|
echo -e "${WHITE}[로그인 정보]${NC}"
|
||||||
echo -e " URL: ${CYAN}https://pharmq.kr${NC}"
|
echo -e " URL: ${CYAN}https://pharmq.kr${NC}"
|
||||||
echo -e " ID: ${CYAN}${USERNAME}${NC}"
|
echo -e " ID: ${CYAN}${USERNAME:-}${NC}"
|
||||||
echo -e " PW: ${CYAN}12341234${NC}"
|
echo -e " PW: ${CYAN}12341234${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -967,9 +1125,9 @@ phase8_verify() {
|
|||||||
# 유용한 명령어
|
# 유용한 명령어
|
||||||
echo -e "${WHITE}유용한 명령어:${NC}"
|
echo -e "${WHITE}유용한 명령어:${NC}"
|
||||||
echo " tailscale status # VPN 상태"
|
echo " tailscale status # VPN 상태"
|
||||||
echo " pct enter ${CT_VMID} # CT 접속"
|
echo " pct enter ${CT_VMID:-200} # CT 접속"
|
||||||
echo " pct exec ${CT_VMID} -- systemctl status pharmq-api # API 상태"
|
echo " pct exec ${CT_VMID:-200} -- systemctl status pharmq-api # API 상태"
|
||||||
if [ -n "$VM_VMID" ]; then
|
if [ -n "${VM_VMID:-}" ]; then
|
||||||
echo " qm status ${VM_VMID} # Windows VM 상태"
|
echo " qm status ${VM_VMID} # Windows VM 상태"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1009,7 +1167,7 @@ main() {
|
|||||||
echo -e "${PURPLE}╔════════════════════════════════════════════╗${NC}"
|
echo -e "${PURPLE}╔════════════════════════════════════════════╗${NC}"
|
||||||
echo -e "${PURPLE}║ ║${NC}"
|
echo -e "${PURPLE}║ ║${NC}"
|
||||||
echo -e "${PURPLE}║${NC} ${WHITE}PharmQ PVE 원클릭 통합 설치${NC} ${PURPLE}║${NC}"
|
echo -e "${PURPLE}║${NC} ${WHITE}PharmQ PVE 원클릭 통합 설치${NC} ${PURPLE}║${NC}"
|
||||||
echo -e "${PURPLE}║${NC} ${CYAN}Repo Fix → VPN → PBS → CT → 등록${NC} ${PURPLE}║${NC}"
|
echo -e "${PURPLE}║${NC} ${CYAN}Repo→VPN→PBS→CT→등록→RDP→VNC${NC} ${PURPLE}║${NC}"
|
||||||
echo -e "${PURPLE}║ ║${NC}"
|
echo -e "${PURPLE}║ ║${NC}"
|
||||||
echo -e "${PURPLE}╚════════════════════════════════════════════╝${NC}"
|
echo -e "${PURPLE}╚════════════════════════════════════════════╝${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1021,7 +1179,9 @@ main() {
|
|||||||
phase5_create_ct
|
phase5_create_ct
|
||||||
phase6_setup_ct
|
phase6_setup_ct
|
||||||
phase7_register || print_warn "Phase 7 실패 — 수동 등록 필요"
|
phase7_register || print_warn "Phase 7 실패 — 수동 등록 필요"
|
||||||
phase8_verify
|
phase8_rdp_setup || print_warn "Phase 8 실패 — RDP 수동 설정 필요"
|
||||||
|
phase9_novnc_setup || print_warn "Phase 9 실패 — noVNC 수동 설치 필요"
|
||||||
|
phase10_verify
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user