v0.4.0 UPGRADE GUIDE - nself-org/nchat GitHub Wiki
Upgrading From: v0.3.0 Upgrading To: v0.4.0 Estimated Time: 15-30 minutes (excluding optional media server setup) Difficulty: Intermediate
- Pre-Upgrade Checklist
- Backup Your Data
- Update Application Code
- Update Dependencies
- Database Migration
- Environment Configuration
- Optional: Media Server Setup
- Restart Services
- Post-Upgrade Verification
- Rollback Instructions
- Troubleshooting
Before starting the upgrade, ensure you have:
- Backup of all data (database, files, configuration)
- Access to production server (SSH, console, etc.)
- 30 minutes of maintenance window (optional for zero-downtime)
- Node.js 20+ and pnpm 9+ installed
- Current version confirmed:
cat package.json | grep versionshould show0.3.0 - All services running:
pnpm backend:statusshould show all services up - Recent backup tested: Verify you can restore from backup
Minimum Requirements (same as v0.3.0):
- Node.js: 20.0.0 or higher
- pnpm: 9.0.0 or higher
- PostgreSQL: 14+ (via nself CLI)
- RAM: 4GB minimum, 8GB recommended
- Disk: 10GB free space
Additional Requirements for E2EE:
- No additional requirements (uses CPU for crypto operations)
Additional Requirements for Video Calls:
- RAM: 8GB minimum, 16GB recommended (for background effects)
- GPU: Optional but recommended for background effects
- Bandwidth: 10 Mbps upload/download per video stream
Additional Requirements for Media Server:
- RAM: 8GB minimum, 16GB recommended
- CPU: 4+ cores recommended
- Bandwidth: 100 Mbps minimum, 500 Mbps recommended
- Public IP: Required for production TURN server
- Ports: 3100 (HTTP), 3478 (TURN), 40000-49999 (RTC)
# Create timestamp for backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Backup PostgreSQL database
cd .backend
docker exec -t nself-postgres pg_dump -U postgres nchat > "backups/nchat_${TIMESTAMP}.sql"
# Verify backup was created
ls -lh "backups/nchat_${TIMESTAMP}.sql"# Backup all configuration files
mkdir -p backups/config_${TIMESTAMP}
cp .env.local "backups/config_${TIMESTAMP}/"
cp .backend/.env "backups/config_${TIMESTAMP}/"
cp -r .backend/migrations "backups/config_${TIMESTAMP}/"# If using MinIO file storage
cd .backend
docker exec nself-minio mc mirror /data "backups/files_${TIMESTAMP}"
# Or if using local file storage
cp -r .backend/storage "backups/storage_${TIMESTAMP}"# Check backup sizes
du -sh backups/*
# Verify SQL backup is valid (check for errors)
grep -i error "backups/nchat_${TIMESTAMP}.sql"IMPORTANT: Store backups in a safe location outside the application directory.
# Stash any local changes
git stash
# Pull latest v0.4.0 code
git fetch origin
git checkout v0.4.0
# OR if on main branch
git pull origin main
# Check current version
cat package.json | grep '"version"'
# Should show: "version": "0.4.0"# Download v0.4.0 release
wget https://github.com/nself-org/nchat/archive/refs/tags/v0.4.0.tar.gz
# Extract
tar -xzf v0.4.0.tar.gz
# Move files (backup current first!)
mv nself-chat nself-chat-v0.3.0-backup
mv nself-chat-0.4.0 nself-chat
cd nself-chat# Remove old dependencies
rm -rf node_modules
rm -f pnpm-lock.yaml
# Install new dependencies
pnpm install
# Verify installation
pnpm list --depth=0 | grep -E "signalapp|tensorflow|mediasoup"Expected output should include:
@signalapp/libsignal-client 0.69.0
@tensorflow/tfjs 4.22.0
mediasoup-client 3.18.5
pnpm --version
# Should be 9.15.4 or higher
# If not, update pnpm
corepack enable
corepack prepare [email protected] --activate# Should show no errors
pnpm install --frozen-lockfile
# If errors, run without frozen lockfile
pnpm installFor zero-downtime upgrades, you can skip this step. The migrations are additive only.
# Stop frontend (optional)
# pkill -f "next dev" or pm2 stop nchat-frontendcd .backend
nself status | grep postgres
# Should show: postgres: running
# Test connection
docker exec -t nself-postgres psql -U postgres -d nchat -c "SELECT version();"# List migration files for v0.4.0
ls -la migrations/013_e2ee_system.sql
ls -la migrations/014_e2ee_system.sql
ls -la migrations/015_voice_calls.sql
ls -la migrations/016_live_streaming.sql
# Preview migration (first 50 lines of E2EE migration)
head -50 migrations/014_e2ee_system.sql# Run all pending migrations
nself db migrate up
# Expected output:
# ✓ Running migration: 014_e2ee_system.sql
# ✓ Running migration: 015_voice_calls.sql
# ✓ Running migration: 016_live_streaming.sql
# ✓ All migrations completed successfully# Check new tables were created
docker exec -t nself-postgres psql -U postgres -d nchat -c "
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'nchat_%'
AND table_name IN (
'nchat_user_master_keys',
'nchat_identity_keys',
'nchat_signed_prekeys',
'nchat_one_time_prekeys',
'nchat_signal_sessions',
'nchat_safety_numbers',
'nchat_e2ee_audit_log'
)
ORDER BY table_name;
"
# Expected output: All 7 tables listed# Check existing data is intact
docker exec -t nself-postgres psql -U postgres -d nchat -c "
SELECT
(SELECT COUNT(*) FROM nchat_users) as users,
(SELECT COUNT(*) FROM nchat_channels) as channels,
(SELECT COUNT(*) FROM nchat_messages) as messages;
"
# Compare with your pre-upgrade countsEdit your .env.local file and add the following:
# ═══════════════════════════════════════════════════════════════
# E2EE CONFIGURATION (v0.4.0)
# ═══════════════════════════════════════════════════════════════
# Enable end-to-end encryption feature
NEXT_PUBLIC_FEATURE_E2EE=true
# Debug mode for E2EE (set to false in production)
NEXT_PUBLIC_E2EE_DEBUG=false
# ═══════════════════════════════════════════════════════════════
# VIDEO CALLING CONFIGURATION (v0.4.0)
# ═══════════════════════════════════════════════════════════════
# Enable HD video calling
NEXT_PUBLIC_FEATURE_VIDEO_CALLS_HD=true
# Enable background effects (blur, virtual backgrounds)
NEXT_PUBLIC_FEATURE_BACKGROUND_EFFECTS=true
# Enable screen sharing
NEXT_PUBLIC_FEATURE_SCREEN_SHARING=true
# Enable screen recording
NEXT_PUBLIC_FEATURE_SCREEN_RECORDING=true
# ═══════════════════════════════════════════════════════════════
# MEDIA SERVER CONFIGURATION (v0.4.0)
# ═══════════════════════════════════════════════════════════════
# Media server URL (if using external media server)
# For local development, use default: http://localhost:3100
NEXT_PUBLIC_MEDIA_SERVER_URL=http://localhost:3100
# Media server public IP (REQUIRED for production)
# Replace with your actual public IP
MEDIA_SERVER_PUBLIC_IP=127.0.0.1
# Number of MediaSoup workers (1 per CPU core recommended)
MEDIASOUP_NUM_WORKERS=4
# Enable recording functionality
RECORDING_ENABLED=true
# JWT secret for media server authentication
# Generate with: openssl rand -base64 32
# IMPORTANT: Use a strong secret in production
JWT_SECRET=change-this-to-a-secure-random-string-min-32-chars
# ═══════════════════════════════════════════════════════════════
# TURN SERVER CONFIGURATION (v0.4.0)
# ═══════════════════════════════════════════════════════════════
# TURN server credential (for NAT traversal)
# Generate with: openssl rand -base64 32
TURN_CREDENTIAL=change-this-to-a-secure-turn-credential
# TURN server public IP (same as media server in most cases)
TURN_PUBLIC_IP=127.0.0.1
# TURN server URL (default for local development)
NEXT_PUBLIC_TURN_SERVER_URL=turn:localhost:3478
# STUN server URL (can use public STUN servers)
NEXT_PUBLIC_STUN_SERVER_URL=stun:stun.l.google.com:19302The AppConfig schema has been extended. Update your configuration via admin panel or direct database update:
-- Update app_configuration table with new E2EE settings
UPDATE app_configuration
SET config = jsonb_set(
jsonb_set(
config,
'{features,endToEndEncryption}',
'true'
),
'{encryption}',
'{
"enabled": true,
"enforceForPrivateChannels": true,
"enforceForDirectMessages": true,
"allowUnencryptedPublicChannels": true,
"enableSafetyNumbers": true,
"requireDeviceVerification": false,
"automaticKeyRotation": true,
"keyRotationDays": 7
}'::jsonb
)
WHERE id = 1;
-- Update video calling settings
UPDATE app_configuration
SET config = jsonb_set(
config,
'{videoCalls}',
'{
"maxParticipants": 50,
"defaultResolution": "720p",
"enableSimulcast": true,
"enableBackgroundEffects": true,
"enableScreenSharing": true,
"enableRecording": false
}'::jsonb
)
WHERE id = 1;# Run environment validation
pnpm validate:env
# For production, run production validation
pnpm validate:env:prodThe media server is optional for basic E2EE functionality but required for video calling features.
cd .backend
# Run automated setup wizard
./scripts/setup-media-server.sh
# Follow the prompts:
# 1. Enter your public IP address
# 2. Choose number of workers (default: 4)
# 3. Generate secure secrets (or provide your own)
# 4. Confirm configurationIf you prefer manual setup or need custom configuration:
cd .backend
# 1. Create media server configuration
cp custom-services/media-server/.env.example custom-services/media-server/.env
# 2. Edit configuration
nano custom-services/media-server/.env
# Update these values:
# - MEDIA_SERVER_PUBLIC_IP=your.public.ip
# - JWT_SECRET=your-secure-secret
# - TURN_CREDENTIAL=your-turn-secret
# 3. Build media server
cd custom-services/media-server
pnpm install
pnpm build
# 4. Start media server
docker-compose -f ../../docker-compose.media.yml up -d
# 5. Verify media server is running
curl http://localhost:3100/api/health
# Should return: {"status": "ok"}If you only want E2EE and not video calling:
# In .env.local, disable video features
NEXT_PUBLIC_FEATURE_VIDEO_CALLS_HD=false
NEXT_PUBLIC_FEATURE_BACKGROUND_EFFECTS=false
NEXT_PUBLIC_FEATURE_SCREEN_SHARING=false
# E2EE will work without media server
NEXT_PUBLIC_FEATURE_E2EE=truecd .backend
# Stop all services
nself stop
# Start all services (including new media server if enabled)
nself start
# Verify all services are running
nself status
# Check logs for any errors
nself logs | tail -50# Kill existing dev server
pkill -f "next dev"
# Start new dev server
pnpm dev
# Or with Turbopack (faster)
pnpm dev:turbo# Rebuild production
pnpm build
# Restart with PM2
pm2 restart nchat-frontend
# Check status
pm2 status
pm2 logs nchat-frontend --lines 50# Rebuild Docker image
pnpm build:docker
# Stop existing container
docker stop nself-chat
# Start new container
docker-compose up -d
# Check logs
docker logs nself-chat -f# Check all services are responding
curl http://localhost:3000/api/health
curl http://localhost:3100/api/health # Media server
curl http://api.localhost/healthz # Hasura
# Check WebSocket connection
wscat -c ws://realtime.localhost
# Should connect successfully# Test basic pages load
curl -I http://localhost:3000/
curl -I http://localhost:3000/chat
curl -I http://localhost:3000/settings
# Should all return 200 OKVia Browser:
- Open http://localhost:3000
- Log in as test user ([email protected] / password123)
- Go to Settings → Security
- Click "Enable End-to-End Encryption"
- Enter a password (e.g., "TestPassword123")
- Save the recovery code shown
- Verify E2EE status shows "Enabled" with lock icon
Via API:
# Initialize E2EE for a user
curl -X POST http://localhost:3000/api/e2ee/initialize \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"password": "TestPassword123"}'
# Should return: {"success": true, "deviceId": "...", "recoveryCode": "..."}Via Browser:
- Open http://localhost:3000/chat
- Click on a DM or channel
- Click the video camera icon
- Allow camera/microphone permissions
- Start a test call
- Verify video appears
- Test background blur (if enabled)
Via API:
# Check media server health
curl http://localhost:3100/api/health
# Should return: {"status": "ok", "workers": 4, "rooms": 0}
# Check ICE servers
curl http://localhost:3100/api/ice-servers \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Should return TURN/STUN server configuration# Verify E2EE tables exist and are accessible
docker exec -t nself-postgres psql -U postgres -d nchat -c "
SELECT COUNT(*) FROM nchat_user_master_keys;
SELECT COUNT(*) FROM nchat_identity_keys;
SELECT COUNT(*) FROM nchat_signal_sessions;
"
# Should return 0 for fresh install (no data yet)Open browser console (F12) and check for:
- ❌ No red errors
⚠️ Warnings are okay (deprecation warnings from dependencies)- ✅ Should see successful GraphQL connections
# Check CPU usage
top -p $(pgrep -f "next")
# Check memory usage
ps aux | grep next
# Check Docker container stats
docker stats --no-stream
# Should be similar to pre-upgrade levelsIf you encounter critical issues, you can rollback to v0.3.0.
cd .backend
nself stop
pkill -f "next dev"# Restore from backup
cd .backend
docker exec -i nself-postgres psql -U postgres -d nchat < "backups/nchat_${TIMESTAMP}.sql"
# Verify restoration
docker exec -t nself-postgres psql -U postgres -d nchat -c "SELECT COUNT(*) FROM nchat_messages;"# If using Git
git checkout v0.3.0
# If using backup directory
rm -rf nself-chat
mv nself-chat-v0.3.0-backup nself-chat
cd nself-chatcp "backups/config_${TIMESTAMP}/.env.local" .
cp "backups/config_${TIMESTAMP}/.backend/.env" .backend/rm -rf node_modules
pnpm installcd .backend
nself start
cd ..
pnpm dev# Check version
cat package.json | grep version
# Should show: 0.3.0
# Verify application loads
curl http://localhost:3000/Error: migration 014_e2ee_system.sql failed
Solution:
# Check error details
nself logs postgres | tail -100
# Manually rollback failed migration
docker exec -t nself-postgres psql -U postgres -d nchat -c "
DROP TABLE IF EXISTS nchat_user_master_keys CASCADE;
DROP TABLE IF EXISTS nchat_identity_keys CASCADE;
-- ... drop other new tables
"
# Re-run migration
nself db migrate upError: "E2EE not initialized" or "Failed to encrypt message"
Solution:
# Check E2EE tables exist
docker exec -t nself-postgres psql -U postgres -d nchat -c "
SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename LIKE '%e2ee%';
"
# Check browser console for errors
# Open DevTools (F12) → Console
# Verify feature flag is enabled
echo $NEXT_PUBLIC_FEATURE_E2EE
# Should output: true
# Clear browser cache and localStorage
# In browser console: localStorage.clear()Error: Media server container exits immediately
Solution:
# Check logs
docker logs nself-media-server
# Common issues:
# 1. Port already in use
sudo lsof -i :3100
# Kill process if needed: sudo kill -9 <PID>
# 2. Missing environment variables
cd .backend/custom-services/media-server
cat .env | grep -E "PUBLIC_IP|JWT_SECRET|TURN"
# 3. Docker resource limits
docker info | grep -E "CPUs|Memory"
# Ensure Docker has enough resources (4GB+ RAM)Error: Video call starts but no video appears
Solution:
# 1. Check ICE servers
curl http://localhost:3100/api/ice-servers
# 2. Check browser permissions
# In browser: Settings → Site Settings → Permissions
# Ensure camera and microphone are allowed
# 3. Check network connectivity
# Open browser console during call
# Look for WebRTC errors
# 4. Test STUN/TURN connectivity
# Use online TURN test: https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/Error: Application using more memory after upgrade
Solution:
# Expected memory increase:
# - E2EE: +50-100MB (crypto libraries)
# - Video calls: +100-200MB per active call
# - Background effects: +100-150MB (TensorFlow.js)
# Optimize settings:
# In .env.local
NEXT_PUBLIC_FEATURE_BACKGROUND_EFFECTS=false # Disable if not needed
MEDIASOUP_NUM_WORKERS=2 # Reduce workers if low resources
# Restart with updated configError: TypeScript compilation errors after upgrade
Solution:
# Clear TypeScript cache
rm -rf .next
rm -rf node_modules/.cache
# Reinstall dependencies
rm -rf node_modules
pnpm install
# Run type check
pnpm type-check
# If errors persist, check TypeScript version
pnpm list typescript
# Should be 5.7.3 or higherIf running on a small VPS or limited resources:
# In .env.local
# Reduce media server workers
MEDIASOUP_NUM_WORKERS=2
# Disable resource-intensive features
NEXT_PUBLIC_FEATURE_BACKGROUND_EFFECTS=false
NEXT_PUBLIC_FEATURE_SCREEN_RECORDING=false
# Reduce video quality default
NEXT_PUBLIC_DEFAULT_VIDEO_QUALITY=360p
# Limit max participants
NEXT_PUBLIC_MAX_CALL_PARTICIPANTS=10If running on dedicated servers:
# In .env.local
# Increase workers (1 per CPU core)
MEDIASOUP_NUM_WORKERS=16
# Enable all features
NEXT_PUBLIC_FEATURE_BACKGROUND_EFFECTS=true
NEXT_PUBLIC_FEATURE_SCREEN_RECORDING=true
# Increase video quality
NEXT_PUBLIC_DEFAULT_VIDEO_QUALITY=1080p
# Increase participant limit
NEXT_PUBLIC_MAX_CALL_PARTICIPANTS=50If you're stuck or need assistance:
-
Check Documentation:
-
Search Existing Issues:
-
Ask for Help:
- Discord: discord.gg/nself
- Email: [email protected]
-
Report a Bug:
After completing the upgrade, verify:
- All services running:
pnpm backend:status - Application loads: http://localhost:3000
- User can log in
- E2EE can be enabled in settings
- Video calls can be initiated (if media server enabled)
- No console errors in browser DevTools
- Database has new tables (E2EE tables)
- Existing data intact (messages, users, channels)
- Performance is acceptable
- Backups are stored safely
- Monitoring/logging working (if applicable)
Congratulations! You've successfully upgraded to nChat v0.4.0.
Enjoy the new end-to-end encryption and video calling features! 🔒🎥