diff --git a/.env.example b/.env.example index cd1af0e..95d36fa 100644 --- a/.env.example +++ b/.env.example @@ -28,5 +28,8 @@ ANALYSIS_CALLBACK_SECRET=change-me # Slack Incoming Webhook (rally-track-back-log 채널, 비우면 알림 비활성) SLACK_BACK_WEBHOOK= +# Cloudflare Tunnel 토큰 (rally-proxmox 터널의 replica 커넥터용) +CLOUDFLARE_TUNNEL_TOKEN= + # 최초 배포 시에만 update로 설정해 테이블 생성 후 validate로 되돌릴 것 DDL_AUTO=validate diff --git a/README.md b/README.md index 5d87ad5..6b744f4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ | Raspberry Pi 5 (`192.168.219.156`) | MariaDB 11.4 · Spring backend(:8080) · React frontend(:8082) · MinIO(:9000, 콘솔 :9001 로컬) | `~/RallyTrack/devops` (docker compose) | | ml-server (`192.168.219.150`) | FastAPI AI 분석 서버(:8000) | `~/RallyTrack/aiAnalysis-server` (venv + systemd `rallytrack-ai`) | -- **공개 주소: https://app.rallytrack.win** — Cloudflare Tunnel(`rally-proxmox`, 커넥터는 Proxmox 호스트)의 public hostname → `http://192.168.219.156:8082`. 포트 개방 없음, HTTPS는 Cloudflare 엣지가 처리 +- **공개 주소: https://app.rallytrack.win** — Cloudflare Tunnel(`rally-proxmox`)의 public hostname → `http://192.168.219.156:8082`. 포트 개방 없음, HTTPS는 Cloudflare 엣지가 처리. **커넥터 2개(이중화)**: Proxmox 호스트(pve) + Pi의 `rally-cloudflared` 컨테이너 → 한쪽이 꺼져도 웹 접속 유지 - LAN 직결 주소: `http://192.168.219.156:8082` (큰 영상 업로드는 이쪽으로 — Cloudflare 무료 플랜은 **요청 본문 100MB 제한**이라 100MB 초과 업로드는 도메인 경유 시 실패) - presigned URL은 `S3_PUBLIC_ENDPOINT`(현재 `https://app.rallytrack.win`)로 서명되고, frontend nginx가 `/rallytrack-videos/` → MinIO로 프록시 (`pi/nginx-rallytrack.conf`는 호스트 nginx 대안, 현재 미사용) - DB에는 스토리지 URL 대신 **object key만 저장** → MinIO↔S3 전환 시 DB 불변 diff --git a/docker-compose.pi.yml b/docker-compose.pi.yml index 1966f4e..e88490e 100644 --- a/docker-compose.pi.yml +++ b/docker-compose.pi.yml @@ -102,6 +102,19 @@ services: mem_limit: 128m restart: unless-stopped + # Cloudflare Tunnel replica — Proxmox 호스트의 커넥터가 꺼져도 + # app.rallytrack.win 웹 접속을 Pi 단독으로 유지 (동일 터널, 동일 토큰) + cloudflared: + image: cloudflare/cloudflared:latest + container_name: rally-cloudflared + command: tunnel --no-autoupdate run + environment: + TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN} + networks: + - rallytrack-net + mem_limit: 128m + restart: unless-stopped + volumes: db_data: minio_data: diff --git a/ml-server/deploy-ai.sh b/ml-server/deploy-ai.sh new file mode 100755 index 0000000..6b7beab --- /dev/null +++ b/ml-server/deploy-ai.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# RallyTrack AI 서버 배포 스크립트 — GitHub에서 pull 후 서비스 재시작 +# 사용: ~/RallyTrack/aiAnalysis-server 클론 후 이 스크립트 실행 (ml-server에서) +set -e + +ROOT="$HOME/RallyTrack/aiAnalysis-server" + +echo "=== git pull ===" +git -C "$ROOT" pull --ff-only + +echo "=== 의존성 갱신 ===" +"$ROOT/.venv/bin/pip" install -q -r "$ROOT/requirements.txt" + +echo "=== 서비스 재시작 ===" +sudo systemctl restart rallytrack-ai +sleep 3 +systemctl is-active rallytrack-ai && curl -s http://localhost:8000/health && echo diff --git a/pi/deploy.sh b/pi/deploy.sh new file mode 100755 index 0000000..5fc3d9d --- /dev/null +++ b/pi/deploy.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# RallyTrack Pi 배포 스크립트 — GitHub에서 pull 후 재빌드/재기동 +# 사용: ~/RallyTrack/devops/pi/deploy.sh (Pi에서 실행) +set -e + +ROOT="$HOME/RallyTrack" + +echo "=== git pull ===" +git -C "$ROOT/backend" pull --ff-only +git -C "$ROOT/frontend" pull --ff-only +git -C "$ROOT/devops" pull --ff-only + +echo "=== docker compose up ===" +cd "$ROOT/devops" +docker compose -f docker-compose.pi.yml --env-file .env up -d --build + +echo "=== 상태 ===" +docker compose -f docker-compose.pi.yml ps