Skip to content

What to do BEFORE running deploy-remote.sh for 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 → Identifiers with Description KsoftLivePlayer and Bundle ID com.zerolatency.liveplayer (⚠️ exactly — NOT com.example.* nor com.ksoft.olimpico-live). See the Complete Guide.

1. Generate the License Key (1 min)

On your Mac (not on the server):

bash
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-31

Expected output:

🔑 License Key generated:

   OLIMP-U3RhZGlvIE9saW1waWNv-20271231-a1b2c3d4

   Client: Stadio Olimpico
   Expires: 2027-12-31
   Issued:  2026-07-22

Save LICENCE_SECRET and LICENSE_KEY — both are needed in step 3.

2. Verify the server connection (1 min)

bash
# 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
exit

Minimum requirements: CPU 2 cores, RAM 2 GB, SSD 10 GB free.

3. Populate the .env file on the server (2 min)

bash
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/.env

Make sure it contains AT LEAST:

ini
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-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p

Note: .env is NOT synced via rsync for security. It must be edited manually on the server.

Exit the server:

bash
exit

4. Prepare the local .env for the Control Room (optional)

If you want to run the Control Room in dev mode against the production server:

bash
cp zerolatency-live-player-regia/.env.example zerolatency-live-player-regia/.env.local

Not needed for production deploy — the built Control Room uses the nginx proxy.

5. Verify the deploy module is present (1 min)

bash
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:

bash
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.conf

Line 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:

  1. --target=NAME / DEPLOY_TARGET=NAME — explicit target
  2. OLIMPICO_SERVER/OLIMPICO_USER/... — legacy override (backward compatibility)
  3. Interactive menu — when deploy-remote.sh runs from a terminal without flags
  4. 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):

bash
# 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/olimpico

This 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)

bash
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.sh

What happens: rsync → npm install → build → PM2 restart → nginx reload → health check

The deploy is automatic and identical for every target: only targets.conf changes (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:

bash
# 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 (was olimpico-api). On an already-deployed server, delete the old process before starting the new one.

8. Quick post-deploy verification (2 min)

bash
# 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

ProblemCommand
PM2 does not startssh debian@192.168.1.127 'pm2 logs zerolatency-live-player-api --lines 30'
Invalid licensessh debian@192.168.1.127 'cat /opt/olimpico/olimpico-live/zerolatency-live-player-api/.env | grep LICENSE'
nginx does not startssh debian@192.168.1.127 'sudo nginx -t'
MongoDB not respondingssh debian@192.168.1.127 'sudo systemctl status mongod'
Build failedssh debian@192.168.1.127 'cd /opt/olimpico/olimpico-live/zerolatency-live-player-api && cat dist/index.js | head -5'

References

DocumentLink
Full deploy guide (multi-tenant)Deploy
Features overviewOverview
Apple Developer AccountComplete Guide
Build IPA for iPadBuild Flutter App
Post-deploy testingPost-deploy

© 2026 Zerolatency — All Rights Reserved