SECTION 01

Platform Overview

EscenarioAI is an AI-powered browser-based Digital Audio Workstation (DAW) and track mixer. It enables musicians, producers, and audio engineers to upload, separate, process, and mix audio tracks entirely in the browser, powered by server-side AI models for stem separation, voice cloning, text-to-instrument synthesis, and intelligent VST parameter mapping.

System Architecture

┌─────────────────────────────────────────────────────────────────────────┐ CLIENT LAYER escenarioai.com studio.escenarioai.com admin.escenarioai.com Landing Page React 19 + Zustand 5 Admin SPA (Static HTML) Web Audio + Workers (Vanilla JS) └────────────────────────────────┬────────────────────────────────────────┘ HTTPS / WSS ┌─────────────────────────────────────────────────────────────────────────┐ REVERSE PROXY (Nginx + Certbot SSL) Routes: /api/* → :8000 | /ws/* → :8000 | /* → static files └────────────────────────────────┬────────────────────────────────────────┘ HTTP (localhost only) ┌─────────────────────────────────────────────────────────────────────────┐ APPLICATION LAYER (Docker Compose) FastAPI Backend Celery Worker VST Host :8000 (4 workers) concurrency=2 :9090 (Carla+Wine64) Auth, API, WS Audio processing Plugin loading Stem separation Parameter extraction └──────────┬─────────────────┬─────────────────┬──────────────────────────┘ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────────────────┐ PostgreSQL 16 │ │ Redis 7 │ │ External Services (Optional) User data │ │ Task broker │ │ Cloudflare R2 (storage) Projects │ │ Cache │ │ RunPod / Modal (GPU) Audio tasks │ │ WS pubsub │ │ OpenAI API (AI chat + VST mapping) └──────────────┘ └──────────────┘ └──────────────────────────────────────┘

Technology Stack

LayerTechnologyVersionPurpose
Frontend (Studio)React + Vite + Zustand19 / 8 / 5Browser-based DAW interface
Audio EngineWeb Audio API + AudioWorklets-Real-time audio processing
Backend APIFastAPI + Uvicorn0.115 / 0.30REST API + WebSocket server
Task QueueCelery + Redis5.4 / 7Async audio processing jobs
DatabasePostgreSQL + SQLAlchemy16 / 2.0Persistent data storage (async)
VST HostingCarla + Wine64 + Pedalboard-Plugin loading & audio routing
AI ServicesOpenAI API1.82Chat, VST parameter mapping
Cloud StorageCloudflare R2 (S3-compatible)-Audio file persistence
GPU ComputeRunPod / Modal-Demucs stem separation, RVC
Reverse ProxyNginx + Certbot-SSL termination, routing
ContainerizationDocker + Docker Compose24+ / v2Service orchestration
i18ni18next267 languages (EN, ES, FR, PT, IT, JA, HI)
SECTION 02

Server Requirements

Hardware Specifications

ResourceMinimumRecommended
CPU4 vCPU8 vCPU (dedicated cores)
RAM8 GB16 GB
Storage100 GB SSD250 GB NVMe SSD
Bandwidth1 Gbps1 Gbps unmetered
OSUbuntu 22.04 LTS (required)

Note: Audio processing (stem separation, mastering) is CPU-intensive. With GPU offloading (RunPod/Modal), the minimum spec is sufficient. Without GPU, the recommended spec is strongly advised for concurrent users.

Network Ports

PortProtocolAccessService
80TCPPublicHTTP (Nginx, redirects to 443)
443TCPPublicHTTPS (Nginx + Certbot SSL)
22TCPAdmin onlySSH access
8000TCPlocalhost onlyFastAPI backend (Docker)
5432TCPDocker internalPostgreSQL
6379TCPDocker internalRedis
9090TCPDocker internalVST Host (Carla)

Domain Requirements

Four DNS A records pointing to your server IP:

SubdomainPurposeContent Served
yourdomain.comLanding pageStatic marketing site
studio.yourdomain.comDAW applicationReact frontend + API proxy
editor.yourdomain.comLegacy editorSeparate audio editor build
admin.yourdomain.comAdmin panelManagement dashboard + API proxy
SECTION 03

Prerequisites Installation

All commands assume a fresh Ubuntu 22.04 LTS server with root access.

System Update

bash
apt update && apt upgrade -y
apt install -y curl wget git unzip software-properties-common

Docker Engine 24+

bash
# Remove old Docker versions
apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null

# Add Docker official GPG key and repository
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine + Compose
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Verify installation
docker --version
docker compose version

Node.js 20+ (via nvm)

bash
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc

# Install Node.js 20 LTS
nvm install 20
nvm use 20
nvm alias default 20

# Verify
node --version  # v20.x.x
npm --version

Nginx

bash
apt install -y nginx
systemctl enable nginx
systemctl start nginx

Certbot (SSL)

bash
apt install -y certbot python3-certbot-nginx

Firewall Configuration

bash
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw --force enable
ufw status
SECTION 04

Backend Deployment

Clone Repository

bash
mkdir -p /opt/escenario
cd /opt/escenario
git clone https://github.com/YOUR_ORG/escenario-backend.git backend
cd backend

Directory Structure

escenario-backend/ ├── main.py # FastAPI entry point ├── requirements.txt # Python 3.11 dependencies (27 packages) ├── Dockerfile # Backend container definition ├── docker-compose.yml # Multi-service orchestration ├── .env # Environment configuration ├── nginx.conf # Reference Nginx config ├── heartbeat.py # Health check utility ├── runpod_handler.py # RunPod GPU integration ├── modal_app.py # Modal.com serverless │ ├── app/ │ ├── api/ # Route handlers │ │ ├── auth.py # Registration, login, JWT │ │ ├── admin.py # Admin dashboard, user mgmt, auto-updater │ │ ├── chat.py # OpenAI-powered AI assistant │ │ ├── processing.py # Stem separation, effects, mastering │ │ ├── projects.py # Project CRUD + track management │ │ ├── upload.py # Audio file uploads │ │ └── vst.py # VST plugin management │ │ │ ├── core/ # Infrastructure │ │ ├── config.py # Pydantic BaseSettings (.env loader) │ │ ├── database.py # Async SQLAlchemy engine (pool_size=20) │ │ └── security.py # JWT creation, password hashing │ │ │ ├── models/ # SQLAlchemy ORM models │ │ ├── user.py # User + PlanTier enum │ │ ├── project.py # Project, Track, AudioTask │ │ ├── vst.py # VSTPlugin + format/platform enums │ │ └── collaboration.py # Rooms, participants, messages │ │ │ ├── schemas/ # Pydantic request/response models │ │ ├── auth.py # UserCreate, UserResponse, Token │ │ └── project.py # ProjectCreate, TrackResponse │ │ │ ├── services/ # Business logic layer │ │ ├── audio_analysis.py # BPM/key detection (librosa) │ │ ├── audio_tools.py # Audio utility functions │ │ ├── autotune.py # Pitch correction (praat-parselmouth) │ │ ├── auto_gain_stager.py # Loudness normalization │ │ ├── effects_processor.py # FX chain (pedalboard) │ │ ├── vocal_precleaner.py # Noise reduction │ │ ├── mastering_processor.py # Multi-band mastering │ │ ├── sidechain_processor.py # Sidechain compression │ │ ├── vst_service.py # VST loading + parameter extraction │ │ ├── vst_ai_mapper.py # AI parameter mapping (OpenAI) │ │ ├── storage.py # R2/S3 file operations │ │ ├── gpu_dispatch.py # RunPod/Modal job dispatch │ │ ├── export_matrix.py # Multi-format audio export │ │ └── region_editor.py # Audio region operations │ │ │ ├── workers/ # Celery task definitions │ │ ├── celery_app.py # Celery configuration + Redis broker │ │ ├── tasks.py # Audio processing tasks │ │ └── vst_tasks.py # VST scan/process tasks │ │ │ └── collaboration/ # Real-time features │ ├── manager.py # Redis-backed room state │ └── router.py # WebSocket endpoint handlers │ └── vst_host/ # Separate microservice ├── Dockerfile # Ubuntu 22.04 + Wine64 + Carla ├── server.py # FastAPI VST bridge server └── requirements.txt # fastapi, numpy, soundfile

Environment Configuration

Create the .env file in the backend root directory:

.env
# ============================================
# EscenarioAI Backend Configuration
# ============================================

# --- Database (PostgreSQL) ---
DATABASE_URL=postgresql+asyncpg://escenario:YOUR_DB_PASSWORD@db:5432/escenario_db
DATABASE_URL_SYNC=postgresql://escenario:YOUR_DB_PASSWORD@db:5432/escenario_db

# --- Redis ---
REDIS_URL=redis://redis:6379/0

# --- Authentication ---
SECRET_KEY=GENERATE_A_64_CHAR_RANDOM_STRING_HERE
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=1440

# --- Cloud Storage (Cloudflare R2) ---
R2_ENDPOINT_URL=https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=YOUR_R2_ACCESS_KEY
R2_SECRET_ACCESS_KEY=YOUR_R2_SECRET_KEY
R2_BUCKET_NAME=escenario-audio

# --- GPU Processing (Optional) ---
RUNPOD_API_KEY=
RUNPOD_ENDPOINT_ID=
MODAL_WEBHOOK_URL=

# --- AI Services ---
OPENAI_API_KEY=sk-YOUR_OPENAI_API_KEY

# --- CORS (comma-separated origins) ---
ALLOWED_ORIGINS=https://yourdomain.com,https://studio.yourdomain.com,https://editor.yourdomain.com,https://admin.yourdomain.com,http://localhost:5173

# --- Upload Limits ---
MAX_UPLOAD_SIZE_MB=100
MAX_VST_UPLOAD_SIZE_MB=500

# --- VST Host ---
VST_HOST_URL=http://vst-host:9090

Security: Generate SECRET_KEY with: python3 -c "import secrets; print(secrets.token_urlsafe(48))"

Docker Compose Services

The platform runs as 5 interconnected Docker services:

1. PostgreSQL Database (db)

PostgreSQL 16 Alpine with persistent volume. Auto-creates the escenario_db database. Health check ensures the service is ready before dependents start.

2. Redis (redis)

Redis 7 Alpine for Celery task brokering, WebSocket pub/sub, and session caching. No persistence configured (ephemeral cache).

3. Backend (backend)

Python 3.11-slim running FastAPI via Uvicorn with 4 workers. Binds to 127.0.0.1:8000 (not public). Mounts workspace volume for audio files, host Docker socket for auto-updater functionality.

4. Celery Worker (celery-worker)

Same Docker image as backend, runs Celery with --concurrency=2 on the default queue. Handles all async audio processing: stem separation, effects, mastering, VST operations.

5. VST Host (vst-host)

Ubuntu 22.04 with Wine64 (Windows VST bridging), Carla (headless plugin rack), and audio libraries. Exposes port 9090 internally for the backend to communicate with.

Launch the Platform

bash
cd /opt/escenario/backend

# Build and start all services
docker compose up -d --build

# Monitor build progress
docker compose logs -f

# Verify all services are healthy
docker compose ps

# Test API health endpoint
curl http://localhost:8000/health

Expected response: {"status": "healthy", "version": "1.0.0", "service": "EscenarioAI"}

Create Admin User

bash
# Enter the backend container
docker compose exec backend bash

# Generate password hash
python3 -c "from passlib.context import CryptContext; \
  pwd = CryptContext(schemes=['bcrypt']); \
  print(pwd.hash('YOUR_ADMIN_PASSWORD'))"

# Insert admin user via psql
docker compose exec db psql -U escenario -d escenario_db -c \
  "INSERT INTO users (email, full_name, hashed_password, plan, is_active, is_admin) \
   VALUES ('admin@yourdomain.com', 'Admin', 'PASTE_HASH_HERE', 'PRO', true, true);"
SECTION 05

Frontend Deployment

Studio DAW (Primary Application)

The main DAW interface built with React 19, Vite 8, and Zustand 5.

bash
# Clone the frontend repository
cd /opt/escenario
git clone https://github.com/YOUR_ORG/escenario-frontend.git frontend
cd frontend

# Ensure Node 20 is active
source ~/.nvm/nvm.sh && nvm use 20

# Install dependencies
npm install

# Update API proxy in vite.config.js to point to your server
# (only needed for local dev; production uses Nginx proxy)

# Build for production
npm run build

# Deploy build output
mkdir -p /var/www/escenario/frontend
cp -r dist/* /var/www/escenario/frontend/

Key Frontend Components

ComponentFilePurpose
Main DAWStudio.jsxMulti-track timeline, transport, mixing (75KB)
Audio EngineAudioEngine.jsWeb Audio graph, routing, effects chain (27KB)
VST PanelVSTPluginPanel.jsxPlugin upload, parameter control, AI mapping
CollaborationCollabPanel.jsxReal-time rooms via WebSocket
MixerMixerPanel.jsxChannel strips, faders, routing
MasteringMasteringPanel.jsxMulti-band processing, presets, export
AI ChatAiChat.jsxOpenAI-powered production assistant
Vocal RecorderVocalRecorder.jsxBrowser recording with MP3 encoding

Dependencies

PackageVersionPurpose
react19.2UI framework
zustand5.0State management (stores)
axios1.16HTTP client for API calls
react-router-dom7.15Client-side routing
i18next26.2Internationalization (7 languages)
lamejs1.2Client-side MP3 encoding

Editor (Legacy Audio Editor)

bash
# Clone and build the editor
cd /opt/escenario
git clone https://github.com/YOUR_ORG/escenario-editor.git editor
cd editor

# Build (if applicable) or copy directly
mkdir -p /var/www/escenario/editor
cp -r ./* /var/www/escenario/editor/

Admin Panel

A static HTML single-page application with no build step required.

bash
mkdir -p /var/www/escenario/admin
# Deploy the admin panel HTML file
cp /opt/escenario/admin-panel/index.html /var/www/escenario/admin/

Admin panel features: User management (create/edit/deactivate), platform analytics, VST plugin oversight, system health monitoring, GPU queue status, auto-updater, documentation, and support portal link.

Landing Page

bash
mkdir -p /var/www/escenario/landing
# Deploy landing page files
cp /opt/escenario/escenario-landing/* /var/www/escenario/landing/

Includes: index.html, terms.html, privacy.html, dmca.html, refund.html, logo assets.

SECTION 06

Nginx Configuration

Studio Subdomain (Primary DAW)

nginx
# /etc/nginx/sites-available/studio-escenario
server {
    listen 80;
    server_name studio.yourdomain.com;

    client_max_body_size 150M;
    root /var/www/escenario/frontend;
    index index.html;

    # API proxy
    location /api/ {
        proxy_pass http://127.0.0.1:8000/api/;
        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_read_timeout 300s;
        proxy_connect_timeout 10s;
    }

    # WebSocket for collaboration
    location /ws/ {
        proxy_pass http://127.0.0.1:8000/ws/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }

    # Static file serving (audio workspace)
    location /static/ {
        proxy_pass http://127.0.0.1:8000/static/;
        proxy_set_header Host $host;
    }

    # Health check passthrough
    location /health {
        proxy_pass http://127.0.0.1:8000/health;
    }

    # SPA fallback
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript
               text/xml application/xml text/javascript audio/wav audio/mpeg;
    gzip_min_length 1000;
}

Admin Subdomain

nginx
# /etc/nginx/sites-available/admin-escenario
server {
    listen 80;
    server_name admin.yourdomain.com;

    root /var/www/escenario/admin;
    index index.html;

    location /api/ {
        proxy_pass http://127.0.0.1:8000/api/;
        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_read_timeout 300s;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Editor Subdomain

nginx
# /etc/nginx/sites-available/editor-escenario
server {
    listen 80;
    server_name editor.yourdomain.com;

    root /var/www/escenario/editor;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
}

Landing Page (Root Domain)

nginx
# /etc/nginx/sites-available/landing-escenario
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    root /var/www/escenario/landing;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Enable Sites & SSL

bash
# Enable all sites
ln -sf /etc/nginx/sites-available/studio-escenario /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/admin-escenario /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/editor-escenario /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/landing-escenario /etc/nginx/sites-enabled/

# Remove default site
rm -f /etc/nginx/sites-enabled/default

# Test configuration
nginx -t

# Reload Nginx
systemctl reload nginx

# Issue SSL certificates for all domains
certbot --nginx \
  -d yourdomain.com \
  -d www.yourdomain.com \
  -d studio.yourdomain.com \
  -d editor.yourdomain.com \
  -d admin.yourdomain.com \
  --non-interactive --agree-tos -m admin@yourdomain.com

# Verify auto-renewal
certbot renew --dry-run
SECTION 07

Database Schema

All tables are auto-created by SQLAlchemy on first startup via Base.metadata.create_all(). No manual migrations required for fresh deployments.

users
idInteger PKAuto-increment, indexed
emailString(255)Unique, indexed, NOT NULL
full_nameString(255)NOT NULL
hashed_passwordString(255)bcrypt hash, NOT NULL
organizationString(255)Nullable
countryString(100)Nullable
planEnum(PlanTier)FREE | PRO | ENTERPRISE, default PRO
is_activeBooleanDefault true
is_adminBooleanDefault false
created_atDateTime(tz)Server default now()
updated_atDateTime(tz)Auto-updates on change
projects
idInteger PKAuto-increment
user_idInteger FKReferences users.id, CASCADE delete
nameString(255)NOT NULL
bpmFloatDefault 120.0
sample_rateIntegerDefault 44100
created_atDateTime(tz)Server default now()
updated_atDateTime(tz)Auto-updates
tracks
idInteger PKAuto-increment
project_idInteger FKReferences projects.id, CASCADE delete
nameString(255)NOT NULL
typeString(50)Default "audio"
file_urlTextPublic URL or R2 path
file_keyString(500)Storage key reference
durationFloatSeconds
volumeFloatDefault 0.8 (0.0-1.0)
panFloatDefault 0.0 (-1.0 to 1.0)
mutedBooleanDefault false
soloBooleanDefault false
colorString(7)Hex color, default #6366f1
order_indexIntegerTrack ordering
effectsJSONFX chain configuration
detected_bpmFloatAuto-detected BPM
detected_keyString(20)Auto-detected musical key
created_atDateTime(tz)Server default now()
audio_tasks
idInteger PKAuto-increment
user_idInteger FKReferences users.id, CASCADE delete
project_idInteger FKReferences projects.id, SET NULL on delete
task_typeString(50)stem_separation, mastering, effects, etc.
celery_task_idString(255)Celery async task reference
statusString(50)pending | processing | completed | failed
input_file_keyString(500)Source audio file key
resultJSONProcessing output metadata
errorTextError message if failed
created_atDateTime(tz)Server default now()
completed_atDateTime(tz)Nullable, set on completion
vst_plugins
idInteger PKAuto-increment
user_idInteger FKReferences users.id, CASCADE delete
nameString(255)Plugin display name
filenameString(500)Original uploaded filename
file_keyString(500)Storage path reference
formatEnum(PluginFormat)VST3 | VST2 | CLAP
platformEnum(PluginPlatform)LINUX | WINDOWS | MACOS | UNIVERSAL
parametersJSONExtracted parameter list with ranges
is_scannedBooleanDefault false, set after scan
is_loadedBooleanCurrently loaded in Carla
load_errorTextError message if load failed
vendorString(255)Plugin manufacturer
categoryString(100)Effect, Instrument, Analyzer, etc.
created_atDateTime(tz)Server default now()
collaboration_rooms
idInteger PKAuto-increment
project_idInteger FKReferences projects.id, CASCADE
owner_idInteger FKReferences users.id
invite_codeString(12)Unique, indexed, shareable link
nameString(255)Room display name
max_participantsIntegerDefault 8
is_activeBooleanDefault true
created_at / closed_atDateTime(tz)Lifecycle timestamps
room_participants
idInteger PKAuto-increment
room_idInteger FKReferences collaboration_rooms.id, CASCADE
user_idInteger FKReferences users.id
roleString(20)Default "editor" (editor | viewer)
is_connectedBooleanWebSocket connection status
colorString(7)Participant cursor color
joined_at / left_atDateTime(tz)Session timestamps
room_messages
idBigInteger PKAuto-increment (high volume)
room_idInteger FKReferences collaboration_rooms.id, CASCADE
user_idInteger FKReferences users.id
contentTextMessage body
created_atDateTime(tz)Server default now()

Enum Storage: PostgreSQL stores enum member names (uppercase: FREE, PRO, ENTERPRISE), not values. This is SQLAlchemy's default behavior with PostgreSQL Enum types.

SECTION 08

API Reference

All endpoints are prefixed with /api/v1. Protected routes require a JWT Bearer token in the Authorization header.

Authentication

POST/api/v1/auth/registerCreate new user account
POST/api/v1/auth/loginGet JWT access token
GET/api/v1/auth/meGet current user profile

Projects & Tracks

POST/api/v1/projects/Create project
GET/api/v1/projects/List user's projects
GET/api/v1/projects/{id}Get project with tracks
PATCH/api/v1/projects/{id}Update project settings
DELETE/api/v1/projects/{id}Delete project + tracks

Audio Processing

POST/api/v1/processing/separate-stemsAI stem separation (Demucs)
POST/api/v1/processing/autotunePitch correction
POST/api/v1/processing/effectsApply FX chain
POST/api/v1/processing/masterMulti-band mastering

File Upload

POST/api/v1/upload/Upload audio file (max 100MB)

AI Chat

POST/api/v1/chat/AI production assistant (OpenAI)

VST Plugin Management ENTERPRISE

POST/api/v1/vst/uploadUpload VST plugin (max 500MB)
GET/api/v1/vst/pluginsList user's plugins
GET/api/v1/vst/plugins/{id}Plugin details + parameters
GET/api/v1/vst/plugins/{id}/parametersExtracted parameter list
POST/api/v1/vst/plugins/{id}/rescanRe-scan plugin parameters
POST/api/v1/vst/plugins/{id}/ai-mapAI maps params from text prompt
POST/api/v1/vst/plugins/{id}/processProcess audio through plugin
POST/api/v1/vst/plugins/{id}/ai-processAI map + process in one shot
DELETE/api/v1/vst/plugins/{id}Remove plugin

Admin Panel ADMIN ONLY

GET/api/v1/admin/dashboardPlatform analytics overview
GET/api/v1/admin/usersList all users (paginated)
POST/api/v1/admin/users/createCreate user account manually
PATCH/api/v1/admin/users/{id}Update user (plan, status, admin)
GET/api/v1/admin/system-healthDocker, disk, memory status
GET/api/v1/admin/gpu-queueGPU job queue status
GET/api/v1/admin/vst-pluginsAll plugins across all users
GET/api/v1/admin/updater/statusGit status (commits behind)
POST/api/v1/admin/updater/runPull + rebuild containers

Real-Time Collaboration

GET/ws/room/{invite_code}WebSocket connection (upgrade)

Authentication: Include Authorization: Bearer <token> header on all protected routes. Tokens expire after 24 hours (configurable via ACCESS_TOKEN_EXPIRE_MINUTES).

SECTION 09

Cloud Storage (Cloudflare R2)

EscenarioAI uses Cloudflare R2 (S3-compatible) for persistent audio file storage. This is optional for development but recommended for production.

Setup Steps

  1. Log in to Cloudflare Dashboard → R2 Object Storage
  2. Create a bucket named escenario-audio
  3. Go to Manage R2 API Tokens → Create token with read/write permissions
  4. Note your Account ID (visible in the dashboard URL)

Environment Variables

env
R2_ENDPOINT_URL=https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=your_access_key_id
R2_SECRET_ACCESS_KEY=your_secret_access_key
R2_BUCKET_NAME=escenario-audio

File Organization

escenario-audio/ (R2 Bucket) ├── uploads/{user_id}/ │ ├── originals/ # Raw uploaded audio files │ ├── stems/ # Separated stems (vocals, drums, bass, other) │ └── exports/ # Mastered and exported files │ └── vst_plugins/{user_id}/ # Uploaded VST binaries

Local Storage Fallback

If R2 is not configured (empty environment variables), the platform falls back to local filesystem storage at /var/workspace/ inside the Docker volume. This works for development and single-server deployments but does not persist across container rebuilds unless the volume is backed up.

SECTION 10

GPU Processing (Optional)

Heavy AI processing (Demucs stem separation, RVC voice cloning) can be offloaded to serverless GPU providers for faster results.

RunPod Serverless

  1. Sign up at runpod.io
  2. Create a Serverless Endpoint with a GPU template (A40/A100 recommended)
  3. Deploy the runpod_handler.py from the repository as the handler
  4. Set environment variables:
env
RUNPOD_API_KEY=your_runpod_api_key
RUNPOD_ENDPOINT_ID=your_endpoint_id

Modal.com Webhook

  1. Sign up at modal.com
  2. Deploy modal_app.py as a Modal app
  3. Copy the webhook URL to your environment:
env
MODAL_WEBHOOK_URL=https://your-org--escenario-audio.modal.run

CPU Fallback

No GPU? No problem. If neither RunPod nor Modal is configured, all processing falls back to CPU on the Celery worker. Stem separation will take 2-5 minutes per track instead of 6-15 seconds, but it works without any external dependencies.

SECTION 11

Auto-Updater System

The admin panel includes a one-click deployment system that pulls the latest code from GitHub and rebuilds Docker containers without SSH access.

How It Works

  1. Admin clicks "Check for Updates" in the admin panel
  2. Backend executes git fetch on the host source directory
  3. Compares local HEAD with remote HEAD, reports commits behind
  4. Admin clicks "Deploy Update"
  5. Backend executes git pull + docker compose up -d --build on host
  6. Containers rebuild with new code, zero-downtime via rolling restart

Required Docker Mounts

These volume mounts in docker-compose.yml are essential for the updater to work:

yaml
services:
  backend:
    volumes:
      - /opt/escenario/backend:/opt/escenario/backend    # Host source code
      - /var/run/docker.sock:/var/run/docker.sock        # Docker API access
      - /usr/bin/docker:/usr/bin/docker                  # Docker binary

Security Note: Mounting the Docker socket gives the backend container full Docker control over the host. This is required for the auto-updater but means the container has elevated privileges. Ensure only admin users can trigger the updater endpoint.

API Endpoints

GET/api/v1/admin/updater/statusReturns current commit, remote commit, commits behind count
POST/api/v1/admin/updater/runExecutes git pull + docker compose rebuild

Git Configuration

Ensure the host source directory has a valid git remote configured:

bash
cd /opt/escenario/backend
git remote -v  # Should show your GitHub repo

# If using SSH auth, ensure the host has a valid deploy key
# If using HTTPS, configure credential caching:
git config credential.helper store
SECTION 12

Security Considerations

Authentication & Authorization

MechanismImplementationConfiguration
Password Hashingbcrypt via passlibCost factor 12 (default)
Token FormatJWT (JSON Web Token)HS256 algorithm
Token Expiry24 hoursACCESS_TOKEN_EXPIRE_MINUTES=1440
Admin Guardis_admin flag on User modelChecked via dependency injection
Plan GatingPlanTier check per endpointEnterprise features reject Free/Pro

Network Security

  • PostgreSQL: Only accessible within Docker network (no port mapping to host)
  • Redis: Only accessible within Docker network
  • Backend API: Binds to 127.0.0.1:8000 only (not public)
  • VST Host: Internal Docker network only (no port mapping)
  • Nginx: Only public-facing service (ports 80/443)

CORS Configuration

Only explicitly whitelisted origins are allowed. Configure via ALLOWED_ORIGINS environment variable. Never use wildcard (*) in production.

Firewall (UFW) Recommended Rules

bash
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Recommendations

  • Rotate SECRET_KEY periodically (invalidates all active sessions)
  • Use strong, unique database passwords
  • Enable Nginx rate limiting for login endpoints
  • Set up fail2ban for SSH brute-force protection
  • Keep Docker images updated (docker compose pull weekly)
  • Monitor /var/log/nginx/access.log for anomalies
  • Back up PostgreSQL daily (see Maintenance section)
SECTION 13

Maintenance & Monitoring

Service Logs

bash
# All services
docker compose logs -f

# Specific service
docker compose logs -f backend
docker compose logs -f celery-worker
docker compose logs -f vst-host

# Last 100 lines
docker compose logs --tail=100 backend

# Nginx logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

Database Backups

bash
# Manual backup
docker compose exec db pg_dump -U escenario escenario_db > backup_$(date +%Y%m%d).sql

# Automated daily backup (add to crontab)
0 3 * * * cd /opt/escenario/backend && docker compose exec -T db pg_dump -U escenario escenario_db | gzip > /opt/escenario/backups/db_$(date +\%Y\%m\%d).sql.gz

# Restore from backup
docker compose exec -T db psql -U escenario escenario_db < backup_20260522.sql

Health Check Endpoints

EndpointExpected ResponseChecks
GET /health200 OKAPI is responsive
GET /200 OKApplication root
docker compose psAll "healthy"Container status

Disk Space Management

bash
# Check workspace volume usage
docker system df

# Prune unused Docker resources
docker system prune -f

# Check audio workspace size
docker compose exec backend du -sh /var/workspace/

# PostgreSQL database size
docker compose exec db psql -U escenario -d escenario_db \
  -c "SELECT pg_size_pretty(pg_database_size('escenario_db'));"

Restart Services

bash
# Restart a single service
docker compose restart backend

# Rebuild and restart (after code changes)
docker compose up -d --build backend celery-worker

# Full stack restart
docker compose down && docker compose up -d

# Reload Nginx (after config changes)
nginx -t && systemctl reload nginx
SECTION 14

Licensing & White-Label

EscenarioAI is designed as a self-contained platform that can be white-labeled and deployed under any brand.

Rebranding Checklist

ItemFile/LocationWhat to Change
Domain/CORS.env (ALLOWED_ORIGINS)Replace all domain references
Nginx configs/etc/nginx/sites-available/Update server_name directives
SSL certificatesCertbotRe-run certbot with new domains
Landing page/var/www/escenario/landing/Replace branding, logos, copy
Admin panel/var/www/escenario/admin/Update title, logos, support URL
Frontendvite.config.js, index.htmlUpdate title, favicon, API URL
Email templatesapp/services/Update sender name/address

Offline Operation

The platform can run fully offline (no external dependencies) with these trade-offs:

FeatureOnlineOffline Alternative
File StorageCloudflare R2Local Docker volume (/var/workspace)
GPU ProcessingRunPod / ModalLocal CPU (Celery worker)
AI ChatOpenAI APIDisabled (remove chat endpoint)
VST AI MappingOpenAI APIManual parameter control only
SSL CertificatesLet's EncryptSelf-signed or internal CA

To run offline, simply leave R2_*, RUNPOD_*, MODAL_*, and OPENAI_* environment variables empty. The platform gracefully degrades to local alternatives.

Scaling Considerations

  • Horizontal scaling: Add more Celery workers by increasing --concurrency or deploying additional worker containers
  • Database scaling: PostgreSQL supports read replicas for high-read workloads
  • CDN: Put Cloudflare or similar CDN in front of the landing page and static assets
  • Load balancing: Multiple backend instances behind Nginx upstream for high availability
  • Storage: R2 provides virtually unlimited storage with no egress fees

Support & Updates

Licensed deployments receive:

  • Access to the private GitHub repository with all source code
  • One-click updates via the admin panel auto-updater
  • Database migrations handled automatically by SQLAlchemy
  • Docker images pinned to stable versions for reproducibility

Self-Contained: The entire platform (frontend, backend, database, cache, VST host) runs from a single docker compose up -d command. No external services are required for core functionality.