# Daneshyar classroom and media-server deployer

Run the deployer on your PC. It connects to the servers over SSH and performs
the installation remotely; you do not copy commands into each server.

## What it automates

For an additional media server, the deployer:

1. asks for the main application server and new media-server SSH details;
2. installs and configures coturn on the new Ubuntu server;
3. opens TURN ports in UFW when UFW is installed;
4. creates or preserves the private HMAC credential used by WebRTC;
5. uploads the current database manager to the main application server;
6. creates/migrates the `media_servers` registry when needed;
7. registers the new server in the application database; and
8. checks connectivity, service health, and current capacity.

New classrooms are then pinned to the healthy server with the lowest load
percentage. A class keeps the same assigned server for its lifetime; refreshing
or re-entering does not randomly move it. If one server is full, new classes
overflow to the next healthy registered server.

The primary installation mode additionally configures Laravel Reverb, Redis,
the queue worker, the main coturn relay, Apache's WebSocket proxy, database
migrations, and a five-second media health/load timer.

## Requirements

- Windows PC: Python 3 and PowerShell. The launcher creates an isolated Python
  environment and installs Paramiko automatically.
- Servers: Ubuntu/Debian, SSH access, and either `root` or a sudo-capable user.
- The main server must already contain the deployed Laravel app and `.env` at
  `/var/www/daneshyar` unless a different path is entered.
- The cloud-provider firewall must allow SSH, TURN `3478/udp`, TURN `3478/tcp`,
  and relay traffic `49152-65535/udp`. The script can update UFW, but it cannot
  change Hetzner/AWS/Cloudflare provider firewalls.

If coturn is behind one-to-one NAT, set its public address in `public_ip` in the
JSON config. A normal VPS with a public address should leave it as `null`.

## Fastest use: add one media server

Open Command Prompt or PowerShell in the project directory and run:

```powershell
scripts\deploy_media_server.bat
```

The default action is `add-relays`. It asks for:

- SSH details for the main app server;
- its SSH password, or it uses your SSH key/agent;
- the new media server address, name, region, port, and capacity; and
- that server's SSH/sudo password.

Verify each server IP before accepting a new SSH host key. After installation,
the script prints the registered servers and their health. No manual database
command is required.

## First primary classroom-server installation

Once the application itself is deployed, run:

```powershell
scripts\deploy_media_server.bat install
```

This installs or repairs the complete classroom runtime on the main server. It
also offers to provision extra TURN relays in the same run. It is safe to run
again: existing application data and classroom room keys are retained.

To build and deploy the current application before installing the runtime:

```powershell
scripts\deploy_media_server.bat install --deploy-app
```

`--deploy-app` uses the existing atomic `scripts/update.py` target, so its host,
port, user, and live path must match the classroom installer config.

## Check everything without changing it

```powershell
scripts\deploy_media_server.bat status
```

This checks coturn, Redis, Reverb, the queue worker, the health timer, database
registration, reachability, and reported media-server load.

To validate targets without making an SSH connection:

```powershell
scripts\deploy_media_server.bat --dry-run
```

## Reusable configuration for multiple servers

Copy the supplied example:

```powershell
Copy-Item scripts\classroom_servers.example.json scripts\classroom_servers.json
```

Edit `scripts/classroom_servers.json` and replace
`SECOND_SERVER_PUBLIC_IP`. Add more objects to `extra_relays` to provision
several servers in one run. The real file is ignored by Git.

The safest credential choices are:

- leave passwords out and let the deployer prompt without echo;
- use an SSH key through `key_file` or your SSH agent; or
- keep `password_env` in JSON and set that environment variable only for the
  current terminal.

For a fully unattended run, set the named password variables and use:

```powershell
scripts\deploy_media_server.bat --config scripts\classroom_servers.json --non-interactive --accept-new-host-key
```

You may place `password` or `sudo_password` in the ignored JSON file, but that
stores credentials as plain text and is not recommended. `password_env` and
`sudo_password_env` are supported for every server object.

Useful relay fields:

```json
{
  "name": "TURN relay 2",
  "host": "203.0.113.20",
  "ssh_port": 22,
  "ssh_user": "root",
  "password_env": "DANESHYAR_RELAY_2_PASSWORD",
  "turn_port": 3478,
  "realm": "mydaneshyar.ir",
  "region": "de-fsn1",
  "capacity": 80,
  "priority": 20,
  "public_ip": null
}
```

Lower `priority` wins when two healthy servers have the same load percentage.
If `turn_secret` is supplied, the installer uses it. Otherwise it preserves the
secret already present on that relay or securely creates one on first install.

## Linux/macOS PC

Install Paramiko once, then run the Python entrypoint:

```bash
python3 -m pip install paramiko
python3 scripts/media_server_deployer.py
```

The same `install`, `status`, `--config`, `--non-interactive`, and `--dry-run`
arguments are available.

## Architecture boundary

This deployer installs TURN relays for reliable microphone, camera, and screen
share connectivity and Reverb for classroom signaling. TURN relays forward
encrypted WebRTC traffic; they are not an SFU that mixes or selectively routes
large conferences. The database already supports a future `sfu` server kind,
but an SFU such as LiveKit/mediasoup would require a separate integration when
large-room media mixing is needed.

## Manage servers from Super Admin

After deploying the application and running migrations, open:

```text
Super Admin → Monitoring → Media Servers
```

From there a Super Admin can add or edit a server, store encrypted SSH
credentials, install/repair coturn, test connectivity, restart the service,
read recent coturn logs, drain a server, re-enable it, and inspect the audited
operation history. Remote commands are limited to these predefined actions;
the website intentionally does not expose an arbitrary shell terminal.

Installation adds a systemd restart policy, so coturn starts after a server
reboot and restarts automatically after a crash. Non-root SSH users must have
passwordless sudo for the controlled operations.
