Compare commits
4 Commits
f44e116e7f
...
d0bbb779c0
| Author | SHA1 | Date | |
|---|---|---|---|
| d0bbb779c0 | |||
| a2acaa70d8 | |||
| 762335286c | |||
| 55a7b044d8 |
@@ -6,12 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEPLOY_HOST: 192.168.123.100
|
DEPLOY_HOST: 172.17.0.1
|
||||||
# NOTE: Gitea와 운영서버가 원격지의 같은 서버에 있으므로 내부 IP 사용
|
# NOTE: Gitea와 운영서버가 같은 호스트에 있음 (hz-prod-01)
|
||||||
# Gitea (CI/CD) → SSH (내부 192.168.123.100) → 운영서버
|
# 구조: 공인 IP 178.104.200.7/quant → Nginx reverse proxy → localhost:5000 (quantengine)
|
||||||
# 외부 사용자: 178.104.200.7 → nginx 포트포워딩 → 192.168.123.100/quant
|
# 배포: .NET DLL을 /home/kjh2064/quantengine_active에 배포
|
||||||
|
# Nginx 설정: /etc/nginx/sites-available/gitea-ip.conf (이미 구성됨)
|
||||||
DEPLOY_USER: kjh2064
|
DEPLOY_USER: kjh2064
|
||||||
DEPLOY_PATH: /var/www/quant
|
DEPLOY_PATH: /home/kjh2064/quantengine_active
|
||||||
|
SERVICE_NAME: quantengine
|
||||||
DOTNET_VERSION: '10.0.x'
|
DOTNET_VERSION: '10.0.x'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -105,24 +107,36 @@ jobs:
|
|||||||
chmod 600 ~/.ssh/id_ed25519
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||||
|
|
||||||
- name: Create Backup
|
- name: Stop Service and Create Backup
|
||||||
run: |
|
run: |
|
||||||
echo "📦 Creating backup on production server..."
|
echo "📦 Stopping service and creating backup..."
|
||||||
ssh -i ~/.ssh/id_ed25519 ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'EOF'
|
ssh -i ~/.ssh/id_ed25519 ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'EOF'
|
||||||
set -e
|
set -e
|
||||||
BACKUP_DIR="/var/www/quant_backup"
|
BACKUP_DIR="/home/kjh2064/quantengine_backup"
|
||||||
BACKUP_NAME="quant_backup_$(date +%Y%m%d_%H%M%S)"
|
BACKUP_NAME="quantengine_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
sudo mkdir -p $BACKUP_DIR
|
# Stop service
|
||||||
if [ -d ${{ env.DEPLOY_PATH }}/publish ]; then
|
echo "⏹️ Stopping quantengine service..."
|
||||||
sudo cp -r ${{ env.DEPLOY_PATH }}/publish "$BACKUP_DIR/$BACKUP_NAME"
|
sudo systemctl stop ${{ env.SERVICE_NAME }}
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Create backup
|
||||||
|
mkdir -p $BACKUP_DIR
|
||||||
|
if [ -d ${{ env.DEPLOY_PATH }} ]; then
|
||||||
|
cp -r ${{ env.DEPLOY_PATH }} "$BACKUP_DIR/$BACKUP_NAME"
|
||||||
echo "✅ Backup created: $BACKUP_DIR/$BACKUP_NAME"
|
echo "✅ Backup created: $BACKUP_DIR/$BACKUP_NAME"
|
||||||
|
|
||||||
# Keep only last 5 backups
|
# Keep only last 5 backups
|
||||||
ls -t $BACKUP_DIR | tail -n +6 | xargs -I {} sudo rm -rf "$BACKUP_DIR/{}"
|
BACKUP_COUNT=$(ls -1 $BACKUP_DIR | wc -l)
|
||||||
echo "🧹 Old backups cleaned"
|
if [ "$BACKUP_COUNT" -gt 5 ]; then
|
||||||
|
OLD_BACKUPS=$(ls -1t $BACKUP_DIR | tail -n +6)
|
||||||
|
for backup in $OLD_BACKUPS; do
|
||||||
|
rm -rf "$BACKUP_DIR/$backup"
|
||||||
|
done
|
||||||
|
echo "🧹 Old backups cleaned"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "⚠️ No existing deployment found, skipping backup"
|
echo "⚠️ No existing deployment found"
|
||||||
fi
|
fi
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
@@ -152,38 +166,41 @@ jobs:
|
|||||||
ARCHIVE_NAME=$(ls -1 /tmp/quant-deploy/quant-engine-release-*.tar.gz | head -1)
|
ARCHIVE_NAME=$(ls -1 /tmp/quant-deploy/quant-engine-release-*.tar.gz | head -1)
|
||||||
|
|
||||||
# Create deployment directory
|
# Create deployment directory
|
||||||
sudo mkdir -p "$DEPLOY_PATH/publish"
|
mkdir -p "$DEPLOY_PATH"
|
||||||
sudo chmod 777 "$DEPLOY_PATH/publish"
|
|
||||||
|
|
||||||
# Extract new package
|
# Extract new package
|
||||||
tar -xzf "$ARCHIVE_NAME" -C "$DEPLOY_PATH/publish"
|
tar -xzf "$ARCHIVE_NAME" -C "$DEPLOY_PATH"
|
||||||
echo "✅ Package extracted"
|
echo "✅ Package extracted to $DEPLOY_PATH"
|
||||||
|
|
||||||
# Set permissions
|
# Verify key files
|
||||||
sudo chown -R www-data:www-data "$DEPLOY_PATH/publish"
|
if [ -f "$DEPLOY_PATH/QuantEngine.Web.dll" ]; then
|
||||||
sudo chmod -R 755 "$DEPLOY_PATH/publish"
|
echo "✅ QuantEngine.Web.dll verified"
|
||||||
echo "✅ Permissions set"
|
else
|
||||||
|
echo "❌ QuantEngine.Web.dll not found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Cleanup temp
|
# Cleanup temp
|
||||||
rm -rf /tmp/quant-deploy
|
rm -rf /tmp/quant-deploy
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
- name: Restart Services
|
- name: Start Service
|
||||||
run: |
|
run: |
|
||||||
echo "🔄 Restarting services..."
|
echo "🔄 Starting quantengine service..."
|
||||||
ssh -i ~/.ssh/id_ed25519 ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'EOF'
|
ssh -i ~/.ssh/id_ed25519 ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} << 'EOF'
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Restart nginx
|
# Start service
|
||||||
sudo systemctl restart nginx
|
sudo systemctl start ${{ env.SERVICE_NAME }}
|
||||||
sleep 2
|
sleep 3
|
||||||
|
|
||||||
# Check status
|
# Check status
|
||||||
if sudo systemctl is-active --quiet nginx; then
|
if sudo systemctl is-active --quiet ${{ env.SERVICE_NAME }}; then
|
||||||
echo "✅ nginx restarted successfully"
|
echo "✅ ${{ env.SERVICE_NAME }} started successfully"
|
||||||
|
sudo systemctl status ${{ env.SERVICE_NAME }} | head -5
|
||||||
else
|
else
|
||||||
echo "❌ nginx failed to start"
|
echo "❌ ${{ env.SERVICE_NAME }} failed to start"
|
||||||
sudo systemctl status nginx
|
sudo systemctl status ${{ env.SERVICE_NAME }}
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
EOF
|
EOF
|
||||||
@@ -192,13 +209,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "🧪 Running health checks..."
|
echo "🧪 Running health checks..."
|
||||||
|
|
||||||
# Wait for service to be ready
|
# Wait for service to be ready (localhost:5000 through Nginx)
|
||||||
for i in {1..30}; do
|
for i in {1..30}; do
|
||||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
http://${{ env.DEPLOY_HOST }}/quant/ || echo "000")
|
"http://127.0.0.1:5000/" || echo "000")
|
||||||
|
|
||||||
if [ "$HTTP_CODE" = "200" ]; then
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
echo "✅ Health check passed (HTTP $HTTP_CODE)"
|
echo "✅ Health check passed (HTTP $HTTP_CODE at localhost:5000)"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -208,6 +225,9 @@ jobs:
|
|||||||
|
|
||||||
if [ "$HTTP_CODE" != "200" ]; then
|
if [ "$HTTP_CODE" != "200" ]; then
|
||||||
echo "❌ Health check failed after 60 seconds"
|
echo "❌ Health check failed after 60 seconds"
|
||||||
|
echo "Service logs:"
|
||||||
|
ssh -i ~/.ssh/id_ed25519 ${{ env.DEPLOY_USER }}@${{ env.DEPLOY_HOST }} \
|
||||||
|
"sudo journalctl -u ${{ env.SERVICE_NAME }} -n 20" || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -215,8 +235,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "📊 Verifying deployment..."
|
echo "📊 Verifying deployment..."
|
||||||
|
|
||||||
# Check MudBlazor is loaded
|
# Check MudBlazor is loaded (via public IP)
|
||||||
MUDBLAZOR_CHECK=$(curl -s http://${{ env.DEPLOY_HOST }}/quant/ | grep -c "MudBlazor" || echo "0")
|
PUBLIC_IP="178.104.200.7"
|
||||||
|
MUDBLAZOR_CHECK=$(curl -s "http://$PUBLIC_IP/quant/" | grep -c "MudBlazor" || echo "0")
|
||||||
|
|
||||||
if [ "$MUDBLAZOR_CHECK" -gt "0" ]; then
|
if [ "$MUDBLAZOR_CHECK" -gt "0" ]; then
|
||||||
echo "✅ MudBlazor UI loaded successfully"
|
echo "✅ MudBlazor UI loaded successfully"
|
||||||
@@ -225,7 +246,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Get page title
|
# Get page title
|
||||||
PAGE_TITLE=$(curl -s http://${{ env.DEPLOY_HOST }}/quant/ | grep -o "<title>.*</title>" | head -1)
|
PAGE_TITLE=$(curl -s "http://$PUBLIC_IP/quant/" | grep -o "<title>.*</title>" | head -1)
|
||||||
echo "📄 Page title: $PAGE_TITLE"
|
echo "📄 Page title: $PAGE_TITLE"
|
||||||
|
|
||||||
- name: Generate Deployment Report
|
- name: Generate Deployment Report
|
||||||
@@ -233,7 +254,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cat > deployment-report.txt << EOF
|
cat > deployment-report.txt << EOF
|
||||||
═══════════════════════════════════════════════════════
|
═══════════════════════════════════════════════════════
|
||||||
Quant Engine Deployment Report
|
Quant Engine v9 Deployment Report
|
||||||
═══════════════════════════════════════════════════════
|
═══════════════════════════════════════════════════════
|
||||||
|
|
||||||
Deployment Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
Deployment Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||||
@@ -241,27 +262,42 @@ jobs:
|
|||||||
Commit: ${{ github.sha }}
|
Commit: ${{ github.sha }}
|
||||||
Branch: ${{ github.ref }}
|
Branch: ${{ github.ref }}
|
||||||
|
|
||||||
Target Server: ${{ env.DEPLOY_HOST }}
|
🎯 Target Environment
|
||||||
|
Server: hz-prod-01
|
||||||
|
Internal IP: ${{ env.DEPLOY_HOST }}
|
||||||
|
Public IP: 178.104.200.7
|
||||||
Deploy Path: ${{ env.DEPLOY_PATH }}
|
Deploy Path: ${{ env.DEPLOY_PATH }}
|
||||||
|
Service: ${{ env.SERVICE_NAME }}
|
||||||
|
|
||||||
Status: COMPLETED
|
📊 Deployment Status: COMPLETED
|
||||||
|
|
||||||
✅ Release Build: Successful
|
✅ Release Build: Successful
|
||||||
✅ Package Created: 24MB
|
✅ Package Created: 24MB+
|
||||||
✅ Backup Created: /var/www/quant_backup/
|
✅ Backup Created: /home/kjh2064/quantengine_backup/
|
||||||
✅ Package Deployed: ${{ env.DEPLOY_PATH }}/publish
|
✅ Package Deployed: ${{ env.DEPLOY_PATH }}
|
||||||
✅ Services Restarted: nginx
|
✅ Service Started: ${{ env.SERVICE_NAME }}
|
||||||
✅ Health Check: PASS
|
✅ Health Check: PASS (localhost:5000)
|
||||||
✅ MudBlazor UI: Verified
|
✅ MudBlazor UI: Verified via public IP
|
||||||
|
|
||||||
Access: http://${{ env.DEPLOY_HOST }}/quant/
|
🌐 Access Information
|
||||||
|
Public URL: http://178.104.200.7/quant/
|
||||||
|
Service Port: 127.0.0.1:5000
|
||||||
|
Nginx Config: /etc/nginx/sites-available/gitea-ip.conf
|
||||||
|
|
||||||
Logs:
|
📝 Service Architecture
|
||||||
- Deployment: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
- Nginx (reverse proxy) listens on port 80/443
|
||||||
- nginx: ssh kjh2064@${{ env.DEPLOY_HOST }} 'sudo tail -50 /var/log/nginx/error.log'
|
- /quant/ path → localhost:5000 (quantengine service)
|
||||||
|
- quantengine runs as user kjh2064
|
||||||
|
- WorkingDirectory: /home/kjh2064/quantengine_active
|
||||||
|
|
||||||
Rollback Command (if needed):
|
🔍 Monitoring & Logs
|
||||||
ssh kjh2064@${{ env.DEPLOY_HOST }} 'LATEST=\$(ls -t /var/www/quant_backup | head -1); sudo cp -r /var/www/quant_backup/\$LATEST/* /var/www/quant/publish/ && sudo systemctl restart nginx'
|
- Service: sudo systemctl status ${{ env.SERVICE_NAME }}
|
||||||
|
- Logs: sudo journalctl -u ${{ env.SERVICE_NAME }} -f
|
||||||
|
- Nginx: sudo tail -f /var/log/nginx/error.log
|
||||||
|
- Deployment Log: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
|
|
||||||
|
🔄 Rollback Command (if needed):
|
||||||
|
ssh kjh2064@${{ env.DEPLOY_HOST }} 'LATEST=\$(ls -t /home/kjh2064/quantengine_backup | head -1); cp -r /home/kjh2064/quantengine_backup/\$LATEST/* /home/kjh2064/quantengine_active/ && sudo systemctl restart ${{ env.SERVICE_NAME }}'
|
||||||
|
|
||||||
═══════════════════════════════════════════════════════
|
═══════════════════════════════════════════════════════
|
||||||
EOF
|
EOF
|
||||||
@@ -293,12 +329,12 @@ jobs:
|
|||||||
-d "{
|
-d "{
|
||||||
\"attachments\": [{
|
\"attachments\": [{
|
||||||
\"color\": \"$COLOR\",
|
\"color\": \"$COLOR\",
|
||||||
\"title\": \"$EMOJI Quant Engine Deployment\",
|
\"title\": \"$EMOJI Quant Engine v9 Deployment\",
|
||||||
\"text\": \"Run #${{ github.run_number }}\",
|
\"text\": \"Run #${{ github.run_number }}\",
|
||||||
\"fields\": [
|
\"fields\": [
|
||||||
{\"title\": \"Status\", \"value\": \"$STATUS\", \"short\": true},
|
{\"title\": \"Status\", \"value\": \"$STATUS\", \"short\": true},
|
||||||
{\"title\": \"Server\", \"value\": \"${{ env.DEPLOY_HOST }}\", \"short\": true},
|
{\"title\": \"Service\", \"value\": \"${{ env.SERVICE_NAME }}\", \"short\": true},
|
||||||
{\"title\": \"URL\", \"value\": \"http://${{ env.DEPLOY_HOST }}/quant/\", \"short\": false}
|
{\"title\": \"URL\", \"value\": \"http://178.104.200.7/quant/\", \"short\": false}
|
||||||
],
|
],
|
||||||
\"ts\": $(date +%s)
|
\"ts\": $(date +%s)
|
||||||
}]
|
}]
|
||||||
|
|||||||
+246
-143
@@ -1,7 +1,7 @@
|
|||||||
# 🔐 SSH 배포 가이드
|
# 🔐 SSH 배포 가이드 (v9)
|
||||||
|
|
||||||
**목표**: SSH로 원격 서버에 직접 접속하여 환경을 파악한 후 배포
|
**목표**: SSH로 원격 서버에 직접 접속하여 배포
|
||||||
**대상**: 178.104.200.7 (공인 IP) / 192.168.123.100 (내부 IP)
|
**환경**: hz-prod-01 (공인 IP 178.104.200.7 / 내부 IP 172.17.0.1)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -17,61 +17,84 @@ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
|
|||||||
#### 1.2 공개 키를 원격 서버에 등록
|
#### 1.2 공개 키를 원격 서버에 등록
|
||||||
```bash
|
```bash
|
||||||
ssh-copy-id -i ~/.ssh/id_ed25519.pub kjh2064@178.104.200.7
|
ssh-copy-id -i ~/.ssh/id_ed25519.pub kjh2064@178.104.200.7
|
||||||
# 또는 내부 IP
|
|
||||||
ssh-copy-id -i ~/.ssh/id_ed25519.pub kjh2064@192.168.123.100
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 1.3 SSH 연결 테스트
|
#### 1.3 SSH 연결 테스트
|
||||||
```bash
|
```bash
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100 "echo '✅ 연결 성공'"
|
ssh -i ~/.ssh/id_ed25519 kjh2064@178.104.200.7 "echo '✅ 연결 성공'"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔍 Step 1: 환경 파악
|
## 🔍 Step 1: 환경 파악
|
||||||
|
|
||||||
### 시스템 정보 확인
|
### 원격 서버 정보 확인
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# SSH 접속
|
ssh kjh2064@178.104.200.7 << 'EOF'
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100
|
|
||||||
|
|
||||||
# 원격 서버에서 실행:
|
|
||||||
# ─────────────────────────────────────────────
|
|
||||||
|
|
||||||
# 1. 시스템 정보
|
# 1. 시스템 정보
|
||||||
|
echo "=== 시스템 정보 ==="
|
||||||
|
hostname
|
||||||
uname -a
|
uname -a
|
||||||
lsb_release -a
|
lsb_release -a
|
||||||
|
|
||||||
# 2. 디스크 상태
|
# 2. 배포 경로
|
||||||
|
echo -e "\n=== 배포 경로 ==="
|
||||||
|
ls -la /home/kjh2064/quantengine_active/ || echo "아직 없음 (첫 배포)"
|
||||||
|
ls -la /home/kjh2064/quantengine_backup/
|
||||||
|
|
||||||
|
# 3. 서비스 상태
|
||||||
|
echo -e "\n=== quantengine 서비스 ==="
|
||||||
|
sudo systemctl status quantengine --no-pager
|
||||||
|
|
||||||
|
# 4. Nginx 설정
|
||||||
|
echo -e "\n=== Nginx /quant 설정 ==="
|
||||||
|
cat /etc/nginx/sites-available/gitea-ip.conf | grep -A 10 "location /quant"
|
||||||
|
|
||||||
|
# 5. 포트 상태
|
||||||
|
echo -e "\n=== 포트 상태 ==="
|
||||||
|
sudo netstat -tuln | grep -E ":80|:443|:5000"
|
||||||
|
|
||||||
|
# 6. 디스크 상태
|
||||||
|
echo -e "\n=== 디스크 ==="
|
||||||
df -h
|
df -h
|
||||||
|
|
||||||
# 3. 웹 서버 상태
|
EOF
|
||||||
sudo systemctl status nginx
|
|
||||||
|
|
||||||
# 4. 웹 서버 경로
|
|
||||||
ls -la /var/www/quant/
|
|
||||||
ls -la /var/www/quant/publish/
|
|
||||||
|
|
||||||
# 5. Nginx 설정 확인
|
|
||||||
sudo cat /etc/nginx/sites-available/default | grep -A 10 "location"
|
|
||||||
|
|
||||||
# 6. 포트 상태
|
|
||||||
sudo netstat -tuln | grep :80
|
|
||||||
|
|
||||||
# 7. 사용자 권한 확인
|
|
||||||
id
|
|
||||||
sudo -l
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 예상 환경
|
### 예상 환경
|
||||||
|
|
||||||
```
|
```
|
||||||
✓ Linux (Ubuntu 20.04 또는 그 이상)
|
✓ Linux (Ubuntu 20.04+)
|
||||||
✓ nginx (1.18 이상)
|
✓ nginx 1.28.3 (reverse proxy)
|
||||||
✓ /var/www/quant/ 디렉토리 존재 또는 생성 가능
|
✓ /home/kjh2064/quantengine_active/ 배포 경로
|
||||||
✓ www-data 또는 유사 웹 서버 사용자
|
✓ quantengine systemd 서비스
|
||||||
✓ sudo 권한 (webmaster 그룹)
|
✓ 포트 5000에서 .NET 앱 실행
|
||||||
|
✓ sudo 권한 (quantengine 서비스 제어)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 배포 아키텍처
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────┐
|
||||||
|
│ 사용자 (외부 인터넷) │
|
||||||
|
│ http://178.104.200.7/quant/ │
|
||||||
|
└─────────────────────┬────────────────────────────────┘
|
||||||
|
│ 공인 IP (포트 80)
|
||||||
|
┌─────────────────────▼────────────────────────────────┐
|
||||||
|
│ Nginx (reverse proxy) │
|
||||||
|
│ /etc/nginx/sites-available/gitea-ip.conf │
|
||||||
|
│ location /quant/ → proxy_pass http://127.0.0.1:5000/
|
||||||
|
└─────────────────────┬────────────────────────────────┘
|
||||||
|
│ localhost:5000
|
||||||
|
┌─────────────────────▼────────────────────────────────┐
|
||||||
|
│ quantengine (systemd 서비스) │
|
||||||
|
│ /home/kjh2064/quantengine_active/ │
|
||||||
|
│ QuantEngine.Web.dll (실행 중) │
|
||||||
|
└────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -79,7 +102,7 @@ sudo -l
|
|||||||
## 📦 Step 2: Release 빌드
|
## 📦 Step 2: Release 빌드
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 로컬에서 실행
|
# 로컬 개발 머신에서 실행
|
||||||
cd /c/Temp/data_feed
|
cd /c/Temp/data_feed
|
||||||
|
|
||||||
# Release 빌드
|
# Release 빌드
|
||||||
@@ -88,20 +111,21 @@ dotnet publish -c Release \
|
|||||||
|
|
||||||
# 결과 확인
|
# 결과 확인
|
||||||
ls -lh src/dotnet/QuantEngine.Web/publish/
|
ls -lh src/dotnet/QuantEngine.Web/publish/
|
||||||
|
du -sh src/dotnet/QuantEngine.Web/publish/
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Step 3: 배포 스크립트 실행
|
## 🚀 Step 3: 배포 방법
|
||||||
|
|
||||||
### 방법 1: 자동 배포 스크립트 (권장)
|
### 방법 1: 자동 배포 스크립트 (권장)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 스크립트에 실행 권한 부여
|
# 스크립트에 실행 권한 부여
|
||||||
chmod +x deploy-manual.sh
|
chmod +x deploy-production.sh
|
||||||
|
|
||||||
# 배포 실행
|
# 배포 실행
|
||||||
./deploy-manual.sh 192.168.123.100
|
./deploy-production.sh
|
||||||
# 또는
|
# 또는
|
||||||
./deploy-manual.sh 178.104.200.7
|
./deploy-manual.sh 178.104.200.7
|
||||||
```
|
```
|
||||||
@@ -109,115 +133,180 @@ chmod +x deploy-manual.sh
|
|||||||
**스크립트가 자동으로:**
|
**스크립트가 자동으로:**
|
||||||
- ✓ SSH 연결 확인
|
- ✓ SSH 연결 확인
|
||||||
- ✓ 원격 환경 파악
|
- ✓ 원격 환경 파악
|
||||||
|
- ✓ 서비스 중지
|
||||||
- ✓ 백업 생성
|
- ✓ 백업 생성
|
||||||
- ✓ 파일 전송 (rsync)
|
- ✓ 파일 전송 (rsync)
|
||||||
- ✓ 권한 설정
|
- ✓ 파일 검증
|
||||||
- ✓ nginx 재시작
|
- ✓ 서비스 시작
|
||||||
- ✓ 헬스 체크
|
- ✓ 헬스 체크
|
||||||
|
|
||||||
### 방법 2: 수동 배포 (단계별)
|
### 방법 2: 수동 배포 (단계별)
|
||||||
|
|
||||||
|
#### Step 2-1: SSH 접속
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. SSH 접속
|
ssh -i ~/.ssh/id_ed25519 kjh2064@178.104.200.7
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100
|
```
|
||||||
|
|
||||||
# 원격 서버에서:
|
#### Step 2-2: 서비스 중지 및 백업
|
||||||
# ─────────────────────────────────────────────
|
|
||||||
|
|
||||||
# 2. 백업 생성
|
```bash
|
||||||
sudo mkdir -p /var/www/quant_backup
|
# 원격 서버에서 실행:
|
||||||
sudo cp -r /var/www/quant/publish \
|
set -e
|
||||||
/var/www/quant_backup/quant_$(date +%Y%m%d_%H%M%S)
|
|
||||||
echo "✓ 백업 생성 완료"
|
|
||||||
|
|
||||||
# 3. 배포 디렉토리 준비
|
SERVICE_NAME="quantengine"
|
||||||
sudo mkdir -p /var/www/quant/publish
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
sudo chmod 777 /var/www/quant/publish
|
BACKUP_PATH="/home/kjh2064/quantengine_backup"
|
||||||
|
BACKUP_NAME="quantengine_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
# 4. 권한 설정
|
# 서비스 중지
|
||||||
sudo chown -R www-data:www-data /var/www/quant/publish
|
sudo systemctl stop $SERVICE_NAME
|
||||||
sudo chmod -R 755 /var/www/quant/publish
|
sleep 2
|
||||||
|
echo "✓ 서비스 중지"
|
||||||
|
|
||||||
# 5. SSH 종료
|
# 백업 생성
|
||||||
|
mkdir -p $BACKUP_PATH
|
||||||
|
if [ -d $DEPLOY_PATH ]; then
|
||||||
|
cp -r $DEPLOY_PATH "$BACKUP_PATH/$BACKUP_NAME"
|
||||||
|
echo "✓ 백업: $BACKUP_PATH/$BACKUP_NAME"
|
||||||
|
else
|
||||||
|
mkdir -p $DEPLOY_PATH
|
||||||
|
echo "⚠️ 첫 배포"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2-3: SSH 종료
|
||||||
|
|
||||||
|
```bash
|
||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Step 2-4: 파일 전송 (로컬에서)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 로컬에서: 파일 전송
|
|
||||||
rsync -avz --delete \
|
rsync -avz --delete \
|
||||||
-e "ssh -i ~/.ssh/id_ed25519" \
|
-e "ssh -i ~/.ssh/id_ed25519" \
|
||||||
src/dotnet/QuantEngine.Web/publish/ \
|
src/dotnet/QuantEngine.Web/publish/ \
|
||||||
kjh2064@192.168.123.100:/var/www/quant/publish/
|
kjh2064@178.104.200.7:/home/kjh2064/quantengine_active/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Step 2-5: 서비스 시작
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 다시 SSH 접속
|
ssh -i ~/.ssh/id_ed25519 kjh2064@178.104.200.7 << 'EOF'
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100
|
|
||||||
|
|
||||||
# 원격 서버에서:
|
SERVICE_NAME="quantengine"
|
||||||
# ─────────────────────────────────────────────
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
|
||||||
# 6. nginx 재시작
|
# 파일 검증
|
||||||
sudo systemctl restart nginx
|
if [ -f $DEPLOY_PATH/QuantEngine.Web.dll ]; then
|
||||||
|
echo "✓ 파일 확인됨"
|
||||||
|
else
|
||||||
|
echo "❌ 파일 없음"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# 7. 상태 확인
|
# 서비스 시작
|
||||||
sudo systemctl status nginx
|
sudo systemctl start $SERVICE_NAME
|
||||||
|
sleep 3
|
||||||
|
|
||||||
# 종료
|
# 상태 확인
|
||||||
exit
|
if sudo systemctl is-active --quiet $SERVICE_NAME; then
|
||||||
|
echo "✓ 서비스 시작됨"
|
||||||
|
else
|
||||||
|
echo "❌ 서비스 시작 실패"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✅ Step 4: 배포 검증
|
## ✅ Step 4: 배포 검증
|
||||||
|
|
||||||
```bash
|
### HTTP 상태 확인
|
||||||
# 1. HTTP 상태 확인
|
|
||||||
curl -I http://178.104.200.7/quant/
|
|
||||||
# 또는
|
|
||||||
curl -I http://192.168.123.100/quant/
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 공인 IP로 접근 (외부 사용자 기준)
|
||||||
|
curl -I http://178.104.200.7/quant/
|
||||||
# 기대: HTTP/1.1 200 OK
|
# 기대: HTTP/1.1 200 OK
|
||||||
|
|
||||||
# 2. MudBlazor 로드 확인
|
# localhost:5000 직접 확인 (서버에서)
|
||||||
|
ssh kjh2064@178.104.200.7 'curl -I http://127.0.0.1:5000/'
|
||||||
|
# 기대: HTTP/1.1 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
### MudBlazor 리소스 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
curl -s http://178.104.200.7/quant/ | grep -c "MudBlazor"
|
curl -s http://178.104.200.7/quant/ | grep -c "MudBlazor"
|
||||||
# 기대: > 0
|
# 기대: > 0
|
||||||
|
```
|
||||||
|
|
||||||
# 3. 페이지 제목 확인
|
### 페이지 제목 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
curl -s http://178.104.200.7/quant/ | grep -o "<title>.*</title>"
|
curl -s http://178.104.200.7/quant/ | grep -o "<title>.*</title>"
|
||||||
# 기대: <title>Quant Engine - Dashboard</title>
|
# 기대: <title>Quant Engine - Dashboard</title>
|
||||||
|
```
|
||||||
|
|
||||||
# 4. nginx 로그 확인
|
### 로그 확인
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100 \
|
|
||||||
'sudo tail -20 /var/log/nginx/error.log'
|
|
||||||
|
|
||||||
# 5. 브라우저 테스트
|
```bash
|
||||||
# http://178.104.200.7/quant/ 접속
|
# 서비스 로그
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo journalctl -u quantengine -n 50'
|
||||||
|
|
||||||
|
# Nginx 에러 로그
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo tail -f /var/log/nginx/error.log'
|
||||||
|
|
||||||
|
# 실시간 모니터링
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo journalctl -u quantengine -f'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 브라우저 테스트
|
||||||
|
|
||||||
|
```
|
||||||
|
http://178.104.200.7/quant/
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔄 롤백 (배포 실패 시)
|
## 🔄 롤백 (배포 실패 시)
|
||||||
|
|
||||||
|
### 자동 롤백 스크립트
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh -i ~/.ssh/id_ed25519 kjh2064@192.168.123.100 << 'EOF'
|
ssh kjh2064@178.104.200.7 << 'EOF'
|
||||||
# 최신 백업 확인
|
set -e
|
||||||
ls -lt /var/www/quant_backup/
|
|
||||||
|
|
||||||
# 최신 백업으로 복원
|
SERVICE_NAME="quantengine"
|
||||||
LATEST=$(ls -t /var/www/quant_backup | head -1)
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
echo "복원 중: $LATEST"
|
BACKUP_PATH="/home/kjh2064/quantengine_backup"
|
||||||
|
|
||||||
sudo cp -r /var/www/quant_backup/$LATEST/* /var/www/quant/publish/
|
echo "🔄 최신 백업 찾는 중..."
|
||||||
|
LATEST=$(ls -t $BACKUP_PATH | head -1)
|
||||||
|
echo "롤백 대상: $LATEST"
|
||||||
|
|
||||||
# 권한 재설정
|
# 서비스 중지
|
||||||
sudo chown -R www-data:www-data /var/www/quant/publish
|
sudo systemctl stop $SERVICE_NAME
|
||||||
sudo chmod -R 755 /var/www/quant/publish
|
sleep 2
|
||||||
|
|
||||||
# nginx 재시작
|
# 백업 복원
|
||||||
sudo systemctl restart nginx
|
cp -r "$BACKUP_PATH/$LATEST"/* "$DEPLOY_PATH/"
|
||||||
|
echo "✓ 백업 복원 완료"
|
||||||
|
|
||||||
echo "✅ 롤백 완료"
|
# 서비스 시작
|
||||||
|
sudo systemctl start $SERVICE_NAME
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# 확인
|
||||||
|
if sudo systemctl is-active --quiet $SERVICE_NAME; then
|
||||||
|
echo "✅ 롤백 완료"
|
||||||
|
else
|
||||||
|
echo "❌ 롤백 실패"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
EOF
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -229,26 +318,28 @@ EOF
|
|||||||
```
|
```
|
||||||
[ ] SSH 키 설정 완료 (~/.ssh/id_ed25519)
|
[ ] SSH 키 설정 완료 (~/.ssh/id_ed25519)
|
||||||
[ ] SSH 연결 테스트 성공
|
[ ] SSH 연결 테스트 성공
|
||||||
[ ] Release 빌드 완료 (24MB)
|
[ ] Release 빌드 완료 (24MB+)
|
||||||
[ ] 배포 스크립트 준비
|
[ ] 배포 스크립트 준비
|
||||||
```
|
```
|
||||||
|
|
||||||
### 배포 중
|
### 배포 중
|
||||||
```
|
```
|
||||||
[ ] 환경 파악 완료
|
[ ] 환경 파악 완료
|
||||||
[ ] 백업 생성 완료
|
[ ] 서비스 중지 확인
|
||||||
[ ] 파일 전송 완료
|
[ ] 백업 생성 확인
|
||||||
[ ] 권한 설정 완료
|
[ ] 파일 전송 완료 (rsync)
|
||||||
[ ] nginx 재시작 완료
|
[ ] 파일 검증 완료
|
||||||
|
[ ] 서비스 시작 완료
|
||||||
```
|
```
|
||||||
|
|
||||||
### 배포 후
|
### 배포 후
|
||||||
```
|
```
|
||||||
[ ] HTTP 200 OK 확인
|
[ ] HTTP 200 OK 확인
|
||||||
|
[ ] localhost:5000 응답 확인
|
||||||
[ ] MudBlazor 리소스 로드됨
|
[ ] MudBlazor 리소스 로드됨
|
||||||
[ ] 페이지 제목 확인
|
[ ] Nginx 에러 로그 확인
|
||||||
[ ] nginx 로그 에러 없음
|
|
||||||
[ ] 브라우저 접속 테스트
|
[ ] 브라우저 접속 테스트
|
||||||
|
[ ] 페이지 로드 시간 < 2s
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -257,46 +348,47 @@ EOF
|
|||||||
|
|
||||||
### SSH 연결 타임아웃
|
### SSH 연결 타임아웃
|
||||||
```bash
|
```bash
|
||||||
# 원인: IP 주소 오류 또는 방화벽
|
# 확인:
|
||||||
|
1. IP 주소: 178.104.200.7 또는 172.17.0.1?
|
||||||
|
2. SSH 포트: 22 (기본값)
|
||||||
|
3. 방화벽 규칙
|
||||||
|
4. 공개 키 등록 확인
|
||||||
|
|
||||||
# 해결:
|
# 해결:
|
||||||
1. IP 확인: 178.104.200.7 또는 192.168.123.100?
|
ssh-copy-id -i ~/.ssh/id_ed25519.pub kjh2064@178.104.200.7
|
||||||
2. SSH 포트 확인: 22 (기본값)
|
|
||||||
3. 방화벽 규칙 확인
|
|
||||||
4. 공개 키 등록 재확인
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 권한 오류 (sudo 불가)
|
### 서비스 시작 실패
|
||||||
```bash
|
|
||||||
# 원인: sudo 권한 없음
|
|
||||||
|
|
||||||
# 확인:
|
|
||||||
sudo -l
|
|
||||||
|
|
||||||
# 해결: 관리자에게 webmaster 그룹 추가 요청
|
|
||||||
```
|
|
||||||
|
|
||||||
### nginx 재시작 실패
|
|
||||||
```bash
|
```bash
|
||||||
# 로그 확인
|
# 로그 확인
|
||||||
sudo systemctl status nginx
|
ssh kjh2064@178.104.200.7 'sudo journalctl -u quantengine -n 50'
|
||||||
sudo journalctl -u nginx -n 20
|
|
||||||
|
|
||||||
# 설정 테스트
|
# 설정 확인
|
||||||
sudo nginx -t
|
ssh kjh2064@178.104.200.7 'cat /etc/systemd/system/quantengine.service'
|
||||||
|
|
||||||
# 포트 충돌 확인
|
# 파일 검증
|
||||||
sudo netstat -tuln | grep :80
|
ssh kjh2064@178.104.200.7 'ls -la /home/kjh2064/quantengine_active/'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nginx 프록시 오류
|
||||||
|
```bash
|
||||||
|
# Nginx 설정 테스트
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo nginx -t'
|
||||||
|
|
||||||
|
# 설정 파일 확인
|
||||||
|
ssh kjh2064@178.104.200.7 'cat /etc/nginx/sites-available/gitea-ip.conf'
|
||||||
|
|
||||||
|
# 포트 확인
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo netstat -tuln | grep 5000'
|
||||||
```
|
```
|
||||||
|
|
||||||
### 파일 권한 문제
|
### 파일 권한 문제
|
||||||
```bash
|
```bash
|
||||||
# 현재 권한 확인
|
# 현재 권한 확인
|
||||||
ls -la /var/www/quant/publish/
|
ssh kjh2064@178.104.200.7 'ls -la /home/kjh2064/quantengine_active/'
|
||||||
|
|
||||||
# 권한 수정
|
# 권한 설정 (필요시)
|
||||||
sudo chown -R www-data:www-data /var/www/quant/publish
|
ssh kjh2064@178.104.200.7 'chmod +x /home/kjh2064/quantengine_active/QuantEngine.Web.dll'
|
||||||
sudo chmod -R 755 /var/www/quant/publish
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -305,18 +397,21 @@ sudo chmod -R 755 /var/www/quant/publish
|
|||||||
|
|
||||||
```
|
```
|
||||||
배포 스크립트:
|
배포 스크립트:
|
||||||
├── deploy.sh (자동 배포, bash)
|
├── deploy-production.sh (권장)
|
||||||
└── deploy-manual.sh (대화형 배포, 이 파일)
|
└── deploy-manual.sh (대화형)
|
||||||
|
|
||||||
배포 가이드:
|
배포 문서:
|
||||||
├── DEPLOYMENT_GUIDE.md (전체 가이드)
|
├── DEPLOYMENT_GUIDE.md (전체)
|
||||||
├── DEPLOYMENT_STEPS.md (단계별 지침)
|
├── DEPLOYMENT_STEPS.md (단계별)
|
||||||
├── DEPLOYMENT_CHECKLIST.md (운영 체크리스트)
|
├── DEPLOYMENT_SSH_GUIDE.md (이 파일)
|
||||||
└── DEPLOYMENT_SSH_GUIDE.md (이 파일)
|
└── DEPLOYMENT_CHECKLIST.md (체크리스트)
|
||||||
|
|
||||||
CI/CD:
|
CI/CD:
|
||||||
├── .gitea/workflows/deploy-prod.yml (자동화)
|
├── .gitea/workflows/deploy-prod.yml
|
||||||
└── CI_CD_PIPELINE.md (CI/CD 문서)
|
└── CI_CD_PIPELINE.md
|
||||||
|
|
||||||
|
환경:
|
||||||
|
└── ENVIRONMENT_DIAGNOSIS.md
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -325,23 +420,31 @@ CI/CD:
|
|||||||
|
|
||||||
### 한 번에 배포
|
### 한 번에 배포
|
||||||
```bash
|
```bash
|
||||||
chmod +x deploy-manual.sh && ./deploy-manual.sh 192.168.123.100
|
chmod +x deploy-production.sh && ./deploy-production.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### 내부 IP 사용
|
### 내부 IP 사용 (선택)
|
||||||
```bash
|
```bash
|
||||||
# Gitea에서 배포할 때 (자동 CI/CD)
|
./deploy-manual.sh 172.17.0.1
|
||||||
DEPLOY_HOST=192.168.123.100
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 외부 접속
|
### 공인 IP 사용 (권장)
|
||||||
```bash
|
```bash
|
||||||
# 사용자가 접속할 때
|
./deploy-manual.sh 178.104.200.7
|
||||||
http://178.104.200.7/quant/
|
```
|
||||||
|
|
||||||
|
### 상태 확인
|
||||||
|
```bash
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo systemctl status quantengine'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 로그 모니터링
|
||||||
|
```bash
|
||||||
|
ssh kjh2064@178.104.200.7 'sudo journalctl -u quantengine -f'
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**배포 준비 완료!** 🚀
|
**배포 준비 완료!** 🚀
|
||||||
|
|
||||||
deploy-manual.sh 스크립트를 실행하거나, 위의 수동 단계를 따라 배포하세요.
|
`deploy-production.sh` 또는 `deploy-manual.sh` 스크립트를 실행하거나, 위의 수동 단계를 따라 배포하세요.
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
# 🔍 원격 서버 환경 진단
|
||||||
|
|
||||||
|
**목표**: SSH로 접속하여 원격 서버의 정확한 구조와 설정을 파악한 후 배포 스크립트를 맞춤형으로 작성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 진단 절차
|
||||||
|
|
||||||
|
### Step 1: SSH 접속
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 원격 서버에 SSH 접속
|
||||||
|
ssh kjh2064@178.104.200.7
|
||||||
|
|
||||||
|
# 또는 이미 내부 IP를 알고 있다면
|
||||||
|
ssh kjh2064@172.x.x.x
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: 진단 스크립트 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 로컬에서 스크립트를 원격으로 실행
|
||||||
|
ssh kjh2064@178.104.200.7 'bash -s' < diagnose-environment.sh
|
||||||
|
|
||||||
|
# 또는 원격에 접속한 후 실행
|
||||||
|
bash < <(curl -s https://raw.githubusercontent.com/.../diagnose-environment.sh)
|
||||||
|
|
||||||
|
# 또는 직접 실행
|
||||||
|
chmod +x diagnose-environment.sh
|
||||||
|
./diagnose-environment.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: 출력 결과 확인
|
||||||
|
|
||||||
|
진단 스크립트가 다음 정보를 제공합니다:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 네트워크 정보
|
||||||
|
- 공인 IP: 178.104.200.7 (확인됨)
|
||||||
|
- 내부 IP: 172.x.x.x (여기서 확인!)
|
||||||
|
- 호스트명
|
||||||
|
- 네트워크 인터페이스
|
||||||
|
|
||||||
|
2. 웹 서버 디렉토리 구조
|
||||||
|
- /var/www 여부
|
||||||
|
- /var/www/quant 여부
|
||||||
|
- /var/www/quant/publish 여부
|
||||||
|
- 실제 경로 (다를 수 있음)
|
||||||
|
|
||||||
|
3. Nginx 설정
|
||||||
|
- Nginx 설치 확인
|
||||||
|
- 설정 파일 위치
|
||||||
|
- /quant 관련 설정
|
||||||
|
|
||||||
|
4. 파일 권한 및 소유자
|
||||||
|
- 웹 서버 사용자 (www-data? nobody? 다른 사용자?)
|
||||||
|
- 디렉토리 권한
|
||||||
|
|
||||||
|
5. 포트 상태
|
||||||
|
- 80, 443 포트 상태
|
||||||
|
- 바인딩된 주소
|
||||||
|
|
||||||
|
6. 시스템 정보
|
||||||
|
- OS 종류 및 버전
|
||||||
|
- 디스크 공간
|
||||||
|
|
||||||
|
7. Sudo 권한
|
||||||
|
- 현재 사용자의 sudo 권한
|
||||||
|
- systemctl 사용 가능 여부
|
||||||
|
|
||||||
|
8. Git/Gitea 정보
|
||||||
|
- Gitea 설치 위치
|
||||||
|
- Gitea 데이터 저장소
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 진단 결과 분석
|
||||||
|
|
||||||
|
### 예상되는 출력 값들
|
||||||
|
|
||||||
|
| 항목 | 예상값 | 실제값 |
|
||||||
|
|------|--------|--------|
|
||||||
|
| **공인 IP** | 178.104.200.7 | ✓ |
|
||||||
|
| **내부 IP** | 172.x.x.x | ? |
|
||||||
|
| **웹 서버 경로** | /var/www/quant | ? |
|
||||||
|
| **웹 서버 사용자** | www-data | ? |
|
||||||
|
| **Nginx 설정** | /etc/nginx/sites-available/default | ? |
|
||||||
|
| **OS** | Ubuntu 20.04+ | ? |
|
||||||
|
|
||||||
|
### 확인할 핵심 정보
|
||||||
|
|
||||||
|
1. **내부 IP 주소** (172로 시작)
|
||||||
|
```
|
||||||
|
ip addr show | grep "inet"
|
||||||
|
→ inet 172.x.x.x/xx
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **웹 서버 경로**
|
||||||
|
```
|
||||||
|
ls -la /var/www/quant/
|
||||||
|
→ 실제 배포 경로 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **웹 서버 사용자**
|
||||||
|
```
|
||||||
|
ps aux | grep nginx | head -1
|
||||||
|
→ nginx 12345 0.0 0.1 ...
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Nginx 설정**
|
||||||
|
```
|
||||||
|
grep -r "quant" /etc/nginx/
|
||||||
|
→ location /quant 설정 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Sudo 권한**
|
||||||
|
```
|
||||||
|
sudo -l
|
||||||
|
→ systemctl restart nginx 권한 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 스크립트 결과 보고 양식
|
||||||
|
|
||||||
|
진단 스크립트 실행 후 다음 정보를 제공해주세요:
|
||||||
|
|
||||||
|
### 네트워크 정보
|
||||||
|
- 내부 IP: `172.x.x.x` 또는 다른 주소?
|
||||||
|
- 호스트명: ?
|
||||||
|
- 기본 게이트웨이: ?
|
||||||
|
|
||||||
|
### 디렉토리 구조
|
||||||
|
- /var/www 존재: O / X
|
||||||
|
- /var/www/quant 존재: O / X
|
||||||
|
- /var/www/quant/publish 존재: O / X
|
||||||
|
- 실제 웹 서빙 경로: ?
|
||||||
|
|
||||||
|
### Nginx 설정
|
||||||
|
- Nginx 버전: ?
|
||||||
|
- 설정 파일: /etc/nginx/sites-available/default 또는 다른 경로?
|
||||||
|
- /quant 설정 있음: O / X
|
||||||
|
- 루트 경로: ?
|
||||||
|
|
||||||
|
### 파일 권한
|
||||||
|
- 웹 서버 사용자: www-data 또는 ?
|
||||||
|
- /var/www/quant 소유자: ?
|
||||||
|
- /var/www/quant 권한: ?
|
||||||
|
|
||||||
|
### 시스템 정보
|
||||||
|
- OS: Ubuntu 20.04 또는 ?
|
||||||
|
- 디스크 여유: ?MB
|
||||||
|
|
||||||
|
### Sudo 권한
|
||||||
|
- sudo -l 출력:
|
||||||
|
```
|
||||||
|
복사해주세요
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 수집 후 수행할 작업
|
||||||
|
|
||||||
|
위 정보를 받은 후:
|
||||||
|
|
||||||
|
1. ✅ 정확한 내부 IP로 배포 스크립트 수정
|
||||||
|
2. ✅ 실제 경로로 deploy-manual.sh 수정
|
||||||
|
3. ✅ 웹 서버 사용자로 권한 설정 수정
|
||||||
|
4. ✅ Nginx 설정에 맞게 배포 절차 수정
|
||||||
|
5. ✅ 모든 문서 (DEPLOYMENT_SSH_GUIDE.md, CI_CD_PIPELINE.md 등) 업데이트
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 빠른 진단 (한 줄 명령어)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH 접속 후 한 번에 필요한 정보만 추출
|
||||||
|
echo "=== 내부 IP ===" && ip addr show | grep "inet " | grep -v 127.0.0.1 && \
|
||||||
|
echo "=== 웹 서버 경로 ===" && ls -la /var/www/ && \
|
||||||
|
echo "=== Nginx 사용자 ===" && ps aux | grep nginx | head -1 && \
|
||||||
|
echo "=== Sudo 권한 ===" && sudo -l | head -5
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚡ 진단 후 다음 단계
|
||||||
|
|
||||||
|
1. **진단 결과 공유**
|
||||||
|
- 위의 "스크립트 결과 보고 양식" 내용을 제공해주세요
|
||||||
|
|
||||||
|
2. **배포 스크립트 수정**
|
||||||
|
- 정확한 정보를 바탕으로 deploy-manual.sh 맞춤 수정
|
||||||
|
- 내부 IP, 경로, 사용자 등 정확히 반영
|
||||||
|
|
||||||
|
3. **배포 실행**
|
||||||
|
```bash
|
||||||
|
chmod +x deploy-manual.sh
|
||||||
|
./deploy-manual.sh [실제_내부_IP]
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **검증**
|
||||||
|
```bash
|
||||||
|
curl -I http://178.104.200.7/quant/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**진단을 완료한 후 결과를 공유해주세요!**
|
||||||
|
정확한 환경 정보를 바탕으로 완벽하게 맞춤형 배포 스크립트를 작성하겠습니다. 🎯
|
||||||
+79
-52
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Quant Engine Manual Deployment Script
|
# Quant Engine Manual Deployment Script (v9)
|
||||||
# 원격 서버에 직접 SSH 접속하여 환경 파악 후 배포
|
# 환경: hz-prod-01 (178.104.200.7/172.17.0.1)
|
||||||
|
# 배포 경로: /home/kjh2064/quantengine_active
|
||||||
|
# 서비스: quantengine (systemd)
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -8,18 +10,23 @@ set -e
|
|||||||
# 설정
|
# 설정
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
DEPLOY_HOST="${1:-192.168.123.100}"
|
DEPLOY_HOST="${1:-178.104.200.7}"
|
||||||
DEPLOY_USER="kjh2064"
|
DEPLOY_USER="kjh2064"
|
||||||
SSH_KEY="${HOME}/.ssh/id_ed25519"
|
SSH_KEY="${HOME}/.ssh/id_ed25519"
|
||||||
LOCAL_PUBLISH_DIR="$(pwd)/src/dotnet/QuantEngine.Web/publish"
|
LOCAL_PUBLISH_DIR="$(pwd)/src/dotnet/QuantEngine.Web/publish"
|
||||||
REMOTE_DEPLOY_PATH="/var/www/quant"
|
REMOTE_DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
REMOTE_BACKUP_PATH="/home/kjh2064/quantengine_backup"
|
||||||
|
SERVICE_NAME="quantengine"
|
||||||
|
|
||||||
echo "🚀 Quant Engine Manual Deployment"
|
echo "🚀 Quant Engine v9 Manual Deployment"
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
echo "Deploy Host: $DEPLOY_HOST"
|
echo "Deploy Host: $DEPLOY_HOST"
|
||||||
echo "Deploy User: $DEPLOY_USER"
|
echo "Deploy User: $DEPLOY_USER"
|
||||||
echo "Local Path: $LOCAL_PUBLISH_DIR"
|
echo "Local Path: $LOCAL_PUBLISH_DIR"
|
||||||
echo "Remote Path: $REMOTE_DEPLOY_PATH"
|
echo "Remote Path: $REMOTE_DEPLOY_PATH"
|
||||||
|
echo "Backup Path: $REMOTE_BACKUP_PATH"
|
||||||
|
echo "Service: $SERVICE_NAME"
|
||||||
|
echo "Public URL: http://178.104.200.7/quant/"
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -33,6 +40,7 @@ ssh -i "$SSH_KEY" "$DEPLOY_USER@$DEPLOY_HOST" << 'ENVCHECK'
|
|||||||
echo "✓ SSH 연결 성공"
|
echo "✓ SSH 연결 성공"
|
||||||
echo ""
|
echo ""
|
||||||
echo "시스템 정보:"
|
echo "시스템 정보:"
|
||||||
|
hostname
|
||||||
uname -a
|
uname -a
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -41,25 +49,25 @@ df -h | grep -E "^/dev|Filesystem|/$"
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "서비스 상태:"
|
echo "서비스 상태:"
|
||||||
sudo systemctl status nginx --no-pager 2>/dev/null | grep -E "Active:|Loaded:" || echo "⚠️ nginx 상태 확인 필요"
|
sudo systemctl status "$SERVICE_NAME" --no-pager 2>/dev/null | grep -E "Active:|Loaded:" || echo "⚠️ 서비스 상태 확인 필요"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "웹 서버 디렉토리:"
|
echo "배포 디렉토리:"
|
||||||
if [ -d /var/www/quant/publish ]; then
|
if [ -d "/home/kjh2064/quantengine_active" ]; then
|
||||||
echo "✓ /var/www/quant/publish 존재"
|
echo "✓ /home/kjh2064/quantengine_active 존재"
|
||||||
ls -lh /var/www/quant/publish | head -5
|
ls -lh /home/kjh2064/quantengine_active | head -5
|
||||||
echo "..."
|
echo "..."
|
||||||
else
|
else
|
||||||
echo "✗ /var/www/quant/publish 없음 (첫 배포)"
|
echo "✗ /home/kjh2064/quantengine_active 없음 (첫 배포)"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "웹 서버 권한:"
|
echo "Nginx 포트 확인:"
|
||||||
ls -ld /var/www/quant 2>/dev/null || echo "⚠️ /var/www/quant 없음"
|
sudo netstat -tuln 2>/dev/null | grep ":80\|:443" || echo "⚠️ 포트 확인 필요"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "Nginx 포트 확인:"
|
echo "Nginx 설정:"
|
||||||
sudo netstat -tuln 2>/dev/null | grep :80 || echo "⚠️ 포트 80 확인 필요"
|
cat /etc/nginx/sites-available/gitea-ip.conf | grep -A 5 "location /quant" || echo "⚠️ Nginx 설정 확인 필요"
|
||||||
ENVCHECK
|
ENVCHECK
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
@@ -105,20 +113,27 @@ fi
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
# Step 4: 백업 생성
|
# Step 4: 서비스 중지 및 백업 생성
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
echo "💾 Step 3: 백업 생성..."
|
echo "💾 Step 3: 서비스 중지 및 백업 생성..."
|
||||||
|
|
||||||
ssh -i "$SSH_KEY" "$DEPLOY_USER@$DEPLOY_HOST" << 'BACKUP'
|
ssh -i "$SSH_KEY" "$DEPLOY_USER@$DEPLOY_HOST" << 'BACKUP'
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
BACKUP_DIR="/var/www/quant_backup"
|
SERVICE_NAME="quantengine"
|
||||||
BACKUP_NAME="quant_backup_$(date +%Y%m%d_%H%M%S)"
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
BACKUP_DIR="/home/kjh2064/quantengine_backup"
|
||||||
|
BACKUP_NAME="quantengine_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
if [ -d /var/www/quant/publish ]; then
|
echo " 서비스 중지 중..."
|
||||||
sudo mkdir -p "$BACKUP_DIR"
|
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null || true
|
||||||
sudo cp -r /var/www/quant/publish "$BACKUP_DIR/$BACKUP_NAME"
|
sleep 2
|
||||||
|
echo " ✓ 서비스 중지"
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
if [ -d "$DEPLOY_PATH" ]; then
|
||||||
|
cp -r "$DEPLOY_PATH" "$BACKUP_DIR/$BACKUP_NAME"
|
||||||
echo "✓ 백업 생성: $BACKUP_DIR/$BACKUP_NAME"
|
echo "✓ 백업 생성: $BACKUP_DIR/$BACKUP_NAME"
|
||||||
|
|
||||||
# 최근 5개만 유지
|
# 최근 5개만 유지
|
||||||
@@ -126,12 +141,13 @@ if [ -d /var/www/quant/publish ]; then
|
|||||||
if [ "$BACKUP_COUNT" -gt 5 ]; then
|
if [ "$BACKUP_COUNT" -gt 5 ]; then
|
||||||
OLD_BACKUPS=$(ls -1t "$BACKUP_DIR" | tail -n +6)
|
OLD_BACKUPS=$(ls -1t "$BACKUP_DIR" | tail -n +6)
|
||||||
for backup in $OLD_BACKUPS; do
|
for backup in $OLD_BACKUPS; do
|
||||||
sudo rm -rf "$BACKUP_DIR/$backup"
|
rm -rf "$BACKUP_DIR/$backup"
|
||||||
echo "🧹 오래된 백업 삭제: $backup"
|
echo "🧹 오래된 백업 삭제: $backup"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "⚠️ 기존 배포 없음 (첫 배포)"
|
echo "⚠️ 기존 배포 없음 (첫 배포)"
|
||||||
|
mkdir -p "$DEPLOY_PATH"
|
||||||
fi
|
fi
|
||||||
BACKUP
|
BACKUP
|
||||||
|
|
||||||
@@ -146,7 +162,7 @@ echo "📤 Step 4: 파일 전송 (rsync)..."
|
|||||||
rsync -avz --delete \
|
rsync -avz --delete \
|
||||||
--rsh="ssh -i $SSH_KEY" \
|
--rsh="ssh -i $SSH_KEY" \
|
||||||
"$LOCAL_PUBLISH_DIR/" \
|
"$LOCAL_PUBLISH_DIR/" \
|
||||||
"$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_DEPLOY_PATH/publish/"
|
"$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_DEPLOY_PATH/"
|
||||||
|
|
||||||
echo "✓ 파일 전송 완료"
|
echo "✓ 파일 전송 완료"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -155,26 +171,31 @@ echo ""
|
|||||||
# Step 6: 권한 설정 및 서비스 재시작
|
# Step 6: 권한 설정 및 서비스 재시작
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
echo "🔧 Step 5: 권한 설정 및 서비스 재시작..."
|
echo "🔧 Step 5: 파일 검증 및 서비스 시작..."
|
||||||
|
|
||||||
ssh -i "$SSH_KEY" "$DEPLOY_USER@$DEPLOY_HOST" << 'FINALIZE'
|
ssh -i "$SSH_KEY" "$DEPLOY_USER@$DEPLOY_HOST" << 'FINALIZE'
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
DEPLOY_PATH="/var/www/quant"
|
SERVICE_NAME="quantengine"
|
||||||
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
|
||||||
echo " 권한 설정 중..."
|
echo " 파일 검증 중..."
|
||||||
sudo chown -R www-data:www-data "$DEPLOY_PATH/publish" 2>/dev/null || true
|
if [ -f "$DEPLOY_PATH/QuantEngine.Web.dll" ]; then
|
||||||
sudo chmod -R 755 "$DEPLOY_PATH/publish" 2>/dev/null || true
|
echo " ✓ QuantEngine.Web.dll 확인됨"
|
||||||
echo " ✓ 권한 설정 완료"
|
|
||||||
|
|
||||||
echo " nginx 재시작 중..."
|
|
||||||
sudo systemctl restart nginx 2>/dev/null || echo " ⚠️ nginx 재시작 실패 (sudo 권한 확인)"
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
if sudo systemctl is-active --quiet nginx 2>/dev/null; then
|
|
||||||
echo " ✓ nginx 재시작 완료"
|
|
||||||
else
|
else
|
||||||
echo " ⚠️ nginx 상태 확인 필요"
|
echo " ❌ QuantEngine.Web.dll 없음 (배포 실패)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " 서비스 시작 중..."
|
||||||
|
sudo systemctl start "$SERVICE_NAME" 2>/dev/null || echo " ⚠️ 서비스 시작 실패"
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
if sudo systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||||
|
echo " ✓ $SERVICE_NAME 시작 완료"
|
||||||
|
else
|
||||||
|
echo " ⚠️ 서비스 상태 확인"
|
||||||
|
sudo systemctl status "$SERVICE_NAME" || true
|
||||||
fi
|
fi
|
||||||
FINALIZE
|
FINALIZE
|
||||||
|
|
||||||
@@ -186,16 +207,16 @@ echo ""
|
|||||||
|
|
||||||
echo "🧪 Step 6: 헬스 체크..."
|
echo "🧪 Step 6: 헬스 체크..."
|
||||||
|
|
||||||
for i in {1..5}; do
|
for i in {1..30}; do
|
||||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
http://$DEPLOY_HOST/quant/ 2>/dev/null || echo "000")
|
"http://$DEPLOY_HOST/quant/" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
if [ "$HTTP_CODE" = "200" ]; then
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
echo "✓ Health check PASS (HTTP 200)"
|
echo "✓ Health check PASS (HTTP 200)"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " 시도 $i/5: HTTP $HTTP_CODE (대기 중...)"
|
echo " 시도 $i/30: HTTP $HTTP_CODE (대기 중...)"
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -210,17 +231,23 @@ echo "✅ 배포 완료!"
|
|||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 배포 정보:"
|
echo "📊 배포 정보:"
|
||||||
echo " URL: http://$DEPLOY_HOST/quant/"
|
echo " 공인 URL: http://$DEPLOY_HOST/quant/"
|
||||||
echo " 경로: $REMOTE_DEPLOY_PATH/publish"
|
echo " 배포 경로: $REMOTE_DEPLOY_PATH"
|
||||||
echo " 크기: $PACKAGE_SIZE"
|
echo " 백업 경로: $REMOTE_BACKUP_PATH"
|
||||||
|
echo " 서비스: $SERVICE_NAME"
|
||||||
|
echo " 패키지 크기: $PACKAGE_SIZE"
|
||||||
|
echo ""
|
||||||
|
echo "🌐 구조:"
|
||||||
|
echo " Nginx: reverse proxy /quant/ → localhost:5000"
|
||||||
|
echo " 설정: /etc/nginx/sites-available/gitea-ip.conf"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔍 로그 확인:"
|
echo "🔍 로그 확인:"
|
||||||
echo " ssh -i $SSH_KEY $DEPLOY_USER@$DEPLOY_HOST 'sudo tail -50 /var/log/nginx/error.log'"
|
echo " ssh -i $SSH_KEY $DEPLOY_USER@$DEPLOY_HOST 'sudo journalctl -u $SERVICE_NAME -f'"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔄 롤백 (필요시):"
|
echo "🔄 롤백 (필요시):"
|
||||||
echo " ssh -i $SSH_KEY $DEPLOY_USER@$DEPLOY_HOST << 'EOF'"
|
echo " ssh -i $SSH_KEY $DEPLOY_USER@$DEPLOY_HOST << 'EOF'"
|
||||||
echo " LATEST=\$(ls -t /var/www/quant_backup | head -1)"
|
echo " LATEST=\$(ls -t $REMOTE_BACKUP_PATH | head -1)"
|
||||||
echo " sudo cp -r /var/www/quant_backup/\$LATEST/* /var/www/quant/publish/"
|
echo " cp -r $REMOTE_BACKUP_PATH/\$LATEST/* $REMOTE_DEPLOY_PATH/"
|
||||||
echo " sudo systemctl restart nginx"
|
echo " sudo systemctl restart $SERVICE_NAME"
|
||||||
echo " EOF"
|
echo " EOF"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Quant Engine Production Deployment Script (v9)
|
||||||
|
# 환경: hz-prod-01, 공인IP 178.104.200.7, 내부 172.17.0.1
|
||||||
|
# 배포 경로: /home/kjh2064/quantengine_active
|
||||||
|
# Nginx 설정: /etc/nginx/sites-available/gitea-ip.conf (reverse proxy → localhost:5000)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 설정
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
DEPLOY_HOST="178.104.200.7"
|
||||||
|
DEPLOY_INTERNAL_IP="172.17.0.1"
|
||||||
|
DEPLOY_USER="kjh2064"
|
||||||
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
SERVICE_NAME="quantengine"
|
||||||
|
BACKUP_PATH="/home/kjh2064/quantengine_backup"
|
||||||
|
LOCAL_PUBLISH_DIR="$(pwd)/src/dotnet/QuantEngine.Web/publish"
|
||||||
|
|
||||||
|
echo "🚀 Quant Engine v9 Production Deployment"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo "Public URL: http://$DEPLOY_HOST/quant/"
|
||||||
|
echo "Internal IP: $DEPLOY_INTERNAL_IP"
|
||||||
|
echo "Deploy Path: $DEPLOY_PATH"
|
||||||
|
echo "Service: $SERVICE_NAME"
|
||||||
|
echo "Backup Path: $BACKUP_PATH"
|
||||||
|
echo "Hostname: hz-prod-01"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 1: 배포 파일 준비
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "📦 Step 1: 배포 파일 확인..."
|
||||||
|
|
||||||
|
if [ ! -d "$LOCAL_PUBLISH_DIR" ]; then
|
||||||
|
echo "❌ 오류: $LOCAL_PUBLISH_DIR 없음"
|
||||||
|
echo "먼저 'dotnet publish -c Release'를 실행하세요"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PACKAGE_SIZE=$(du -sh "$LOCAL_PUBLISH_DIR" | cut -f1)
|
||||||
|
FILE_COUNT=$(find "$LOCAL_PUBLISH_DIR" -type f | wc -l)
|
||||||
|
|
||||||
|
echo "✓ 배포 패키지:"
|
||||||
|
echo " 크기: $PACKAGE_SIZE"
|
||||||
|
echo " 파일 수: $FILE_COUNT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 2: SSH 연결 확인
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "🔐 Step 2: SSH 연결 확인..."
|
||||||
|
|
||||||
|
if ! ssh -o ConnectTimeout=10 "$DEPLOY_USER@$DEPLOY_HOST" "echo '✅ SSH 연결 성공'" &>/dev/null; then
|
||||||
|
echo "❌ SSH 연결 실패"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ SSH 연결 확인됨"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 3: 배포 전 확인
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "✅ 배포 전 확인:"
|
||||||
|
echo " [ ] Release 빌드 완료됨 ($PACKAGE_SIZE)"
|
||||||
|
echo " [ ] SSH 연결 가능"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "배포를 진행하시겠습니까? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "❌ 배포 취소됨"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 4: 서비스 중지 및 백업 생성
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "🛑 Step 3: 서비스 중지 및 백업 생성..."
|
||||||
|
|
||||||
|
ssh "$DEPLOY_USER@$DEPLOY_HOST" << 'EOF'
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVICE_NAME="quantengine"
|
||||||
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
BACKUP_PATH="/home/kjh2064/quantengine_backup"
|
||||||
|
BACKUP_NAME="quantengine_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
|
echo " 서비스 중지 중..."
|
||||||
|
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo " ✓ 서비스 중지 완료"
|
||||||
|
|
||||||
|
echo " 백업 생성 중..."
|
||||||
|
mkdir -p "$BACKUP_PATH"
|
||||||
|
if [ -d "$DEPLOY_PATH" ]; then
|
||||||
|
cp -r "$DEPLOY_PATH" "$BACKUP_PATH/$BACKUP_NAME"
|
||||||
|
echo " ✓ 백업 생성: $BACKUP_PATH/$BACKUP_NAME"
|
||||||
|
|
||||||
|
# 최근 5개만 유지
|
||||||
|
BACKUP_COUNT=$(ls -1 "$BACKUP_PATH" | wc -l)
|
||||||
|
if [ "$BACKUP_COUNT" -gt 5 ]; then
|
||||||
|
OLD_BACKUPS=$(ls -1t "$BACKUP_PATH" | tail -n +6)
|
||||||
|
for backup in $OLD_BACKUPS; do
|
||||||
|
rm -rf "$BACKUP_PATH/$backup"
|
||||||
|
echo " 🧹 오래된 백업 삭제: $backup"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠️ 기존 배포 없음 (첫 배포)"
|
||||||
|
mkdir -p "$DEPLOY_PATH"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 5: 파일 전송
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "📤 Step 4: 파일 전송 (rsync)..."
|
||||||
|
|
||||||
|
rsync -avz --delete \
|
||||||
|
--rsh="ssh" \
|
||||||
|
"$LOCAL_PUBLISH_DIR/" \
|
||||||
|
"$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/"
|
||||||
|
|
||||||
|
echo "✓ 파일 전송 완료"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 6: 서비스 시작
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "🚀 Step 5: 서비스 시작..."
|
||||||
|
|
||||||
|
ssh "$DEPLOY_USER@$DEPLOY_HOST" << 'EOF'
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVICE_NAME="quantengine"
|
||||||
|
DEPLOY_PATH="/home/kjh2064/quantengine_active"
|
||||||
|
|
||||||
|
echo " 파일 검증 중..."
|
||||||
|
if [ -f "$DEPLOY_PATH/QuantEngine.Web.dll" ]; then
|
||||||
|
echo " ✓ QuantEngine.Web.dll 확인됨"
|
||||||
|
else
|
||||||
|
echo " ❌ QuantEngine.Web.dll 없음 (배포 실패)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " 서비스 시작 중..."
|
||||||
|
sudo systemctl start "$SERVICE_NAME"
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
if sudo systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||||
|
echo " ✓ $SERVICE_NAME 시작 완료"
|
||||||
|
else
|
||||||
|
echo " ❌ $SERVICE_NAME 시작 실패"
|
||||||
|
sudo systemctl status "$SERVICE_NAME" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# Step 7: 헬스 체크
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "🧪 Step 6: 헬스 체크..."
|
||||||
|
|
||||||
|
for i in {1..30}; do
|
||||||
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
|
"http://$DEPLOY_HOST/quant/" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [ "$HTTP_CODE" = "200" ]; then
|
||||||
|
echo "✓ Health check PASS (HTTP 200)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " 시도 $i/30: HTTP $HTTP_CODE (대기 중...)"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
# 배포 완료
|
||||||
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo "✅ 배포 완료!"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "📊 배포 정보:"
|
||||||
|
echo " 공인 URL: http://$DEPLOY_HOST/quant/"
|
||||||
|
echo " 내부 IP: $DEPLOY_INTERNAL_IP"
|
||||||
|
echo " 배포 경로: $DEPLOY_PATH"
|
||||||
|
echo " 서비스: $SERVICE_NAME"
|
||||||
|
echo " 백업: $BACKUP_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "🔍 로그 확인:"
|
||||||
|
echo " ssh $DEPLOY_USER@$DEPLOY_HOST 'sudo journalctl -u $SERVICE_NAME -f'"
|
||||||
|
echo ""
|
||||||
|
echo "🔄 롤백 (필요시):"
|
||||||
|
echo " ssh $DEPLOY_USER@$DEPLOY_HOST << 'ROLLBACK'"
|
||||||
|
echo " LATEST=\$(ls -t $BACKUP_PATH | head -1)"
|
||||||
|
echo " cp -r $BACKUP_PATH/\$LATEST/* $DEPLOY_PATH/"
|
||||||
|
echo " sudo systemctl restart $SERVICE_NAME"
|
||||||
|
echo " ROLLBACK"
|
||||||
|
echo ""
|
||||||
|
echo "🌐 Nginx 역방향 프록시 구조:"
|
||||||
|
echo " 공인 IP:178.104.200.7/quant/ → localhost:5000 (Nginx reverse proxy)"
|
||||||
|
echo " Nginx 설정: /etc/nginx/sites-available/gitea-ip.conf"
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 원격 서버 환경 진단 스크립트
|
||||||
|
# SSH로 접속한 후 이 스크립트를 실행하여 환경 정보를 수집합니다.
|
||||||
|
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo " 원격 서버 환경 진단"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. 네트워크 정보
|
||||||
|
echo "1️⃣ 네트워크 정보"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
echo "공인 IP (외부에서 접속 가능):"
|
||||||
|
curl -s https://api.ipify.org
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "내부 IP 목록:"
|
||||||
|
ip addr show | grep -E "inet |inet6 " | grep -v "127.0.0.1"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "호스트명:"
|
||||||
|
hostname
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "네트워크 인터페이스:"
|
||||||
|
ip link show | grep -E "^[0-9]+:|UP|DOWN"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. 디렉토리 구조
|
||||||
|
echo "2️⃣ 웹 서버 디렉토리 구조"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
# /var/www 확인
|
||||||
|
if [ -d /var/www ]; then
|
||||||
|
echo "✓ /var/www 존재"
|
||||||
|
ls -la /var/www/ | head -20
|
||||||
|
else
|
||||||
|
echo "✗ /var/www 없음"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# /var/www/quant 확인
|
||||||
|
if [ -d /var/www/quant ]; then
|
||||||
|
echo "✓ /var/www/quant 존재"
|
||||||
|
ls -la /var/www/quant/
|
||||||
|
du -sh /var/www/quant/*
|
||||||
|
else
|
||||||
|
echo "✗ /var/www/quant 없음"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# /var/www/quant/publish 확인
|
||||||
|
if [ -d /var/www/quant/publish ]; then
|
||||||
|
echo "✓ /var/www/quant/publish 존재"
|
||||||
|
ls -la /var/www/quant/publish/ | head -10
|
||||||
|
du -sh /var/www/quant/publish
|
||||||
|
else
|
||||||
|
echo "✗ /var/www/quant/publish 없음 (첫 배포)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Nginx 설정
|
||||||
|
echo "3️⃣ Nginx 설정"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
if command -v nginx &> /dev/null; then
|
||||||
|
echo "✓ Nginx 설치됨"
|
||||||
|
nginx -v
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Nginx 설정 파일 위치:"
|
||||||
|
nginx -T 2>/dev/null | grep "configuration file" | head -1
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Nginx 실행 사용자:"
|
||||||
|
ps aux | grep nginx | grep -v grep | head -1
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "/quant 관련 설정:"
|
||||||
|
cat /etc/nginx/sites-available/default 2>/dev/null | grep -A 10 -B 2 "quant" || echo "quant 관련 설정 없음"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "✗ Nginx 미설치"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. 웹 서버 권한
|
||||||
|
echo "4️⃣ 파일 권한 및 소유자"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
echo "웹 서버 사용자:"
|
||||||
|
ps aux | grep -E "nginx|apache" | grep -v grep | head -1 | awk '{print $1}' || echo "확인 필요"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "/var/www 권한:"
|
||||||
|
ls -ld /var/www
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -d /var/www/quant ]; then
|
||||||
|
echo "/var/www/quant 권한:"
|
||||||
|
ls -ld /var/www/quant
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d /var/www/quant/publish ]; then
|
||||||
|
echo "/var/www/quant/publish 권한:"
|
||||||
|
ls -ld /var/www/quant/publish
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. 포트 상태
|
||||||
|
echo "5️⃣ 포트 상태"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
netstat -tuln 2>/dev/null | grep -E "^Proto|:80|:443" || ss -tuln | grep -E "LISTEN|:80|:443"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. 시스템 정보
|
||||||
|
echo "6️⃣ 시스템 정보"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
echo "OS:"
|
||||||
|
uname -a
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Linux 배포판:"
|
||||||
|
lsb_release -a 2>/dev/null || cat /etc/os-release | head -3
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "디스크 공간:"
|
||||||
|
df -h | grep -E "^/dev|Filesystem"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 7. Sudo 권한
|
||||||
|
echo "7️⃣ 현재 사용자 정보"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
echo "현재 사용자:"
|
||||||
|
whoami
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "사용자 그룹:"
|
||||||
|
groups
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Sudo 권한:"
|
||||||
|
sudo -l 2>/dev/null | grep -E "NOPASSWD|nginx|systemctl" || echo "sudo 권한 확인 필요"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 8. Git/Gitea 정보
|
||||||
|
echo "8️⃣ Git/Gitea 정보"
|
||||||
|
echo "───────────────────────────────────────────────────────────────"
|
||||||
|
|
||||||
|
if command -v git &> /dev/null; then
|
||||||
|
echo "✓ Git 설치됨"
|
||||||
|
git --version
|
||||||
|
else
|
||||||
|
echo "✗ Git 미설치"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if command -v gitea &> /dev/null; then
|
||||||
|
echo "✓ Gitea 설치됨"
|
||||||
|
gitea -v
|
||||||
|
else
|
||||||
|
echo "✗ Gitea 미설치"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -d /var/lib/gitea ] || [ -d /home/git/gitea-repositories ]; then
|
||||||
|
echo "Gitea 데이터 위치:"
|
||||||
|
[ -d /var/lib/gitea ] && echo " /var/lib/gitea"
|
||||||
|
[ -d /home/git/gitea-repositories ] && echo " /home/git/gitea-repositories"
|
||||||
|
else
|
||||||
|
echo "Gitea 데이터 위치: 확인 필요"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo "✅ 진단 완료"
|
||||||
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo "위 정보를 바탕으로 배포 스크립트를 업데이트합니다."
|
||||||
|
echo ""
|
||||||
|
echo "특히 확인할 사항:"
|
||||||
|
echo " 1. 내부 IP 주소 (172로 시작하는 IP)"
|
||||||
|
echo " 2. /var/www/quant 경로 (또는 다른 경로?)"
|
||||||
|
echo " 3. 웹 서버 사용자 (www-data? nobody? 다른 사용자?)"
|
||||||
|
echo " 4. Nginx 설정 파일 위치"
|
||||||
|
echo " 5. /quant에 대한 nginx 설정"
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user