# How to run Room on a server with Docker

This guide puts the API and MongoDB in Docker, then serves the website with Nginx over HTTPS. Camera and microphone only work on HTTPS once you leave your own computer.

You need a Linux server with a public IP, a domain name that points at that IP, and permission to install Docker and Nginx. The steps use `meet.example.com` as the site name. Replace it with your domain.

## 1. Install Docker

Install Docker Engine and the Compose plugin from the Docker documentation for your distribution. Confirm both commands work:

```bash
docker --version
docker compose version
```

## 2. Get the code

```bash
git clone <your-repo-url> videocall
cd videocall
```

## 3. Set the API for this server

Open `docker-compose.yml`. The `server` service reads its settings from the `environment` block. Change these before the first start:

- `CLIENT_ORIGIN` must be the exact public site address, with `https` and no slash at the end. Example: `https://meet.example.com`.
- `JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET` must be long random strings. Generate them with `openssl rand -base64 32` and use a different value for each.
- Bind the API to this machine only, so the internet talks to Nginx, not to port 4000:

```yaml
ports:
  - "127.0.0.1:4000:4000"
```

- On a public server, delete the `ports` section under `mongo`. The API reaches MongoDB on the Docker network as `mongodb://mongo:27017/videocall`. Publishing `27017` exposes the database.

Add any of these under `server.environment` when you need them. Names match `server/.env.example`.

| Name | Purpose |
| --- | --- |
| `STUN_URL` | STUN server. The default is `stun:stun.l.google.com:19302`. |
| `TURN_URL`, `TURN_USERNAME`, `TURN_CREDENTIAL` | TURN relay. Required when two people cannot connect directly. |
| `RATE_LIMIT_WINDOW_MS`, `RATE_LIMIT_MAX` | Cap for all API requests. `RATE_LIMIT_MAX=0` turns it off. |
| `AUTH_RATE_LIMIT_WINDOW_MS`, `AUTH_RATE_LIMIT_MAX` | Cap for login, signup, and guest join. |
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI` | Google sign-in. Leave them unset to keep it off. |

`GOOGLE_REDIRECT_URI` must be `https://meet.example.com/api/auth/google/callback`.

## 4. Start MongoDB and the API

From the repository root:

```bash
docker compose up -d --build
docker compose ps
curl -fsS http://127.0.0.1:4000/api/health
```

`curl` prints `{"ok":true}` when the API is up. If it fails, read `docker compose logs server`.

## 5. Build the website

Install Node.js 20 or newer on the server, then build the client. The page calls `/api` and `/socket.io` on the same host, so the build does not need an API address.

```bash
cd client
npm install --legacy-peer-deps
npm run build
sudo mkdir -p /var/www/videocall
sudo cp -r dist/. /var/www/videocall/
cd ..
```

For Google sign-in, create `client/.env.production` with `VITE_GOOGLE_AUTH=true` before `npm run build`.

## 6. Serve the site with Nginx and HTTPS

Install Nginx and Certbot, then allow HTTP and HTTPS through the firewall. Leave port 4000 closed to the public.

```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
```

Create `/etc/nginx/sites-available/videocall` from `deploy/nginx.conf`, with three edits: your domain, Certbot certificate paths, and `127.0.0.1` instead of the Docker name `server`. The checked-in file uses `server` because that name exists only inside Compose.

```nginx
server {
  listen 80;
  server_name meet.example.com;
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name meet.example.com;

  ssl_certificate /etc/letsencrypt/live/meet.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/meet.example.com/privkey.pem;

  location /api/ {
    proxy_pass http://127.0.0.1:4000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto https;
  }

  location /socket.io/ {
    proxy_pass http://127.0.0.1:4000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
  }

  location / {
    root /var/www/videocall;
    try_files $uri /index.html;
  }
}
```

Issue the certificate, then enable the site:

```bash
sudo certbot certonly --nginx -d meet.example.com
sudo ln -s /etc/nginx/sites-available/videocall /etc/nginx/sites-enabled/videocall
sudo nginx -t
sudo systemctl reload nginx
```

If Certbot runs before the certificate files exist, comment out the `ssl_certificate` lines, reload Nginx, run Certbot, then restore those lines and reload again.

## 7. Check the running site

Open `https://meet.example.com`. Create a meeting, join from a second browser, and confirm the camera turns on. Both browsers must use the `https` address. A page opened by IP, or as `http`, will not get the camera.

Calls between different networks also need the `TURN_*` values from step 3. Restart the API after adding them:

```bash
docker compose up -d server
```

## Update a later version

```bash
git pull
docker compose up -d --build
cd client && npm install --legacy-peer-deps && npm run build
sudo cp -r dist/. /var/www/videocall/
```

MongoDB data stays in the `mongo-data` volume across recreates. `docker compose down -v` deletes that volume.
