OpenVibe.Live Setup Guide
Complete deployment guide: OVH Public Cloud + Ubuntu 25.04 + Cloudflare + Let's Encrypt + Nginx — plus OVH plan sizing analysis
1. Recommended Production Model
For a small or medium public deployment, the safest baseline is:
- OVH Public Cloud instance in the nearest region to your users
- Ubuntu 25.04
- Cloudflare proxy for the main website
- Nginx on the origin server
- Let's Encrypt certificate on the origin
- Cloudflare SSL/TLS mode set to Full (strict)
- Node 20 LTS via nvm (Node Version Manager)
systemdfor process supervisionufwon the box- Only open the extra streaming ports you actively use
2. What OpenVibe.Live Exposes
The current server in server/index.js provides:
- HTTP on
PORT, default3000 - WebSocket upgrades on
/ws/chat,/ws/broadcast,/ws/control, and/ws/call - Optional RTMP ingest
- Optional JSMPEG relay
- Optional WebRTC /
mediasoup - Persistent data under
data/
Typical ports
| Port | Protocol | Purpose |
|---|---|---|
| 3000 | TCP | Internal Node app (behind Nginx) |
| 80 | TCP | HTTP redirect & Let's Encrypt validation |
| 443 | TCP | HTTPS to Nginx |
| 1935 | TCP | RTMP ingest |
| 9710 | TCP | JSMPEG video relay |
| 9711 | TCP | JSMPEG audio relay |
| 4443 | TCP/UDP | WebRTC entry point |
| 10000-10100 | UDP | mediasoup RTP range |
| 9935 | TCP | HTTP-FLV playback (if enabled) |
3. OVH Instance Creation
From the OVH "Create an instance" flow:
- Template: your chosen instance flavor, e.g.
B3-16 - Region: nearest to your users, e.g. Seattle /
US-WEST-LZ-SEA-A - Image:
Ubuntu 25.04 - SSH key: required
So for this deployment, generate either:
- ECDSA P-384 — recommended if OVH accepts it in your project flow
- RSA 4096 — safest fallback for maximum compatibility
4. Generate an SSH Key for OVH
Run these commands on your local machine, not on the server.
Option A: ECDSA P-384 key
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ecdsa -b 384 -f ~/.ssh/ovh_openvibelive_ecdsa -C "ovh-openvibelive"
Option B: RSA 4096 key
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t rsa -b 4096 -o -a 100 -f ~/.ssh/ovh_openvibelive_rsa -C "ovh-openvibelive"
Lock down the private key
# ECDSA
chmod 600 ~/.ssh/ovh_openvibelive_ecdsa
chmod 644 ~/.ssh/ovh_openvibelive_ecdsa.pub
# RSA
chmod 600 ~/.ssh/ovh_openvibelive_rsa
chmod 644 ~/.ssh/ovh_openvibelive_rsa.pub
Print the public key to paste into OVH
# ECDSA
cat ~/.ssh/ovh_openvibelive_ecdsa.pub
# RSA
cat ~/.ssh/ovh_openvibelive_rsa.pub
Copy the entire single-line public key into the OVH SSH key field.
Test the key fingerprint locally
# ECDSA
ssh-keygen -lf ~/.ssh/ovh_openvibelive_ecdsa.pub
# RSA
ssh-keygen -lf ~/.ssh/ovh_openvibelive_rsa.pub
5. Import the SSH Key into OVH
- Go to your Public Cloud project
- Open the SSH keys area, or paste the key directly during instance creation
- Give the key a clear name, e.g.
openvibelive-seattle-prod - Paste the public key line from the
.pubfile - Create the instance with that key attached
6. Connect to the New Instance
After the instance is created and shows as ready, connect over SSH. Most OVH Ubuntu images use the ubuntu user.
ECDSA example
ssh -i ~/.ssh/ovh_openvibelive_ecdsa ubuntu@YOUR_SERVER_IP
RSA example
ssh -i ~/.ssh/ovh_openvibelive_rsa ubuntu@YOUR_SERVER_IP
Optional: SSH config alias
Host openvibe.tools
HostName YOUR_SERVER_IP
User ubuntu
IdentityFile ~/.ssh/ovh_openvibelive_ecdsa
IdentitiesOnly yes
Then connect with:
ssh openvibe.tools
7. First-Login Hardening
Run these commands on the server.
Update the box
sudo apt update
sudo apt full-upgrade -y
sudo apt autoremove -y
Install baseline packages
sudo apt install -y \
git curl wget unzip ca-certificates gnupg \
nginx ffmpeg ufw fail2ban \
build-essential python3 python3-pip jq
Optional: create a dedicated app user
sudo adduser --disabled-password --gecos "" openvibelive
sudo usermod -aG sudo openvibelive
Then add your public key for that user:
sudo mkdir -p /home/openvibelive/.ssh
sudo nano /home/openvibelive/.ssh/authorized_keys
sudo chown -R openvibelive:openvibelive /home/openvibelive/.ssh
sudo chmod 700 /home/openvibelive/.ssh
sudo chmod 600 /home/openvibelive/.ssh/authorized_keys
Harden SSH
sudo nano /etc/ssh/sshd_config
Recommended settings:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
Reload SSH:
sudo systemctl reload ssh
8. Install Node.js via nvm
We use nvm (Node Version Manager) instead of system packages. This avoids the recurring /usr/bin/env: 'node': No such file or directory problem where NodeSource installs node somewhere systemd can't find it.
Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
Close and reopen your terminal (or source your profile) so nvm is available:
source ~/.bashrc
command -v nvm # should print "nvm"
Install Node 20 LTS
nvm install 20
nvm alias default 20 # make it the default for new shells
node -v
npm -v
Verify
which node # e.g. /home/ubuntu/.nvm/versions/node/v20.x.x/bin/node
which npm # same nvm-managed path
~/.nvm/. It is a shell function, not a binary — systemd can't see it directly. The systemd section below uses a wrapper script that sources nvm before launching the app.9. Clone OpenVibe.Live
cd /opt
sudo git clone https://github.com/OpenVibe.Live/OpenVibe.Live.com.git openvibelive
sudo chown -R $USER:$USER /opt/openvibelive
cd /opt/openvibelive
npm install
If native modules later need rebuilding:
npm rebuild
mediasoup fails to compile, browser-native WebRTC broadcasting won't be ready until that's fixed.10. Configure .env
cd /opt/openvibelive
cp .env.example .env
nano .env
Recommended starting .env
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-this-now
NODE_ENV=production
HOST=0.0.0.0
PORT=3000
BASE_URL=https://your-domain.example
JWT_SECRET=replace-with-a-long-random-secret
DATABASE_URL=postgres://live_runtime:password@localhost:5432/ov_live
DATABASE_DIRECT_URL=postgres://live_owner:password@localhost:5432/ov_live
RTMP_PORT=1935
JSMPEG_VIDEO_PORT=9710
JSMPEG_AUDIO_PORT=9711
WEBRTC_PORT=4443
MEDIASOUP_LISTEN_IP=0.0.0.0
MEDIASOUP_ANNOUNCED_IP=YOUR_PUBLIC_IP
MEDIASOUP_MIN_PORT=10000
MEDIASOUP_MAX_PORT=10100
VOD_PATH=./data/vods
CLIPS_PATH=./data/clips
THUMBNAILS_PATH=./data/thumbnails
EMOTES_PATH=./data/emotes
MAX_VOD_SIZE_MB=128
MAX_EMOTE_SIZE_KB=128
MAX_EMOTES_PER_USER=10
MIN_CASHOUT=5
ESCROW_HOLD_DAYS=14
Generate a strong JWT secret
openssl rand -hex 32
- Set
BASE_URLto your final public HTTPS hostname - Set
MEDIASOUP_ANNOUNCED_IPto the real public OVH IP if you use WebRTC - Keep upload and media limits low on small servers
- Do not expose unused protocols
11. Create Runtime Directories
The app creates them on boot, but you can pre-create them:
cd /opt/openvibelive
mkdir -p data/vods data/clips data/media data/thumbnails data/emotes data/avatars
12. Bootstrap the App
Initialize the database if needed:
cd /opt/openvibelive
npm run init-db
Or just start it once manually:
npm start
Then stop it and move on to systemd setup.
13. Cloudflare DNS Setup
Main website
Create these records in Cloudflare DNS:
Arecord for@pointing atYOUR_OVH_PUBLIC_IPCNAMEforwwwpointing at your apex hostname
Set both to Proxied (orange cloud) after the origin is working.
Optional: direct hostnames for non-HTTP protocols
Only create these if you really need them:
| Record | Type | Value | Proxy |
|---|---|---|---|
rtmp | A | YOUR_OVH_PUBLIC_IP | DNS only |
webrtc | A | YOUR_OVH_PUBLIC_IP | DNS only |
jsmpeg | A | YOUR_OVH_PUBLIC_IP | DNS only |
14. Let's Encrypt on Ubuntu 25.04
For end-to-end encryption with Cloudflare, the origin must present a valid certificate. Cloudflare's Full (strict) mode requires the origin cert to be unexpired, valid for the hostname, and issued by a publicly trusted CA.
Install Certbot
sudo apt install -y snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/local/bin/certbot
certbot --version
Temporary Nginx HTTP site
Before requesting the cert, create a plain HTTP Nginx site so your domain answers on port 80.
sudo nano /etc/nginx/sites-available/openvibelive
server {
listen 80;
listen [::]:80;
server_name your-domain.example www.your-domain.example;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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 3600;
}
}
Enable it:
sudo ln -sf /etc/nginx/sites-available/openvibelive /etc/nginx/sites-enabled/openvibelive
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Request the certificate
sudo certbot --nginx -d your-domain.example -d www.your-domain.example
Verify auto-renewal
sudo systemctl list-timers | grep certbot || true
sudo certbot renew --dry-run
15. Cloudflare End-to-End Encryption
Once the origin has a valid Let's Encrypt cert:
- Open the Cloudflare dashboard
- Go to SSL/TLS
- Set encryption mode to Full (strict)
This gives you encrypted browser-to-Cloudflare and encrypted Cloudflare-to-origin traffic, with origin certificate validation.
Recommended Cloudflare settings
- Always Use HTTPS — enabled
- Automatic HTTPS Rewrites — enabled
- WAF / bot protections (if available on your plan)
- Rate limiting for sensitive paths (if available)
16. Restore the Real Visitor IP
By default, your origin sees Cloudflare edge IPs. Cloudflare provides the original visitor IP in the CF-Connecting-IP header.
Nginx real IP config
sudo nano /etc/nginx/conf.d/cloudflare-realip.conf
real_ip_header CF-Connecting-IP;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
real_ip_recursive on;
sudo nginx -t
sudo systemctl reload nginx
Optional: custom log format with Cloudflare info
sudo nano /etc/nginx/conf.d/log_format_cloudflare.conf
log_format cloudflare_combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'cf_ray=$http_cf_ray cf_ip=$http_cf_connecting_ip';
Apply it in your site config with:
access_log /var/log/nginx/openvibelive.access.log cloudflare_combined;
trust proxy enabled. Correct Nginx real-IP handling ensures logs, moderation, rate limiting, and security signals use the real visitor IP instead of a Cloudflare edge IP.17. Final Nginx HTTPS Config
After Certbot runs, tighten the site config:
server {
listen 80;
listen [::]:80;
server_name your-domain.example www.your-domain.example;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.example www.your-domain.example;
ssl_certificate /etc/letsencrypt/live/your-domain.example/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.example/privkey.pem;
access_log /var/log/nginx/openvibelive.access.log cloudflare_combined;
error_log /var/log/nginx/openvibelive.error.log;
client_max_body_size 128M;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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 3600;
}
}
sudo nginx -t
sudo systemctl reload nginx
18. Firewall (UFW)
Minimal website-only deployment
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
If you need RTMP ingest
sudo ufw allow 1935/tcp
If you need JSMPEG
sudo ufw allow 9710/tcp
sudo ufw allow 9711/tcp
If you need WebRTC / mediasoup
sudo ufw allow 4443/tcp
sudo ufw allow 4443/udp
sudo ufw allow 10000:10100/udp
19. OVH Security Groups
OVH's OpenStack-based Public Cloud default security groups can allow broad traffic by default. Do not rely on OVH defaults alone.
Use at least one of these:
ufwon the instance- OVH/OpenStack security groups (if you manage networking that way)
- Nginx allowlists for sensitive origin paths
20. systemd service
systemd doesn't run interactive shells, so it can't see the nvm shell function or the node/npm binaries it manages. We use a tiny wrapper script that sources nvm before launching the app.
Create the wrapper script
sudo nano /opt/openvibelive/start.sh
Paste:
#!/usr/bin/env bash
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
cd /opt/openvibelive
exec npm start
Make it executable:
sudo chmod +x /opt/openvibelive/start.sh
Create the service unit
sudo nano /etc/systemd/system/openvibelive.service
Paste the following unit file:
[Unit]
Description=OpenVibe.Live
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/openvibelive
Environment=NODE_ENV=production
ExecStart=/opt/openvibelive/start.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
User= must match whoever installed nvm. If you installed nvm as ubuntu, use User=ubuntu. The script reads $HOME/.nvm from that user's home directory.openvibelive user, install nvm under that user, change User=ubuntu to User=openvibelive, and ensure ownership of /opt/openvibelive matches.Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable openvibelive
sudo systemctl start openvibelive
sudo systemctl status openvibelive
View logs:
journalctl -u openvibelive -f
21. Close registration after bootstrap
After you create your initial admin and trusted test accounts, close public registration. This is one of the cheapest and strongest anti-abuse controls in the project.
cd /opt/openvibe.live/current
# Use the site administration settings to close registration.
22. Optional fail2ban baseline
Install:
sudo apt install -y fail2ban
Create a basic jail file:
sudo nano /etc/fail2ban/jail.local
Example:
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
Then:
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status
23. Protocol-specific exposure guidance
RTMP
Expose 1935/tcp only if you need OBS or FFmpeg ingest.
JSMPEG
Expose 9710/tcp and 9711/tcp only if you use the relay.
WebRTC
Expose only the exact WebRTC TCP/UDP and RTP ports you need. Make sure:
MEDIASOUP_ANNOUNCED_IPmatches your public OVH IP- Your firewall allows the RTP range
- Your Cloudflare setup is not expected to proxy raw media ports
24. Operational checks
App health
Verify:
http://127.0.0.1:3000/api/healthon the serverhttps://your-domain.example/api/healththrough Nginx and Cloudflare
TLS
- Browser sees a valid certificate
- Cloudflare SSL/TLS mode is Full (strict)
- No redirect loops
- No mixed-content warnings
Visitor IP restoration
Check Nginx logs and confirm the client IP is not just a Cloudflare edge IP.
Port audit
Check that only intended ports are reachable from the internet:
sudo ss -tulpn
sudo ufw status verbose
25. Full command summary
If you want the short version, the high-level order is:
- Generate an OVH-compatible SSH key locally
- Create the OVH Ubuntu 25.04 instance with that public key
- SSH into the new instance
- Update packages and install Nginx, FFmpeg,
ufw, andfail2ban - Install nvm and Node 20 LTS
- Clone OpenVibe.Live into
/opt/openvibelive - Configure
.env - Start the app once and verify
/api/health - Set Cloudflare DNS to the OVH IP
- Configure Nginx
- Issue a Let's Encrypt certificate with Certbot
- Enable Cloudflare Full (strict)
- Add Cloudflare real-IP config in Nginx
- Enable
systemdfor OpenVibe.Live - Close public registration after bootstrap
- Open only the extra media ports you actually need
26. Security reminders
- Never use ED25519 if the OVH flow in your account rejects it
- Keep your private SSH key only on trusted admin machines
- Disable password SSH once key auth is confirmed
- Keep
JWT_SECRETlong and random - Keep the website behind Cloudflare
- Do not expose raw media ports unnecessarily
- Keep upload limits low on small servers
- Close registration when not actively onboarding users
- Monitor
data/growth for VODs, clips, thumbnails, avatars, and emotes
27. References
This guide was aligned with current public guidance from:
- OVH Public Cloud instance creation and SSH-key setup guidance
- Cloudflare documentation for
CF-Connecting-IPand restoring original visitor IPs - Cloudflare documentation for Full (strict) mode
- Current Certbot installation and Nginx integration guidance
28. Setup summary
For OVH + Ubuntu 25.04, the best OpenVibe.Live deployment pattern is:
- RSA or ECDSA SSH key uploaded to OVH
- Ubuntu 25.04 on OVH Public Cloud
- Node 20 LTS via nvm
- Nginx reverse proxy on the box
- Let's Encrypt certificate on the origin
- Cloudflare proxy with Full (strict)
- Cloudflare real-IP restoration in Nginx
systemd,ufw,fail2ban- Only one streaming protocol exposed at a time unless you have a real need for more
OVH Public Cloud Sizing Guide
Executive summary
Best overall pick — B3-32
- 32 GB RAM — enough for Node, PostgreSQL, WebSockets, chat, thumbnails, clips, and moderate media workload
- 8 vCores — sane floor for a mixed single-box deployment
- 200 GB NVMe — much more realistic than 50–100 GB once VODs and clips start accumulating
- 2 Gbit/s — leaves real headroom for 200 viewers at practical streaming bitrates
Best budget / staging pick
- B3-8 — cheapest decent general-purpose box
- C3-8 — cheaper CPU-heavier test box (only 100 GB storage)
Best safer production pick — B3-64
- 16 vCores is much healthier for 200 viewers with WebRTC, call features, game traffic, clip creation
- 4 Gbit/s helps if bitrate climbs or you add more streams / cameras / rooms later
What limits OpenVibe.Live on a single OVH instance
The bottleneck is not just RAM. The main constraints are:
- Outbound bandwidth — the first hard wall
- CPU — especially for WebRTC
- Disk space — once VODs are enabled
- Disk I/O
- Operational headroom for Node, FFmpeg, thumbnails, clips, chat, and WebSockets
Bandwidth is the first hard wall
For all three playback methods, the origin server pays outbound bandwidth per viewer:
- JSMPEG: server relays the live stream to every viewer
- RTMP / HTTP-FLV: server still pays outbound per viewer
- WebRTC SFU: server forwards media to each viewer; outbound scales with audience
CPU becomes more important for WebRTC
- JSMPEG: usually more bandwidth-bound than CPU-bound
- RTMP ingest + direct playback: also heavily bandwidth-bound
- WebRTC / mediasoup: usually more CPU-sensitive (SFU packet forwarding, transport handling, encryption overhead, more real-time state)
Storage dominates once VODs are enabled
The service uses PostgreSQL for its database and OpenVibe.Media for VODs, clips, thumbnails, and media assets. The OS and app don't need much space — recorded video does.
Bandwidth math for 200 viewers
A useful first-order formula:
For 200 viewers:
- At 1.5 Mbps per viewer: ~300 Mbps raw egress
- At 2.5 Mbps per viewer: ~500 Mbps raw egress
- At 4.0 Mbps per viewer: ~800 Mbps raw egress
Real deployments need headroom for TLS/protocol overhead, chat/API/thumbnails, bitrate spikes, reconnections, and background jobs. Target around 70% of the listed port speed as usable sustained capacity.
Safe viewer counts at 70% utilization
| NIC cap | Safe usable Mbps | ~1.5 Mbps/viewer | ~2.5 Mbps/viewer | ~4.0 Mbps/viewer |
|---|---|---|---|---|
| 250 Mbit/s | 175 | 116 | 70 | 43 |
| 500 Mbit/s | 350 | 233 | 140 | 87 |
| 1,000 Mbit/s | 700 | 466 | 280 | 175 |
| 2,000 Mbit/s | 1,400 | 933 | 560 | 350 |
| 4,000 Mbit/s | 2,800 | 1,866 | 1,120 | 700 |
| 8,000 Mbit/s | 5,600 | 3,733 | 2,240 | 1,400 |
| 10,000 Mbit/s | 7,000 | 4,666 | 2,800 | 1,750 |
| 16,000 Mbit/s | 11,200 | 7,466 | 4,480 | 2,800 |
What that means for 200 viewers
- 250 Mbit/s plans — not enough except for very low bitrates
- 500 Mbit/s plans — can work for low-mid bitrate, but not comfortable
- 1 Gbit/s plans — viable if you keep average delivered bitrate moderate
- 2 Gbit/s plans — where the setup gets comfortable
- 4 Gbit/s plans — stop thinking about bandwidth, start thinking about CPU and storage
Storage math for VODs and clips
Rule of thumb: 1 Mbps ≈ 0.44 GB/hour
- 1.5 Mbps ≈ 0.66 GB/hour
- 2.5 Mbps ≈ 1.10 GB/hour
- 4.0 Mbps ≈ 1.76 GB/hour
- 6.0 Mbps ≈ 2.64 GB/hour
Usable media space after OS/app reserve (~15–25 GB)
| Raw disk | Usable media space |
|---|---|
| 50 GB | 25–35 GB |
| 100 GB | 75–85 GB |
| 200 GB | 175–185 GB |
| 400 GB | 375–385 GB |
Approximate retained recording hours (at 2.5 Mbps)
- 30 GB usable, about 27 hours
- 80 GB usable, about 73 hours
- 180 GB usable, about 164 hours
- 380 GB usable, about 345 hours
At 4.0 Mbps
- 30 GB usable, about 17 hours
- 80 GB usable, about 45 hours
- 180 GB usable, about 102 hours
- 380 GB usable, about 216 hours
Family-by-family analysis
B3 family — best overall fit
The new B3 family is the strongest match for OpenVibe.Live because it balances decent vCPU counts, generous RAM, NVMe storage, strong network steps, and good pricing.
| Plan | RAM | vCPU | Disk | NIC | Price/hour |
|---|---|---|---|---|---|
| B3-8 | 8 GB | 2 | 50 GB NVMe | 500 Mbit/s | $0.0508 |
| B3-16 | 16 GB | 4 | 100 GB NVMe | 1,000 Mbit/s | $0.1016 |
| B3-32 | 32 GB | 8 | 200 GB NVMe | 2,000 Mbit/s | $0.2033 |
| B3-64 | 64 GB | 16 | 400 GB NVMe | 4,000 Mbit/s | $0.4065 |
| B3-128 | 128 GB | 32 | 400 GB NVMe | 8,000 Mbit/s | $0.8131 |
| B3-256 | 256 GB | 64 | 400 GB NVMe | 16,000 Mbit/s | $1.6262 |
- B3-8: good dev box, too small for serious 200-viewer ambitions
- B3-16: good small production / alpha / staging box
- B3-32: best overall single-box production choice
- B3-64: best safer serious production choice for 200 viewers with headroom
- B3-128 / B3-256: overkill for early OpenVibe.Live
B2 family — older, mostly outclassed
| Plan | RAM | vCPU | Disk | NIC | Price |
|---|---|---|---|---|---|
| B2-7 | 7 GB | 2 | 50 GB SSD | 250 Mbit/s | $29.04/mo |
| B2-15 | 15 GB | 4 | 100 GB SSD | 250 Mbit/s | $55.44/mo |
| B2-30 | 30 GB | 8 | 200 GB SSD | 500 Mbit/s | $112.20/mo |
| B2-60 | 60 GB | 16 | 400 GB SSD | 1,000 Mbit/s | $217.80/mo |
| B2-120 | 120 GB | 32 | 400 GB SSD | 10,000 Mbit/s | $429.00/mo |
C3 family — CPU-heavy, not best value here
| Plan | RAM | vCPU | Disk | NIC | Price/hour |
|---|---|---|---|---|---|
| C3-4 | 4 GB | 2 | 50 GB NVMe | 250 Mbit/s | $0.0453 |
| C3-8 | 8 GB | 4 | 100 GB NVMe | 500 Mbit/s | $0.0907 |
| C3-16 | 16 GB | 8 | 200 GB NVMe | 1,000 Mbit/s | $0.1813 |
| C3-32 | 32 GB | 16 | 400 GB NVMe | 2,000 Mbit/s | $0.3627 |
| C3-64 | 64 GB | 32 | 400 GB NVMe | 4,000 Mbit/s | $0.7254 |
| C3-128 | 128 GB | 64 | 400 GB NVMe | 8,000 Mbit/s | $1.4508 |
C3 gets interesting if your deployment is heavily WebRTC-centric and CPU-bound. But for OpenVibe.Live, B3 usually wins because the app wants more RAM, more bandwidth, more storage, and better economics per box.
C2 family — least attractive
| Plan | RAM | vCPU | Disk | NIC | Price |
|---|---|---|---|---|---|
| C2-7 | 7 GB | 2 | 50 GB SSD | 250 Mbit/s | $42.24/mo |
| C2-15 | 15 GB | 4 | 100 GB SSD | 250 Mbit/s | $81.83/mo |
| C2-30 | 30 GB | 8 | 200 GB SSD | 500 Mbit/s | $165.00/mo |
| C2-60 | 60 GB | 16 | 400 GB SSD | 1,000 Mbit/s | $323.40/mo |
| C2-120 | 120 GB | 32 | 400 GB SSD | 10,000 Mbit/s | $640.20/mo |
C2 is expensive, older, and has weaker bandwidth than the B3 alternative. Not recommended for OpenVibe.Live.
Streaming method plan fit
WebRTC / mediasoup
The method most likely to become CPU-sensitive first.
- B3-32 for moderate production
- B3-64 for safer 200-viewer production
- C3-32 only if you are convinced CPU will matter more than RAM/bandwidth economics
If your expected audience is up to 200 and WebRTC is a real primary path, start at B3-64 — the full balance of 16 vCores + 4 Gbit/s + 400 GB NVMe is much healthier.
JSMPEG
More straightforward on the server side — becomes bandwidth-bound quickly.
- B3-16 for smaller audiences and testing
- B3-32 for up to 200 viewers at moderate bitrates
- B3-64 if you want bitrate headroom or larger audience spikes
For a JSMPEG-heavy public deployment, B3-32 is the sweet spot.
RTMP ingest + direct playback
RTMP ingest itself is light. Viewer delivery is what costs you — again outbound bandwidth and storage.
- B3-16 for low-mid audience counts
- B3-32 for a real public rollout
- B3-64 if you expect higher bitrate, spikes, or multiple simultaneous live loads
$200 OVH credit analysis
OVH gives $200 in public cloud credit that expires after 90 days. Two key questions: how long the credit lasts running continuously, and whether the plan can run the full 90 days within the credit window.
How long $200 lasts on each plan
| Plan | Price/hour | $200 lasts | Hours |
|---|---|---|---|
| B3-8 | $0.0508 | 164 days | 3,937 h |
| B3-16 | $0.1016 | 82 days | 1,969 h |
| B3-32 | $0.2033 | 41 days | 984 h |
| B3-64 | $0.4065 | 20.5 days | 492 h |
| B3-128 | $0.8131 | 10.3 days | 246 h |
| B3-256 | $1.6262 | 5.1 days | 123 h |
| B2 family | |||
| B2-7 | $0.0813 | 102.5 days | 2,460 h |
| B2-15 | $0.1539 | 54 days | 1,300 h |
| B2-30 | $0.3123 | 26.7 days | 640 h |
| B2-60 | $0.6060 | 13.8 days | 330 h |
| B2-120 | $1.1923 | 7 days | 168 h |
| C3 family | |||
| C3-4 | $0.0453 | 184 days | 4,415 h |
| C3-8 | $0.0907 | 92 days | 2,205 h |
| C3-16 | $0.1813 | 46 days | 1,103 h |
| C3-32 | $0.3627 | 23 days | 551 h |
| C3-64 | $0.7254 | 11.5 days | 276 h |
| C2 family | |||
| C2-7 | $0.1176 | 70.9 days | 1,701 h |
| C2-15 | $0.2276 | 36.6 days | 879 h |
| C2-30 | $0.4586 | 18.2 days | 436 h |
| C2-60 | $0.8986 | 9.3 days | 223 h |
| C2-120 | $1.7786 | 4.7 days | 112 h |
90-day continuous run cost (hourly plans)
| Plan | 30-day cost | 90-day cost |
|---|---|---|
| B3-8 | $36.58 | $109.73 |
| B3-16 | $73.15 | $219.46 |
| B3-32 | $146.38 | $439.13 |
| B3-64 | $292.68 | $878.04 |
| C3-4 | $32.62 | $97.85 |
| C3-8 | $65.30 | $195.91 |
| C3-16 | $130.54 | $391.61 |
| C3-32 | $261.14 | $783.43 |
Best credit strategies
Recommended picks by scenario
Scenario A — dev, staging, private alpha
Pick: B3-8 — cheapest balanced plan. Enough for app setup, testing, internal streams, chat, docs, and smoke validation. Credit lasts the full 90 days easily.
Scenario B — public beta, one main stream, realistic growth
Pick: B3-16 (budget) or B3-32 (best value). Compared with B3-16, B3-32 gives 2× RAM, 2× vCPU, 2× disk, 2× network for exactly 2× price — the operational breathing room is much better.
Scenario C — target up to 200 concurrent viewers on one box
Pick: B3-32 (minimum serious) or B3-64 (safer). For 200 viewers, the question becomes: what is your average delivered bitrate? How WebRTC-heavy is the workload? How much VOD retention locally? B3-32 is the first deliberate production choice; B3-64 is less stressful.
Scenario D — WebRTC-first, higher CPU pressure, future growth
Pick: B3-64 — only slightly more expensive than C3-32 while giving more RAM, more network, equivalent vCPU count, and better overall OpenVibe.Live balance.
Final recommendation
If you want the single OVH plan that makes the most sense for OpenVibe.Live, including storage, mixed real-time features, and streaming toward 200 viewers:
Price · RAM · vCPU · NVMe storage · Outbound bandwidth · Realism for local VOD/clip retention
Bottom line in one sentence
| Plan | Verdict |
|---|---|
| B3-8 | Best cheap build/test box |
| B3-16 | Okay starter production box |
| B3-32 | Best overall OpenVibe.Live plan |
| B3-64 | Best safer 200-viewer / WebRTC-heavy plan |
| B2 / C2 | Mostly not worth it here |
| C3 | Only if unusually CPU-biased and accept weaker overall value |