> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bitbonsai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-Node Setup

> Add worker nodes to speed up encoding

Scale BitBonsai's encoding capacity by adding worker nodes across multiple machines.

## What is Multi-Node Encoding?

Multi-node encoding distributes video transcoding jobs across multiple physical machines, dramatically reducing total encoding time.

**How it works:**

* **Main Node**: Owns the PostgreSQL database, distributes jobs, hosts the web UI
* **Child Nodes**: Worker-only nodes that pull jobs from the main node's queue
* **Shared Storage**: NFS mount ensures all nodes access the same video files
* **Automatic Load Balancing**: Jobs are distributed based on each node's current load and capacity

**Example:**

```
Main Node (192.168.1.100):
  - PostgreSQL database
  - Web UI (port 4210)
  - Encodes jobs (4 concurrent)

Child Node 1 (192.168.1.170):
  - Encodes jobs (8 concurrent)
  - Proxies API calls to main

Total capacity: 12 concurrent encoding jobs
```

***

## Architecture

The main node owns the database and web UI. Child nodes are workers that connect to the main node's database.

```
[Web UI] -> [Main Node] -> [Database]
                ↓
         [Child Nodes] -> [NFS Storage]
```

All nodes must mount the same NFS share to access video files.

***

## Prerequisites

Before setting up multi-node:

<Card title="Shared Storage Required" icon="folder">
  All nodes must access the **same video files** via NFS/SMB network mount.

  Without shared storage, child nodes cannot read source videos or write encoded files.
</Card>

<CardGroup cols={2}>
  <Card title="Main Node" icon="server">
    * PostgreSQL 15+ (8GB RAM recommended)
    * Docker + Docker Compose
    * NFS mount to video storage
  </Card>

  <Card title="Child Nodes" icon="microchip">
    * Docker installed
    * NFS mount to **same path** as main node
    * Network access to main node
  </Card>
</CardGroup>

***

## Setup Instructions

### Step 1: Configure NFS Server

On your NAS or file server:

```bash theme={null}
# Example: Unraid NFS export
/mnt/user/videos 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

# Restart NFS
exportfs -ra
```

### Step 2: Mount NFS on All Nodes

Mount the shared storage at the **same path** on every node:

```bash theme={null}
# On main node (192.168.1.100)
sudo mkdir -p /mnt/videos
sudo mount -t nfs 192.168.1.1:/mnt/user/videos /mnt/videos

# On child node 1 (192.168.1.170)
sudo mkdir -p /mnt/videos
sudo mount -t nfs 192.168.1.1:/mnt/user/videos /mnt/videos

# On child node 2 (192.168.1.171)
sudo mkdir -p /mnt/videos
sudo mount -t nfs 192.168.1.1:/mnt/user/videos /mnt/videos
```

Make permanent in `/etc/fstab`:

```
192.168.1.1:/mnt/user/videos /mnt/videos nfs defaults,_netdev 0 0
```

### Step 3: Deploy Main Node

On the main node (192.168.1.100):

```yaml theme={null}
# docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_DB: bitbonsai
      POSTGRES_USER: bitbonsai
      POSTGRES_PASSWORD: secure_password
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    restart: unless-stopped

  backend:
    image: bitbonsai/backend:latest
    ports:
      - "3100:3100"
    environment:
      DATABASE_URL: postgresql://bitbonsai:secure_password@postgres:5432/bitbonsai
      NODE_MODE: MAIN
      CONCURRENT_JOBS: 4
    volumes:
      - /mnt/videos:/media
    depends_on:
      - postgres
    restart: unless-stopped

  frontend:
    image: bitbonsai/frontend:latest
    ports:
      - "4210:80"
    environment:
      API_URL: http://192.168.1.100:3100
    restart: unless-stopped
```

Start:

```bash theme={null}
docker compose up -d
```

### Step 4: Deploy Child Nodes

On child node 1 (192.168.1.170):

```yaml theme={null}
# docker-compose.yml
version: '3.8'

services:
  backend:
    image: bitbonsai/backend:latest
    ports:
      - "3100:3100"
    environment:
      DATABASE_URL: postgresql://bitbonsai:secure_password@192.168.1.100:5432/bitbonsai
      NODE_MODE: LINKED
      MAIN_NODE_URL: http://192.168.1.100:3100
      CONCURRENT_JOBS: 8
    volumes:
      - /mnt/videos:/media
    restart: unless-stopped
```

Start:

```bash theme={null}
docker compose up -d
```

Repeat for additional child nodes (192.168.1.171, etc.)

### Step 5: Verify Node Registration

Check the web UI at `http://192.168.1.100:4210`:

1. Go to **Settings → Nodes**
2. You should see:
   * Main Node (192.168.1.100) - Status: ONLINE
   * Child Node 1 (192.168.1.170) - Status: ONLINE
   * Child Node 2 (192.168.1.171) - Status: ONLINE

***

## How Job Distribution Works

BitBonsai uses smart load balancing:

1. **User scans library** → Jobs added to queue (status: QUEUED)
2. **Scheduler polls** every 5 seconds
3. **For each node:**
   * Check current load (active jobs / max concurrent)
   * If load \< 100%, assign next QUEUED job to this node
4. **Node picks up job** → status changes to ENCODING
5. **Job completes** → status changes to COMPLETED

**Load calculation:**

```
Node Load = (Active Jobs / Max Concurrent Jobs) × 100

Example:
- Main Node: 3/4 jobs = 75% load
- Child Node 1: 6/8 jobs = 75% load
- Child Node 2: 2/8 jobs = 25% load ← Gets next job
```

***

## Troubleshooting

### Child Node Not Appearing in UI

**Symptom:** Child node started but not visible in Settings → Nodes

**Fix:**

```bash theme={null}
# On child node, check logs
docker logs bitbonsai-backend

# Look for:
# ✓ Connected to database at postgresql://192.168.1.100:5432/bitbonsai
# ✓ Registered as LINKED node with ID: node_xyz

# If missing, check:
# 1. DATABASE_URL points to main node's PostgreSQL
# 2. PostgreSQL port 5432 is accessible (firewall)
# 3. NODE_MODE=LINKED is set
```

### Jobs Stuck in QUEUED

**Symptom:** Jobs remain QUEUED, no node picks them up

**Fix:**

1. Check all nodes are ONLINE in Settings → Nodes
2. Verify NFS mounts are working:
   ```bash theme={null}
   docker exec bitbonsai-backend ls -la /media
   ```
3. Check logs for errors:
   ```bash theme={null}
   docker logs bitbonsai-backend | grep ERROR
   ```

### File Not Found Errors

**Symptom:** Job fails with "ENOENT: no such file or directory"

**Fix:**

* Verify NFS mount path is **identical** on all nodes
* Check NFS permissions (should be `rw`, not `ro`)
* Test file access:
  ```bash theme={null}
  docker exec bitbonsai-backend cat /media/Movies/test.mp4
  ```

***

## Performance Tips

| Tip                       | Why                                    |
| ------------------------- | -------------------------------------- |
| **Use 10GbE network**     | NFS throughput critical for 4K video   |
| **Enable NFS async mode** | Faster writes (use UPS for safety)     |
| **Match NFS mount paths** | Avoids path rewriting overhead         |
| **Use SSD for database**  | Faster job updates and queries         |
| **Monitor node load**     | Add nodes when load > 80% consistently |

***

## Related Guides

* **[GPU Acceleration](/advanced/gpu-acceleration)** - Add GPU support to nodes
* **[Monitoring](/guides/monitoring)** - Track multi-node performance
* **[Troubleshooting](/advanced/troubleshooting)** - Fix common multi-node issues
