What to do BEFORE running
deploy-remote.shfor the first time. Estimated time: 10 minutes.
📱 App name: the iPad app is distributed as KsoftLivePlayer (store/Enterprise) with display name Zerolatency Live Player and bundle ID
com.zerolatency.liveplayer.🍎 Apple checklist: before distributing to iPads, register the App ID on
developer.apple.com/account → Certificates, Identifiers & Profiles → Identifierswith DescriptionKsoftLivePlayerand Bundle IDcom.zerolatency.liveplayer(⚠️ exactly — NOTcom.example.*norcom.ksoft.olimpico-live). See the Complete Guide.
1. Generate the License Key (1 min)
On your Mac (not on the server):
cd zerolatency-live-player-keygen
# Choose a strong secret for the HMAC
export LICENSE_SECRET="olimpico-live-$(openssl rand -hex 16)"
# Generate the key
npx tsx src/generate-license.ts "Stadio Olimpico" 2027-12-31Expected output:
🔑 License Key generated:
OLIMP-U3RhZGlvIE9saW1waWNv-20271231-a1b2c3d4
Client: Stadio Olimpico
Expires: 2027-12-31
Issued: 2026-07-22Save LICENCE_SECRET and LICENSE_KEY — both are needed in step 3.
2. Verify the server connection (1 min)
# Using the configured SSH key
ssh debian@192.168.1.127
# Verify it's Debian 12
cat /etc/debian_version # Must start with 12.
# Verify uptime
uptime
# Verify disk space
df -h /
# Verify RAM
free -h
# Exit the server
exitMinimum requirements: CPU 2 cores, RAM 2 GB, SSD 10 GB free.
3. Populate the .env file on the server (2 min)
ssh debian@192.168.1.127
# Open the .env created by deploy.sh
# (if you don't have sudo, use: nano, the file might be owned by debian)
sudo nano /opt/olimpico/olimpico-live/zerolatency-live-player-api/.envMake sure it contains AT LEAST:
PORT=3002
HOST=0.0.0.0
MONGODB_URI=mongodb://localhost:27017/liveplayer
NODE_ENV=production
# License — PUT THE ONE GENERATED IN STEP 1
LICENSE_KEY=OLIMP-U3RhZGlvIE9saW1waWNv-20271231-a1b2c3d4
LICENSE_SECRET=olimpico-live-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5pNote:
.envis NOT synced via rsync for security. It must be edited manually on the server.
Exit the server:
exit4. Prepare the local .env for the Control Room (optional)
If you want to run the Control Room in dev mode against the production server:
cp zerolatency-live-player-regia/.env.example zerolatency-live-player-regia/.env.localNot needed for production deploy — the built Control Room uses the nginx proxy.
5. Verify the deploy module is present (1 min)
cd zerolatency-live-player-deploy
# Verify that all required files exist
ls -la deploy.sh deploy-remote.sh targets.conf backup.sh .rsync-exclude nginx-zerolatency.conf .env.example README.md
# Check the branch
cd ..
git branch
# You should be on: agent (or the current working branch)5bis. Choose the deploy target (multi-tenant)
The deploy supports multiple servers/stadiums via the targets.conf registry (one line per target). Before the first deploy, verify/add the target:
cd zerolatency-live-player-deploy
# List the configured targets
bash deploy-remote.sh --list
# Open the registry and add a new stadium if needed
nano targets.confLine format: name | user@host | ssh_host_alias | ssh_key | remote_dir | www_dir | nginx_site | db_name
Target selection happens in this order of precedence:
--target=NAME/DEPLOY_TARGET=NAME— explicit targetOLIMPICO_SERVER/OLIMPICO_USER/... — legacy override (backward compatibility)- Interactive menu — when
deploy-remote.shruns from a terminal without flags - First target in
targets.conf— non-interactive default (CI/automation)
6. Run provisioning if not already done (5 min)
If the server is new (no previous deploy):
# Copy deploy.sh to the server
scp zerolatency-live-player-deploy/deploy.sh debian@192.168.1.127:/tmp/
# SSH and run
ssh debian@192.168.1.127
sudo bash /tmp/deploy.sh /opt/olimpicoThis installs: Node.js 22, MongoDB 7.0, nginx, PM2, UFW firewall, backup cron.
⚠️ If provisioning has already been done, do not repeat it — go straight to the deploy.
7. Run the deploy (3 min)
cd zerolatency-live-player-deploy
# Interactive target selection menu (recommended on first use):
bash deploy-remote.sh
# Direct deploy to a specific target (e.g. olimpico):
bash deploy-remote.sh --target=olimpico
# Or via env:
DEPLOY_TARGET=olimpico bash deploy-remote.sh
# Legacy (backward compatibility — custom server):
OLIMPICO_SERVER=192.168.2.50 OLIMPICO_USER=admin bash deploy-remote.shWhat happens: rsync → npm install → build → PM2 restart → nginx reload → health check
The deploy is automatic and identical for every target: only
targets.confchanges (SSH credentials + paths). No script changes needed to deploy a new stadium.
⚠️ Server migration — folder rename (one-time, only on an already-deployed server)
If the server was already deployed with the old folder names (olimpico-live-api, olimpico-live-regia, olimpico-live-deploy), the first deploy with the new names requires a manual migration after deploy-remote.sh:
# 1. Move the .env into the new folder (excluded from rsync, it stayed in the old one)
sudo mv /opt/olimpico/olimpico-live/olimpico-live-api/.env \
/opt/olimpico/olimpico-live/zerolatency-live-player-api/.env
# 2. Update the path in the backup cron
sudo sed -i 's|olimpico-live-deploy|zerolatency-live-player-deploy|' /etc/cron.d/olimpico-backup
# 3. Restart PM2 from the new folder (the process changes name: from "olimpico-api" to "zerolatency-live-player-api")
cd /opt/olimpico/olimpico-live/zerolatency-live-player-api
pm2 delete olimpico-api 2>/dev/null # delete the OLD process (old name)
pm2 start ecosystem.config.cjs # restarts with the NEW name
pm2 save
# 4. Rename the MongoDB database (was `olimpico_live`, now `liveplayer`)
mongosh --eval 'db.adminCommand({ renameCollection: "olimpico_live.regia" , to: "liveplayer.regia" })' --quiet 2>/dev/null || true
mongosh --eval 'db.adminCommand({ renameCollection: "olimpico_live.tablets", to: "liveplayer.tablets" })' --quiet 2>/dev/null || true
mongosh --eval 'db.adminCommand({ renameCollection: "olimpico_live.links" , to: "liveplayer.links" })' --quiet 2>/dev/null || true
mongosh --eval 'db.adminCommand({ renameCollection: "olimpico_live.events", to: "liveplayer.events" })' --quiet 2>/dev/null || true
# Or, alternatively: mongodump olimpico_live → mongorestore liveplayer --drop
# 5. Remove the old orphan folders
sudo rm -rf /opt/olimpico/olimpico-live/olimpico-live-api \
/opt/olimpico/olimpico-live/olimpico-live-regia \
/opt/olimpico/olimpico-live/olimpico-live-deploy
# 6. Verify
pm2 status # zerolatency-live-player-api → online
curl -H "X-API-Key: <API_KEY>" http://localhost:3002/api/devices
mongosh liveplayer --eval 'db.getCollectionNames()' --quiet⚠️ The PM2 process is now called
zerolatency-live-player-api(wasolimpico-api). On an already-deployed server, delete the old process before starting the new one.
8. Quick post-deploy verification (2 min)
# Backend health check (requires the API key)
curl -H "X-API-Key: <API_KEY>" http://192.168.1.127/api/devices
# Expected response: [] (empty device list)
# Server health check
curl -I http://192.168.1.127/health
# Verify PM2
ssh debian@192.168.1.127 'pm2 status'
# You should see: zerolatency-live-player-api → online
# Swagger UI
open http://192.168.1.127/docs🆘 Quick troubleshooting
| Problem | Command |
|---|---|
| PM2 does not start | ssh debian@192.168.1.127 'pm2 logs zerolatency-live-player-api --lines 30' |
| Invalid license | ssh debian@192.168.1.127 'cat /opt/olimpico/olimpico-live/zerolatency-live-player-api/.env | grep LICENSE' |
| nginx does not start | ssh debian@192.168.1.127 'sudo nginx -t' |
| MongoDB not responding | ssh debian@192.168.1.127 'sudo systemctl status mongod' |
| Build failed | ssh debian@192.168.1.127 'cd /opt/olimpico/olimpico-live/zerolatency-live-player-api && cat dist/index.js | head -5' |
References
| Document | Link |
|---|---|
| Full deploy guide (multi-tenant) | Deploy |
| Features overview | Overview |
| Apple Developer Account | Complete Guide |
| Build IPA for iPad | Build Flutter App |
| Post-deploy testing | Post-deploy |