Clean up tunnel infrastructure and migrate to Gitea
Some checks failed
Deploy to Production Server / Deploy to 178.63.127.19 (push) Has been cancelled
Some checks failed
Deploy to Production Server / Deploy to 178.63.127.19 (push) Has been cancelled
This commit is contained in:
138
.github/workflows/deploy.yml
vendored
Normal file
138
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
name: Deploy to Production Server
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch: # Allow manual trigger
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to 178.63.127.19
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies (Backend)
|
||||
run: |
|
||||
npm ci
|
||||
|
||||
- name: Install dependencies (Frontend)
|
||||
run: |
|
||||
cd frontend
|
||||
npm ci
|
||||
|
||||
- name: Build Frontend
|
||||
run: |
|
||||
cd frontend
|
||||
npm run build
|
||||
env:
|
||||
NODE_ENV: production
|
||||
VITE_API_URL: http://178.63.127.19:3000
|
||||
|
||||
- name: Run Tests (if any)
|
||||
run: |
|
||||
npm test || echo "No tests configured"
|
||||
continue-on-error: true
|
||||
|
||||
- name: Deploy to Production Server
|
||||
uses: appleboy/ssh-action@v1.0.0
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
username: ${{ secrets.SERVER_USER }}
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
port: ${{ secrets.SERVER_PORT || 22 }}
|
||||
script: |
|
||||
echo "🚀 Starting deployment..."
|
||||
|
||||
# Navigate to project directory
|
||||
cd ${{ secrets.DEPLOY_PATH || '/var/www/turbotrades' }}
|
||||
|
||||
# Stop the application
|
||||
echo "⏸️ Stopping application..."
|
||||
pm2 stop turbotrades || echo "App not running"
|
||||
|
||||
# Backup current version
|
||||
echo "💾 Creating backup..."
|
||||
cp -r . ../turbotrades-backup-$(date +%Y%m%d-%H%M%S) || true
|
||||
|
||||
# Pull latest code
|
||||
echo "📥 Pulling latest code..."
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
|
||||
# Install backend dependencies
|
||||
echo "📦 Installing backend dependencies..."
|
||||
npm ci --production
|
||||
|
||||
# Build and install frontend
|
||||
echo "🎨 Building frontend..."
|
||||
cd frontend
|
||||
npm ci
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Run database migrations (if any)
|
||||
echo "🗄️ Running migrations..."
|
||||
npm run migrate || echo "No migrations to run"
|
||||
|
||||
# Start the application
|
||||
echo "▶️ Starting application..."
|
||||
pm2 start ecosystem.config.js || pm2 start index.js --name turbotrades
|
||||
pm2 save
|
||||
|
||||
# Verify deployment
|
||||
echo "✅ Deployment complete!"
|
||||
pm2 list
|
||||
|
||||
- name: Health Check
|
||||
run: |
|
||||
sleep 10
|
||||
curl -f http://178.63.127.19:3000/api/health || echo "⚠️ Health check failed"
|
||||
|
||||
- name: Notify Success
|
||||
if: success()
|
||||
run: |
|
||||
echo "✅ Deployment successful!"
|
||||
echo "🌐 Server: 178.63.127.19"
|
||||
echo "👤 Repository: git.turbotrades.dev/iDefineHD/TurboTrades"
|
||||
echo "📅 Time: $(date)"
|
||||
|
||||
- name: Notify Failure
|
||||
if: failure()
|
||||
run: |
|
||||
echo "❌ Deployment failed!"
|
||||
echo "Check the logs above for details"
|
||||
|
||||
- name: Rollback on Failure
|
||||
if: failure()
|
||||
uses: appleboy/ssh-action@v1.0.0
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
username: ${{ secrets.SERVER_USER }}
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
port: ${{ secrets.SERVER_PORT || 22 }}
|
||||
script: |
|
||||
echo "🔄 Rolling back to previous version..."
|
||||
cd ${{ secrets.DEPLOY_PATH || '/var/www/turbotrades' }}
|
||||
|
||||
# Find latest backup
|
||||
BACKUP=$(ls -t ../turbotrades-backup-* | head -1)
|
||||
|
||||
if [ -n "$BACKUP" ]; then
|
||||
echo "Found backup: $BACKUP"
|
||||
rm -rf ./*
|
||||
cp -r $BACKUP/* .
|
||||
pm2 restart turbotrades
|
||||
echo "✅ Rollback complete"
|
||||
else
|
||||
echo "❌ No backup found!"
|
||||
fi
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,6 +9,7 @@ pnpm-lock.yaml
|
||||
.env.local
|
||||
.env.production
|
||||
.env.development
|
||||
.env.tunnel
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
@@ -79,3 +80,7 @@ uploads/
|
||||
*.backup
|
||||
*.bak
|
||||
*.old
|
||||
|
||||
# Cloudflare Tunnel
|
||||
.cloudflared/
|
||||
.tunnel-urls.json
|
||||
|
||||
271
CLEANUP_SUMMARY.md
Normal file
271
CLEANUP_SUMMARY.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 🧹 TurboTrades Cleanup Summary
|
||||
|
||||
**Date:** January 10, 2026
|
||||
**Action:** Removed tunnel infrastructure and updated repository to Gitea
|
||||
|
||||
---
|
||||
|
||||
## ✅ Actions Completed
|
||||
|
||||
### 1. Removed Tunnel Files
|
||||
|
||||
**Deleted Scripts:**
|
||||
- ❌ `scripts/dev-tunnel.js`
|
||||
- ❌ `scripts/tunnel.js`
|
||||
- ❌ `scripts/quick-tunnel.js`
|
||||
- ❌ `scripts/cloudflare-tunnel.js`
|
||||
- ❌ `scripts/setup-cloudflare-tunnel.js`
|
||||
- ❌ `scripts/vscode-tunnel-config.js`
|
||||
|
||||
**Deleted Documentation:**
|
||||
- ❌ `TUNNEL.md`
|
||||
- ❌ `TUNNEL_QUICKSTART.md`
|
||||
- ❌ `TUNNEL_CONFIG.md`
|
||||
- ❌ `.cloudflared/` directory
|
||||
|
||||
**Removed from package.json:**
|
||||
```json
|
||||
- "tunnel": "node scripts/quick-tunnel.js"
|
||||
- "tunnel:setup": "node scripts/setup-cloudflare-tunnel.js"
|
||||
- "tunnel:stable": "node scripts/cloudflare-tunnel.js"
|
||||
- "tunnel:vscode": "node scripts/vscode-tunnel-config.js"
|
||||
```
|
||||
|
||||
### 2. Updated Repository to Gitea
|
||||
|
||||
**Old Repository:**
|
||||
```
|
||||
https://github.com/iDefineHD/TurboTrades.git
|
||||
```
|
||||
|
||||
**New Repository:**
|
||||
```
|
||||
https://git.turbotrades.dev/iDefineHD/TurboTrades.git
|
||||
```
|
||||
|
||||
**Files Updated:**
|
||||
|
||||
#### `ecosystem.config.js`
|
||||
```javascript
|
||||
// Changed from:
|
||||
repo: "https://github.com/iDefineHD/TurboTrades.git"
|
||||
|
||||
// To:
|
||||
repo: "https://git.turbotrades.dev/iDefineHD/TurboTrades.git"
|
||||
```
|
||||
|
||||
#### `.github/workflows/deploy.yml`
|
||||
```yaml
|
||||
# Updated repository reference in notification:
|
||||
echo "👤 Repository: git.turbotrades.dev/iDefineHD/TurboTrades"
|
||||
```
|
||||
|
||||
#### Git Remote Configuration
|
||||
```bash
|
||||
# Updated local git remote:
|
||||
git remote set-url origin https://git.turbotrades.dev/iDefineHD/TurboTrades.git
|
||||
```
|
||||
|
||||
#### Documentation Updates:
|
||||
- ✅ `DEPLOY_NOW.md` - Updated all GitHub URLs to Gitea
|
||||
- ✅ `DEPLOYMENT_GUIDE.md` - Updated references and placeholder URLs
|
||||
- ✅ `scripts/setup-server.sh` - Updated instructions and clone URLs
|
||||
|
||||
---
|
||||
|
||||
## 📝 Current Configuration
|
||||
|
||||
### Repository Details
|
||||
- **Platform:** Gitea (self-hosted)
|
||||
- **URL:** https://git.turbotrades.dev/iDefineHD/TurboTrades.git
|
||||
- **Owner:** iDefineHD
|
||||
- **Branch:** main
|
||||
|
||||
### Deployment
|
||||
- **Server:** 178.63.127.19
|
||||
- **User:** root
|
||||
- **Path:** /var/www/turbotrades
|
||||
- **Process Manager:** PM2
|
||||
|
||||
### CI/CD
|
||||
- **Workflow:** `.github/workflows/deploy.yml`
|
||||
- **Trigger:** Push to main branch or manual dispatch
|
||||
- **Actions:** Build, test, deploy, health check, rollback on failure
|
||||
|
||||
---
|
||||
|
||||
## 🔄 What Was Kept
|
||||
|
||||
### Development Tools
|
||||
- ✅ Vite dev server with proxy configuration
|
||||
- ✅ WebSocket proxy support
|
||||
- ✅ Hot module replacement
|
||||
- ✅ VS Code dev tunnels compatibility
|
||||
|
||||
### Deployment Infrastructure
|
||||
- ✅ GitHub Actions workflow (compatible with Gitea Actions)
|
||||
- ✅ PM2 ecosystem configuration
|
||||
- ✅ Server setup scripts
|
||||
- ✅ Deployment documentation
|
||||
- ✅ Health check endpoints
|
||||
|
||||
### Frontend Configuration
|
||||
**Vite proxy configuration retained:**
|
||||
```javascript
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://localhost:3000",
|
||||
changeOrigin: true,
|
||||
},
|
||||
"/ws": {
|
||||
target: "http://localhost:3000",
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**Allowed hosts include:**
|
||||
- `.devtunnels.ms` - VS Code Dev Tunnels
|
||||
- `localhost`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
### For Development
|
||||
1. Use VS Code port forwarding for sharing:
|
||||
- Open Ports panel
|
||||
- Forward port 5173 (frontend)
|
||||
- Set visibility to Public
|
||||
- Share the URL
|
||||
|
||||
2. WebSocket connects automatically through proxy
|
||||
|
||||
3. No environment variables needed for local dev
|
||||
|
||||
### For Deployment
|
||||
|
||||
1. **Ensure Gitea repository is accessible:**
|
||||
```bash
|
||||
git remote -v
|
||||
# Should show: https://git.turbotrades.dev/iDefineHD/TurboTrades.git
|
||||
```
|
||||
|
||||
2. **Push changes:**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Cleanup: Remove tunnel infrastructure, update to Gitea"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. **Configure Gitea CI/CD** (if using Gitea Actions):
|
||||
- Add secrets in repository settings
|
||||
- Ensure workflow is enabled
|
||||
- Test deployment pipeline
|
||||
|
||||
4. **Manual deployment option:**
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
cd /var/www/turbotrades
|
||||
git pull origin main
|
||||
npm ci --production
|
||||
cd frontend && npm ci && npm run build && cd ..
|
||||
pm2 restart turbotrades
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Breaking Changes
|
||||
|
||||
### Removed Features
|
||||
- ❌ Cloudflare Tunnel integration
|
||||
- ❌ Localtunnel support
|
||||
- ❌ Ngrok integration
|
||||
- ❌ Automatic tunnel configuration scripts
|
||||
|
||||
### Migration Notes
|
||||
If you were using the tunnel scripts:
|
||||
- Use VS Code built-in port forwarding instead
|
||||
- Or set up Cloudflare Tunnel manually
|
||||
- Or use ngrok directly: `ngrok http 5173`
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation Updates
|
||||
|
||||
### Updated Files
|
||||
- `DEPLOY_NOW.md` - All references updated
|
||||
- `DEPLOYMENT_GUIDE.md` - GitHub → Gitea references
|
||||
- `scripts/setup-server.sh` - Repository URLs updated
|
||||
- `.github/workflows/deploy.yml` - Notification text updated
|
||||
|
||||
### Removed Files
|
||||
- All tunnel-related documentation removed
|
||||
- Cloudflare tunnel configuration removed
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification Checklist
|
||||
|
||||
- [x] All tunnel scripts removed
|
||||
- [x] Tunnel documentation removed
|
||||
- [x] package.json scripts cleaned up
|
||||
- [x] Git remote updated to Gitea
|
||||
- [x] ecosystem.config.js updated
|
||||
- [x] GitHub Actions workflow updated
|
||||
- [x] Deployment documentation updated
|
||||
- [x] Setup scripts updated
|
||||
- [x] .gitignore includes tunnel artifacts
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Files to Review Before Pushing
|
||||
|
||||
1. `.env` - Ensure no tunnel URLs are hardcoded
|
||||
2. `frontend/.env` - Check API URL configuration
|
||||
3. `ecosystem.config.js` - Verify Gitea repo URL
|
||||
4. `.github/workflows/deploy.yml` - Test workflow syntax
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tips
|
||||
|
||||
### For Local Development
|
||||
- Use VS Code port forwarding for quick sharing
|
||||
- WebSocket connections work through Vite proxy
|
||||
- No configuration changes needed
|
||||
|
||||
### For Production
|
||||
- Push to Gitea triggers deployment
|
||||
- Monitor CI/CD pipeline in Gitea
|
||||
- PM2 handles process management
|
||||
- Automatic rollback on failure
|
||||
|
||||
### For Sharing Work
|
||||
**Quick option:**
|
||||
1. Open VS Code Ports panel
|
||||
2. Forward port 5173
|
||||
3. Make it Public
|
||||
4. Share the URL
|
||||
|
||||
**No .env changes needed!**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Summary
|
||||
|
||||
- ✅ Removed 6 tunnel scripts
|
||||
- ✅ Removed 4 tunnel documentation files
|
||||
- ✅ Updated repository to Gitea
|
||||
- ✅ Updated all documentation
|
||||
- ✅ Cleaned package.json
|
||||
- ✅ Updated git remote
|
||||
- ✅ Ready for Gitea deployment
|
||||
|
||||
**Result:** Cleaner codebase, self-hosted repository, maintained functionality.
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** January 10, 2026
|
||||
**Status:** ✅ Complete
|
||||
812
DEPLOYMENT_GUIDE.md
Normal file
812
DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,812 @@
|
||||
# TurboTrades Deployment Guide
|
||||
|
||||
Complete guide to deploy TurboTrades to your production server at `178.63.127.19`
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [Prerequisites](#prerequisites)
|
||||
2. [Server Setup](#server-setup)
|
||||
3. [GitHub Secrets Configuration](#github-secrets-configuration)
|
||||
4. [Initial Deployment](#initial-deployment)
|
||||
5. [Automatic Deployments](#automatic-deployments)
|
||||
6. [Manual Deployment](#manual-deployment)
|
||||
7. [Monitoring & Maintenance](#monitoring--maintenance)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
9. [Rollback Procedures](#rollback-procedures)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Prerequisites
|
||||
|
||||
### On Your Local Machine:
|
||||
- [x] Git installed
|
||||
- [x] GitHub account with repository access
|
||||
- [x] SSH access to server (178.63.127.19)
|
||||
|
||||
### On Your Server (178.63.127.19):
|
||||
- [ ] Ubuntu/Debian Linux
|
||||
- [ ] Node.js 18+ installed
|
||||
- [ ] MongoDB installed and running
|
||||
- [ ] PM2 process manager
|
||||
- [ ] Nginx (optional, for reverse proxy)
|
||||
- [ ] Git installed
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Server Setup
|
||||
|
||||
### Step 1: SSH into Your Server
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
# Or with specific user:
|
||||
ssh yourusername@178.63.127.19
|
||||
```
|
||||
|
||||
### Step 2: Install Required Software
|
||||
|
||||
```bash
|
||||
# Update system
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# Install Node.js 20.x
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
# Install MongoDB
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | sudo apt-key add -
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
|
||||
sudo apt update
|
||||
sudo apt install -y mongodb-org
|
||||
|
||||
# Start MongoDB
|
||||
sudo systemctl start mongod
|
||||
sudo systemctl enable mongod
|
||||
|
||||
# Install PM2 globally
|
||||
sudo npm install -g pm2
|
||||
|
||||
# Install Git
|
||||
sudo apt install -y git
|
||||
|
||||
# Install Nginx (optional)
|
||||
sudo apt install -y nginx
|
||||
```
|
||||
|
||||
### Step 3: Create Deployment Directory
|
||||
|
||||
```bash
|
||||
# Create directory
|
||||
sudo mkdir -p /var/www/turbotrades
|
||||
sudo chown -R $USER:$USER /var/www/turbotrades
|
||||
|
||||
# Navigate to directory
|
||||
cd /var/www/turbotrades
|
||||
```
|
||||
|
||||
### Step 4: Generate SSH Deploy Key (Optional but Recommended)
|
||||
|
||||
```bash
|
||||
# Generate SSH key for deployment
|
||||
ssh-keygen -t ed25519 -C "deploy@turbotrades" -f ~/.ssh/turbotrades_deploy_key
|
||||
|
||||
# Display public key (add to GitHub Deploy Keys)
|
||||
cat ~/.ssh/turbotrades_deploy_key.pub
|
||||
|
||||
# Display private key (add to GitHub Secrets)
|
||||
cat ~/.ssh/turbotrades_deploy_key
|
||||
```
|
||||
|
||||
### Step 5: Clone Repository
|
||||
|
||||
```bash
|
||||
cd /var/www/turbotrades
|
||||
git clone https://git.turbotrades.dev/iDefineHD/TurboTrades.git .
|
||||
|
||||
# Or with SSH key:
|
||||
git clone git@git.turbotrades.dev:iDefineHD/TurboTrades.git .
|
||||
```
|
||||
|
||||
### Step 6: Create Environment File
|
||||
|
||||
```bash
|
||||
cd /var/www/turbotrades
|
||||
nano .env
|
||||
```
|
||||
|
||||
Add the following configuration:
|
||||
|
||||
```env
|
||||
# Server Configuration
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Database
|
||||
MONGODB_URI=mongodb://localhost:27017/turbotrades
|
||||
|
||||
# Session Secret (Generate a secure random string)
|
||||
SESSION_SECRET=your-super-secret-session-key-change-this
|
||||
|
||||
# Steam API
|
||||
STEAM_API_KEY=your-steam-api-key-here
|
||||
STEAM_RETURN_URL=http://178.63.127.19:3000/auth/steam/return
|
||||
|
||||
# JWT Secret (Generate a secure random string)
|
||||
JWT_SECRET=your-super-secret-jwt-key-change-this
|
||||
JWT_ACCESS_EXPIRY=15m
|
||||
JWT_REFRESH_EXPIRY=7d
|
||||
|
||||
# CORS
|
||||
CORS_ORIGIN=http://178.63.127.19
|
||||
|
||||
# Redis (if using)
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Admin Steam IDs (comma-separated)
|
||||
ADMIN_STEAM_IDS=76561198000000000,76561198111111111
|
||||
|
||||
# Bot Configuration
|
||||
STEAM_BOT_USERNAME=your-bot-username
|
||||
STEAM_BOT_PASSWORD=your-bot-password
|
||||
STEAM_BOT_SHARED_SECRET=your-bot-shared-secret
|
||||
STEAM_BOT_IDENTITY_SECRET=your-bot-identity-secret
|
||||
|
||||
# CSGOFloat API (optional)
|
||||
CSGOFLOAT_API_KEY=your-csgofloat-api-key
|
||||
|
||||
# Pricing API (optional)
|
||||
PRICING_API_KEY=your-pricing-api-key
|
||||
```
|
||||
|
||||
Save and exit (Ctrl+X, Y, Enter)
|
||||
|
||||
### Step 7: Install Dependencies
|
||||
|
||||
```bash
|
||||
# Backend dependencies
|
||||
npm ci --production
|
||||
|
||||
# Frontend dependencies and build
|
||||
cd frontend
|
||||
npm ci
|
||||
npm run build
|
||||
cd ..
|
||||
```
|
||||
|
||||
### Step 8: Setup PM2
|
||||
|
||||
```bash
|
||||
# Start application with PM2
|
||||
pm2 start ecosystem.config.js --env production
|
||||
|
||||
# Save PM2 configuration
|
||||
pm2 save
|
||||
|
||||
# Setup PM2 to start on boot
|
||||
pm2 startup
|
||||
# Follow the instructions provided by the command above
|
||||
|
||||
# Check status
|
||||
pm2 status
|
||||
pm2 logs turbotrades
|
||||
```
|
||||
|
||||
### Step 9: Configure Nginx (Optional but Recommended)
|
||||
|
||||
```bash
|
||||
sudo nano /etc/nginx/sites-available/turbotrades
|
||||
```
|
||||
|
||||
Add the following configuration:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name 178.63.127.19 yourdomain.com;
|
||||
|
||||
# Frontend (Vite build)
|
||||
location / {
|
||||
root /var/www/turbotrades/frontend/dist;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
|
||||
# Backend API
|
||||
location /api {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
|
||||
# WebSocket support
|
||||
location /ws {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
# Auth routes
|
||||
location /auth {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Enable the site:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/turbotrades /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
### Step 10: Configure Firewall
|
||||
|
||||
```bash
|
||||
# Allow SSH, HTTP, and HTTPS
|
||||
sudo ufw allow 22/tcp
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
sudo ufw enable
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 GitHub Secrets Configuration
|
||||
|
||||
### Step 1: Go to GitHub Repository Settings
|
||||
|
||||
1. Go to your repository: `https://git.turbotrades.dev/iDefineHD/TurboTrades`
|
||||
2. Click **Settings** → **Secrets** (or CI/CD settings depending on Gitea version)
|
||||
3. Click **New repository secret**
|
||||
|
||||
### Step 2: Add Required Secrets
|
||||
|
||||
Add each of these secrets:
|
||||
|
||||
#### `SERVER_HOST`
|
||||
```
|
||||
178.63.127.19
|
||||
```
|
||||
|
||||
#### `SERVER_USER`
|
||||
```
|
||||
root
|
||||
```
|
||||
(or your SSH username)
|
||||
|
||||
#### `SERVER_PORT`
|
||||
```
|
||||
22
|
||||
```
|
||||
|
||||
#### `SSH_PRIVATE_KEY`
|
||||
```
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
[Your private key content from ~/.ssh/turbotrades_deploy_key]
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
```
|
||||
|
||||
#### `DEPLOY_PATH`
|
||||
```
|
||||
/var/www/turbotrades
|
||||
```
|
||||
|
||||
### Step 3: Add Deploy Key to GitHub (If Using SSH)
|
||||
|
||||
1. Go to **Settings** → **Deploy keys**
|
||||
2. Click **Add deploy key**
|
||||
3. Title: `Production Server 178.63.127.19`
|
||||
4. Key: Paste your public key from `~/.ssh/turbotrades_deploy_key.pub`
|
||||
5. ✅ Check **Allow write access** (if needed)
|
||||
6. Click **Add key**
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Initial Deployment
|
||||
|
||||
### Method 1: Manual Initial Setup (Recommended)
|
||||
|
||||
Already completed in [Server Setup](#server-setup) above!
|
||||
|
||||
### Method 2: Using PM2 Deploy
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
pm2 deploy ecosystem.config.js production setup
|
||||
pm2 deploy ecosystem.config.js production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Automatic Deployments
|
||||
|
||||
### How It Works
|
||||
|
||||
The CI/CD workflow (`.github/workflows/deploy.yml`) automatically deploys when:
|
||||
1. You push to the `main` branch
|
||||
2. You manually trigger the workflow
|
||||
|
||||
### Deployment Process
|
||||
|
||||
1. **Trigger**: Push to `main` branch
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: Add new feature"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
2. **CI/CD Pipeline**: Automatically runs
|
||||
- ✅ Checks out code
|
||||
- ✅ Builds frontend
|
||||
- ✅ Runs tests
|
||||
- ✅ Deploys to server via SSH
|
||||
- ✅ Restarts PM2
|
||||
- ✅ Runs health check
|
||||
- ✅ Rolls back if failed
|
||||
|
||||
3. **Monitor**: Check repository Actions tab for progress
|
||||
|
||||
### Manual Trigger
|
||||
|
||||
1. Go to **Actions** tab on GitHub
|
||||
2. Select **Deploy to Production Server**
|
||||
3. Click **Run workflow**
|
||||
4. Select branch (usually `main`)
|
||||
5. Click **Run workflow**
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Manual Deployment
|
||||
|
||||
### Quick Deploy (SSH to Server)
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
ssh root@178.63.127.19
|
||||
|
||||
# Navigate to project
|
||||
cd /var/www/turbotrades
|
||||
|
||||
# Pull latest changes
|
||||
git pull origin main
|
||||
|
||||
# Install dependencies
|
||||
npm ci --production
|
||||
cd frontend && npm ci && npm run build && cd ..
|
||||
|
||||
# Restart application
|
||||
pm2 restart turbotrades
|
||||
|
||||
# Check status
|
||||
pm2 status
|
||||
pm2 logs turbotrades --lines 50
|
||||
```
|
||||
|
||||
### Using PM2 Deploy Command
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
pm2 deploy ecosystem.config.js production update
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring & Maintenance
|
||||
|
||||
### Check Application Status
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
ssh root@178.63.127.19
|
||||
|
||||
# Check PM2 status
|
||||
pm2 status
|
||||
|
||||
# View logs
|
||||
pm2 logs turbotrades
|
||||
|
||||
# View last 100 lines
|
||||
pm2 logs turbotrades --lines 100
|
||||
|
||||
# View only errors
|
||||
pm2 logs turbotrades --err
|
||||
|
||||
# Monitor in real-time
|
||||
pm2 monit
|
||||
```
|
||||
|
||||
### Check Server Resources
|
||||
|
||||
```bash
|
||||
# CPU and Memory usage
|
||||
htop
|
||||
|
||||
# Disk usage
|
||||
df -h
|
||||
|
||||
# Check MongoDB status
|
||||
sudo systemctl status mongod
|
||||
|
||||
# Check Nginx status
|
||||
sudo systemctl status nginx
|
||||
```
|
||||
|
||||
### Database Backup
|
||||
|
||||
```bash
|
||||
# Create backup directory
|
||||
mkdir -p /var/backups/turbotrades
|
||||
|
||||
# Backup MongoDB
|
||||
mongodump --out /var/backups/turbotrades/backup-$(date +%Y%m%d-%H%M%S)
|
||||
|
||||
# Automated daily backup (add to crontab)
|
||||
crontab -e
|
||||
# Add this line:
|
||||
0 2 * * * mongodump --out /var/backups/turbotrades/backup-$(date +\%Y\%m\%d)
|
||||
```
|
||||
|
||||
### View Application Logs
|
||||
|
||||
```bash
|
||||
# PM2 logs
|
||||
pm2 logs turbotrades
|
||||
|
||||
# Application logs (if file-based)
|
||||
tail -f /var/www/turbotrades/logs/app.log
|
||||
|
||||
# Nginx access logs
|
||||
tail -f /var/log/nginx/access.log
|
||||
|
||||
# Nginx error logs
|
||||
tail -f /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
# Restart application
|
||||
pm2 restart turbotrades
|
||||
|
||||
# Restart all PM2 apps
|
||||
pm2 restart all
|
||||
|
||||
# Restart MongoDB
|
||||
sudo systemctl restart mongod
|
||||
|
||||
# Restart Nginx
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# Reload Nginx (without downtime)
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Issue: Application Won't Start
|
||||
|
||||
```bash
|
||||
# Check PM2 logs
|
||||
pm2 logs turbotrades --err
|
||||
|
||||
# Check if port is already in use
|
||||
sudo lsof -i :3000
|
||||
|
||||
# Check environment variables
|
||||
pm2 show turbotrades
|
||||
|
||||
# Restart with fresh environment
|
||||
pm2 delete turbotrades
|
||||
pm2 start ecosystem.config.js --env production
|
||||
```
|
||||
|
||||
### Issue: Cannot Connect to Database
|
||||
|
||||
```bash
|
||||
# Check MongoDB status
|
||||
sudo systemctl status mongod
|
||||
|
||||
# Start MongoDB
|
||||
sudo systemctl start mongod
|
||||
|
||||
# Check MongoDB logs
|
||||
sudo tail -f /var/log/mongodb/mongod.log
|
||||
|
||||
# Test MongoDB connection
|
||||
mongosh
|
||||
```
|
||||
|
||||
### Issue: "Permission Denied" Errors
|
||||
|
||||
```bash
|
||||
# Fix ownership
|
||||
sudo chown -R $USER:$USER /var/www/turbotrades
|
||||
|
||||
# Fix permissions
|
||||
chmod -R 755 /var/www/turbotrades
|
||||
```
|
||||
|
||||
### Issue: CI/CD Deployment Fails
|
||||
|
||||
1. **Check CI/CD logs**
|
||||
- Go to repository Actions tab
|
||||
- Click on failed workflow
|
||||
- Review error messages
|
||||
|
||||
2. **Verify Secrets**
|
||||
- Settings → Secrets and variables → Actions
|
||||
- Ensure all secrets are set correctly
|
||||
|
||||
3. **Test SSH Connection Manually**
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
```
|
||||
|
||||
4. **Check Deployment Path**
|
||||
```bash
|
||||
ssh root@178.63.127.19 "ls -la /var/www/turbotrades"
|
||||
```
|
||||
|
||||
### Issue: 502 Bad Gateway (Nginx)
|
||||
|
||||
```bash
|
||||
# Check if app is running
|
||||
pm2 status
|
||||
|
||||
# Restart application
|
||||
pm2 restart turbotrades
|
||||
|
||||
# Check Nginx configuration
|
||||
sudo nginx -t
|
||||
|
||||
# View Nginx error logs
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
### Issue: Out of Memory
|
||||
|
||||
```bash
|
||||
# Check memory usage
|
||||
free -h
|
||||
|
||||
# Increase PM2 memory limit
|
||||
pm2 stop turbotrades
|
||||
# Edit ecosystem.config.js and increase max_memory_restart
|
||||
pm2 start ecosystem.config.js
|
||||
|
||||
# Add swap space (if needed)
|
||||
sudo fallocate -l 2G /swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⏮️ Rollback Procedures
|
||||
|
||||
### Automatic Rollback
|
||||
|
||||
The CI/CD workflow automatically rolls back if deployment fails.
|
||||
|
||||
### Manual Rollback
|
||||
|
||||
#### Method 1: Using Backups
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
ssh root@178.63.127.19
|
||||
|
||||
# List backups
|
||||
ls -lt /var/www/ | grep turbotrades-backup
|
||||
|
||||
# Restore from backup
|
||||
cd /var/www
|
||||
rm -rf turbotrades/*
|
||||
cp -r turbotrades-backup-YYYYMMDD-HHMMSS/* turbotrades/
|
||||
|
||||
# Restart application
|
||||
cd turbotrades
|
||||
pm2 restart turbotrades
|
||||
```
|
||||
|
||||
#### Method 2: Using Git
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
ssh root@178.63.127.19
|
||||
cd /var/www/turbotrades
|
||||
|
||||
# View commit history
|
||||
git log --oneline
|
||||
|
||||
# Rollback to specific commit
|
||||
git reset --hard COMMIT_HASH
|
||||
|
||||
# Reinstall dependencies
|
||||
npm ci --production
|
||||
cd frontend && npm ci && npm run build && cd ..
|
||||
|
||||
# Restart
|
||||
pm2 restart turbotrades
|
||||
```
|
||||
|
||||
#### Method 3: Rollback to Previous Tag
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
cd /var/www/turbotrades
|
||||
|
||||
# List tags
|
||||
git tag -l
|
||||
|
||||
# Checkout specific tag
|
||||
git checkout v1.0.0
|
||||
|
||||
# Rebuild and restart
|
||||
npm ci --production
|
||||
cd frontend && npm ci && npm run build && cd ..
|
||||
pm2 restart turbotrades
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Deployment Checklist
|
||||
|
||||
### Before Deployment
|
||||
- [ ] All tests pass locally
|
||||
- [ ] Environment variables configured
|
||||
- [ ] Database migrations ready (if any)
|
||||
- [ ] Backup current production data
|
||||
- [ ] Notify team about deployment
|
||||
|
||||
### During Deployment
|
||||
- [ ] Monitor CI/CD workflow
|
||||
- [ ] Watch server logs
|
||||
- [ ] Check PM2 status
|
||||
- [ ] Verify health endpoint
|
||||
|
||||
### After Deployment
|
||||
- [ ] Test critical features
|
||||
- [ ] Check error logs
|
||||
- [ ] Verify database connectivity
|
||||
- [ ] Test admin panel
|
||||
- [ ] Test user authentication
|
||||
- [ ] Monitor performance metrics
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Best Practices
|
||||
|
||||
1. **Keep Secrets Safe**
|
||||
- Never commit `.env` file
|
||||
- Use GitHub Secrets for sensitive data
|
||||
- Rotate secrets regularly
|
||||
|
||||
2. **Keep Software Updated**
|
||||
```bash
|
||||
sudo apt update && sudo apt upgrade
|
||||
npm update
|
||||
```
|
||||
|
||||
3. **Enable Firewall**
|
||||
```bash
|
||||
sudo ufw enable
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
4. **Use HTTPS** (Recommended)
|
||||
```bash
|
||||
sudo apt install certbot python3-certbot-nginx
|
||||
sudo certbot --nginx -d yourdomain.com
|
||||
```
|
||||
|
||||
5. **Regular Backups**
|
||||
- Database backups daily
|
||||
- Code backups before deployment
|
||||
- Test restore procedures
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support & Resources
|
||||
|
||||
### Useful Commands
|
||||
|
||||
```bash
|
||||
# Full deployment script
|
||||
cd /var/www/turbotrades && \
|
||||
git pull origin main && \
|
||||
npm ci --production && \
|
||||
cd frontend && npm ci && npm run build && cd .. && \
|
||||
pm2 restart turbotrades && \
|
||||
pm2 logs turbotrades --lines 20
|
||||
|
||||
# Quick restart
|
||||
pm2 restart turbotrades && pm2 logs turbotrades
|
||||
|
||||
# Check everything
|
||||
pm2 status && \
|
||||
sudo systemctl status mongod && \
|
||||
sudo systemctl status nginx
|
||||
```
|
||||
|
||||
### Logs Locations
|
||||
|
||||
- PM2 Logs: `~/.pm2/logs/`
|
||||
- Application Logs: `/var/www/turbotrades/logs/`
|
||||
- Nginx Access: `/var/log/nginx/access.log`
|
||||
- Nginx Error: `/var/log/nginx/error.log`
|
||||
- MongoDB: `/var/log/mongodb/mongod.log`
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
```bash
|
||||
# Install monitoring tools
|
||||
sudo npm install -g pm2-logrotate
|
||||
pm2 install pm2-logrotate
|
||||
|
||||
# Monitor resources
|
||||
pm2 monit
|
||||
htop
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Quick Reference
|
||||
|
||||
### Deploy from Local Machine
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Your message"
|
||||
git push origin main
|
||||
# CI/CD pipeline handles the rest!
|
||||
```
|
||||
|
||||
### Manual Deploy on Server
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
cd /var/www/turbotrades
|
||||
git pull && npm ci --production && cd frontend && npm ci && npm run build && cd .. && pm2 restart turbotrades
|
||||
```
|
||||
|
||||
### Check Status
|
||||
```bash
|
||||
ssh root@178.63.127.19 "pm2 status && pm2 logs turbotrades --lines 20"
|
||||
```
|
||||
|
||||
### Emergency Restart
|
||||
```bash
|
||||
ssh root@178.63.127.19 "pm2 restart turbotrades"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**🎉 Your deployment is now automated and production-ready!**
|
||||
|
||||
For issues or questions, check the troubleshooting section or review the logs.
|
||||
351
DEPLOY_NOW.md
Normal file
351
DEPLOY_NOW.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# 🚀 Quick Deployment Guide for TurboTrades
|
||||
|
||||
**Server:** 178.63.127.19
|
||||
**Repository:** git.turbotrades.dev/iDefineHD/TurboTrades
|
||||
**User:** root (or your SSH user)
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Super Quick Deploy (5 Minutes)
|
||||
|
||||
### 1️⃣ **Push Your Code**
|
||||
|
||||
```bash
|
||||
cd C:\Users\dg-ho\Documents\projects\TurboTrades
|
||||
|
||||
git add .
|
||||
git commit -m "feat: Complete admin panel with deployment setup"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 2️⃣ **Setup Server (One-Time)**
|
||||
|
||||
SSH into your server:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
```
|
||||
|
||||
Run the automated setup script:
|
||||
|
||||
```bash
|
||||
# Download and run setup script
|
||||
curl -o setup.sh https://git.turbotrades.dev/iDefineHD/TurboTrades/raw/branch/main/scripts/setup-server.sh
|
||||
chmod +x setup.sh
|
||||
sudo ./setup.sh
|
||||
```
|
||||
|
||||
**OR** manually setup:
|
||||
|
||||
```bash
|
||||
# Update system
|
||||
apt update && apt upgrade -y
|
||||
|
||||
# Install Node.js 20
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y nodejs
|
||||
|
||||
# Install MongoDB
|
||||
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
|
||||
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list
|
||||
apt update && apt install -y mongodb-org
|
||||
systemctl start mongod && systemctl enable mongod
|
||||
|
||||
# Install PM2
|
||||
npm install -g pm2
|
||||
|
||||
# Install Nginx
|
||||
apt install -y nginx
|
||||
systemctl start nginx && systemctl enable nginx
|
||||
|
||||
# Create directory
|
||||
mkdir -p /var/www/turbotrades
|
||||
cd /var/www/turbotrades
|
||||
|
||||
# Clone repository
|
||||
git clone https://git.turbotrades.dev/iDefineHD/TurboTrades.git .
|
||||
```
|
||||
|
||||
### 3️⃣ **Configure Environment**
|
||||
|
||||
Create `.env` file on server:
|
||||
|
||||
```bash
|
||||
nano /var/www/turbotrades/.env
|
||||
```
|
||||
|
||||
Add this configuration:
|
||||
|
||||
```env
|
||||
# Server
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Database
|
||||
MONGODB_URI=mongodb://localhost:27017/turbotrades
|
||||
|
||||
# Secrets (CHANGE THESE!)
|
||||
SESSION_SECRET=your-random-secret-here-change-this-123456789
|
||||
JWT_SECRET=your-jwt-secret-here-change-this-987654321
|
||||
JWT_ACCESS_EXPIRY=15m
|
||||
JWT_REFRESH_EXPIRY=7d
|
||||
|
||||
# Steam API
|
||||
STEAM_API_KEY=your-steam-api-key
|
||||
STEAM_RETURN_URL=http://178.63.127.19:3000/auth/steam/return
|
||||
|
||||
# CORS
|
||||
CORS_ORIGIN=http://178.63.127.19
|
||||
|
||||
# Admin Steam IDs (Your Steam ID)
|
||||
ADMIN_STEAM_IDS=76561198000000000
|
||||
|
||||
# Optional: Steam Bot
|
||||
STEAM_BOT_USERNAME=
|
||||
STEAM_BOT_PASSWORD=
|
||||
STEAM_BOT_SHARED_SECRET=
|
||||
STEAM_BOT_IDENTITY_SECRET=
|
||||
```
|
||||
|
||||
Save with `Ctrl+X`, then `Y`, then `Enter`
|
||||
|
||||
### 4️⃣ **Deploy Application**
|
||||
|
||||
```bash
|
||||
cd /var/www/turbotrades
|
||||
|
||||
# Install dependencies
|
||||
npm ci --production
|
||||
|
||||
# Build frontend
|
||||
cd frontend
|
||||
npm ci
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Start with PM2
|
||||
pm2 start ecosystem.config.js --env production
|
||||
pm2 save
|
||||
pm2 startup
|
||||
```
|
||||
|
||||
### 5️⃣ **Configure Nginx (Optional but Recommended)**
|
||||
|
||||
```bash
|
||||
nano /etc/nginx/sites-available/turbotrades
|
||||
```
|
||||
|
||||
Paste this:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name 178.63.127.19;
|
||||
|
||||
location / {
|
||||
root /var/www/turbotrades/frontend/dist;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
location /auth {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Enable and restart:
|
||||
|
||||
```bash
|
||||
ln -s /etc/nginx/sites-available/turbotrades /etc/nginx/sites-enabled/
|
||||
nginx -t
|
||||
systemctl restart nginx
|
||||
```
|
||||
|
||||
### 6️⃣ **Configure GitHub Actions (Automatic Deployments)**
|
||||
|
||||
1. Go to your repository settings/secrets (Gitea CI/CD settings)
|
||||
2. Click **"New repository secret"** or equivalent
|
||||
3. Add these secrets:
|
||||
|
||||
| Name | Value |
|
||||
|------|-------|
|
||||
| `SERVER_HOST` | `178.63.127.19` |
|
||||
| `SERVER_USER` | `root` (or your SSH username) |
|
||||
| `SERVER_PORT` | `22` |
|
||||
| `SSH_PRIVATE_KEY` | Your SSH private key (see below) |
|
||||
| `DEPLOY_PATH` | `/var/www/turbotrades` |
|
||||
|
||||
#### Generate SSH Key for Deployment:
|
||||
|
||||
On your server:
|
||||
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -C "deploy@turbotrades" -f ~/.ssh/turbotrades_deploy
|
||||
cat ~/.ssh/turbotrades_deploy.pub >> ~/.ssh/authorized_keys
|
||||
cat ~/.ssh/turbotrades_deploy # Copy this for GitHub Secret
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 After Setup - How to Deploy
|
||||
|
||||
### Automatic Deployment (Recommended):
|
||||
|
||||
```bash
|
||||
# Just push to main branch
|
||||
git add .
|
||||
git commit -m "Your changes"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
GitHub Actions will automatically:
|
||||
✅ Build frontend
|
||||
✅ Deploy to server
|
||||
✅ Restart PM2
|
||||
✅ Health check
|
||||
|
||||
Watch progress in your Gitea repository's Actions tab
|
||||
|
||||
### Manual Deployment:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
cd /var/www/turbotrades
|
||||
git pull origin main
|
||||
npm ci --production
|
||||
cd frontend && npm ci && npm run build && cd ..
|
||||
pm2 restart turbotrades
|
||||
pm2 logs turbotrades
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Check Status
|
||||
|
||||
### From Your Computer:
|
||||
|
||||
```bash
|
||||
# Check if site is running
|
||||
curl http://178.63.127.19:3000/api/health
|
||||
|
||||
# Check PM2 status via SSH
|
||||
ssh root@178.63.127.19 "pm2 status"
|
||||
|
||||
# Check logs via SSH
|
||||
ssh root@178.63.127.19 "pm2 logs turbotrades --lines 50"
|
||||
```
|
||||
|
||||
### On Server:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
|
||||
# Check PM2
|
||||
pm2 status
|
||||
pm2 logs turbotrades
|
||||
|
||||
# Check MongoDB
|
||||
systemctl status mongod
|
||||
|
||||
# Check Nginx
|
||||
systemctl status nginx
|
||||
|
||||
# Check application logs
|
||||
tail -f /var/www/turbotrades/logs/pm2-combined.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Quick Fixes
|
||||
|
||||
### App Not Starting:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
cd /var/www/turbotrades
|
||||
pm2 logs turbotrades --err
|
||||
pm2 restart turbotrades
|
||||
```
|
||||
|
||||
### MongoDB Not Running:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
systemctl start mongod
|
||||
systemctl status mongod
|
||||
```
|
||||
|
||||
### Need to Restart Everything:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
pm2 restart all
|
||||
systemctl restart mongod
|
||||
systemctl restart nginx
|
||||
```
|
||||
|
||||
### Port 3000 Already in Use:
|
||||
|
||||
```bash
|
||||
ssh root@178.63.127.19
|
||||
lsof -i :3000
|
||||
pm2 delete turbotrades
|
||||
pm2 start ecosystem.config.js --env production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Important URLs
|
||||
|
||||
- **Gitea Repo:** https://git.turbotrades.dev/iDefineHD/TurboTrades
|
||||
- **CI/CD Actions:** Check your Gitea repository's Actions tab
|
||||
- **Repository Secrets:** https://git.turbotrades.dev/iDefineHD/TurboTrades/settings
|
||||
- **Your Server:** http://178.63.127.19
|
||||
- **API Health:** http://178.63.127.19:3000/api/health
|
||||
- **Admin Panel:** http://178.63.127.19/admin
|
||||
|
||||
---
|
||||
|
||||
## 🎉 You're Done!
|
||||
|
||||
Visit: **http://178.63.127.19**
|
||||
|
||||
Your admin panel is fully functional with:
|
||||
- ✅ User Management
|
||||
- ✅ Promotion Analytics
|
||||
- ✅ Trading & Market Settings
|
||||
- ✅ Announcements
|
||||
- ✅ Maintenance Mode
|
||||
|
||||
---
|
||||
|
||||
## 📞 Need Help?
|
||||
|
||||
1. Check server logs: `ssh root@178.63.127.19 "pm2 logs"`
|
||||
2. Check Gitea Actions in your repository
|
||||
3. Review full guide: `DEPLOYMENT_GUIDE.md`
|
||||
|
||||
**Happy deploying! 🚀**
|
||||
@@ -1,318 +1,322 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useAuthStore } from './auth'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { useAuthStore } from "./auth";
|
||||
import { useToast } from "vue-toastification";
|
||||
|
||||
const toast = useToast()
|
||||
const toast = useToast();
|
||||
|
||||
export const useWebSocketStore = defineStore('websocket', () => {
|
||||
export const useWebSocketStore = defineStore("websocket", () => {
|
||||
// State
|
||||
const ws = ref(null)
|
||||
const isConnected = ref(false)
|
||||
const isConnecting = ref(false)
|
||||
const reconnectAttempts = ref(0)
|
||||
const maxReconnectAttempts = ref(5)
|
||||
const reconnectDelay = ref(1000)
|
||||
const heartbeatInterval = ref(null)
|
||||
const reconnectTimeout = ref(null)
|
||||
const messageQueue = ref([])
|
||||
const listeners = ref(new Map())
|
||||
const ws = ref(null);
|
||||
const isConnected = ref(false);
|
||||
const isConnecting = ref(false);
|
||||
const reconnectAttempts = ref(0);
|
||||
const maxReconnectAttempts = ref(5);
|
||||
const reconnectDelay = ref(1000);
|
||||
const heartbeatInterval = ref(null);
|
||||
const reconnectTimeout = ref(null);
|
||||
const messageQueue = ref([]);
|
||||
const listeners = ref(new Map());
|
||||
|
||||
// Computed
|
||||
const connectionStatus = computed(() => {
|
||||
if (isConnected.value) return 'connected'
|
||||
if (isConnecting.value) return 'connecting'
|
||||
return 'disconnected'
|
||||
})
|
||||
if (isConnected.value) return "connected";
|
||||
if (isConnecting.value) return "connecting";
|
||||
return "disconnected";
|
||||
});
|
||||
|
||||
const canReconnect = computed(() => {
|
||||
return reconnectAttempts.value < maxReconnectAttempts.value
|
||||
})
|
||||
return reconnectAttempts.value < maxReconnectAttempts.value;
|
||||
});
|
||||
|
||||
// Helper functions
|
||||
const getWebSocketUrl = () => {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
const host = window.location.host
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
const host = window.location.host;
|
||||
|
||||
// In development, use the proxy
|
||||
if (import.meta.env.DEV) {
|
||||
return `ws://localhost:3000/ws`
|
||||
}
|
||||
|
||||
return `${protocol}//${host}/ws`
|
||||
}
|
||||
// Always use the current host (works with VS Code tunnels and proxies)
|
||||
return `${protocol}//${host}/ws`;
|
||||
};
|
||||
|
||||
const clearHeartbeat = () => {
|
||||
if (heartbeatInterval.value) {
|
||||
clearInterval(heartbeatInterval.value)
|
||||
heartbeatInterval.value = null
|
||||
clearInterval(heartbeatInterval.value);
|
||||
heartbeatInterval.value = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clearReconnectTimeout = () => {
|
||||
if (reconnectTimeout.value) {
|
||||
clearTimeout(reconnectTimeout.value)
|
||||
reconnectTimeout.value = null
|
||||
clearTimeout(reconnectTimeout.value);
|
||||
reconnectTimeout.value = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const startHeartbeat = () => {
|
||||
clearHeartbeat()
|
||||
clearHeartbeat();
|
||||
|
||||
// Send ping every 30 seconds
|
||||
heartbeatInterval.value = setInterval(() => {
|
||||
if (isConnected.value && ws.value?.readyState === WebSocket.OPEN) {
|
||||
send({ type: 'ping' })
|
||||
send({ type: "ping" });
|
||||
}
|
||||
}, 30000)
|
||||
}
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
// Actions
|
||||
const connect = () => {
|
||||
if (ws.value?.readyState === WebSocket.OPEN || isConnecting.value) {
|
||||
console.log('WebSocket already connected or connecting')
|
||||
return
|
||||
console.log("WebSocket already connected or connecting");
|
||||
return;
|
||||
}
|
||||
|
||||
isConnecting.value = true
|
||||
clearReconnectTimeout()
|
||||
isConnecting.value = true;
|
||||
clearReconnectTimeout();
|
||||
|
||||
try {
|
||||
const wsUrl = getWebSocketUrl()
|
||||
console.log('Connecting to WebSocket:', wsUrl)
|
||||
const wsUrl = getWebSocketUrl();
|
||||
console.log("Connecting to WebSocket:", wsUrl);
|
||||
|
||||
ws.value = new WebSocket(wsUrl)
|
||||
ws.value = new WebSocket(wsUrl);
|
||||
|
||||
ws.value.onopen = () => {
|
||||
console.log('WebSocket connected')
|
||||
isConnected.value = true
|
||||
isConnecting.value = false
|
||||
reconnectAttempts.value = 0
|
||||
console.log("WebSocket connected");
|
||||
isConnected.value = true;
|
||||
isConnecting.value = false;
|
||||
reconnectAttempts.value = 0;
|
||||
|
||||
startHeartbeat()
|
||||
startHeartbeat();
|
||||
|
||||
// Send queued messages
|
||||
while (messageQueue.value.length > 0) {
|
||||
const message = messageQueue.value.shift()
|
||||
send(message)
|
||||
const message = messageQueue.value.shift();
|
||||
send(message);
|
||||
}
|
||||
|
||||
// Emit connected event
|
||||
emit('connected', { timestamp: Date.now() })
|
||||
}
|
||||
emit("connected", { timestamp: Date.now() });
|
||||
};
|
||||
|
||||
ws.value.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
console.log('WebSocket message received:', data)
|
||||
const data = JSON.parse(event.data);
|
||||
console.log("WebSocket message received:", data);
|
||||
|
||||
handleMessage(data)
|
||||
handleMessage(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to parse WebSocket message:', error)
|
||||
console.error("Failed to parse WebSocket message:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ws.value.onerror = (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
isConnecting.value = false
|
||||
}
|
||||
console.error("WebSocket error:", error);
|
||||
isConnecting.value = false;
|
||||
};
|
||||
|
||||
ws.value.onclose = (event) => {
|
||||
console.log('WebSocket closed:', event.code, event.reason)
|
||||
isConnected.value = false
|
||||
isConnecting.value = false
|
||||
clearHeartbeat()
|
||||
console.log("WebSocket closed:", event.code, event.reason);
|
||||
isConnected.value = false;
|
||||
isConnecting.value = false;
|
||||
clearHeartbeat();
|
||||
|
||||
// Emit disconnected event
|
||||
emit('disconnected', {
|
||||
emit("disconnected", {
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
// Attempt to reconnect
|
||||
if (!event.wasClean && canReconnect.value) {
|
||||
scheduleReconnect()
|
||||
scheduleReconnect();
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Failed to create WebSocket connection:', error)
|
||||
isConnecting.value = false
|
||||
console.error("Failed to create WebSocket connection:", error);
|
||||
isConnecting.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const disconnect = () => {
|
||||
clearHeartbeat()
|
||||
clearReconnectTimeout()
|
||||
reconnectAttempts.value = maxReconnectAttempts.value // Prevent auto-reconnect
|
||||
clearHeartbeat();
|
||||
clearReconnectTimeout();
|
||||
reconnectAttempts.value = maxReconnectAttempts.value; // Prevent auto-reconnect
|
||||
|
||||
if (ws.value) {
|
||||
ws.value.close(1000, 'Client disconnect')
|
||||
ws.value = null
|
||||
ws.value.close(1000, "Client disconnect");
|
||||
ws.value = null;
|
||||
}
|
||||
|
||||
isConnected.value = false
|
||||
isConnecting.value = false
|
||||
}
|
||||
isConnected.value = false;
|
||||
isConnecting.value = false;
|
||||
};
|
||||
|
||||
const scheduleReconnect = () => {
|
||||
if (!canReconnect.value) {
|
||||
console.log('Max reconnect attempts reached')
|
||||
toast.error('Lost connection to server. Please refresh the page.')
|
||||
return
|
||||
console.log("Max reconnect attempts reached");
|
||||
toast.error("Lost connection to server. Please refresh the page.");
|
||||
return;
|
||||
}
|
||||
|
||||
reconnectAttempts.value++
|
||||
const delay = reconnectDelay.value * Math.pow(2, reconnectAttempts.value - 1)
|
||||
reconnectAttempts.value++;
|
||||
const delay =
|
||||
reconnectDelay.value * Math.pow(2, reconnectAttempts.value - 1);
|
||||
|
||||
console.log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempts.value}/${maxReconnectAttempts.value})`)
|
||||
console.log(
|
||||
`Reconnecting in ${delay}ms (attempt ${reconnectAttempts.value}/${maxReconnectAttempts.value})`
|
||||
);
|
||||
|
||||
clearReconnectTimeout()
|
||||
clearReconnectTimeout();
|
||||
reconnectTimeout.value = setTimeout(() => {
|
||||
connect()
|
||||
}, delay)
|
||||
}
|
||||
connect();
|
||||
}, delay);
|
||||
};
|
||||
|
||||
const send = (message) => {
|
||||
if (!ws.value || ws.value.readyState !== WebSocket.OPEN) {
|
||||
console.warn('WebSocket not connected, queueing message:', message)
|
||||
messageQueue.value.push(message)
|
||||
return false
|
||||
console.warn("WebSocket not connected, queueing message:", message);
|
||||
messageQueue.value.push(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = typeof message === 'string' ? message : JSON.stringify(message)
|
||||
ws.value.send(payload)
|
||||
return true
|
||||
const payload =
|
||||
typeof message === "string" ? message : JSON.stringify(message);
|
||||
ws.value.send(payload);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to send WebSocket message:', error)
|
||||
return false
|
||||
console.error("Failed to send WebSocket message:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleMessage = (data) => {
|
||||
const { type, data: payload, timestamp } = data
|
||||
const { type, data: payload, timestamp } = data;
|
||||
|
||||
switch (type) {
|
||||
case 'connected':
|
||||
console.log('Server confirmed connection:', payload)
|
||||
break
|
||||
case "connected":
|
||||
console.log("Server confirmed connection:", payload);
|
||||
break;
|
||||
|
||||
case 'pong':
|
||||
case "pong":
|
||||
// Heartbeat response
|
||||
break
|
||||
break;
|
||||
|
||||
case 'notification':
|
||||
case "notification":
|
||||
if (payload?.message) {
|
||||
toast.info(payload.message)
|
||||
toast.info(payload.message);
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case 'balance_update':
|
||||
case "balance_update":
|
||||
// Update user balance
|
||||
const authStore = useAuthStore()
|
||||
const authStore = useAuthStore();
|
||||
if (payload?.balance !== undefined) {
|
||||
authStore.updateBalance(payload.balance)
|
||||
authStore.updateBalance(payload.balance);
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case 'item_sold':
|
||||
toast.success(`Your item "${payload?.itemName || 'item'}" has been sold!`)
|
||||
break
|
||||
case "item_sold":
|
||||
toast.success(
|
||||
`Your item "${payload?.itemName || "item"}" has been sold!`
|
||||
);
|
||||
break;
|
||||
|
||||
case 'item_purchased':
|
||||
toast.success(`Successfully purchased "${payload?.itemName || 'item'}"!`)
|
||||
break
|
||||
case "item_purchased":
|
||||
toast.success(
|
||||
`Successfully purchased "${payload?.itemName || "item"}"!`
|
||||
);
|
||||
break;
|
||||
|
||||
case 'trade_status':
|
||||
if (payload?.status === 'completed') {
|
||||
toast.success('Trade completed successfully!')
|
||||
} else if (payload?.status === 'failed') {
|
||||
toast.error(`Trade failed: ${payload?.reason || 'Unknown error'}`)
|
||||
case "trade_status":
|
||||
if (payload?.status === "completed") {
|
||||
toast.success("Trade completed successfully!");
|
||||
} else if (payload?.status === "failed") {
|
||||
toast.error(`Trade failed: ${payload?.reason || "Unknown error"}`);
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case 'price_update':
|
||||
case 'listing_update':
|
||||
case 'market_update':
|
||||
case "price_update":
|
||||
case "listing_update":
|
||||
case "market_update":
|
||||
// These will be handled by listeners
|
||||
break
|
||||
break;
|
||||
|
||||
case 'announcement':
|
||||
case "announcement":
|
||||
if (payload?.message) {
|
||||
toast.warning(payload.message, { timeout: 10000 })
|
||||
toast.warning(payload.message, { timeout: 10000 });
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
console.error('Server error:', payload)
|
||||
case "error":
|
||||
console.error("Server error:", payload);
|
||||
if (payload?.message) {
|
||||
toast.error(payload.message)
|
||||
toast.error(payload.message);
|
||||
}
|
||||
break
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Unhandled message type:', type)
|
||||
console.log("Unhandled message type:", type);
|
||||
}
|
||||
|
||||
// Emit to listeners
|
||||
emit(type, payload)
|
||||
}
|
||||
emit(type, payload);
|
||||
};
|
||||
|
||||
const on = (event, callback) => {
|
||||
if (!listeners.value.has(event)) {
|
||||
listeners.value.set(event, [])
|
||||
listeners.value.set(event, []);
|
||||
}
|
||||
listeners.value.get(event).push(callback)
|
||||
listeners.value.get(event).push(callback);
|
||||
|
||||
// Return unsubscribe function
|
||||
return () => off(event, callback)
|
||||
}
|
||||
return () => off(event, callback);
|
||||
};
|
||||
|
||||
const off = (event, callback) => {
|
||||
if (!listeners.value.has(event)) return
|
||||
if (!listeners.value.has(event)) return;
|
||||
|
||||
const callbacks = listeners.value.get(event)
|
||||
const index = callbacks.indexOf(callback)
|
||||
const callbacks = listeners.value.get(event);
|
||||
const index = callbacks.indexOf(callback);
|
||||
|
||||
if (index > -1) {
|
||||
callbacks.splice(index, 1)
|
||||
callbacks.splice(index, 1);
|
||||
}
|
||||
|
||||
if (callbacks.length === 0) {
|
||||
listeners.value.delete(event)
|
||||
listeners.value.delete(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const emit = (event, data) => {
|
||||
if (!listeners.value.has(event)) return
|
||||
if (!listeners.value.has(event)) return;
|
||||
|
||||
const callbacks = listeners.value.get(event)
|
||||
callbacks.forEach(callback => {
|
||||
const callbacks = listeners.value.get(event);
|
||||
callbacks.forEach((callback) => {
|
||||
try {
|
||||
callback(data)
|
||||
callback(data);
|
||||
} catch (error) {
|
||||
console.error(`Error in event listener for "${event}":`, error)
|
||||
console.error(`Error in event listener for "${event}":`, error);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const once = (event, callback) => {
|
||||
const wrappedCallback = (data) => {
|
||||
callback(data)
|
||||
off(event, wrappedCallback)
|
||||
}
|
||||
return on(event, wrappedCallback)
|
||||
}
|
||||
callback(data);
|
||||
off(event, wrappedCallback);
|
||||
};
|
||||
return on(event, wrappedCallback);
|
||||
};
|
||||
|
||||
const clearListeners = () => {
|
||||
listeners.value.clear()
|
||||
}
|
||||
listeners.value.clear();
|
||||
};
|
||||
|
||||
// Ping the server
|
||||
const ping = () => {
|
||||
send({ type: 'ping' })
|
||||
}
|
||||
send({ type: "ping" });
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
@@ -337,5 +341,5 @@ export const useWebSocketStore = defineStore('websocket', () => {
|
||||
emit,
|
||||
clearListeners,
|
||||
ping,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
@@ -12,6 +12,13 @@ export default defineConfig({
|
||||
},
|
||||
server: {
|
||||
port: 5173,
|
||||
host: true, // Listen on all addresses
|
||||
allowedHosts: [
|
||||
".trycloudflare.com", // Cloudflare Quick Tunnels
|
||||
".turbo.local", // Custom tunnel domains
|
||||
".devtunnels.ms", // VS Code Dev Tunnels
|
||||
"localhost",
|
||||
],
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://localhost:3000",
|
||||
@@ -19,8 +26,9 @@ export default defineConfig({
|
||||
// Don't rewrite - backend expects /api prefix
|
||||
},
|
||||
"/ws": {
|
||||
target: "ws://localhost:3000",
|
||||
target: "http://localhost:3000",
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
459
scripts/setup-server.sh
Normal file
459
scripts/setup-server.sh
Normal file
@@ -0,0 +1,459 @@
|
||||
#!/bin/bash
|
||||
|
||||
#######################################################
|
||||
# TurboTrades Server Setup Script
|
||||
# Automated setup for production server 178.63.127.19
|
||||
#######################################################
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SERVER_IP="178.63.127.19"
|
||||
DEPLOY_PATH="/var/www/turbotrades"
|
||||
APP_NAME="turbotrades"
|
||||
NODE_VERSION="20"
|
||||
|
||||
# Functions
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if running as root
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
print_warning "This script should be run as root. Some commands may require sudo."
|
||||
read -p "Continue anyway? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Update system
|
||||
update_system() {
|
||||
print_status "Updating system packages..."
|
||||
apt update && apt upgrade -y
|
||||
print_success "System updated"
|
||||
}
|
||||
|
||||
# Install Node.js
|
||||
install_nodejs() {
|
||||
print_status "Installing Node.js ${NODE_VERSION}..."
|
||||
|
||||
if command -v node &> /dev/null; then
|
||||
NODE_CURRENT=$(node -v)
|
||||
print_warning "Node.js is already installed: $NODE_CURRENT"
|
||||
read -p "Reinstall/Update? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash -
|
||||
apt-get install -y nodejs
|
||||
|
||||
print_success "Node.js installed: $(node -v)"
|
||||
print_success "NPM installed: $(npm -v)"
|
||||
}
|
||||
|
||||
# Install MongoDB
|
||||
install_mongodb() {
|
||||
print_status "Installing MongoDB..."
|
||||
|
||||
if command -v mongod &> /dev/null; then
|
||||
print_warning "MongoDB is already installed"
|
||||
read -p "Reinstall? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Import MongoDB public key
|
||||
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
|
||||
gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
|
||||
|
||||
# Add MongoDB repository
|
||||
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | \
|
||||
tee /etc/apt/sources.list.d/mongodb-org-7.0.list
|
||||
|
||||
# Install MongoDB
|
||||
apt update
|
||||
apt install -y mongodb-org
|
||||
|
||||
# Start and enable MongoDB
|
||||
systemctl start mongod
|
||||
systemctl enable mongod
|
||||
|
||||
print_success "MongoDB installed and started"
|
||||
}
|
||||
|
||||
# Install PM2
|
||||
install_pm2() {
|
||||
print_status "Installing PM2..."
|
||||
|
||||
if command -v pm2 &> /dev/null; then
|
||||
print_warning "PM2 is already installed: $(pm2 -v)"
|
||||
read -p "Reinstall? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
npm install -g pm2
|
||||
|
||||
# Setup PM2 startup script
|
||||
pm2 startup systemd -u $SUDO_USER --hp /home/$SUDO_USER
|
||||
|
||||
print_success "PM2 installed: $(pm2 -v)"
|
||||
}
|
||||
|
||||
# Install Nginx
|
||||
install_nginx() {
|
||||
print_status "Installing Nginx..."
|
||||
|
||||
if command -v nginx &> /dev/null; then
|
||||
print_warning "Nginx is already installed"
|
||||
read -p "Continue anyway? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
apt install -y nginx
|
||||
systemctl start nginx
|
||||
systemctl enable nginx
|
||||
|
||||
print_success "Nginx installed and started"
|
||||
}
|
||||
|
||||
# Install Git
|
||||
install_git() {
|
||||
print_status "Installing Git..."
|
||||
|
||||
if command -v git &> /dev/null; then
|
||||
print_success "Git is already installed: $(git --version)"
|
||||
return
|
||||
fi
|
||||
|
||||
apt install -y git
|
||||
print_success "Git installed: $(git --version)"
|
||||
}
|
||||
|
||||
# Create deployment directory
|
||||
create_deploy_directory() {
|
||||
print_status "Creating deployment directory: ${DEPLOY_PATH}"
|
||||
|
||||
mkdir -p ${DEPLOY_PATH}
|
||||
|
||||
# Set ownership to current user
|
||||
if [ -n "$SUDO_USER" ]; then
|
||||
chown -R $SUDO_USER:$SUDO_USER ${DEPLOY_PATH}
|
||||
fi
|
||||
|
||||
print_success "Deployment directory created"
|
||||
}
|
||||
|
||||
# Setup firewall
|
||||
setup_firewall() {
|
||||
print_status "Configuring firewall..."
|
||||
|
||||
if ! command -v ufw &> /dev/null; then
|
||||
apt install -y ufw
|
||||
fi
|
||||
|
||||
# Allow SSH, HTTP, HTTPS
|
||||
ufw allow 22/tcp
|
||||
ufw allow 80/tcp
|
||||
ufw allow 443/tcp
|
||||
|
||||
# Enable firewall
|
||||
ufw --force enable
|
||||
|
||||
print_success "Firewall configured"
|
||||
ufw status
|
||||
}
|
||||
|
||||
# Generate SSH deploy key
|
||||
generate_deploy_key() {
|
||||
print_status "Generating SSH deploy key..."
|
||||
|
||||
SSH_DIR="/home/$SUDO_USER/.ssh"
|
||||
DEPLOY_KEY="$SSH_DIR/turbotrades_deploy_key"
|
||||
|
||||
if [ -f "$DEPLOY_KEY" ]; then
|
||||
print_warning "Deploy key already exists at $DEPLOY_KEY"
|
||||
read -p "Generate new key? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p $SSH_DIR
|
||||
ssh-keygen -t ed25519 -C "deploy@turbotrades" -f $DEPLOY_KEY -N ""
|
||||
|
||||
chown -R $SUDO_USER:$SUDO_USER $SSH_DIR
|
||||
chmod 700 $SSH_DIR
|
||||
chmod 600 $DEPLOY_KEY
|
||||
chmod 644 $DEPLOY_KEY.pub
|
||||
|
||||
print_success "Deploy key generated!"
|
||||
echo ""
|
||||
print_status "=== PUBLIC KEY (Add to GitHub Deploy Keys) ==="
|
||||
cat $DEPLOY_KEY.pub
|
||||
echo ""
|
||||
print_status "=== PRIVATE KEY (Add to GitHub Secrets as SSH_PRIVATE_KEY) ==="
|
||||
cat $DEPLOY_KEY
|
||||
echo ""
|
||||
print_warning "Save these keys securely!"
|
||||
}
|
||||
|
||||
# Create .env template
|
||||
create_env_template() {
|
||||
print_status "Creating .env template..."
|
||||
|
||||
ENV_FILE="${DEPLOY_PATH}/.env.example"
|
||||
|
||||
cat > $ENV_FILE << 'EOF'
|
||||
# Server Configuration
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Database
|
||||
MONGODB_URI=mongodb://localhost:27017/turbotrades
|
||||
|
||||
# Session Secret (Generate a secure random string)
|
||||
SESSION_SECRET=change-this-to-a-random-string
|
||||
|
||||
# Steam API
|
||||
STEAM_API_KEY=your-steam-api-key-here
|
||||
STEAM_RETURN_URL=http://178.63.127.19:3000/auth/steam/return
|
||||
|
||||
# JWT Secret (Generate a secure random string)
|
||||
JWT_SECRET=change-this-to-a-random-string
|
||||
JWT_ACCESS_EXPIRY=15m
|
||||
JWT_REFRESH_EXPIRY=7d
|
||||
|
||||
# CORS
|
||||
CORS_ORIGIN=http://178.63.127.19
|
||||
|
||||
# Redis (if using)
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Admin Steam IDs (comma-separated)
|
||||
ADMIN_STEAM_IDS=76561198000000000
|
||||
|
||||
# Bot Configuration
|
||||
STEAM_BOT_USERNAME=your-bot-username
|
||||
STEAM_BOT_PASSWORD=your-bot-password
|
||||
STEAM_BOT_SHARED_SECRET=your-bot-shared-secret
|
||||
STEAM_BOT_IDENTITY_SECRET=your-bot-identity-secret
|
||||
|
||||
# CSGOFloat API (optional)
|
||||
CSGOFLOAT_API_KEY=your-csgofloat-api-key
|
||||
|
||||
# Pricing API (optional)
|
||||
PRICING_API_KEY=your-pricing-api-key
|
||||
EOF
|
||||
|
||||
print_success ".env template created at $ENV_FILE"
|
||||
print_warning "Remember to create ${DEPLOY_PATH}/.env with actual values!"
|
||||
}
|
||||
|
||||
# Create Nginx configuration
|
||||
create_nginx_config() {
|
||||
print_status "Creating Nginx configuration..."
|
||||
|
||||
NGINX_CONFIG="/etc/nginx/sites-available/turbotrades"
|
||||
|
||||
cat > $NGINX_CONFIG << 'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name 178.63.127.19;
|
||||
|
||||
client_max_body_size 10M;
|
||||
|
||||
# Frontend (Vite build)
|
||||
location / {
|
||||
root /var/www/turbotrades/frontend/dist;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
|
||||
# Backend API
|
||||
location /api {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_connect_timeout 75s;
|
||||
}
|
||||
|
||||
# WebSocket support
|
||||
location /ws {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
# Auth routes
|
||||
location /auth {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
}
|
||||
EOF
|
||||
|
||||
# Enable the site
|
||||
ln -sf $NGINX_CONFIG /etc/nginx/sites-enabled/turbotrades
|
||||
|
||||
# Test Nginx configuration
|
||||
nginx -t
|
||||
|
||||
# Restart Nginx
|
||||
systemctl restart nginx
|
||||
|
||||
print_success "Nginx configuration created and enabled"
|
||||
}
|
||||
|
||||
# Create logs directory
|
||||
create_logs_directory() {
|
||||
print_status "Creating logs directory..."
|
||||
|
||||
LOG_DIR="${DEPLOY_PATH}/logs"
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
if [ -n "$SUDO_USER" ]; then
|
||||
chown -R $SUDO_USER:$SUDO_USER $LOG_DIR
|
||||
fi
|
||||
|
||||
print_success "Logs directory created at $LOG_DIR"
|
||||
}
|
||||
|
||||
# Print next steps
|
||||
print_next_steps() {
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
print_success "Server setup complete!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
print_status "Next steps:"
|
||||
echo ""
|
||||
echo "1. Add the deploy key to Gitea:"
|
||||
echo " - Go to: https://git.turbotrades.dev/iDefineHD/TurboTrades/settings/keys"
|
||||
echo " - Add the PUBLIC key shown above"
|
||||
echo ""
|
||||
echo "2. Add Repository Secrets:"
|
||||
echo " - Go to: https://git.turbotrades.dev/iDefineHD/TurboTrades/settings"
|
||||
echo " - Add these secrets:"
|
||||
echo " - SERVER_HOST: ${SERVER_IP}"
|
||||
echo " - SERVER_USER: $(whoami)"
|
||||
echo " - SERVER_PORT: 22"
|
||||
echo " - SSH_PRIVATE_KEY: (the private key shown above)"
|
||||
echo " - DEPLOY_PATH: ${DEPLOY_PATH}"
|
||||
echo ""
|
||||
echo "3. Clone your repository:"
|
||||
echo " cd ${DEPLOY_PATH}"
|
||||
echo " git clone https://git.turbotrades.dev/iDefineHD/TurboTrades.git ."
|
||||
echo ""
|
||||
echo "4. Create .env file:"
|
||||
echo " cp ${DEPLOY_PATH}/.env.example ${DEPLOY_PATH}/.env"
|
||||
echo " nano ${DEPLOY_PATH}/.env"
|
||||
echo " (Fill in your actual configuration)"
|
||||
echo ""
|
||||
echo "5. Install dependencies and build:"
|
||||
echo " cd ${DEPLOY_PATH}"
|
||||
echo " npm ci --production"
|
||||
echo " cd frontend && npm ci && npm run build && cd .."
|
||||
echo ""
|
||||
echo "6. Start the application:"
|
||||
echo " pm2 start ecosystem.config.js --env production"
|
||||
echo " pm2 save"
|
||||
echo ""
|
||||
echo "7. Visit your application:"
|
||||
echo " http://${SERVER_IP}"
|
||||
echo ""
|
||||
print_success "Setup complete! 🎉"
|
||||
}
|
||||
|
||||
# Main script
|
||||
main() {
|
||||
echo "=========================================="
|
||||
echo " TurboTrades Server Setup"
|
||||
echo " Server: ${SERVER_IP}"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
check_root
|
||||
|
||||
print_status "Starting server setup..."
|
||||
echo ""
|
||||
|
||||
# Run all setup functions
|
||||
update_system
|
||||
install_nodejs
|
||||
install_mongodb
|
||||
install_pm2
|
||||
install_nginx
|
||||
install_git
|
||||
create_deploy_directory
|
||||
setup_firewall
|
||||
generate_deploy_key
|
||||
create_env_template
|
||||
create_nginx_config
|
||||
create_logs_directory
|
||||
|
||||
# Print next steps
|
||||
print_next_steps
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main
|
||||
Reference in New Issue
Block a user