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

# Connect a Livepeer Gateway on Docker, Linux, or Windows

> Connect your Livepeer Gateway to the network. Orchestrator discovery, selection tuning, and service publication for Docker, Linux, and Windows.

export const windowsGroup = () => <div style={{
  display: 'flex',
  gap: '0.5rem',
  alignItems: 'center',
  marginBottom: '1rem'
}}>
    <span>
      <Icon icon="windows" color="#0078d6" size={22} /> <Badge> Windows </Badge>
    </span>
  </div>;

export const linuxGroup = () => <div style={{
  display: 'flex',
  gap: '0.5rem',
  alignItems: 'center',
  marginBottom: '1rem'
}}>
    <span>
      <Icon icon="linux" color="#ff9a0e" size={22} /> <Badge> Linux </Badge>
    </span>
    <span>
      <Icon icon="apple" color="#60ba47" size={22} /> <Badge> macOS </Badge>
    </span>
  </div>;

export const dockerGroup = () => <div style={{
  display: 'flex',
  gap: '0.5rem',
  alignItems: 'center',
  marginBottom: '1rem'
}}>
    <span>
      <Icon icon="linux" color="#ff9a0e" size={22} /> <Badge> Linux </Badge>
    </span>
    <span>
      <Icon icon="windows" color="#0078d6" size={22} /> <Badge> Windows </Badge>
    </span>
    <span>
      <Icon icon="apple" color="#60ba47" size={22} /> <Badge> macOS </Badge>
    </span>
  </div>;

export const onChain = () => <span>
    <Icon icon="server" size={20} /> <strong>on-chain</strong>
  </span>;

export const offChain = () => <span>
    <Icon icon="floppy-disk" size={20} /> <strong>off-chain</strong>
  </span>;

export const dual = () => <Badge color="green">Dual-mode</Badge>;

export const ai = () => <Badge color="purple">AI</Badge>;

export const video = () => <Badge color="blue">Video</Badge>;

export const StyledStep = ({title, icon, titleSize = 'h3', iconColor = null, titleColor = null, children, className = '', style = {}, ...rest}) => {
  const styledTitle = titleColor ? <span style={{
    color: titleColor
  }}>{title}</span> : title;
  return <Step title={styledTitle} icon={icon} iconColor={iconColor || undefined} titleSize={titleSize} className={className} style={style} {...rest}>
      {children}
    </Step>;
};

