Refactor deployment documentation for ScriptShare, consolidating deployment guides into a single comprehensive document while removing outdated Docker deployment files and scripts. Enhance clarity on deployment options across various platforms and streamline the application structure overview.
Some checks failed
Build and Test / test (push) Has been cancelled
Build and Test / docker-build (push) Has been cancelled

This commit is contained in:
2025-08-20 00:43:09 +01:00
parent 68a02d1e5f
commit 58d8886480
17 changed files with 588 additions and 1893 deletions

65
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,65 @@
name: Build and Test
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Build frontend
run: npm run build
- name: Build API
run: npm run build:api
docker-build:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build frontend Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: scriptshare-frontend:latest
- name: Build API Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.api
push: false
tags: scriptshare-api:latest
- name: Test Docker containers
run: |
# Test that images were built successfully
docker images | grep scriptshare

View File

@ -1,102 +0,0 @@
name: Deploy to DigitalOcean
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
# Test job to run before deployment
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Build frontend
run: npm run build
env:
VITE_APP_NAME: ScriptShare
VITE_APP_URL: https://scriptshare.example.com
VITE_ANALYTICS_ENABLED: true
# Deploy job (only on main branch)
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Get app info
id: app-info
run: |
APP_ID=$(doctl apps list --format ID,Spec.Name --no-header | grep scriptshare | cut -d' ' -f1)
echo "app-id=$APP_ID" >> $GITHUB_OUTPUT
- name: Trigger deployment
run: |
doctl apps create-deployment ${{ steps.app-info.outputs.app-id }} --wait
- name: Run database migrations
run: |
# Wait for deployment to complete
sleep 60
# Run migrations via the app console (if needed)
echo "Deployment completed. Please run database migrations manually if this is the first deployment."
echo "Command: npm run db:setup:prod"
# Database migration job (manual trigger)
migrate:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run migrations
run: npm run db:migrate:prod
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
# Manual workflow dispatch for running migrations
on:
workflow_dispatch:
inputs:
action:
description: 'Action to perform'
required: true
default: 'migrate'
type: choice
options:
- migrate
- setup

View File

