496 lines
11 KiB
Markdown
496 lines
11 KiB
Markdown
# Deployment Guide
|
|
|
|
Complete deployment guide for the LFG9 Forums application.
|
|
|
|
## AWS Infrastructure Setup
|
|
|
|
### 1. DynamoDB Tables
|
|
|
|
Create the following DynamoDB tables:
|
|
|
|
#### Users Table
|
|
```bash
|
|
aws dynamodb create-table \
|
|
--table-name lfg9_forums_users \
|
|
--attribute-definitions \
|
|
AttributeName=userId,AttributeType=S \
|
|
--key-schema \
|
|
AttributeName=userId,KeyType=HASH \
|
|
--billing-mode PAY_PER_REQUEST
|
|
```
|
|
|
|
#### Categories Table
|
|
```bash
|
|
aws dynamodb create-table \
|
|
--table-name lfg9_forums_categories \
|
|
--attribute-definitions \
|
|
AttributeName=categoryId,AttributeType=S \
|
|
--key-schema \
|
|
AttributeName=categoryId,KeyType=HASH \
|
|
--billing-mode PAY_PER_REQUEST
|
|
```
|
|
|
|
#### Threads Table
|
|
```bash
|
|
aws dynamodb create-table \
|
|
--table-name lfg9_forums_threads \
|
|
--attribute-definitions \
|
|
AttributeName=threadId,AttributeType=S \
|
|
AttributeName=categoryId,AttributeType=S \
|
|
AttributeName=authorId,AttributeType=S \
|
|
--key-schema \
|
|
AttributeName=threadId,KeyType=HASH \
|
|
--global-secondary-indexes \
|
|
IndexName=CategoryIdIndex,KeySchema=[{AttributeName=categoryId,KeyType=HASH}],Projection={ProjectionType=ALL} \
|
|
IndexName=AuthorIdIndex,KeySchema=[{AttributeName=authorId,KeyType=HASH}],Projection={ProjectionType=ALL} \
|
|
--billing-mode PAY_PER_REQUEST
|
|
```
|
|
|
|
#### Posts Table
|
|
```bash
|
|
aws dynamodb create-table \
|
|
--table-name lfg9_forums_posts \
|
|
--attribute-definitions \
|
|
AttributeName=postId,AttributeType=S \
|
|
AttributeName=threadId,AttributeType=S \
|
|
AttributeName=authorId,AttributeType=S \
|
|
--key-schema \
|
|
AttributeName=postId,KeyType=HASH \
|
|
--global-secondary-indexes \
|
|
IndexName=ThreadIdIndex,KeySchema=[{AttributeName=threadId,KeyType=HASH}],Projection={ProjectionType=ALL} \
|
|
IndexName=AuthorIdIndex,KeySchema=[{AttributeName=authorId,KeyType=HASH}],Projection={ProjectionType=ALL} \
|
|
--billing-mode PAY_PER_REQUEST
|
|
```
|
|
|
|
#### Files Table
|
|
```bash
|
|
aws dynamodb create-table \
|
|
--table-name lfg9_forums_files \
|
|
--attribute-definitions \
|
|
AttributeName=fileId,AttributeType=S \
|
|
AttributeName=userId,AttributeType=S \
|
|
--key-schema \
|
|
AttributeName=fileId,KeyType=HASH \
|
|
--global-secondary-indexes \
|
|
IndexName=UserIdIndex,KeySchema=[{AttributeName=userId,KeyType=HASH}],Projection={ProjectionType=ALL} \
|
|
--billing-mode PAY_PER_REQUEST
|
|
```
|
|
|
|
### 2. S3 Bucket Setup
|
|
|
|
Create S3 bucket for file uploads:
|
|
|
|
```bash
|
|
aws s3 mb s3://lfg9-forums-uploads --region us-east-1
|
|
```
|
|
|
|
Configure bucket policy for proper access:
|
|
|
|
```json
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Sid": "PublicReadGetObject",
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "s3:GetObject",
|
|
"Resource": "arn:aws:s3:::lfg9-forums-uploads/*"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Configure CORS for the bucket:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"AllowedHeaders": ["*"],
|
|
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
|
|
"AllowedOrigins": ["https://yourdomain.com"],
|
|
"ExposeHeaders": ["ETag"]
|
|
}
|
|
]
|
|
```
|
|
|
|
### 3. IAM Role and Policies
|
|
|
|
Create IAM role for the application:
|
|
|
|
```json
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"dynamodb:GetItem",
|
|
"dynamodb:PutItem",
|
|
"dynamodb:Query",
|
|
"dynamodb:Scan",
|
|
"dynamodb:UpdateItem",
|
|
"dynamodb:DeleteItem"
|
|
],
|
|
"Resource": [
|
|
"arn:aws:dynamodb:*:*:table/lfg9_forums_*",
|
|
"arn:aws:dynamodb:*:*:table/lfg9_forums_*/index/*"
|
|
]
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"s3:GetObject",
|
|
"s3:PutObject",
|
|
"s3:DeleteObject",
|
|
"s3:PutObjectAcl"
|
|
],
|
|
"Resource": "arn:aws:s3:::lfg9-forums-uploads/*"
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"s3:ListBucket"
|
|
],
|
|
"Resource": "arn:aws:s3:::lfg9-forums-uploads"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Backend Deployment
|
|
|
|
### Option 1: AWS ECS with Fargate
|
|
|
|
1. **Create Dockerfile**:
|
|
|
|
```dockerfile
|
|
FROM node:18-alpine
|
|
|
|
WORKDIR /app
|
|
|
|
COPY package*.json ./
|
|
RUN npm ci --only=production
|
|
|
|
COPY dist ./dist
|
|
|
|
EXPOSE 3000
|
|
|
|
CMD ["npm", "start"]
|
|
```
|
|
|
|
2. **Build and push to ECR**:
|
|
|
|
```bash
|
|
# Build the application
|
|
npm run build
|
|
|
|
# Build Docker image
|
|
docker build -t lfg9-forums-backend .
|
|
|
|
# Tag and push to ECR
|
|
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
|
|
docker tag lfg9-forums-backend:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/lfg9-forums-backend:latest
|
|
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/lfg9-forums-backend:latest
|
|
```
|
|
|
|
3. **Create ECS Task Definition**:
|
|
|
|
```json
|
|
{
|
|
"family": "lfg9-forums-backend",
|
|
"networkMode": "awsvpc",
|
|
"requiresCompatibilities": ["FARGATE"],
|
|
"cpu": "512",
|
|
"memory": "1024",
|
|
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
|
|
"taskRoleArn": "arn:aws:iam::123456789012:role/lfg9-forums-task-role",
|
|
"containerDefinitions": [
|
|
{
|
|
"name": "lfg9-forums-backend",
|
|
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/lfg9-forums-backend:latest",
|
|
"portMappings": [
|
|
{
|
|
"containerPort": 3000,
|
|
"protocol": "tcp"
|
|
}
|
|
],
|
|
"environment": [
|
|
{
|
|
"name": "NODE_ENV",
|
|
"value": "production"
|
|
},
|
|
{
|
|
"name": "PORT",
|
|
"value": "3000"
|
|
}
|
|
],
|
|
"secrets": [
|
|
{
|
|
"name": "JWT_SECRET",
|
|
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:lfg9-forums/jwt-secret"
|
|
}
|
|
],
|
|
"logConfiguration": {
|
|
"logDriver": "awslogs",
|
|
"options": {
|
|
"awslogs-group": "/ecs/lfg9-forums-backend",
|
|
"awslogs-region": "us-east-1",
|
|
"awslogs-stream-prefix": "ecs"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Option 2: AWS Lambda with Serverless Framework
|
|
|
|
1. **Install Serverless Framework**:
|
|
|
|
```bash
|
|
npm install -g serverless
|
|
npm install --save-dev serverless-offline
|
|
```
|
|
|
|
2. **Create serverless.yml**:
|
|
|
|
```yaml
|
|
service: lfg9-forums-backend
|
|
|
|
provider:
|
|
name: aws
|
|
runtime: nodejs18.x
|
|
region: us-east-1
|
|
environment:
|
|
NODE_ENV: production
|
|
DYNAMODB_TABLE_PREFIX: ${self:service}-${opt:stage, self:provider.stage}-
|
|
S3_BUCKET_NAME: lfg9-forums-uploads-${opt:stage, self:provider.stage}
|
|
iamRoleStatements:
|
|
- Effect: Allow
|
|
Action:
|
|
- dynamodb:Query
|
|
- dynamodb:Scan
|
|
- dynamodb:GetItem
|
|
- dynamodb:PutItem
|
|
- dynamodb:UpdateItem
|
|
- dynamodb:DeleteItem
|
|
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/${self:service}-${opt:stage, self:provider.stage}-*"
|
|
- Effect: Allow
|
|
Action:
|
|
- s3:GetObject
|
|
- s3:PutObject
|
|
- s3:DeleteObject
|
|
Resource: "arn:aws:s3:::lfg9-forums-uploads-${opt:stage, self:provider.stage}/*"
|
|
|
|
functions:
|
|
api:
|
|
handler: dist/lambda.handler
|
|
events:
|
|
- http:
|
|
path: /{proxy+}
|
|
method: ANY
|
|
cors: true
|
|
|
|
plugins:
|
|
- serverless-offline
|
|
```
|
|
|
|
## Frontend Deployment
|
|
|
|
### Option 1: AWS S3 + CloudFront
|
|
|
|
1. **Build the frontend**:
|
|
|
|
```bash
|
|
cd frontend
|
|
npm run build
|
|
```
|
|
|
|
2. **Create S3 bucket for hosting**:
|
|
|
|
```bash
|
|
aws s3 mb s3://lfg9-forums-frontend --region us-east-1
|
|
```
|
|
|
|
3. **Configure bucket for static website hosting**:
|
|
|
|
```bash
|
|
aws s3 website s3://lfg9-forums-frontend --index-document index.html --error-document index.html
|
|
```
|
|
|
|
4. **Upload build files**:
|
|
|
|
```bash
|
|
aws s3 sync dist/ s3://lfg9-forums-frontend --delete
|
|
```
|
|
|
|
5. **Create CloudFront distribution**:
|
|
|
|
```json
|
|
{
|
|
"DistributionConfig": {
|
|
"CallerReference": "lfg9-forums-frontend-2024",
|
|
"Comment": "LFG9 Forums Frontend Distribution",
|
|
"DefaultCacheBehavior": {
|
|
"TargetOriginId": "S3-lfg9-forums-frontend",
|
|
"ViewerProtocolPolicy": "redirect-to-https",
|
|
"TrustedSigners": {
|
|
"Enabled": false,
|
|
"Quantity": 0
|
|
},
|
|
"ForwardedValues": {
|
|
"QueryString": false,
|
|
"Cookies": {
|
|
"Forward": "none"
|
|
}
|
|
},
|
|
"MinTTL": 0
|
|
},
|
|
"Origins": {
|
|
"Quantity": 1,
|
|
"Items": [
|
|
{
|
|
"Id": "S3-lfg9-forums-frontend",
|
|
"DomainName": "lfg9-forums-frontend.s3.amazonaws.com",
|
|
"S3OriginConfig": {
|
|
"OriginAccessIdentity": ""
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"Enabled": true,
|
|
"PriceClass": "PriceClass_All"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Option 2: Netlify Deployment
|
|
|
|
1. **Create netlify.toml**:
|
|
|
|
```toml
|
|
[build]
|
|
command = "npm run build"
|
|
publish = "dist"
|
|
|
|
[[redirects]]
|
|
from = "/*"
|
|
to = "/index.html"
|
|
status = 200
|
|
|
|
[build.environment]
|
|
VITE_API_URL = "https://api.yourdomain.com"
|
|
```
|
|
|
|
2. **Deploy via Netlify CLI**:
|
|
|
|
```bash
|
|
npm install -g netlify-cli
|
|
netlify login
|
|
netlify deploy --prod --dir=dist
|
|
```
|
|
|
|
## Environment Configuration
|
|
|
|
### Production Environment Variables
|
|
|
|
#### Backend (.env)
|
|
```env
|
|
NODE_ENV=production
|
|
PORT=3000
|
|
JWT_SECRET=your-production-jwt-secret
|
|
JWT_EXPIRES_IN=7d
|
|
AWS_REGION=us-east-1
|
|
DYNAMODB_TABLE_PREFIX=lfg9_forums_
|
|
S3_BUCKET_NAME=lfg9-forums-uploads
|
|
RATE_LIMIT_WINDOW_MS=900000
|
|
RATE_LIMIT_MAX_REQUESTS=100
|
|
MAX_FILE_SIZE=10485760
|
|
MAX_FILES_PER_USER=100
|
|
CORS_ORIGIN=https://yourdomain.com
|
|
```
|
|
|
|
#### Frontend (.env.production)
|
|
```env
|
|
VITE_API_URL=https://api.yourdomain.com
|
|
VITE_WS_URL=wss://api.yourdomain.com
|
|
```
|
|
|
|
## SSL/TLS Configuration
|
|
|
|
### AWS Certificate Manager
|
|
|
|
1. **Request SSL certificate**:
|
|
|
|
```bash
|
|
aws acm request-certificate \
|
|
--domain-name yourdomain.com \
|
|
--subject-alternative-names "*.yourdomain.com" \
|
|
--validation-method DNS
|
|
```
|
|
|
|
2. **Validate certificate** through DNS validation
|
|
|
|
3. **Update CloudFront and ALB** to use the certificate
|
|
|
|
## Monitoring and Logging
|
|
|
|
### CloudWatch Setup
|
|
|
|
1. **Create log groups**:
|
|
|
|
```bash
|
|
aws logs create-log-group --log-group-name /aws/ecs/lfg9-forums-backend
|
|
aws logs create-log-group --log-group-name /aws/lambda/lfg9-forums-backend
|
|
```
|
|
|
|
2. **Set up CloudWatch dashboards** for monitoring:
|
|
- API response times
|
|
- Error rates
|
|
- DynamoDB read/write capacity
|
|
- S3 upload metrics
|
|
|
|
### Health Checks
|
|
|
|
Configure health checks for:
|
|
- Backend API endpoint (`/health`)
|
|
- Database connectivity
|
|
- S3 access
|
|
|
|
## Security Checklist
|
|
|
|
- [ ] Enable AWS WAF on CloudFront
|
|
- [ ] Configure proper CORS origins
|
|
- [ ] Use HTTPS everywhere
|
|
- [ ] Enable DynamoDB encryption at rest
|
|
- [ ] Configure S3 bucket policies correctly
|
|
- [ ] Use AWS Secrets Manager for sensitive data
|
|
- [ ] Enable CloudTrail for API logging
|
|
- [ ] Configure proper IAM roles and policies
|
|
- [ ] Enable MFA for AWS root account
|
|
- [ ] Regularly rotate JWT secrets
|
|
|
|
## Performance Optimization
|
|
|
|
1. **Enable CloudFront caching** for static assets
|
|
2. **Configure DynamoDB auto-scaling**
|
|
3. **Use S3 Transfer Acceleration** for file uploads
|
|
4. **Enable gzip compression** on CloudFront
|
|
5. **Implement CDN** for global content delivery
|
|
6. **Monitor and optimize** database queries
|
|
|
|
## Backup and Disaster Recovery
|
|
|
|
1. **Enable DynamoDB point-in-time recovery**
|
|
2. **Configure S3 cross-region replication**
|
|
3. **Regular database backups**
|
|
4. **Test disaster recovery procedures**
|
|
|
|
## Maintenance
|
|
|
|
1. **Regular security updates**
|
|
2. **Monitor AWS service limits**
|
|
3. **Review and optimize costs**
|
|
4. **Update dependencies regularly**
|
|
5. **Monitor application performance** |