# Generate unique encryption key
python3 -c "from cryptography.fernet import Fernet; print(f'VAULT_ENCRYPTION_KEY={Fernet.generate_key().decode()}')"
# Generate unique JWT secret
python3 -c "import secrets; print(f'JWT_SECRET_KEY={secrets.token_hex(32)}')"
Set these in your environment:
export VAULT_ENCRYPTION_KEY="your-generated-key-here"
export JWT_SECRET_KEY="your-jwt-secret-here"
export DATABASE_URL="sqlite:///nija.db" # Or PostgreSQL URL
export PORT="8000"
⚠️ WARNING: Never commit these keys to git!
pip install -r requirements.txt
python3 test_mvp_components.py
Expected output:
✅ Tests Passed: 4/4 (100.0%)
❌ Tests Failed: 0
# Start FastAPI backend
uvicorn fastapi_backend:app --reload --host 0.0.0.0 --port 8000
Access at: http://localhost:8000
# Start with Gunicorn + Uvicorn workers
gunicorn fastapi_backend:app \
-w 4 \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--access-logfile - \
--error-logfile -
# Build image
docker build -t nija-mvp .
# Run container
docker run -d \
-p 8000:8000 \
-e VAULT_ENCRYPTION_KEY=$VAULT_ENCRYPTION_KEY \
-e JWT_SECRET_KEY=$JWT_SECRET_KEY \
nija-mvp
# Set environment variables in Railway dashboard:
VAULT_ENCRYPTION_KEY=your-key
JWT_SECRET_KEY=your-secret
# Deploy
railway up
curl http://localhost:8000/health
Expected response:
{
"status": "healthy",
"timestamp": "2026-01-27T...",
"service": "NIJA FastAPI Backend",
"version": "2.0.0"
}
curl -X POST http://localhost:8000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "TestPassword123!",
"subscription_tier": "basic"
}'
Expected response:
{
"access_token": "eyJ0eXAi...",
"token_type": "bearer",
"user_id": "user_...",
"email": "test@example.com",
"subscription_tier": "basic"
}
curl -X POST http://localhost:8000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "TestPassword123!"
}'
Open browser to: http://localhost:8000
Should see NIJA login screen.
SELECT * FROM audit_log ORDER BY timestamp DESC LIMIT 100;
SELECT user_id, success, COUNT(*)
FROM login_history
WHERE timestamp > datetime('now', '-1 day')
GROUP BY user_id, success;
from core.enhanced_execution_router import get_enhanced_router
router = get_enhanced_router()
print(router.get_broker_stats())
Set up automated health checks to:
Problem: “vault.db locked” Solution: Close all connections, restart app
Problem: “Cannot decrypt credentials” Solution: Check VAULT_ENCRYPTION_KEY matches original
Problem: “Invalid credentials” Solution: Password must match Argon2 hash, case-sensitive
Problem: “JWT token expired” Solution: Token expires after 24 hours, user must login again
Problem: UI doesn’t load Solution: Check /frontend/static/ files are served correctly
Problem: Toggle doesn’t work Solution: Check API endpoint /api/trading/control exists
# Change DATABASE_URL
export DATABASE_URL="postgresql://user:pass@host/db"
pip install redis
# Configure session backend
upstream nija {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
gunicorn fastapi_backend:app -w 8 ...
# Backup vault.db
cp vault.db vault.db.backup.$(date +%Y%m%d)
# Backup users.db
cp users.db users.db.backup.$(date +%Y%m%d)
Store VAULT_ENCRYPTION_KEY securely:
CRITICAL: Without encryption key, vault data is unrecoverable!
For issues or questions:
/var/log/nija/ or container logspython3 test_mvp_components.pyMVP_4_COMPONENTS_README.md