export const StyledSteps = ({children, iconColor, titleColor, lineColor, iconSize = '24px', className = '', style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || 'var(--accent-dark, #18794E)';
  const resolvedTitleColor = titleColor || 'var(--lp-color-accent)';
  const resolvedLineColor = lineColor || 'var(--lp-color-accent)';
  return <div className={['docs-styled-steps', className].filter(Boolean).join(' ')} style={style} {...rest}>
      <style>{`
        .docs-styled-steps .steps > div > div.absolute > div {
          background-color: ${resolvedIconColor};
        }
        .docs-styled-steps .steps > div > div.w-full > p {
          color: ${resolvedTitleColor};
        }
        .docs-styled-steps .steps > div > div.absolute.w-px {
          background-color: ${resolvedLineColor};
        }
        .docs-styled-steps .steps > div:last-child > div.absolute.w-px::after {
          content: '';
          position: absolute;
          bottom: 0;
          left: 50%;
          transform: translateX(-50%);
          width: 6px;
          height: 6px;
          background-color: ${resolvedLineColor};
          transform: translateX(-50%) rotate(45deg);
        }
      `}</style>
      <div>
        <Steps>{children}</Steps>
      </div>
    </div>;
};

export const BorderedBox = ({children, variant = "default", padding = "var(--lp-spacing-4)", borderRadius = "var(--lp-spacing-px-8)", margin = "", accentBar = "", style = {}, className = "", ...rest}) => {
  const variants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    accent: {
      border: "1px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    muted: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "transparent"
    }
  };
  const accentBarColors = {
    accent: "var(--lp-color-accent)",
    positive: "var(--green-9)"
  };
  return <div data-docs-bordered-box="" data-accent-bar={accentBarColors[accentBar] ? "" : undefined} className={className} style={{
    ...variants[variant],
    padding: padding,
    borderRadius: borderRadius,
    ...margin ? {
      margin
    } : {},
    ...accentBarColors[accentBar] ? {
      position: "relative",
      '--accent-bar-color': accentBarColors[accentBar]
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

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>;
};

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

# <Icon icon="plug" size={26} /> Connect Your Gateway

Connect your Livepeer Gateway to Orchestrators and the network for {video()}, {ai()} Pipelines, or {dual()} service routing.

*This guide covers:*

* {offChain()} **manual connection** via `-orchAddr` (pin specific Orchestrators)
* {onChain()} **automatic discovery** via the Livepeer Network on Arbitrum
* **Verification** that Orchestrators are discovered and reachable
* **Service publication** to make the Gateway accessible to clients
* **Selection tuning** for price caps, performance scoring, and blocklists

<Tip>
  Complete the [Install](/v2/Gateways/setup/install) and [Configure](/v2/Gateways/setup/configure) steps before connecting. Once connected, proceed to [Verify](/v2/Gateways/setup/verify) to confirm end-to-end operation.
</Tip>

<CustomDivider />

<BorderedBox>
  <Tabs>
    <Tab title="Docker" icon="docker">
      ## <Icon icon="docker" iconType="solid" size={32} /> Docker Connection

      {dockerGroup()}

      <StyledSteps iconColor="var(--lp-color-accent-strong)" titleColor="var(--accent)" lineColor="var(--accent)" titleSize="h3">
        <StyledStep title="Connect to Orchestrators">
          Choose how the Gateway discovers Orchestrators based on your operational mode.

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              Off-chain Gateways connect to Orchestrators manually via the `-orchAddr` flag.

              Add the flag to your `docker-compose.yml` under the `command` section:

              ```yaml icon="docker" title="docker-compose.yml" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              command:
                - -gateway
                - -orchAddr=https://orch1.example.com:8935,https://orch2.example.com:8935
                - -httpAddr=0.0.0.0:8935
                - -rtmpAddr=0.0.0.0:1935
              ```

              The Gateway round-robins across the listed Orchestrators and does not discover others. This trades flexibility for predictability: you know exactly which Orchestrators handle jobs and can vet each one before adding it.

              **Finding AI-capable Orchestrators:**

              * [Livepeer Explorer AI Leaderboard](https://explorer.livepeer.org/leaderboard) for live performance data
              * [Livepeer Tools](https://tools.livepeer.cloud) for community dashboard with Orchestrator capabilities
              * The `/getNetworkCapabilities` endpoint on any on-chain Gateway, filtered by pipeline and model

              <Tip>
                For production AI workloads, pinning Orchestrators with `-orchAddr` is the recommended approach. It gives full control over which Orchestrators handle inference jobs.
              </Tip>
            </Tab>

            <Tab title="On-Chain" icon="link">
              On-chain Gateways discover Orchestrators automatically from the Livepeer Network on Arbitrum.

              Set the network and Ethereum RPC in your `docker-compose.yml`:

              ```yaml icon="docker" title="docker-compose.yml" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              command:
                - -gateway
                - -network=arbitrum-one-mainnet
                - -ethUrl=https://arb1.arbitrum.io/rpc
                - -ethKeystorePath=/root/.lpData/keystore
                - -httpAddr=0.0.0.0:8935
                - -rtmpAddr=0.0.0.0:1935
              ```

              The Gateway creates a `DBOrchestratorPoolCache` that:

              * Queries the BondingManager smart contract for all registered Orchestrators
              * Fetches their capabilities, pricing, and performance metrics
              * Updates the list every 25 minutes
              * Handles failures by trying alternative Orchestrators

              <Note>
                On-chain discovery requires ETH in the Gateway account for transactions. Without funds, the Gateway shows "No Orchestrator specified; transcoding will not happen".
              </Note>

              **For AI workloads on-chain**, add the `-aiServiceRegistry` flag to register with the [AIServiceRegistry](https://arbiscan.io/address/0x04C0b249740175999E5BF5c9ac1dA92431EF34C5) contract:

              ```yaml icon="docker" title="docker-compose.yml (AI registry)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              command:
                - -gateway
                - -network=arbitrum-one-mainnet
                - -ethUrl=https://arb1.arbitrum.io/rpc
                - -ethKeystorePath=/root/.lpData/keystore
                - -aiServiceRegistry
                - -httpAddr=0.0.0.0:8935
              ```

              This enables automatic Orchestrator discovery for AI workloads without maintaining a manual `-orchAddr` list.
            </Tab>
          </Tabs>
        </StyledStep>

        <StyledStep title="Verify Discovery">
          After starting the Gateway, confirm Orchestrators are discovered.

          **Check discovered Orchestrators:**

          ```bash icon="terminal" title="List Orchestrators" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl http://localhost:5935/getOrchestrators
          ```

          The response should list at least one Orchestrator with pricing information. An empty list means discovery has not completed or no Orchestrators match the price filters.

          **Check network capabilities (AI models and pipelines):**

          ```bash icon="terminal" title="Network Capabilities" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl http://localhost:8935/getNetworkCapabilities | python3 -m json.tool
          ```

          **Filter for a specific AI model:**

          ```bash icon="terminal" title="Filter by Model" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl -s http://localhost:8935/getNetworkCapabilities | \
            jq '.orchestrators[] | select(.capabilities_prices[].model_id == "ByteDance/SDXL-Lightning")'
          ```

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              <Warning>
                If no Orchestrators appear, verify each `-orchAddr` URL is reachable:

                ```bash icon="terminal" title="Test Orchestrator Reachability" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
                curl https://orch.example.com:8935/getOrchestratorInfo
                ```
              </Warning>
            </Tab>

            <Tab title="On-Chain" icon="link">
              <Warning>
                If no Orchestrators appear after 2 minutes, check container logs for Ethereum connection errors:

                ```bash icon="terminal" title="Check Gateway Logs" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
                docker logs <container_name> --tail 50
                ```
              </Warning>
            </Tab>
          </Tabs>
        </StyledStep>

        <StyledStep title="Service Publication">
          To make the Gateway reachable by external clients and applications, configure the advertised service address.

          ```yaml icon="docker" title="docker-compose.yml" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          command:
            - -gateway
            - -serviceAddr=gateway.example.com:8935
            - -gatewayHost=gateway.example.com
          ```

          * `-serviceAddr` is the address the Gateway advertises to Orchestrators and clients
          * `-gatewayHost` is the external hostname used in API responses

          For a public Gateway, this must be an externally resolvable DNS name, not `localhost` or an internal IP.

          <Note>
            **Video Gateways:** `-serviceAddr` is the address Orchestrators use to report transcoded results back. It must be publicly reachable on port 8935.

            **AI Gateways:** register on-chain with `-aiServiceRegistry` for automatic discovery by AI Orchestrators.
          </Note>

          **DNS setup:**

          Point a subdomain at the Gateway server's public IP:

          ```txt icon="wrench" title="DNS Record" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          ai-gateway.yourdomain.com.   A   <server-ip>
          ```

          External clients must reach the Gateway over HTTPS. Set up TLS termination via a reverse proxy (Caddy, Nginx, or a cloud load balancer) before the service port.
        </StyledStep>

        <StyledStep title="Tune Selection">
          The default selection algorithm works out of the box. For production workloads, these flags give more control.

          **Performance scoring:**

          ```yaml icon="docker" title="docker-compose.yml (scoring)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          command:
            - -orchPerfStatsUrl=https://leaderboard.livepeer.org/api/aggregated_stats
            - -minPerfScore=0.8
          ```

          Excludes Orchestrators below the minimum score. Scores come from live transcoding tests on the community leaderboard.

          **Price caps:**

          ```yaml icon="docker" title="docker-compose.yml (price caps)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          command:
            # Video
            - -maxPricePerUnit=5000
            # AI (per-capability)
            - -maxPricePerCapability=[{"pipeline":"text-to-image","model_id":"black-forest-labs/FLUX.1-dev","price_per_unit":100,"pixels_per_unit":1000000}]
          ```

          **Blocklist:**

          ```yaml icon="docker" title="docker-compose.yml (blocklist)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          command:
            - -orchBlocklist=0xAbCd1234...,0xEfGh5678...
          ```

          Excludes specific Orchestrators from all routing.

          <Card title="Orchestrator Selection Guide" icon="sliders" href="/v2/gateways/guides/advanced-operations/orchestrator-selection" horizontal arrow>
            Full guide to scoring weights, tiering strategies, and failover configuration.
          </Card>
        </StyledStep>
      </StyledSteps>

      <Card title="Next: Verify your Gateway" icon="circle-check" href="/v2/gateways/setup/verify" horizontal arrow>
        Run health checks and end-to-end tests to confirm the Gateway is routing jobs.
      </Card>
    </Tab>

    <Tab title="Linux" icon="linux">
      ## <Icon icon="linux" iconType="solid" size={32} /> Linux Connection

      {linuxGroup()}

      <StyledSteps iconColor="var(--lp-color-accent-strong)" titleColor="var(--accent)" lineColor="var(--accent)" titleSize="h3">
        <StyledStep title="Connect to Orchestrators">
          Choose how the Gateway discovers Orchestrators based on your operational mode.

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              Off-chain Gateways connect to Orchestrators manually via the `-orchAddr` flag.

              Add the flag to your startup command:

              ```bash icon="terminal" title="Off-Chain Startup" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              livepeer \
                -gateway \
                -orchAddr https://orch1.example.com:8935,https://orch2.example.com:8935 \
                -httpAddr 0.0.0.0:8935 \
                -rtmpAddr 0.0.0.0:1935
              ```

              The Gateway round-robins across the listed Orchestrators and does not discover others. This trades flexibility for predictability: you know exactly which Orchestrators handle jobs and can vet each one before adding it.

              **Finding AI-capable Orchestrators:**

              * [Livepeer Explorer AI Leaderboard](https://explorer.livepeer.org/leaderboard) for live performance data
              * [Livepeer Tools](https://tools.livepeer.cloud) for community dashboard with Orchestrator capabilities
              * The `/getNetworkCapabilities` endpoint on any on-chain Gateway, filtered by pipeline and model

              <Tip>
                For production AI workloads, pinning Orchestrators with `-orchAddr` is the recommended approach. It gives full control over which Orchestrators handle inference jobs.
              </Tip>
            </Tab>

            <Tab title="On-Chain" icon="link">
              On-chain Gateways discover Orchestrators automatically from the Livepeer Network on Arbitrum.

              Set the network and Ethereum RPC in your startup command:

              ```bash icon="terminal" title="On-Chain Startup" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              livepeer \
                -gateway \
                -network arbitrum-one-mainnet \
                -ethUrl https://arb1.arbitrum.io/rpc \
                -ethKeystorePath ~/.lpData/keystore \
                -httpAddr 0.0.0.0:8935 \
                -rtmpAddr 0.0.0.0:1935
              ```

              The Gateway creates a `DBOrchestratorPoolCache` that:

              * Queries the BondingManager smart contract for all registered Orchestrators
              * Fetches their capabilities, pricing, and performance metrics
              * Updates the list every 25 minutes
              * Handles failures by trying alternative Orchestrators

              <Note>
                On-chain discovery requires ETH in the Gateway account for transactions. Without funds, the Gateway shows "No Orchestrator specified; transcoding will not happen".
              </Note>

              **For AI workloads on-chain**, add the `-aiServiceRegistry` flag to register with the [AIServiceRegistry](https://arbiscan.io/address/0x04C0b249740175999E5BF5c9ac1dA92431EF34C5) contract:

              ```bash icon="terminal" title="On-Chain with AI Registry" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              livepeer \
                -gateway \
                -network arbitrum-one-mainnet \
                -ethUrl https://arb1.arbitrum.io/rpc \
                -ethKeystorePath ~/.lpData/keystore \
                -aiServiceRegistry \
                -httpAddr 0.0.0.0:8935
              ```

              This enables automatic Orchestrator discovery for AI workloads without maintaining a manual `-orchAddr` list.
            </Tab>
          </Tabs>
        </StyledStep>

        <StyledStep title="Verify Discovery">
          After starting the Gateway, confirm Orchestrators are discovered.

          **Check discovered Orchestrators:**

          ```bash icon="terminal" title="List Orchestrators" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl http://localhost:5935/getOrchestrators
          ```

          The response should list at least one Orchestrator with pricing information. An empty list means discovery has not completed or no Orchestrators match the price filters.

          **Check network capabilities (AI models and pipelines):**

          ```bash icon="terminal" title="Network Capabilities" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl http://localhost:8935/getNetworkCapabilities | python3 -m json.tool
          ```

          **Filter for a specific AI model:**

          ```bash icon="terminal" title="Filter by Model" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl -s http://localhost:8935/getNetworkCapabilities | \
            jq '.orchestrators[] | select(.capabilities_prices[].model_id == "ByteDance/SDXL-Lightning")'
          ```

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              <Warning>
                If no Orchestrators appear, verify each `-orchAddr` URL is reachable:

                ```bash icon="terminal" title="Test Orchestrator Reachability" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
                curl https://orch.example.com:8935/getOrchestratorInfo
                ```
              </Warning>
            </Tab>

            <Tab title="On-Chain" icon="link">
              <Warning>
                If no Orchestrators appear after 2 minutes, check process logs for Ethereum connection errors:

                ```bash icon="terminal" title="Check Gateway Logs" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
                journalctl -u livepeer --tail 50
                ```
              </Warning>
            </Tab>
          </Tabs>
        </StyledStep>

        <StyledStep title="Service Publication">
          To make the Gateway reachable by external clients and applications, configure the advertised service address.

          ```bash icon="terminal" title="Service Address Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          livepeer \
            -gateway \
            -serviceAddr gateway.example.com:8935 \
            -gatewayHost gateway.example.com \
            ...
          ```

          * `-serviceAddr` is the address the Gateway advertises to Orchestrators and clients
          * `-gatewayHost` is the external hostname used in API responses

          For a public Gateway, this must be an externally resolvable DNS name, not `localhost` or an internal IP.

          <Note>
            **Video Gateways:** `-serviceAddr` is the address Orchestrators use to report transcoded results back. It must be publicly reachable on port 8935. If behind NAT, configure port forwarding.

            **AI Gateways:** register on-chain with `-aiServiceRegistry` for automatic discovery by AI Orchestrators.
          </Note>

          **DNS setup:**

          Point a subdomain at the Gateway server's public IP:

          ```txt icon="wrench" title="DNS Record" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          ai-gateway.yourdomain.com.   A   <server-ip>
          ```

          External clients must reach the Gateway over HTTPS. Set up TLS termination via a reverse proxy (Caddy, Nginx, or a cloud load balancer) before the service port.

          **systemd service file example:**

          If running as a systemd service, add the flags to the `ExecStart` line:

          ```ini icon="cog" title="livepeer.service" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          [Service]
          ExecStart=/usr/local/bin/livepeer \
            -gateway \
            -serviceAddr gateway.example.com:8935 \
            -gatewayHost gateway.example.com \
            -network arbitrum-one-mainnet \
            -ethUrl https://arb1.arbitrum.io/rpc \
            -ethKeystorePath /home/livepeer/.lpData/keystore \
            -httpAddr 0.0.0.0:8935
          ```
        </StyledStep>

        <StyledStep title="Tune Selection">
          The default selection algorithm works out of the box. For production workloads, these flags give more control.

          **Performance scoring:**

          ```bash icon="terminal" title="Performance Scoring Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          livepeer \
            -gateway \
            -orchPerfStatsUrl https://leaderboard.livepeer.org/api/aggregated_stats \
            -minPerfScore 0.8 \
            ...
          ```

          Excludes Orchestrators below the minimum score. Scores come from live transcoding tests on the community leaderboard.

          **Price caps:**

          ```bash icon="terminal" title="Price Cap Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          # Video
          -maxPricePerUnit 5000

          # AI (per-capability)
          -maxPricePerCapability '[{"pipeline":"text-to-image","model_id":"black-forest-labs/FLUX.1-dev","price_per_unit":100,"pixels_per_unit":1000000}]'
          ```

          **Blocklist:**

          ```bash icon="terminal" title="Blocklist Flag" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          -orchBlocklist 0xAbCd1234...,0xEfGh5678...
          ```

          Excludes specific Orchestrators from all routing.

          <Card title="Orchestrator Selection Guide" icon="sliders" href="/v2/gateways/guides/advanced-operations/orchestrator-selection" horizontal arrow>
            Full guide to scoring weights, tiering strategies, and failover configuration.
          </Card>
        </StyledStep>
      </StyledSteps>

      <Card title="Next: Verify your Gateway" icon="circle-check" href="/v2/gateways/setup/verify" horizontal arrow>
        Run health checks and end-to-end tests to confirm the Gateway is routing jobs.
      </Card>
    </Tab>

    <Tab title="Windows" icon="windows">
      ## <Icon icon="windows" iconType="solid" size={32} /> Windows Connection

      {windowsGroup()}

      <StyledSteps iconColor="var(--lp-color-accent-strong)" titleColor="var(--accent)" lineColor="var(--accent)" titleSize="h3">
        <StyledStep title="Connect to Orchestrators">
          Choose how the Gateway discovers Orchestrators based on your operational mode.

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              Off-chain Gateways connect to Orchestrators manually via the `-orchAddr` flag.

              Add the flag to your startup command in PowerShell:

              ```powershell icon="terminal" title="Off-Chain Startup" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              .\livepeer.exe `
                -gateway `
                -orchAddr https://orch1.example.com:8935,https://orch2.example.com:8935 `
                -httpAddr 0.0.0.0:8935 `
                -rtmpAddr 0.0.0.0:1935
              ```

              The Gateway round-robins across the listed Orchestrators and does not discover others. This trades flexibility for predictability: you know exactly which Orchestrators handle jobs and can vet each one before adding it.

              **Finding AI-capable Orchestrators:**

              * [Livepeer Explorer AI Leaderboard](https://explorer.livepeer.org/leaderboard) for live performance data
              * [Livepeer Tools](https://tools.livepeer.cloud) for community dashboard with Orchestrator capabilities
              * The `/getNetworkCapabilities` endpoint on any on-chain Gateway, filtered by pipeline and model

              <Tip>
                For production AI workloads, pinning Orchestrators with `-orchAddr` is the recommended approach. It gives full control over which Orchestrators handle inference jobs.
              </Tip>
            </Tab>

            <Tab title="On-Chain" icon="link">
              On-chain Gateways discover Orchestrators automatically from the Livepeer Network on Arbitrum.

              Set the network and Ethereum RPC in your startup command:

              ```powershell icon="terminal" title="On-Chain Startup" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              .\livepeer.exe `
                -gateway `
                -network arbitrum-one-mainnet `
                -ethUrl https://arb1.arbitrum.io/rpc `
                -ethKeystorePath C:\Users\<user>\.lpData\keystore `
                -httpAddr 0.0.0.0:8935 `
                -rtmpAddr 0.0.0.0:1935
              ```

              The Gateway creates a `DBOrchestratorPoolCache` that:

              * Queries the BondingManager smart contract for all registered Orchestrators
              * Fetches their capabilities, pricing, and performance metrics
              * Updates the list every 25 minutes
              * Handles failures by trying alternative Orchestrators

              <Note>
                On-chain discovery requires ETH in the Gateway account for transactions. Without funds, the Gateway shows "No Orchestrator specified; transcoding will not happen".
              </Note>

              **For AI workloads on-chain**, add the `-aiServiceRegistry` flag to register with the [AIServiceRegistry](https://arbiscan.io/address/0x04C0b249740175999E5BF5c9ac1dA92431EF34C5) contract:

              ```powershell icon="terminal" title="On-Chain with AI Registry" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              .\livepeer.exe `
                -gateway `
                -network arbitrum-one-mainnet `
                -ethUrl https://arb1.arbitrum.io/rpc `
                -ethKeystorePath C:\Users\<user>\.lpData\keystore `
                -aiServiceRegistry `
                -httpAddr 0.0.0.0:8935
              ```

              This enables automatic Orchestrator discovery for AI workloads without maintaining a manual `-orchAddr` list.
            </Tab>
          </Tabs>
        </StyledStep>

        <StyledStep title="Verify Discovery">
          After starting the Gateway, confirm Orchestrators are discovered.

          **Check discovered Orchestrators:**

          <Tabs>
            <Tab title="Off-Chain" icon="floppy-disk">
              ```powershell icon="terminal" title="List Orchestrators (PowerShell)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              Invoke-WebRequest -Uri http://localhost:5935/getOrchestrators | Select-Object -ExpandProperty Content
              ```

              Or using `curl.exe`:

              ```powershell icon="terminal" title="List Orchestrators (curl)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              curl.exe http://localhost:5935/getOrchestrators
              ```

              <Warning>
                If no Orchestrators appear, verify each `-orchAddr` URL is reachable:

                ```powershell icon="terminal" title="Test Orchestrator Reachability" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
                curl.exe https://orch.example.com:8935/getOrchestratorInfo
                ```
              </Warning>
            </Tab>

            <Tab title="On-Chain" icon="link">
              ```powershell icon="terminal" title="List Orchestrators (PowerShell)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              Invoke-WebRequest -Uri http://localhost:5935/getOrchestrators | Select-Object -ExpandProperty Content
              ```

              Or using `curl.exe`:

              ```powershell icon="terminal" title="List Orchestrators (curl)" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
              curl.exe http://localhost:5935/getOrchestrators
              ```

              <Warning>
                If no Orchestrators appear after 2 minutes:

                * Check the terminal output for Ethereum connection errors
                * Ensure Windows Firewall allows inbound/outbound on ports 8935 and 1935
              </Warning>
            </Tab>
          </Tabs>

          The response should list at least one Orchestrator with pricing information. An empty list means discovery has not completed or no Orchestrators match the price filters.

          **Check network capabilities (AI models and pipelines):**

          ```powershell icon="terminal" title="Network Capabilities" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          curl.exe http://localhost:8935/getNetworkCapabilities
          ```

          This returns all discovered Orchestrators with their supported models, pricing, and hardware specifications.
        </StyledStep>

        <StyledStep title="Service Publication">
          To make the Gateway reachable by external clients and applications, configure the advertised service address.

          ```powershell icon="terminal" title="Service Address Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          .\livepeer.exe `
            -gateway `
            -serviceAddr gateway.example.com:8935 `
            -gatewayHost gateway.example.com `
            ...
          ```

          * `-serviceAddr` is the address the Gateway advertises to Orchestrators and clients
          * `-gatewayHost` is the external hostname used in API responses

          For a public Gateway, this must be an externally resolvable DNS name, not `localhost` or an internal IP.

          <Note>
            **Video Gateways:** `-serviceAddr` is the address Orchestrators use to report transcoded results back. It must be publicly reachable on port 8935. Configure Windows Firewall to allow inbound traffic on this port.

            **AI Gateways:** register on-chain with `-aiServiceRegistry` for automatic discovery by AI Orchestrators.
          </Note>

          **DNS setup:**

          Point a subdomain at the Gateway server's public IP:

          ```txt icon="wrench" title="DNS Record" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          ai-gateway.yourdomain.com.   A   <server-ip>
          ```

          External clients must reach the Gateway over HTTPS. Set up TLS termination via a reverse proxy before the service port.

          <Warning>
            Windows is suitable for development and testing. For production deployments, Linux or Docker is recommended due to better performance, stability, and GPU driver compatibility.
          </Warning>
        </StyledStep>

        <StyledStep title="Tune Selection">
          The default selection algorithm works out of the box. For production workloads, these flags give more control.

          **Performance scoring:**

          ```powershell icon="terminal" title="Performance Scoring Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          .\livepeer.exe `
            -gateway `
            -orchPerfStatsUrl https://leaderboard.livepeer.org/api/aggregated_stats `
            -minPerfScore 0.8 `
            ...
          ```

          Excludes Orchestrators below the minimum score. Scores come from live transcoding tests on the community leaderboard.

          **Price caps:**

          ```powershell icon="terminal" title="Price Cap Flags" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          # Video
          -maxPricePerUnit 5000

          # AI (per-capability)
          -maxPricePerCapability '[{\"pipeline\":\"text-to-image\",\"model_id\":\"black-forest-labs/FLUX.1-dev\",\"price_per_unit\":100,\"pixels_per_unit\":1000000}]'
          ```

          **Blocklist:**

          ```powershell icon="terminal" title="Blocklist Flag" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
          -orchBlocklist 0xAbCd1234...,0xEfGh5678...
          ```

          Excludes specific Orchestrators from all routing.

          <Card title="Orchestrator Selection Guide" icon="sliders" href="/v2/gateways/guides/advanced-operations/orchestrator-selection" horizontal arrow>
            Full guide to scoring weights, tiering strategies, and failover configuration.
          </Card>
        </StyledStep>
      </StyledSteps>

      <Card title="Next: Verify your Gateway" icon="circle-check" href="/v2/gateways/setup/verify" horizontal arrow>
        Run health checks and end-to-end tests to confirm the Gateway is routing jobs.
      </Card>
    </Tab>
  </Tabs>
</BorderedBox>

<CustomDivider />

## Orchestrator Discovery Overview

Gateways discover Orchestrators through two mechanisms, depending on the operational mode.

<Tabs>
  <Tab title="Off-chain (manual)" icon="floppy-disk">
    Off-chain Gateways use a static list of known Orchestrators passed via `-orchAddr`. The Gateway round-robins across this list and does not discover others.

    This is the recommended approach for:

    * Production AI workloads where you need control over which Orchestrators handle inference
    * Private deployments that do not interact with the public network
    * Testing environments with a known Orchestrator

    To update the list, restart the Gateway with a modified `-orchAddr` value. For dynamic updates without restarts, use `-orchWebhookUrl` instead.
  </Tab>

  <Tab title="On-chain (automatic)" icon="link">
    On-chain Gateways discover Orchestrators automatically by querying the BondingManager smart contract on Arbitrum. The Gateway:

    1. Queries all registered Orchestrators from the contract
    2. Fetches capabilities, pricing, and performance metrics from each
    3. Filters by price limits (`-maxPricePerUnit`, `-maxPricePerCapability`)
    4. Scores candidates using stake, price, and randomness weights
    5. Updates the pool every 25 minutes

    This requires an Arbitrum RPC connection (`-ethUrl`) and ETH in the Gateway account for transactions.

    For AI workloads, add `-aiServiceRegistry` to register with the on-chain AI service registry and enable automatic AI Orchestrator discovery.
  </Tab>
</Tabs>

<CustomDivider />

## Related Pages

<CardGroup cols={2}>
  <Card title="Orchestrator Selection" icon="sliders" href="/v2/gateways/guides/advanced-operations/orchestrator-selection">
    Scoring weights, tiering strategies, failover, and blocklists.
  </Card>

  <Card title="Gateway Discoverability" icon="satellite-dish" href="/v2/gateways/guides/advanced-operations/gateway-discoverability">
    DNS, HTTPS, capability advertising, and on-chain registration.
  </Card>

  <Card title="Marketplace Overview" icon="store" href="/v2/gateways/setup/connect/lp-marketplace">
    How Orchestrators publish offerings and Gateways discover them.
  </Card>

  <Card title="Configuration Flags" icon="book" href="/v2/gateways/resources/reference/technical/configuration-flags">
    Full reference for all Gateway configuration flags.
  </Card>
</CardGroup>