@ -1,248 +1,261 @@
# DigitalOcean Deployment Guide # 🚀 ScriptShare - Platform Deployment Guide
This guide walks you through deploying ScriptShare to DigitalOcean App Platform with a managed MySQL database. ## Overview
## Prerequisites ScriptShare is a modern React application with a Node.js API backend, designed to work seamlessly with any deployment platform including **Vercel**, **Coolify**, **DigitalOcean App Platform**, **Railway**, **Render**, and others.
- DigitalOcean account ## 📦 Application Structure
- GitHub repository containing your code
- Basic familiarity with DigitalOcean App Platform
## Architecture Overview ### Frontend (React + Vite)
- **Dockerfile**: `Dockerfile`
- **Build**: Vite-based React application
- **Output**: Static files served by Nginx
- **Port**: 80
The deployment consists of: ### Backend API (Node.js + Express)
- **Frontend**: Static site (React/Vite build) - **Dockerfile**: `Dockerfile.api`
- **Backend API**: Node.js service with Express - **Runtime**: Node.js 18 with TypeScript
- **Database**: DigitalOcean Managed MySQL Database - **Port**: 3000
- **Health Check**: `/api/health`
## Step 1: Prepare Your Repository ## 🔧 Deployment Options
1. Ensure all the deployment files are in your GitHub repository: ### Option 1: Vercel (Recommended for Frontend)
```
.do/app.yaml # App Platform configuration **Frontend Deployment:**
Dockerfile.api # Backend API container 1. Connect your repository to Vercel
drizzle.config.production.ts # Production DB config 2. Set build command: `npm run build`
scripts/migrate-production.js # Migration script 3. Set output directory: `dist`
scripts/setup-production-db.js # DB setup script 4. Configure environment variables:
env.production.example # Environment variables template
```
2. Commit and push all changes to your main branch.
## Step 2: Create the DigitalOcean App
### Option A: Using the DigitalOcean Console
1. Go to the [DigitalOcean App Platform](https://cloud.digitalocean.com/apps)
2. Click **"Create App"**
3. Choose **"GitHub"** as your source
4. Select your repository and branch (usually `main`)
5. DigitalOcean will automatically detect the `app.yaml` configuration
### Option B: Using the CLI
```bash
# Install doctl CLI
# On macOS: brew install doctl
# On Linux: snap install doctl
# Authenticate
doctl auth init
# Create the app
doctl apps create --spec .do/app.yaml
```
## Step 3: Configure Environment Variables
In the DigitalOcean dashboard, go to your app's Settings > Environment Variables and set:
### Required Variables
```
JWT_SECRET=your-super-secret-jwt-key-here-change-this-in-production
ADMIN_EMAIL=admin@yourcompany.com
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-secure-password
```
### Optional Variables
``` ```
VITE_APP_NAME=ScriptShare
VITE_APP_URL=https://your-domain.vercel.app
VITE_ANALYTICS_ENABLED=true VITE_ANALYTICS_ENABLED=true
RATE_LIMIT_ENABLED=true
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100
``` ```
⚠️ **Security Note**: Generate a strong JWT secret: **API Deployment:**
- Deploy API separately to platforms like Railway, Render, or DigitalOcean
- Or use Vercel Functions (requires code modification)
### Option 2: Coolify (Full Stack)
**Deploy both frontend and API:**
1. Create application from Git repository
2. **Frontend**:
- Use `Dockerfile`
- Port: 80
3. **API**:
- Use `Dockerfile.api`
- Port: 3000
4. Configure environment variables
### Option 3: DigitalOcean App Platform
Create `app.yaml`:
```yaml
name: scriptshare
services:
- name: frontend
source_dir: /
dockerfile_path: Dockerfile
github:
repo: your-username/scriptshare-cursor
branch: main
http_port: 80
routes:
- path: /
- name: api
source_dir: /
dockerfile_path: Dockerfile.api
github:
repo: your-username/scriptshare-cursor
branch: main
http_port: 3000
routes:
- path: /api
envs:
- key: NODE_ENV
value: production
- key: DATABASE_URL
value: ${DATABASE_URL}
databases:
- name: scriptshare-db
engine: MYSQL
version: "8"
```
### Option 4: Railway
1. **Frontend**: Connect repo, Railway auto-detects Dockerfile
2. **API**: Deploy from same repo using `Dockerfile.api`
3. **Database**: Add MySQL service
4. Configure environment variables
### Option 5: Render
1. **Frontend**:
- Static Site
- Build Command: `npm run build`
- Publish Directory: `dist`
2. **API**:
- Web Service
- Docker build using `Dockerfile.api`
3. **Database**: Add MySQL database
## 🏗️ Build Commands
### Frontend
```bash ```bash
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" # Install dependencies
npm install
# Build for production
npm run build
# Preview build
npm run preview
``` ```
## Step 4: Database Setup ### API
The managed MySQL database will be automatically created. After the first deployment:
1. **Run Database Migrations**:
```bash ```bash
# In your app's console (or via GitHub Actions) # Install dependencies
npm run db:setup:prod npm install
# Build TypeScript
npm run build:api
# Start API server
npm run start:api
``` ```
2. **Verify Database Connection**: ## 🔐 Environment Variables
Check the API health endpoint: `https://your-api-url/api/health`
## Step 5: Update App Configuration ### Frontend (Build-time)
- `VITE_APP_NAME` - Application name
- `VITE_APP_URL` - Frontend URL
- `VITE_ANALYTICS_ENABLED` - Enable analytics (true/false)
1. **Update Frontend URLs**: After deployment, update the environment variables with actual URLs: ### API (Runtime)
- `NODE_ENV` - Environment (production/development)
- `PORT` - Server port (default: 3000)
- `DATABASE_URL` - MySQL connection string
- `JWT_SECRET` - JWT secret key
- `CORS_ORIGIN` - Allowed CORS origins
## 🗄️ Database Setup
### MySQL Connection String Format:
``` ```
VITE_APP_URL=https://your-frontend-url.ondigitalocean.app DATABASE_URL=mysql://username:password@host:port/database
VITE_API_URL=https://your-api-url.ondigitalocean.app/api
CORS_ORIGIN=https://your-frontend-url.ondigitalocean.app
``` ```
2. **Redeploy**: The app will automatically redeploy when you change environment variables. ### Required Tables:
The application uses Drizzle ORM. Run migrations after deployment:
## Step 6: Custom Domain (Optional)
1. In your app settings, go to **Domains**
2. Click **Add Domain**
3. Enter your domain name
4. Configure DNS records as instructed
## Database Management
### Connecting to the Database
```bash ```bash
# Get connection string from DigitalOcean dashboard npm run db:migrate
mysql -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED
``` ```
### Running Migrations ## 🔍 Health Checks
### Frontend Health Check:
```
GET /health
```
### API Health Check:
```
GET /api/health
```
## 📝 Platform-Specific Notes
### Vercel
- Frontend deploys automatically
- Use Vercel Functions for API (requires modification)
- Environment variables in Vercel dashboard
### Coolify
- Supports full Docker deployment
- Easy environment variable management
- Built-in SSL and domain management
### DigitalOcean App Platform
- Use `app.yaml` for configuration
- Automatic HTTPS
- Managed database available
### Railway
- Auto-deployment from Git
- Environment variables in dashboard
- Add-on database services
### Render
- Separate frontend (static) and backend (web service)
- Auto-deployment from Git
- Environment variables in dashboard
## 🐳 Docker Commands
### Build Frontend:
```bash ```bash
# Production migration docker build -t scriptshare-frontend .
npm run db:migrate:prod docker run -p 3000:80 scriptshare-frontend
# Create new migration
npm run db:generate
``` ```
### Backup and Restore ### Build API:
DigitalOcean provides automatic daily backups. For manual backups:
```bash ```bash
# Create backup docker build -f Dockerfile.api -t scriptshare-api .
mysqldump -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED > backup.sql docker run -p 3001:3000 scriptshare-api
# Restore backup
mysql -h your-db-host -P 25060 -u your-username -p your-database-name --ssl-mode=REQUIRED < backup.sql
``` ```
## Monitoring and Logs ### Local Development:
### Application Logs
- View logs in DigitalOcean Console: App → Runtime Logs
- Or via CLI: `doctl apps logs <app-id> --type=run`
### Database Monitoring
- Database metrics available in DigitalOcean dashboard
- Set up alerts for CPU, memory, and connection usage
### Health Checks
- API: `https://your-api-url/api/health`
- Frontend: Built-in App Platform health checks
## Scaling
### Vertical Scaling
- Increase instance size in App Platform settings
- Database can be scaled up (not down) in database settings
### Horizontal Scaling
- Increase instance count for API service
- Frontend is automatically scaled as a static site
## Security Best Practices
1. **Environment Variables**: Never commit secrets to Git
2. **Database Access**: Use DigitalOcean's private networking
3. **SSL/TLS**: Enabled by default on App Platform
4. **Database Backups**: Verify daily backups are working
5. **Access Control**: Use DigitalOcean teams for access management
## Troubleshooting
### Common Issues
1. **Build Failures**:
```bash ```bash
# Check build logs docker-compose up
doctl apps logs <app-id> --type=build
``` ```
2. **Database Connection Issues**: ## 🔧 Local Development
- Verify DATABASE_URL format
- Check firewall settings
- Ensure SSL is enabled
3. **CORS Errors**: ### Frontend:
- Verify CORS_ORIGIN matches frontend URL
- Check environment variable casing
4. **Missing Dependencies**:
```bash ```bash
# Clear npm cache and rebuild npm run dev
npm ci --clean-cache
``` ```
### Getting Support ### API:
```bash
npm run build:api
npm run start:api
```
- DigitalOcean Community: https://www.digitalocean.com/community ### Database:
- Support tickets: https://cloud.digitalocean.com/support ```bash
- Documentation: https://docs.digitalocean.com/products/app-platform/ npm run db:studio # Drizzle Studio
npm run db:migrate # Run migrations
```
## Cost Optimization ## 🚀 Quick Deploy Examples
### Current Configuration Costs (Approximate) ### Deploy to Vercel (Frontend):
- **API Service**: $5/month (Basic plan) ```bash
- **Database**: $15/month (1GB RAM, 1 vCPU) vercel --prod
- **Static Site**: $0 (included with API service) ```
- **Total**: ~$20/month
### Cost Reduction Tips ### Deploy to Railway:
1. Use development database for testing ```bash
2. Scale down during low usage periods railway deploy
3. Monitor and optimize database queries ```
4. Use CDN for static assets
## Deployment Checklist ### Deploy to Render:
Connect GitHub repository in Render dashboard
- [ ] Repository configured with deployment files ## 📞 Support
- [ ] Environment variables set in DigitalOcean
- [ ] JWT secret generated and configured
- [ ] Database migrations run successfully
- [ ] Health check endpoints responding
- [ ] Frontend can communicate with API
- [ ] Admin user created and accessible
- [ ] Custom domain configured (if applicable)
- [ ] Monitoring and alerts set up
- [ ] Backup strategy verified
## Next Steps - **Documentation**: Check platform-specific documentation
- **Environment**: Ensure all required environment variables are set
- **Health Checks**: Monitor `/health` and `/api/health` endpoints
- **Logs**: Check platform logs for deployment issues
1. **Set up CI/CD**: Configure GitHub Actions for automated deployments ---
2. **Monitoring**: Set up application performance monitoring
3. **CDN**: Configure CDN for static assets
4. **Analytics**: Integrate application analytics
5. **Error Tracking**: Set up error monitoring service
## Support **Your ScriptShare application is ready for deployment on any modern platform! 🎉**
For issues specific to this deployment setup, please check: Choose the platform that best fits your needs - from simple static hosting to full-stack container deployments.
1. DigitalOcean App Platform documentation
2. Application logs in the DigitalOcean console
3. Database connection and query logs
Remember to regularly update dependencies and monitor security advisories for your application stack.

View File

@ -1,365 +0,0 @@
# 🐳 ScriptShare Docker Deployment Guide
## Overview
This guide covers deploying ScriptShare to any generic Docker server using Docker Compose. The setup includes:
- **Frontend**: React application served by Nginx
- **Backend API**: Node.js Express server
- **Database**: MySQL 8.0
- **Reverse Proxy**: Nginx with load balancing
- **Cache**: Redis (optional)
- **Monitoring**: Health checks and logging
## Prerequisites
- Docker Engine 20.10+
- Docker Compose 2.0+
- At least 2GB RAM
- 10GB+ disk space
- Linux/macOS server (Windows with WSL2)
## Quick Start
### 1. **Prepare Environment**
```bash
# Clone the repository
git clone <your-repo-url>
cd scriptshare-cursor
# Copy and configure environment
cp env.production .env
# Edit .env with your specific settings
nano .env
```
### 2. **Deploy Application**
```bash
# Make scripts executable (Linux/macOS)
chmod +x scripts/*.sh
# Run deployment
./scripts/deploy.sh
```
### 3. **Verify Deployment**
```bash
# Check service status
./scripts/manage.sh status
# View logs
./scripts/manage.sh logs
```
## Configuration
### Environment Variables
Edit `env.production` before deployment:
```bash
# Domain Configuration
APP_URL=https://your-domain.com
FRONTEND_URL=https://your-domain.com
CORS_ORIGIN=https://your-domain.com
# Security (CHANGE THESE!)
JWT_SECRET=your-super-secret-jwt-key
DB_PASSWORD=your-secure-database-password
DB_ROOT_PASSWORD=your-root-password
REDIS_PASSWORD=your-redis-password
# Ports (adjust if needed)
PROXY_PORT=80
PROXY_SSL_PORT=443
API_PORT=3001
```
### SSL Configuration
1. **Place SSL certificates** in `./certs/`:
```
certs/
├── fullchain.pem
└── privkey.pem
```
2. **Enable HTTPS** in `nginx/conf.d/scriptshare.conf`:
- Uncomment the SSL server block
- Update `server_name` with your domain
3. **Restart proxy**:
```bash
./scripts/manage.sh restart scriptshare-proxy
```
## Service Architecture
```
┌─────────────────┐ ┌─────────────────┐
│ Nginx Proxy │────│ Frontend │
│ Port 80/443 │ │ (React+Nginx) │
└─────────────────┘ └─────────────────┘
│ │
│ ┌─────────────────┐
└──────────────│ Backend API │
│ (Node.js) │
└─────────────────┘
┌─────────────────┐
│ MySQL 8.0 │
│ Database │
└─────────────────┘
┌─────────────────┐
│ Redis Cache │
│ (Optional) │
└─────────────────┘
```
## Management Commands
### Service Management
```bash
# Start all services
./scripts/manage.sh start
# Stop all services
./scripts/manage.sh stop
# Restart services
./scripts/manage.sh restart
# View service status
./scripts/manage.sh status
# View logs (all services)
./scripts/manage.sh logs
# View logs (specific service)
./scripts/manage.sh logs scriptshare-api
```
### Database Management
```bash
# Connect to database
./scripts/manage.sh db
# Create backup
./scripts/manage.sh backup
# Run migrations (from API container)
docker-compose -f docker-compose.prod.yml exec scriptshare-api npm run db:migrate:prod
```
### Maintenance
```bash
# Update application
./scripts/manage.sh update
# Clean up Docker resources
./scripts/manage.sh clean
# Open shell in container
./scripts/manage.sh shell scriptshare-api
```
## Port Configuration
| Service | Internal Port | External Port | Description |
|---------|---------------|---------------|-------------|
| Proxy | 80, 443 | 8080, 8443 | Main entry point |
| Frontend | 80 | - | React application |
| API | 3000 | 3001 | REST API |
| Database | 3306 | 3306 | MySQL database |
| Redis | 6379 | 6379 | Cache store |
## Monitoring
### Health Checks
All services include health checks:
```bash
# Check health status
curl http://localhost:8080/health
# API health
curl http://localhost:3001/api/health
# Individual service health
docker ps --format "table {{.Names}}\t{{.Status}}"
```
### Logging
Logs are stored in Docker volumes and can be accessed via:
```bash
# All services
docker-compose -f docker-compose.prod.yml logs -f
# Specific service
docker-compose -f docker-compose.prod.yml logs -f scriptshare-api
# Save logs to file
docker-compose -f docker-compose.prod.yml logs > scriptshare.log
```
## Backup & Recovery
### Automated Backups
Configure automated backups by adding to crontab:
```bash
# Edit crontab
crontab -e
# Add daily backup at 2 AM
0 2 * * * /path/to/scriptshare/scripts/backup.sh
```
### Manual Backup
```bash
# Create backup
./scripts/backup.sh
# Backups are stored in ./backups/
ls -la backups/
```
### Recovery
```bash
# Stop database
docker-compose -f docker-compose.prod.yml stop scriptshare-db
# Restore from backup
gunzip -c backups/scriptshare_backup_YYYYMMDD_HHMMSS.sql.gz | \
docker exec -i scriptshare-db mysql -u root -p'your-root-password'
# Start database
docker-compose -f docker-compose.prod.yml start scriptshare-db
```
## Security Considerations
### 1. **Change Default Passwords**
- Update all passwords in `env.production`
- Use strong, unique passwords
- Consider using environment variable files
### 2. **Network Security**
- Configure firewall rules
- Use reverse proxy for SSL termination
- Implement rate limiting (configured in nginx)
### 3. **SSL/TLS**
- Use Let's Encrypt for free SSL certificates
- Configure HSTS headers
- Use modern TLS protocols only
### 4. **Container Security**
- Keep Docker images updated
- Run containers with non-root users where possible
- Use Docker secrets for sensitive data
## Troubleshooting
### Common Issues
1. **Services won't start**:
```bash
# Check logs
docker-compose -f docker-compose.prod.yml logs
# Check disk space
df -h
# Check memory
free -h
```
2. **Database connection errors**:
```bash
# Test database connectivity
docker exec scriptshare-db mysqladmin ping -u root -p'password'
# Check database logs
docker-compose -f docker-compose.prod.yml logs scriptshare-db
```
3. **API not responding**:
```bash
# Check API health
curl http://localhost:3001/api/health
# Check API logs
docker-compose -f docker-compose.prod.yml logs scriptshare-api
```
### Performance Tuning
1. **Database Optimization**:
- Adjust `innodb_buffer_pool_size` in MySQL configuration
- Monitor slow query log
- Add database indexes as needed
2. **Nginx Optimization**:
- Enable gzip compression (configured)
- Adjust worker processes
- Configure caching headers
3. **Resource Limits**:
- Set memory and CPU limits in docker-compose.prod.yml
- Monitor resource usage with `docker stats`
## Scaling
### Horizontal Scaling
To scale the application:
```bash
# Scale API containers
docker-compose -f docker-compose.prod.yml up -d --scale scriptshare-api=3
# Scale frontend containers
docker-compose -f docker-compose.prod.yml up -d --scale scriptshare-frontend=2
```
### Load Balancing
Nginx automatically load balances between multiple container instances.
## Production Checklist
- [ ] Update all default passwords
- [ ] Configure SSL certificates
- [ ] Set up automated backups
- [ ] Configure monitoring and alerting
- [ ] Set up log rotation
- [ ] Configure firewall rules
- [ ] Test disaster recovery procedures
- [ ] Set up domain and DNS
- [ ] Configure SMTP for emails (if applicable)
- [ ] Set up monitoring dashboard
## Support
For issues and questions:
1. Check the logs first
2. Review this documentation
3. Check Docker and system resources
4. Create an issue in the repository
**Your ScriptShare application is now ready for production deployment! 🚀**

View File

@ -1,8 +1,8 @@
# Production API Dockerfile for DigitalOcean # ScriptShare API Dockerfile
FROM node:18-alpine FROM node:18-alpine
# Install system dependencies for native modules # Install system dependencies for native modules
RUN apk add --no-cache python3 make g++ libc6-compat RUN apk add --no-cache python3 make g++ libc6-compat curl
WORKDIR /app WORKDIR /app
@ -10,208 +10,13 @@ WORKDIR /app
COPY package*.json ./ COPY package*.json ./
# Install dependencies # Install dependencies
RUN npm ci --only=production=false --silent RUN npm ci --only=production=false
# Copy source code # Copy source code
COPY . . COPY . .
# Create API-only build by removing frontend dependencies and files # Build TypeScript
RUN npm uninstall @vitejs/plugin-react-swc vite RUN npx tsc --build
RUN rm -rf src/components src/pages src/contexts src/hooks/use-toast.ts src/utils/toast.ts
RUN rm -rf src/main.tsx src/App.tsx src/index.css
RUN rm -rf public index.html vite.config.ts tailwind.config.ts postcss.config.js
# Keep only API and database files
# The structure will be: src/lib/api/* and src/lib/db/*
# Create a simple Express server
RUN cat > src/server.ts << 'EOF'
import express from 'express';
import cors from 'cors';
import { createUser, getUserByEmail, updateUser, getAllUsers, getUserById } from './lib/api/users.js';
import { getScripts, getScriptById, createScript, updateScript, deleteScript, moderateScript } from './lib/api/scripts.js';
import { login, register, refreshToken } from './lib/api/auth.js';
import { rateScript, getUserRating, getScriptRatingStats } from './lib/api/ratings.js';
import { getPlatformAnalytics, getScriptAnalytics, trackEvent } from './lib/api/analytics.js';
import { createCollection, getUserCollections, getPublicCollections, addScriptToCollection } from './lib/api/collections.js';
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(cors({
origin: process.env.CORS_ORIGIN || '*',
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Health check endpoint
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Auth routes
app.post('/api/auth/login', async (req, res) => {
try {
const result = await login(req.body);
res.json(result);
} catch (error) {
console.error('Login error:', error);
res.status(401).json({ error: 'Invalid credentials' });
}
});
app.post('/api/auth/register', async (req, res) => {
try {
const result = await register(req.body);
res.json(result);
} catch (error) {
console.error('Register error:', error);
res.status(400).json({ error: 'Registration failed' });
}
});
// Scripts routes
app.get('/api/scripts', async (req, res) => {
try {
const result = await getScripts(req.query);
res.json(result);
} catch (error) {
console.error('Get scripts error:', error);
res.status(500).json({ error: 'Failed to fetch scripts' });
}
});
app.get('/api/scripts/:id', async (req, res) => {
try {
const script = await getScriptById(req.params.id);
if (!script) {
return res.status(404).json({ error: 'Script not found' });
}
res.json(script);
} catch (error) {
console.error('Get script error:', error);
res.status(500).json({ error: 'Failed to fetch script' });
}
});
app.post('/api/scripts', async (req, res) => {
try {
const userId = req.headers['x-user-id'] as string;
if (!userId) {
return res.status(401).json({ error: 'Unauthorized' });
}
const result = await createScript(req.body, userId);
res.json(result);
} catch (error) {
console.error('Create script error:', error);
res.status(500).json({ error: 'Failed to create script' });
}
});
// Users routes
app.get('/api/users', async (req, res) => {
try {
const result = await getAllUsers();
res.json(result);
} catch (error) {
console.error('Get users error:', error);
res.status(500).json({ error: 'Failed to fetch users' });
}
});
app.get('/api/users/:id', async (req, res) => {
try {
const user = await getUserById(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
} catch (error) {
console.error('Get user error:', error);
res.status(500).json({ error: 'Failed to fetch user' });
}
});
// Analytics routes
app.get('/api/analytics/platform', async (req, res) => {
try {
const days = parseInt(req.query.days as string) || 30;
const result = await getPlatformAnalytics(days);
res.json(result);
} catch (error) {
console.error('Analytics error:', error);
res.status(500).json({ error: 'Failed to fetch analytics' });
}
});
app.post('/api/analytics/track', async (req, res) => {
try {
const result = await trackEvent(req.body);
res.json(result);
} catch (error) {
console.error('Track event error:', error);
res.status(500).json({ error: 'Failed to track event' });
}
});
// Collections routes
app.get('/api/collections', async (req, res) => {
try {
const userId = req.headers['x-user-id'] as string;
const result = userId ? await getUserCollections(userId) : await getPublicCollections();
res.json(result);
} catch (error) {
console.error('Get collections error:', error);
res.status(500).json({ error: 'Failed to fetch collections' });
}
});
// Ratings routes
app.post('/api/ratings', async (req, res) => {
try {
const result = await rateScript(req.body);
res.json(result);
} catch (error) {
console.error('Rate script error:', error);
res.status(500).json({ error: 'Failed to rate script' });
}
});
app.get('/api/scripts/:id/ratings', async (req, res) => {
try {
const result = await getScriptRatingStats(req.params.id);
res.json(result);
} catch (error) {
console.error('Get ratings error:', error);
res.status(500).json({ error: 'Failed to fetch ratings' });
}
});
// Error handling middleware
app.use((error: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('Unhandled error:', error);
res.status(500).json({ error: 'Internal server error' });
});
// 404 handler
app.use('*', (req, res) => {
res.status(404).json({ error: 'Endpoint not found' });
});
app.listen(PORT, () => {
console.log(`ScriptShare API server running on port ${PORT}`);
console.log(`Environment: ${process.env.NODE_ENV}`);
console.log(`Database URL configured: ${!!process.env.DATABASE_URL}`);
});
EOF
# Install Express and CORS for the API server
RUN npm install express cors @types/express @types/cors
# Build TypeScript (if any TS files remain)
RUN npx tsc --build || echo "TypeScript build completed with warnings"
# Expose port # Expose port
EXPOSE 3000 EXPOSE 3000
@ -221,4 +26,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:3000/api/health || exit 1 CMD curl -f http://localhost:3000/api/health || exit 1
# Start the API server # Start the API server
CMD ["node", "src/server.js"] CMD ["npm", "run", "start:api"]

View File

@ -1,180 +0,0 @@
# 🚀 ScriptShare - Generic Docker Server Deployment
## 🎯 Deployment Summary
Your ScriptShare application has been successfully reconfigured for deployment on any generic Docker server! The setup provides a complete, production-ready environment with all necessary components.
## 📦 What's Included
### **🐳 Docker Infrastructure**
- **Production Docker Compose**: Complete multi-service stack
- **Frontend Container**: React app with Nginx
- **Backend API Container**: Node.js Express server
- **Database Container**: MySQL 8.0 with optimizations
- **Reverse Proxy**: Nginx with load balancing & SSL support
- **Cache Layer**: Redis for session/data caching
- **Health Monitoring**: All services include health checks
### **⚙️ Configuration Files**
- `docker-compose.prod.yml` - Production environment setup
- `env.production` - Environment variables template
- `nginx/nginx.conf` - Main Nginx configuration
- `nginx/conf.d/scriptshare.conf` - Application-specific routing
### **🛠️ Management Tools**
- `scripts/deploy.sh` - Automated deployment script
- `scripts/manage.sh` - Service management (Linux/macOS)
- `scripts/manage.ps1` - Service management (Windows)
- `scripts/backup.sh` - Database backup automation
### **📚 Documentation**
- `DOCKER_DEPLOYMENT.md` - Comprehensive deployment guide
- Complete configuration examples
- Troubleshooting and maintenance guides
## 🚀 Quick Deployment
### **Prerequisites**
- Docker Engine 20.10+
- Docker Compose 2.0+
- 2GB+ RAM, 10GB+ disk space
### **Deploy in 3 Steps**
1. **Configure Environment**:
```bash
cp env.production .env
# Edit .env with your domain and passwords
```
2. **Deploy Application**:
```bash
# Linux/macOS
chmod +x scripts/*.sh
./scripts/deploy.sh
# Windows PowerShell
.\scripts\manage.ps1 start
```
3. **Verify Deployment**:
```bash
# Check status
./scripts/manage.sh status
# View application
http://localhost:8080
```
## 🌐 Service Architecture
```
Internet
┌─────────────────┐ Port 80/443
│ Nginx Proxy │ (Load Balancer)
└─────────────────┘
↓ ↓
┌─────────┐ ┌─────────────────┐
│Frontend │ │ Backend API │
│(React) │ │ (Node.js) │
└─────────┘ └─────────────────┘
┌─────────────────┐
│ MySQL 8.0 │
│ Database │
└─────────────────┘
┌─────────────────┐
│ Redis Cache │
│ (Optional) │
└─────────────────┘
```
## 🔧 Key Features
### **Production Ready**
- ✅ Multi-container architecture
- ✅ Health checks and monitoring
- ✅ Automated backup system
- ✅ SSL/HTTPS support
- ✅ Rate limiting and security headers
- ✅ Database optimizations
- ✅ Log management
- ✅ Resource management
### **Easy Management**
- ✅ One-command deployment
- ✅ Service start/stop/restart
- ✅ Real-time log viewing
- ✅ Database backup/restore
- ✅ Application updates
- ✅ Resource cleanup
- ✅ Health monitoring
### **Scalable**
- ✅ Horizontal scaling support
- ✅ Load balancing configured
- ✅ Container orchestration
- ✅ Resource limits
- ✅ Performance monitoring
## 📋 Post-Deployment Checklist
1. **Security Configuration**:
- [ ] Update all default passwords in `.env`
- [ ] Configure SSL certificates
- [ ] Set up firewall rules
- [ ] Review security headers
2. **Domain Setup**:
- [ ] Point your domain to the server
- [ ] Update `APP_URL` in environment
- [ ] Configure SSL certificates
- [ ] Test HTTPS redirect
3. **Monitoring & Maintenance**:
- [ ] Set up automated backups (cron)
- [ ] Configure log rotation
- [ ] Test disaster recovery
- [ ] Set up monitoring alerts
4. **Application Setup**:
- [ ] Run database migrations
- [ ] Create admin user
- [ ] Test all functionality
- [ ] Configure SMTP (if needed)
## 🆘 Quick Commands
### **Service Management**
```bash
./scripts/manage.sh start # Start all services
./scripts/manage.sh stop # Stop all services
./scripts/manage.sh status # Check service status
./scripts/manage.sh logs # View logs
```
### **Database Operations**
```bash
./scripts/manage.sh backup # Create database backup
./scripts/manage.sh db # Connect to database
```
### **Maintenance**
```bash
./scripts/manage.sh update # Update application
./scripts/manage.sh clean # Clean Docker resources
```
## 📞 Support
- **Documentation**: See `DOCKER_DEPLOYMENT.md` for detailed instructions
- **Troubleshooting**: Check logs with `./scripts/manage.sh logs`
- **Updates**: Use `./scripts/manage.sh update` for application updates
---
**🎉 Your ScriptShare application is now ready for production deployment on any Docker server!**
The setup provides enterprise-grade reliability, security, and scalability while maintaining simplicity for day-to-day operations. All components are containerized, monitored, and ready for production workloads.

128
REVERT_SUMMARY.md Normal file
View File

@ -0,0 +1,128 @@
# ✅ ScriptShare - Reverted to Standard Docker Deployment
## 🔄 Reversion Complete
Your ScriptShare application has been successfully reverted from the complex DigitalOcean-specific setup back to a **clean, standard Docker deployment** that works with **any platform**.
## 🗑️ Removed Files
### Complex Infrastructure Files:
-`docker-compose.prod.yml` - Complex production setup
-`env.production` - Production environment file
-`nginx/nginx.conf` - Custom nginx configuration
-`nginx/conf.d/scriptshare.conf` - Site-specific nginx config
-`nginx/` directory - Removed entirely
### Management Scripts:
-`scripts/deploy.sh` - Complex deployment automation
-`scripts/backup.sh` - Database backup scripts
-`scripts/init-db.sql` - Database initialization
-`scripts/manage.sh` - Linux/macOS management
-`scripts/manage.ps1` - Windows PowerShell management
### Documentation:
-`DOCKER_DEPLOYMENT.md` - Complex deployment guide
-`README_DEPLOYMENT.md` - Deployment summary
-`DEPLOYMENT_SUCCESS.md` - DigitalOcean success page
-`.github/workflows/deploy.yml` - DigitalOcean workflow
## ✅ What You Now Have
### 🐳 Clean Docker Setup:
- **`Dockerfile`** - Simple frontend build (React + Nginx)
- **`Dockerfile.api`** - Clean API server (Node.js + Express)
- **`docker-compose.yml`** - Basic local development setup
- **`src/server.ts`** - Standalone API server
### 📚 Universal Documentation:
- **`DEPLOYMENT.md`** - Platform-agnostic deployment guide
- **`.github/workflows/build.yml`** - Universal CI/CD pipeline
### 🚀 Platform Compatibility:
-**Vercel** - Frontend deployment ready
-**Coolify** - Full Docker deployment
-**DigitalOcean App Platform** - Docker + app.yaml
-**Railway** - Auto-detect Docker builds
-**Render** - Static + web service deployment
-**Any Docker platform** - Standard Dockerfiles
## 🏗️ Current Architecture
```
Simple & Clean:
Frontend (Dockerfile) API (Dockerfile.api)
┌─────────────────┐ ┌─────────────────┐
│ React + Vite │ │ Node.js Express │
│ Built to Dist │ │ TypeScript │
│ Served by │ │ Port 3000 │
│ Nginx │ │ /api/health │
│ Port 80 │ └─────────────────┘
└─────────────────┘
```
## 🚀 Quick Deployment Options
### Option 1: Vercel (Frontend)
```bash
vercel --prod
```
### Option 2: Coolify (Full Stack)
- Import from Git
- Auto-detect Dockerfiles
- Deploy both services
### Option 3: DigitalOcean App Platform
- Create app.yaml (see DEPLOYMENT.md)
- Deploy from repository
### Option 4: Railway
- Connect repository
- Auto-deploy both services
### Option 5: Docker Compose (Local)
```bash
docker-compose up
```
## 🎯 Benefits of This Approach
### ✅ **Platform Agnostic**
- Works with **any** deployment platform
- No vendor lock-in
- Standard Docker practices
### ✅ **Simple & Clean**
- Minimal configuration
- Easy to understand
- Standard build processes
### ✅ **Flexible**
- Deploy frontend and API separately
- Scale components independently
- Choose best platform for each service
### ✅ **Maintainable**
- No complex orchestration
- Standard Docker patterns
- Platform-native features
## 📝 Next Steps
1. **Choose Your Platform**: Vercel, Coolify, Railway, Render, etc.
2. **Configure Environment Variables**: See DEPLOYMENT.md
3. **Deploy**: Follow platform-specific instructions
4. **Monitor**: Use platform-native monitoring tools
## 🎉 Summary
Your ScriptShare application is now **clean, simple, and ready for deployment on any modern platform**. The complex Docker Compose setup has been removed in favor of standard Dockerfiles that work everywhere.
**Key Files:**
- `Dockerfile` - Frontend build
- `Dockerfile.api` - API server
- `DEPLOYMENT.md` - Platform guide
- `src/server.ts` - API entry point
**Ready for:** Vercel, Coolify, DigitalOcean, Railway, Render, and any Docker platform!

View File

@ -1,156 +0,0 @@
version: '3.8'
services:
# MySQL Database
scriptshare-db:
image: mysql:8.0
container_name: scriptshare-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-ScriptShare_Root_2024_Secure_Password}
MYSQL_DATABASE: ${DB_NAME:-scriptshare}
MYSQL_USER: ${DB_USER:-scriptshare_user}
MYSQL_PASSWORD: ${DB_PASSWORD:-ScriptShare_App_2024_Secure!}
MYSQL_CHARSET: utf8mb4
MYSQL_COLLATION: utf8mb4_unicode_ci
volumes:
- scriptshare_db_data:/var/lib/mysql
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro
ports:
- "${DB_PORT:-3306}:3306"
networks:
- scriptshare-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_ROOT_PASSWORD:-ScriptShare_Root_2024_Secure_Password}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
command: >
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--innodb-file-per-table=1
--max-connections=200
# Backend API
scriptshare-api:
build:
context: .
dockerfile: Dockerfile.api
container_name: scriptshare-api
restart: unless-stopped
environment:
- NODE_ENV=production
- DATABASE_URL=mysql://${DB_USER:-scriptshare_user}:${DB_PASSWORD:-ScriptShare_App_2024_Secure!}@scriptshare-db:3306/${DB_NAME:-scriptshare}
- JWT_SECRET=${JWT_SECRET:-production-super-secret-jwt-key-scriptshare-2024-secure}
- CORS_ORIGIN=${FRONTEND_URL:-http://localhost}
- PORT=3000
- DB_HOST=scriptshare-db
- DB_PORT=3306
- DB_USER=${DB_USER:-scriptshare_user}
- DB_PASSWORD=${DB_PASSWORD:-ScriptShare_App_2024_Secure!}
- DB_NAME=${DB_NAME:-scriptshare}
ports:
- "${API_PORT:-3001}:3000"
networks:
- scriptshare-network
depends_on:
scriptshare-db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
volumes:
- scriptshare_api_logs:/app/logs
# Frontend
scriptshare-frontend:
build:
context: .
dockerfile: Dockerfile
args:
- VITE_APP_NAME=${APP_NAME:-ScriptShare}
- VITE_APP_URL=${APP_URL:-https://scriptshare.example.com}
- VITE_ANALYTICS_ENABLED=${ANALYTICS_ENABLED:-false}
- VITE_API_URL=${API_URL:-http://localhost:3001}
container_name: scriptshare-frontend
restart: unless-stopped
ports:
- "${FRONTEND_PORT:-80}:80"
networks:
- scriptshare-network
depends_on:
- scriptshare-api
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
- scriptshare_frontend_logs:/var/log/nginx
# Reverse Proxy (Nginx)
scriptshare-proxy:
image: nginx:alpine
container_name: scriptshare-proxy
restart: unless-stopped
ports:
- "${PROXY_PORT:-8080}:80"
- "${PROXY_SSL_PORT:-8443}:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- scriptshare_proxy_logs:/var/log/nginx
- ${SSL_CERT_PATH:-./certs}:/etc/nginx/certs:ro
networks:
- scriptshare-network
depends_on:
- scriptshare-frontend
- scriptshare-api
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
# Redis Cache (Optional)
scriptshare-redis:
image: redis:7-alpine
container_name: scriptshare-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-ScriptShare_Redis_2024}
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- scriptshare_redis_data:/data
networks:
- scriptshare-network
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 30s
timeout: 10s
retries: 3
volumes:
scriptshare_db_data:
driver: local
scriptshare_api_logs:
driver: local
scriptshare_frontend_logs:
driver: local
scriptshare_proxy_logs:
driver: local
scriptshare_redis_data:
driver: local
networks:
scriptshare-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16

View File

@ -1,52 +0,0 @@
# ScriptShare Production Environment Configuration
# Application Settings
APP_NAME=ScriptShare
APP_URL=https://your-domain.com
ANALYTICS_ENABLED=true
NODE_ENV=production
# Database Configuration
DB_HOST=scriptshare-db
DB_PORT=3306
DB_NAME=scriptshare
DB_USER=scriptshare_user
DB_PASSWORD=ScriptShare_App_2024_Secure!
DB_ROOT_PASSWORD=ScriptShare_Root_2024_Secure_Password
DATABASE_URL=mysql://scriptshare_user:ScriptShare_App_2024_Secure!@scriptshare-db:3306/scriptshare
# Security
JWT_SECRET=production-super-secret-jwt-key-scriptshare-2024-secure-change-this-in-production
# API Configuration
API_PORT=3001
API_URL=http://localhost:3001
CORS_ORIGIN=https://your-domain.com
# Frontend Configuration
FRONTEND_PORT=80
FRONTEND_URL=https://your-domain.com
VITE_APP_NAME=ScriptShare
VITE_APP_URL=https://your-domain.com
VITE_ANALYTICS_ENABLED=true
VITE_API_URL=https://your-domain.com/api
# Proxy Configuration
PROXY_PORT=8080
PROXY_SSL_PORT=8443
# Redis Configuration (Optional)
REDIS_PORT=6379
REDIS_PASSWORD=ScriptShare_Redis_2024
# SSL Configuration
SSL_CERT_PATH=./certs
# Logging
LOG_LEVEL=info
LOG_FILE=/app/logs/scriptshare.log
# Backup Configuration
BACKUP_ENABLED=true
BACKUP_SCHEDULE=0 2 * * *
BACKUP_RETENTION_DAYS=30

View File

@ -1,129 +0,0 @@
# ScriptShare Main Configuration
upstream scriptshare_api {
server scriptshare-api:3000;
}
upstream scriptshare_frontend {
server scriptshare-frontend:80;
}
# HTTP to HTTPS redirect (when SSL is configured)
server {
listen 80;
server_name _;
# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# API routes
location /api/ {
# Rate limiting for API
limit_req zone=api burst=20 nodelay;
# Proxy headers
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 settings
proxy_pass http://scriptshare_api;
proxy_redirect off;
proxy_buffering off;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
# CORS headers (if needed)
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-User-Id' always;
# Handle preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,X-User-Id';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
}
# Special rate limiting for auth endpoints
location /api/auth/ {
limit_req zone=login burst=5 nodelay;
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_pass http://scriptshare_api;
proxy_redirect off;
proxy_buffering off;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
}
# Frontend routes
location / {
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_pass http://scriptshare_frontend;
proxy_redirect off;
# Handle SPA routing
try_files $uri $uri/ @fallback;
}
# Fallback for SPA routing
location @fallback {
proxy_pass http://scriptshare_frontend;
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;
}
# Static assets caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://scriptshare_frontend;
proxy_cache_valid 200 1y;
add_header Cache-Control "public, immutable";
expires 1y;
}
# 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;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Hide nginx version
server_tokens off;
}
# HTTPS Configuration (uncomment and configure when SSL certificates are ready)
# server {
# listen 443 ssl http2;
# server_name your-domain.com;
#
# ssl_certificate /etc/nginx/certs/fullchain.pem;
# ssl_certificate_key /etc/nginx/certs/privkey.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
# ssl_prefer_server_ciphers off;
#
# # Include the same location blocks as above
# include /etc/nginx/conf.d/common-locations.conf;
# }

View File

@ -1,47 +0,0 @@
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging format
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# Performance settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 10M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/rss+xml
application/atom+xml
image/svg+xml;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# Include additional configurations
include /etc/nginx/conf.d/*.conf;
}

View File

@ -1,53 +0,0 @@
#!/bin/bash
# ScriptShare Database Backup Script
set -e
# Load environment variables
if [ -f ".env" ]; then
source .env
fi
# Default values
DB_CONTAINER=${DB_CONTAINER:-scriptshare-db}
BACKUP_DIR=${BACKUP_DIR:-./backups}
RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-30}
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Generate backup filename with timestamp
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/scriptshare_backup_$TIMESTAMP.sql"
echo "🗄️ Starting database backup..."
echo "Backup file: $BACKUP_FILE"
# Create database backup
docker exec "$DB_CONTAINER" mysqldump \
--single-transaction \
--routines \
--triggers \
--all-databases \
-u root \
-p"${DB_ROOT_PASSWORD}" > "$BACKUP_FILE"
# Compress the backup
gzip "$BACKUP_FILE"
BACKUP_FILE="$BACKUP_FILE.gz"
echo "✅ Database backup completed: $BACKUP_FILE"
# Calculate backup size
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "📦 Backup size: $BACKUP_SIZE"
# Clean up old backups
echo "🧹 Cleaning up old backups (older than $RETENTION_DAYS days)..."
find "$BACKUP_DIR" -name "scriptshare_backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete
# List remaining backups
echo "📋 Current backups:"
ls -lh "$BACKUP_DIR"/scriptshare_backup_*.sql.gz 2>/dev/null || echo "No backups found"
echo "✅ Backup process completed successfully!"

View File

@ -1,92 +0,0 @@
#!/bin/bash
# ScriptShare Production Deployment Script
set -e
echo "🚀 Starting ScriptShare deployment..."
# Check if Docker and Docker Compose are installed
if ! command -v docker &> /dev/null; then
echo "❌ Docker is not installed. Please install Docker first."
exit 1
fi
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
echo "❌ Docker Compose is not installed. Please install Docker Compose first."
exit 1
fi
# Check if environment file exists
if [ ! -f "env.production" ]; then
echo "❌ Environment file 'env.production' not found."
echo "Please copy 'env.production' and configure your settings."
exit 1
fi
# Create necessary directories
echo "📁 Creating required directories..."
mkdir -p logs
mkdir -p certs
mkdir -p backups
# Copy environment file
cp env.production .env
# Pull latest images
echo "📥 Pulling Docker images..."
docker-compose -f docker-compose.prod.yml pull
# Build custom images
echo "🔨 Building application images..."
docker-compose -f docker-compose.prod.yml build --no-cache
# Stop existing containers if running
echo "🛑 Stopping existing containers..."
docker-compose -f docker-compose.prod.yml down
# Start the application
echo "🚀 Starting ScriptShare application..."
docker-compose -f docker-compose.prod.yml up -d
# Wait for services to be healthy
echo "⏳ Waiting for services to start..."
sleep 30
# Check service health
echo "🏥 Checking service health..."
services=("scriptshare-db" "scriptshare-api" "scriptshare-frontend" "scriptshare-proxy")
for service in "${services[@]}"; do
if docker-compose -f docker-compose.prod.yml ps | grep -q "$service.*Up"; then
echo "$service is running"
else
echo "$service failed to start"
echo "Checking logs for $service:"
docker-compose -f docker-compose.prod.yml logs "$service"
exit 1
fi
done
# Run database migrations if needed
echo "🗃️ Running database migrations..."
docker-compose -f docker-compose.prod.yml exec -T scriptshare-api npm run db:migrate:prod || echo "⚠️ Database migrations not available or failed"
# Display deployment information
echo ""
echo "🎉 ScriptShare deployment completed successfully!"
echo ""
echo "📊 Service URLs:"
echo " Frontend: http://localhost:$(grep PROXY_PORT .env | cut -d'=' -f2 | tr -d '"')"
echo " API: http://localhost:$(grep API_PORT .env | cut -d'=' -f2 | tr -d '"')/api/health"
echo " Database: localhost:$(grep DB_PORT .env | cut -d'=' -f2 | tr -d '"')"
echo ""
echo "🔧 Management commands:"
echo " View logs: docker-compose -f docker-compose.prod.yml logs -f"
echo " Stop: docker-compose -f docker-compose.prod.yml down"
echo " Restart: docker-compose -f docker-compose.prod.yml restart"
echo ""
echo "📝 Next steps:"
echo " 1. Configure your domain DNS to point to this server"
echo " 2. Set up SSL certificates in ./certs/"
echo " 3. Update env.production with your domain settings"
echo " 4. Run: docker-compose -f docker-compose.prod.yml restart scriptshare-proxy"

View File

@ -1,47 +0,0 @@
-- ScriptShare Database Initialization Script
-- This script sets up the initial database structure and default data
USE scriptshare;
-- Create tables if they don't exist (will be handled by Drizzle migrations)
-- This file can be used for any initial data setup
-- Insert default admin user (optional)
-- Note: Password should be properly hashed in production
INSERT IGNORE INTO users (id, email, username, displayName, isAdmin, isModerator, createdAt, updatedAt)
VALUES (
'admin-default-id',
'admin@scriptshare.local',
'admin',
'Administrator',
true,
true,
NOW(),
NOW()
);
-- Insert sample categories
INSERT IGNORE INTO script_categories (name, description) VALUES
('System Administration', 'Scripts for system administration tasks'),
('Development', 'Development and build automation scripts'),
('Backup & Recovery', 'Backup and recovery automation'),
('Monitoring', 'System and application monitoring scripts'),
('Security', 'Security and audit scripts'),
('Database', 'Database management and maintenance'),
('Network', 'Network configuration and management'),
('DevOps', 'DevOps and CI/CD automation');
-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_scripts_author ON scripts(authorId);
CREATE INDEX IF NOT EXISTS idx_scripts_created ON scripts(createdAt);
CREATE INDEX IF NOT EXISTS idx_scripts_approved ON scripts(isApproved);
CREATE INDEX IF NOT EXISTS idx_ratings_script ON ratings(scriptId);
CREATE INDEX IF NOT EXISTS idx_analytics_script ON script_analytics(scriptId);
CREATE INDEX IF NOT EXISTS idx_analytics_created ON script_analytics(createdAt);
-- Set up database optimization
SET GLOBAL innodb_buffer_pool_size = 268435456; -- 256MB
SET GLOBAL max_connections = 200;
-- Print initialization complete message
SELECT 'ScriptShare database initialization completed!' as message;

View File

@ -1,142 +0,0 @@
# ScriptShare Management Script for Windows PowerShell
param(
[Parameter(Mandatory=$true, Position=0)]
[string]$Command,
[Parameter(Position=1)]
[string]$Service
)
$ComposeFile = "docker-compose.prod.yml"
function Show-Help {
Write-Host "ScriptShare Management Script" -ForegroundColor Green
Write-Host ""
Write-Host "Usage: .\scripts\manage.ps1 [COMMAND] [SERVICE]" -ForegroundColor Yellow
Write-Host ""
Write-Host "Commands:" -ForegroundColor Cyan
Write-Host " start Start all services"
Write-Host " stop Stop all services"
Write-Host " restart Restart all services"
Write-Host " logs Show logs for all services"
Write-Host " logs [svc] Show logs for specific service"
Write-Host " status Show status of all services"
Write-Host " backup Create database backup"
Write-Host " update Update application (pull, build, restart)"
Write-Host " clean Clean up unused Docker resources"
Write-Host " shell [svc] Open shell in service container"
Write-Host " db Connect to database"
Write-Host " help Show this help message"
Write-Host ""
Write-Host "Services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy, scriptshare-redis" -ForegroundColor Gray
}
switch ($Command.ToLower()) {
"start" {
Write-Host "🚀 Starting ScriptShare services..." -ForegroundColor Green
docker-compose -f $ComposeFile up -d
Write-Host "✅ Services started" -ForegroundColor Green
}
"stop" {
Write-Host "🛑 Stopping ScriptShare services..." -ForegroundColor Yellow
docker-compose -f $ComposeFile down
Write-Host "✅ Services stopped" -ForegroundColor Green
}
"restart" {
Write-Host "🔄 Restarting ScriptShare services..." -ForegroundColor Yellow
docker-compose -f $ComposeFile restart
Write-Host "✅ Services restarted" -ForegroundColor Green
}
"logs" {
if ($Service) {
Write-Host "📋 Showing logs for $Service..." -ForegroundColor Cyan
docker-compose -f $ComposeFile logs -f $Service
} else {
Write-Host "📋 Showing logs for all services..." -ForegroundColor Cyan
docker-compose -f $ComposeFile logs -f
}
}
"status" {
Write-Host "📊 Service Status:" -ForegroundColor Cyan
docker-compose -f $ComposeFile ps
Write-Host ""
Write-Host "🏥 Health Status:" -ForegroundColor Cyan
$services = @("scriptshare-db", "scriptshare-api", "scriptshare-frontend", "scriptshare-proxy")
foreach ($svc in $services) {
try {
$health = docker inspect --format='{{.State.Health.Status}}' $svc 2>$null
if (-not $health) { $health = "not found" }
Write-Host " $svc`: $health" -ForegroundColor Gray
} catch {
Write-Host " $svc`: not found" -ForegroundColor Red
}
}
}
"backup" {
Write-Host "🗄️ Creating database backup..." -ForegroundColor Cyan
if (Test-Path ".\scripts\backup.sh") {
bash .\scripts\backup.sh
} else {
Write-Host "❌ Backup script not found. Please run manually:" -ForegroundColor Red
Write-Host "docker exec scriptshare-db mysqladmin ping" -ForegroundColor Gray
}
}
"update" {
Write-Host "🔄 Updating ScriptShare application..." -ForegroundColor Cyan
docker-compose -f $ComposeFile pull
docker-compose -f $ComposeFile build --no-cache
docker-compose -f $ComposeFile up -d
Write-Host "✅ Application updated" -ForegroundColor Green
}
"clean" {
Write-Host "🧹 Cleaning up Docker resources..." -ForegroundColor Yellow
docker system prune -f
docker volume prune -f
Write-Host "✅ Cleanup completed" -ForegroundColor Green
}
"shell" {
if (-not $Service) {
Write-Host "❌ Please specify service name" -ForegroundColor Red
Write-Host "Available services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy" -ForegroundColor Gray
exit 1
}
Write-Host "💻 Opening shell in $Service..." -ForegroundColor Cyan
docker-compose -f $ComposeFile exec $Service /bin/sh
}
"db" {
Write-Host "🗃️ Connecting to database..." -ForegroundColor Cyan
$envFile = ".env"
$dbUser = "scriptshare_user"
$dbPassword = "ScriptShare_App_2024_Secure!"
$dbName = "scriptshare"
if (Test-Path $envFile) {
$env = Get-Content $envFile | ConvertFrom-StringData
if ($env.DB_USER) { $dbUser = $env.DB_USER }
if ($env.DB_PASSWORD) { $dbPassword = $env.DB_PASSWORD }
if ($env.DB_NAME) { $dbName = $env.DB_NAME }
}
docker-compose -f $ComposeFile exec scriptshare-db mysql -u $dbUser -p$dbPassword $dbName
}
"help" {
Show-Help
}
default {
Write-Host "❌ Unknown command: $Command" -ForegroundColor Red
Write-Host ""
Show-Help
exit 1
}
}

View File

@ -1,130 +0,0 @@
#!/bin/bash
# ScriptShare Management Script
set -e
COMPOSE_FILE="docker-compose.prod.yml"
show_help() {
echo "ScriptShare Management Script"
echo ""
echo "Usage: $0 [COMMAND]"
echo ""
echo "Commands:"
echo " start Start all services"
echo " stop Stop all services"
echo " restart Restart all services"
echo " logs Show logs for all services"
echo " logs [svc] Show logs for specific service"
echo " status Show status of all services"
echo " backup Create database backup"
echo " restore Restore database from backup"
echo " update Update application (pull, build, restart)"
echo " clean Clean up unused Docker resources"
echo " shell [svc] Open shell in service container"
echo " db Connect to database"
echo " help Show this help message"
echo ""
echo "Services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy, scriptshare-redis"
}
case "$1" in
start)
echo "🚀 Starting ScriptShare services..."
docker-compose -f "$COMPOSE_FILE" up -d
echo "✅ Services started"
;;
stop)
echo "🛑 Stopping ScriptShare services..."
docker-compose -f "$COMPOSE_FILE" down
echo "✅ Services stopped"
;;
restart)
echo "🔄 Restarting ScriptShare services..."
docker-compose -f "$COMPOSE_FILE" restart
echo "✅ Services restarted"
;;
logs)
if [ -n "$2" ]; then
echo "📋 Showing logs for $2..."
docker-compose -f "$COMPOSE_FILE" logs -f "$2"
else
echo "📋 Showing logs for all services..."
docker-compose -f "$COMPOSE_FILE" logs -f
fi
;;
status)
echo "📊 Service Status:"
docker-compose -f "$COMPOSE_FILE" ps
echo ""
echo "🏥 Health Status:"
for service in scriptshare-db scriptshare-api scriptshare-frontend scriptshare-proxy; do
health=$(docker inspect --format='{{.State.Health.Status}}' "$service" 2>/dev/null || echo "not found")
echo " $service: $health"
done
;;
backup)
echo "🗄️ Creating database backup..."
./scripts/backup.sh
;;
restore)
if [ -z "$2" ]; then
echo "❌ Please specify backup file to restore"
echo "Usage: $0 restore <backup-file>"
exit 1
fi
echo "🔄 Restoring database from $2..."
# Implementation for restore would go here
echo "⚠️ Restore functionality not yet implemented"
;;
update)
echo "🔄 Updating ScriptShare application..."
docker-compose -f "$COMPOSE_FILE" pull
docker-compose -f "$COMPOSE_FILE" build --no-cache
docker-compose -f "$COMPOSE_FILE" up -d
echo "✅ Application updated"
;;
clean)
echo "🧹 Cleaning up Docker resources..."
docker system prune -f
docker volume prune -f
echo "✅ Cleanup completed"
;;
shell)
if [ -z "$2" ]; then
echo "❌ Please specify service name"
echo "Available services: scriptshare-db, scriptshare-api, scriptshare-frontend, scriptshare-proxy"
exit 1
fi
echo "💻 Opening shell in $2..."
docker-compose -f "$COMPOSE_FILE" exec "$2" /bin/sh
;;
db)
echo "🗃️ Connecting to database..."
if [ -f ".env" ]; then
source .env
fi
docker-compose -f "$COMPOSE_FILE" exec scriptshare-db mysql -u "${DB_USER:-scriptshare_user}" -p"${DB_PASSWORD:-ScriptShare_App_2024_Secure!}" "${DB_NAME:-scriptshare}"
;;
help|--help|-h)
show_help
;;
*)
echo "❌ Unknown command: $1"
echo ""
show_help
exit 1
;;
esac

179
src/server.ts Normal file
View File

@ -0,0 +1,179 @@
import express from 'express';
import cors from 'cors';
import { createUser, getUserByEmail, updateUser, getAllUsers, getUserById } from './lib/api/users.js';
import { getScripts, getScriptById, createScript, updateScript, deleteScript, moderateScript } from './lib/api/scripts.js';
import { login, register, refreshToken } from './lib/api/auth.js';
import { rateScript, getUserRating, getScriptRatingStats } from './lib/api/ratings.js';
import { getPlatformAnalytics, getScriptAnalytics, trackEvent } from './lib/api/analytics.js';
import { createCollection, getUserCollections, getPublicCollections, addScriptToCollection } from './lib/api/collections.js';
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(cors({
origin: process.env.CORS_ORIGIN || '*',
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Health check endpoint
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Auth routes
app.post('/api/auth/login', async (req, res) => {
try {
const result = await login(req.body);
res.json(result);
} catch (error) {
console.error('Login error:', error);
res.status(401).json({ error: 'Invalid credentials' });
}
});
app.post('/api/auth/register', async (req, res) => {
try {
const result = await register(req.body);
res.json(result);
} catch (error) {
console.error('Register error:', error);
res.status(400).json({ error: 'Registration failed' });
}
});
// Scripts routes
app.get('/api/scripts', async (req, res) => {
try {
const result = await getScripts(req.query);
res.json(result);
} catch (error) {
console.error('Get scripts error:', error);
res.status(500).json({ error: 'Failed to fetch scripts' });
}
});
app.get('/api/scripts/:id', async (req, res) => {
try {
const script = await getScriptById(req.params.id);
if (!script) {
return res.status(404).json({ error: 'Script not found' });
}
res.json(script);
} catch (error) {
console.error('Get script error:', error);
res.status(500).json({ error: 'Failed to fetch script' });
}
});
app.post('/api/scripts', async (req, res) => {
try {
const userId = req.headers['x-user-id'] as string;
if (!userId) {
return res.status(401).json({ error: 'Unauthorized' });
}
const result = await createScript(req.body, userId);
res.json(result);
} catch (error) {
console.error('Create script error:', error);
res.status(500).json({ error: 'Failed to create script' });
}
});
// Users routes
app.get('/api/users', async (req, res) => {
try {
const result = await getAllUsers();
res.json(result);
} catch (error) {
console.error('Get users error:', error);
res.status(500).json({ error: 'Failed to fetch users' });
}
});
app.get('/api/users/:id', async (req, res) => {
try {
const user = await getUserById(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
} catch (error) {
console.error('Get user error:', error);
res.status(500).json({ error: 'Failed to fetch user' });
}
});
// Analytics routes
app.get('/api/analytics/platform', async (req, res) => {
try {
const days = parseInt(req.query.days as string) || 30;
const result = await getPlatformAnalytics(days);
res.json(result);
} catch (error) {
console.error('Analytics error:', error);
res.status(500).json({ error: 'Failed to fetch analytics' });
}
});
app.post('/api/analytics/track', async (req, res) => {
try {
const result = await trackEvent(req.body);
res.json(result);
} catch (error) {
console.error('Track event error:', error);
res.status(500).json({ error: 'Failed to track event' });
}
});
// Collections routes
app.get('/api/collections', async (req, res) => {
try {
const userId = req.headers['x-user-id'] as string;
const result = userId ? await getUserCollections(userId) : await getPublicCollections();
res.json(result);
} catch (error) {
console.error('Get collections error:', error);
res.status(500).json({ error: 'Failed to fetch collections' });
}
});
// Ratings routes
app.post('/api/ratings', async (req, res) => {
try {
const result = await rateScript(req.body);
res.json(result);
} catch (error) {
console.error('Rate script error:', error);
res.status(500).json({ error: 'Failed to rate script' });
}
});
app.get('/api/scripts/:id/ratings', async (req, res) => {
try {
const result = await getScriptRatingStats(req.params.id);
res.json(result);
} catch (error) {
console.error('Get ratings error:', error);
res.status(500).json({ error: 'Failed to fetch ratings' });
}
});
// Error handling middleware
app.use((error: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('Unhandled error:', error);
res.status(500).json({ error: 'Internal server error' });
});
// 404 handler
app.use('*', (req, res) => {
res.status(404).json({ error: 'Endpoint not found' });
});
app.listen(PORT, () => {
console.log(`ScriptShare API server running on port ${PORT}`);
console.log(`Environment: ${process.env.NODE_ENV}`);
console.log(`Database URL configured: ${!!process.env.DATABASE_URL}`);
});