Deployment
This guide covers deploying True Life to a production FiveM server.
Build for Production
# Full production build
pnpm build
This runs:
pnpm gen- Generate asset referencespnpm typecheck:build- Type check all codepnpm build:client- Build client bundlepnpm build:server- Build server bundlepnpm build:ui- Build UI with Vite
Output Structure
dist/
├── client.js # Client bundle
├── server.js # Server bundle
└── ui/ # UI build output
├── index.html
└── assets/
├── index-[hash].js
├── index-[hash].css
└── [feature]-[hash].js
FiveM Resource Setup
fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
name 'true_life'
description 'True Life FiveM Framework'
version '1.0.0'
-- Server script
server_script 'dist/server.js'
-- Client script
client_script 'dist/client.js'
-- UI files
ui_page 'dist/ui/index.html'
files {
'dist/ui/**/*'
}
-- Dependencies
dependency 'yarn'
dependency 'oxmysql' -- If using MySQL alongside MongoDB
Server Configuration
# server.cfg (FiveM server.cfg format)
# Resource
ensure true_life
# MongoDB
set mongodb_uri "mongodb://user:password@host:27017"
set mongodb_database "true_life_prod"
# Disable dev mode
set dev_mode "false"
set dev_features ""
# OpenTelemetry (optional)
set otel_enabled "true"
set otel_endpoint "http://otel-collector:4318"
set otel_service_name "true_life_prod"
Docker Deployment
MongoDB
# docker-compose.prod.yml
services:
mongo:
image: mongo:7
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
volumes:
- mongo-data:/data/db
networks:
- fivem-network
Full Stack
services:
mongo:
image: mongo:7
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
volumes:
- mongo-data:/data/db
networks:
- internal
otel-collector:
image: otel/opentelemetry-collector-contrib:0.141.0
restart: always
volumes:
- ./infra/otel/otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
networks:
- internal
tempo:
image: grafana/tempo:2.9.0
restart: always
volumes:
- ./infra/tempo/tempo.yaml:/etc/tempo.yaml:ro
- tempo-data:/var/tempo
networks:
- internal
loki:
image: grafana/loki:3.6.2
restart: always
volumes:
- ./infra/loki/loki.yaml:/etc/loki/loki.yaml:ro
- loki-data:/loki
networks:
- internal
grafana:
image: grafana/grafana:12.3.0
restart: always
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
- GF_AUTH_ANONYMOUS_ENABLED=false
volumes:
- ./infra/grafana/provisioning:/etc/grafana/provisioning:ro
- grafana-data:/var/lib/grafana
ports:
- "3001:3000"
networks:
- internal
docs:
image: node:22-alpine
working_dir: /app
command: sh -c "npm install && npm run build && npm run serve"
volumes:
- ./docs:/app
ports:
- "3003:3003"
networks:
- internal
volumes:
mongo-data:
tempo-data:
loki-data:
grafana-data:
networks:
internal:
Environment Variables
Create .env.production:
# MongoDB
MONGO_USER=true_life
MONGO_PASSWORD=secure_password_here
# Grafana
GRAFANA_PASSWORD=secure_admin_password
# OpenTelemetry
OTEL_ENDPOINT=http://otel-collector:4318
CI/CD Pipeline
GitHub Actions Example
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install
- run: pnpm lint
- run: pnpm test
- run: pnpm build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
# Deploy to your server
- name: Deploy
run: |
rsync -avz dist/ user@server:/path/to/resources/true_life/dist/
Security Checklist
- Use strong MongoDB credentials
- Disable dev mode in production
- Set strong Grafana admin password
- Use HTTPS for external endpoints
- Configure firewall rules
- Enable MongoDB authentication
- Rotate secrets regularly
- Monitor for suspicious activity
Performance Optimization
MongoDB Indexes
Ensure indexes are created on startup:
// src/modules/init/repository.ts
export async function ensureIndexes(): Promise<void> {
const db = await getMongoDb();
await db.collection("characters").createIndexes([
{ key: { id: 1 }, unique: true },
{ key: { playerId: 1 } },
]);
await db.collection("accounts").createIndexes([
{ key: { id: 1 }, unique: true },
{ key: { characterId: 1 } },
]);
}
UI Bundle Optimization
Vite automatically optimizes the bundle:
- Code splitting by feature
- Tree shaking
- Minification
- Asset hashing
Telemetry Sampling
For high-traffic servers, configure sampling:
# otel-collector-config.yaml
processors:
probabilistic_sampler:
sampling_percentage: 10 # Sample 10% of traces
Monitoring
Key Metrics to Watch
- Player count
- Error rates
- Response times
- Database query performance
- Memory usage
Alerting
Configure Grafana alerts for:
- Error rate spikes
- High latency
- Database connection failures
- Resource exhaustion
Backup Strategy
MongoDB Backup
# Manual backup
mongodump --uri="mongodb://user:pass@host:27017" --out=/backup/$(date +%Y%m%d)
# Scheduled backup (cron)
0 2 * * * mongodump --uri="..." --out=/backup/$(date +\%Y\%m\%d) --gzip
Restore
mongorestore --uri="mongodb://user:pass@host:27017" /backup/20240101