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

# Configuring Your Orchestrator

> Set the go-livepeer flags needed to run as an Orchestrator - GPU selection, pricing, session limits, networking, and AI worker configuration.

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

export const LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

<CustomDivider style={{margin: "-1rem 0 -1rem 0"}} />

the go-livepeer flags needed to run as an Orchestrator. By the end, a working
startup command is ready and each flag is understood.

**Prerequisites:**

* go-livepeer installed and GPU detected. See <LinkArrow href="/v2/orchestrators/setup/rs-install" label="Install go-livepeer" newline={false} />.
* Arbitrum wallet with ETH for gas. See <LinkArrow href="/v2/orchestrators/setup/sc-connect" label="Connect to Arbitrum" newline={false} />.
* The hardware session limit number from the `livepeer_bench` test in <LinkArrow href="/v2/orchestrators/guides/deployment-details/requirements" label="Requirements" newline={false} />.

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Essential Flags

These flags must be set every time go-livepeer starts as an Orchestrator.

<Steps>
  <Step title="Set the network">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -network arbitrum-one-mainnet
    ```

    Tells go-livepeer which network to connect to. The default is `offchain` - without this flag the
    node does not participate in the Livepeer Protocol at all.

    **Options:**

    * `arbitrum-one-mainnet` - production network
    * `offchain` - local or dev only, no on-chain participation
  </Step>

  <Step title="Connect to Arbitrum RPC">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -ethUrl <YOUR_ARBITRUM_RPC_URL>
    ```

    Points go-livepeer at an Arbitrum One RPC endpoint to read and write on-chain state - Orchestrator
    registration, reward calls, ticket redemption.

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -ethUrl https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY
    ```

    This must be an **Arbitrum One** endpoint, not an Ethereum L1 endpoint. See
    <LinkArrow href="/v2/orchestrators/setup/sc-connect" label="Connect to Arbitrum" newline={false} /> for how to set up a reliable RPC.
  </Step>

  <Step title="Set the Ethereum account (optional)">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -ethAcctAddr <YOUR_ETH_ADDRESS>
    ```

    Specifies which ETH account acts as the Orchestrator identity on the network. This account holds
    staked LPT, receives ETH fee payments, and signs on-chain transactions.

    If omitted, go-livepeer creates a new account and prompts for a passphrase to encrypt the keystore.
    The key is stored at `~/.lpData/arbitrum-one-mainnet/keystore` by default.

    <Warning>
      The private key controls the wallet and all funds on it. Back it up securely before proceeding.
      A lost keystore cannot be recovered.
    </Warning>
  </Step>

  <Step title="Enable Orchestrator and Transcoder mode">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -orchestrator -transcoder
    ```

    `-orchestrator` enables the on-chain protocol role - the node participates in job routing, makes
    reward calls, and is visible to Gateways.

    `-transcoder` enables local GPU transcoding - the node processes jobs using its GPU.

    Use both together for the standard combined setup where one machine handles all roles. For
    alternate configurations:

    <StyledTable variant="bordered">
      <thead>
        <TableRow header>
          <TableCell header>Mode</TableCell>
          <TableCell header>Flags</TableCell>
          <TableCell header>Use when</TableCell>
        </TableRow>
      </thead>

      <tbody>
        <TableRow>
          <TableCell>**Combined** (most common)</TableCell>
          <TableCell>`-orchestrator -transcoder`</TableCell>
          <TableCell>One machine handles all roles</TableCell>
        </TableRow>

        <TableRow>
          <TableCell>**Orchestrator-only**</TableCell>
          <TableCell>`-orchestrator`</TableCell>
          <TableCell>Remote Transcoder workers are connected via `-orchSecret`</TableCell>
        </TableRow>

        <TableRow>
          <TableCell>**Transcoder-only**</TableCell>
          <TableCell>`-transcoder -orchAddr <host:port>`</TableCell>
          <TableCell>Contributing GPU to another Orchestrator's pool</TableCell>
        </TableRow>
      </tbody>
    </StyledTable>

    See <LinkArrow href="/v2/orchestrators/guides/deployment-details/setup-options" label="Alternate Deployments" newline={false} /> for the O-T split and Siphon configurations.
  </Step>

  <Step title="Select the GPU">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -nvidia <GPU_IDs>
    ```

    Specifies which NVIDIA GPUs go-livepeer uses for transcoding. Omitting this flag falls back to
    CPU transcoding, which is significantly slower and not competitive on the network.

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -nvidia 0        # Single GPU - device ID 0
    -nvidia 0,1      # Two GPUs
    -nvidia all      # All available GPUs
    ```

    Check GPU IDs before starting:

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    nvidia-smi -L
    ```

    <Note>
      For AI-only operation (no video transcoding), `-transcoder` is not required but `-nvidia` is
      still needed to expose the GPU to AI Runner containers. See [Adding AI inference](#adding-ai-inference) below.
    </Note>
  </Step>

  <Step title="Set the session limit">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -maxSessions <VALUE>
    ```

    Sets the maximum concurrent transcoding sessions the node accepts. The default is 10. Set it
    to the **minimum of the hardware limit and the bandwidth limit**.

    **Hardware limit:** the last session count from the `livepeer_bench` test in
    <LinkArrow href="/v2/orchestrators/guides/deployment-details/requirements" label="Requirements" newline={false} /> where Real-Time Duration Ratio was ≤ 0.8.

    **Bandwidth limit:** available symmetric bandwidth (Mbps) ÷ 6 Mbps per stream × 0.8 margin.

    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    session limit = min(hardware limit, bandwidth limit)
    ```

    Example: hardware limit 12, bandwidth 100 Mbps → bandwidth limit \~13 → use `-maxSessions 12`.

    <Note>
      `-maxSessions` applies to video transcoding only. AI inference capacity is controlled per pipeline
      by the `capacity` field in `aiModels.json`. See [Adding AI inference](#adding-ai-inference) below.
    </Note>
  </Step>

  <Step title="Set the price">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -pricePerUnit <VALUE_IN_WEI>
    ```

    Sets the price charged per unit of transcoding work. The unit is **wei per pixel**, not ETH.

    * 1 ETH = 1,000,000,000,000,000,000 wei
    * A typical starting price is **500-2,000 wei per pixel**
    * Check current market rates at [tools.Livepeer.cloud](https://tools.livepeer.cloud/ai/network-capabilities)

    Setting this in ETH rather than wei results in a price orders of magnitude below market rate.
    Setting it too high means Gateways route jobs to lower-priced Orchestrators instead.

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -pricePerUnit 1000
    ```

    <Note>
      `-pricePerUnit` sets the startup price. The on-chain registered price used for discovery is set
      separately during activation via `livepeer_cli`. Both can be adjusted independently later.
    </Note>
  </Step>

  <Step title="Set the service address">
    ```text icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -serviceAddr <YOUR_PUBLIC_IP_OR_HOSTNAME>:<PORT>
    ```

    Declares the public address at which Gateways reach the Orchestrator. This is stored on-chain
    during activation and is how the network discovers the node.

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -serviceAddr 203.0.113.42:8935
    # or with a domain name (preferred):
    -serviceAddr orch.yourdomain.com:8935
    ```

    **Common mistakes:**

    * Using an internal IP (`192.168.x.x`, `10.x.x.x`) - not routable from the internet
    * Using `0.0.0.0` - binds locally but is not a network address
    * Changing the IP without updating on-chain registration - Gateways lose contact

    A domain name is preferable to a bare IP. If the server's IP changes, a DNS record can be updated
    without a new on-chain registration transaction.
  </Step>
</Steps>

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Full Startup Command

Replace every placeholder with actual values:

```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
livepeer \
  -network arbitrum-one-mainnet \
  -ethUrl https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY \
  -ethAcctAddr YOUR_ETH_ADDRESS \
  -orchestrator \
  -transcoder \
  -nvidia 0 \
  -maxSessions 10 \
  -pricePerUnit 1000 \
  -serviceAddr YOUR_PUBLIC_IP:8935
```

On first run with a new account (omitting `-ethAcctAddr`), go-livepeer prompts for a passphrase
to create and encrypt a new keystore. This passphrase is required on every subsequent start.

For verbose logging while getting started:

```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
livepeer ... -v 6
```

This outputs detailed logs including transcoding activity, RPC calls, and session events.

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Adding AI Inference

To serve AI inference jobs alongside or instead of transcoding, three additional flags are needed.

<Accordion title="AI worker flags" icon="microchip">
  ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  -aiWorker \
  -aiModels /path/to/aiModels.json \
  -aiModelsDir /path/to/models/
  ```

  <StyledTable variant="bordered">
    <thead>
      <TableRow header>
        <TableCell header>Flag</TableCell>
        <TableCell header>What it does</TableCell>
      </TableRow>
    </thead>

    <tbody>
      <TableRow>
        <TableCell>`-aiWorker`</TableCell>
        <TableCell>Enables the AI worker component. Without this flag, go-livepeer ignores all AI configuration.</TableCell>
      </TableRow>

      <TableRow>
        <TableCell>`-aiModels`</TableCell>
        <TableCell>Path to `aiModels.json` - defines which pipelines and models to serve. Default: `~/.lpData/aiModels.json`</TableCell>
      </TableRow>

      <TableRow>
        <TableCell>`-aiModelsDir`</TableCell>
        <TableCell>Path to the directory where go-livepeer looks for cached model weights. Default: `~/.lpData/models/`</TableCell>
      </TableRow>

      <TableRow>
        <TableCell>`-aiRunnerImage`</TableCell>
        <TableCell>Optional. The Docker image for AI Runner containers. Defaults to `livepeer/ai-runner:latest`. Pin to a specific tag in production.</TableCell>
      </TableRow>
    </tbody>
  </StyledTable>

  **When running in Docker**, the AI Orchestrator needs access to the Docker socket to manage AI
  runner containers:

  ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  docker run \
    --name livepeer_ai_orchestrator \
    -v ~/.lpData/:/root/.lpData/ \
    -v /var/run/docker.sock:/var/run/docker.sock \
    --network host \
    --gpus all \
    livepeer/go-livepeer:master \
    -orchestrator \
    -serviceAddr 0.0.0.0:8936 \
    -nvidia 0 \
    -aiWorker \
    -aiModels /root/.lpData/aiModels.json \
    -aiModelsDir ~/.lpData/models
  ```

  <Note>
    The AI Orchestrator uses port **8936** by default to avoid conflict with a transcoding Orchestrator
    on the same machine (which uses 8935). Set `-serviceAddr` accordingly.
  </Note>

  <Warning>
    With Docker-out-of-Docker, the `-aiModelsDir` path must be a path on the **host machine**, not
    inside the container. Docker uses this path to mount model files into AI Runner containers it spawns.
  </Warning>

  For the full guide to configuring `aiModels.json` and receiving the first AI job, see
  <LinkArrow href="/v2/orchestrators/guides/workloads-and-ai/batch-ai-setup" label="Batch AI Setup" newline={false} />.
</Accordion>

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Variants

<AccordionGroup>
  <Accordion title="Docker - full Orchestrator in a container" icon="docker">
    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    docker run \
      --name livepeer_orchestrator \
      -v ~/.lpData/:/root/.lpData/ \
      --network host \
      --gpus all \
      livepeer/go-livepeer:latest \
      -network arbitrum-one-mainnet \
      -ethUrl https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY \
      -orchestrator \
      -transcoder \
      -nvidia 0 \
      -maxSessions 10 \
      -pricePerUnit 1000 \
      -serviceAddr YOUR_PUBLIC_IP:8935
    ```

    Mount `~/.lpData/` so the keystore and data persist between container restarts. Without this
    mount, a new ETH account is created on every run.
  </Accordion>

  <Accordion title="systemd service" icon="server">
    Create `/etc/systemd/system/livepeer.service`:

    ```ini icon="code" title="/etc/systemd/system/livepeer.service" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    [Unit]
    Description=Livepeer Orchestrator
    After=network.target

    [Service]
    Type=simple
    User=ubuntu
    ExecStart=/usr/local/bin/livepeer \
      -network arbitrum-one-mainnet \
      -ethUrl https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY \
      -orchestrator \
      -transcoder \
      -nvidia 0 \
      -maxSessions 10 \
      -pricePerUnit 1000 \
      -serviceAddr YOUR_PUBLIC_IP:8935
    Restart=on-failure
    RestartSec=10

    [Install]
    WantedBy=multi-user.target
    ```

    Enable and start:

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    sudo systemctl daemon-reload
    sudo systemctl enable livepeer
    sudo systemctl start livepeer
    journalctl -u livepeer -f
    ```
  </Accordion>

  <Accordion title="Config file pattern" icon="file-code">
    go-livepeer does not have a native config file flag. The standard pattern stores flags in a plain
    text file and expands them at startup:

    ```bash icon="code" title="/etc/livepeer/livepeer.conf" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -network arbitrum-one-mainnet
    -ethUrl https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY
    -orchestrator
    -transcoder
    -nvidia 0
    -maxSessions 10
    -pricePerUnit 1000
    -serviceAddr YOUR_PUBLIC_IP:8935
    ```

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    livepeer $(< /etc/livepeer/livepeer.conf)
    ```

    In a systemd unit file, this requires an `ExecStart` wrapper shell script rather than calling the
    binary directly - systemd does not perform shell expansion in `ExecStart`.
  </Accordion>
</AccordionGroup>

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Next Steps

<CardGroup cols={3}>
  <Card title="Connect to Arbitrum" icon="link" href="/v2/orchestrators/setup/sc-connect" arrow horizontal>
    Set up the Arbitrum RPC endpoint and fund the wallet with ETH for gas.
  </Card>

  <Card title="Activate on the network" icon="circle-check" href="/v2/orchestrators/setup/activate" arrow horizontal>
    Register the Orchestrator on-chain and enter the Active Set via `livepeer_cli`.
  </Card>

  <Card title="CLI reference" icon="terminal" href="/v2/orchestrators/resources/technical/cli-flags" arrow horizontal>
    Every flag, its type, default, and description.
  </Card>
</CardGroup>
