diff --git a/pharmq-setup.sh b/pharmq-setup.sh index 9abbcb7..6cda6e0 100644 --- a/pharmq-setup.sh +++ b/pharmq-setup.sh @@ -127,7 +127,7 @@ print_info() { echo -e "${CYAN} $1${NC}"; } # Phase 1: PVE Repository Fix # ============================================================ phase1_repo_fix() { - print_phase "Phase 1/8: PVE Repository Fix" + print_phase "Phase 1/10: PVE Repository Fix" # Proxmox 환경 확인 if [ ! -f /etc/pve/storage.cfg ]; then @@ -207,7 +207,7 @@ EOF # Phase 2: PVE Host Tailscale → Headscale 등록 # ============================================================ phase2_tailscale_pve() { - print_phase "Phase 2/8: PVE Host Tailscale 등록" + print_phase "Phase 2/10: PVE Host Tailscale 등록" # Headscale 서버 주소 자동 감지 (LAN vs 외부) # ping만으로는 부정확 (외부 약국에 192.168.0.100 장비가 있을 수 있음) @@ -283,7 +283,7 @@ phase2_tailscale_pve() { # Phase 3: 약국 정보 수집 # ============================================================ phase3_collect_info() { - print_phase "Phase 3/8: 약국 정보 수집" + print_phase "Phase 3/10: 약국 정보 수집" # 명령행 인자가 있으면 사용, 없으면 대화형 입력 if [ -n "$ARGS_NAME" ]; then @@ -334,7 +334,7 @@ phase3_collect_info() { # Phase 4: PBS 등록 + Windows VM 복원 # ============================================================ phase4_pbs_restore() { - print_phase "Phase 4/8: PBS 등록 + Windows VM 복원" + print_phase "Phase 4/10: PBS 등록 + Windows VM 복원" # 이미 VM이 존재하면 스킵 local TARGET_CHECK="${ARGS_VM_VMID:-201}" @@ -587,7 +587,7 @@ PYEOF # Phase 5: Ubuntu CT 생성 # ============================================================ phase5_create_ct() { - print_phase "Phase 5/8: Ubuntu CT 생성" + print_phase "Phase 5/10: Ubuntu CT 생성" # 이미 ubuntu-api CT가 존재하면 스킵 for vmid in $(seq 200 299); do @@ -685,7 +685,7 @@ phase5_create_ct() { # Phase 6: CT 내부 환경 구축 # ============================================================ phase6_setup_ct() { - print_phase "Phase 6/8: CT 내부 환경 구축" + print_phase "Phase 6/10: CT 내부 환경 구축" # 헬퍼: CT 내부에서 명령 실행 ct_exec() { @@ -780,7 +780,7 @@ SVCEOF" # Phase 7: 약국 + 장비 + 계정 등록 # ============================================================ phase7_register() { - print_phase "Phase 7/8: 약국 + 장비 + 계정 등록" + print_phase "Phase 7/10: 약국 + 장비 + 계정 등록" # 7-1. 약국 생성 (CT를 primary 장비로) print_step "약국 생성 중... (farmq.db)" @@ -888,10 +888,161 @@ JSONEOF } # ============================================================ -# Phase 8: 검증 + 결과 출력 +# Phase 8: RDP 자동 연결 설정 # ============================================================ -phase8_verify() { - print_phase "Phase 8/8: 검증 + 결과 출력" +phase8_rdp_setup() { + 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' + + + + + no + yes + + + +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 헬스체크 print_step "API 서버 헬스체크 중..." @@ -953,9 +1104,16 @@ phase8_verify() { echo -e " API: http://${CT_VPN_IP}:8082" 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 " 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 "" @@ -967,9 +1125,9 @@ phase8_verify() { # 유용한 명령어 echo -e "${WHITE}유용한 명령어:${NC}" echo " tailscale status # VPN 상태" - echo " pct enter ${CT_VMID} # CT 접속" - echo " pct exec ${CT_VMID} -- systemctl status pharmq-api # API 상태" - if [ -n "$VM_VMID" ]; then + echo " pct enter ${CT_VMID:-200} # CT 접속" + echo " pct exec ${CT_VMID:-200} -- systemctl status pharmq-api # API 상태" + if [ -n "${VM_VMID:-}" ]; then echo " qm status ${VM_VMID} # Windows VM 상태" fi echo "" @@ -1009,7 +1167,7 @@ main() { echo -e "${PURPLE}╔════════════════════════════════════════════╗${NC}" echo -e "${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 "" @@ -1021,7 +1179,9 @@ main() { phase5_create_ct phase6_setup_ct 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 "$@"