> For the complete documentation index, see [llms.txt](https://docs.eyepop.ai/developer-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.eyepop.ai/developer-documentation/deployment/eyepop-on-premise-ai-runtime/qualcomm-dragonwing-qnn.md).

# Qualcomm Dragonwing (QNN)

{% hint style="warning" %}
**Early access.** Validated only on the **Innodisk EXEC-Q911**. Support for other QNN-capable Dragonwing devices is planned; these steps are device-specific for now.
{% endhint %}

## Dragonwing Runtime

Run the EyePop runtime on a Qualcomm Dragonwing device with Docker, accelerated by the on-device NPU through the Qualcomm AI Runtime (QAIRT) via the QNN execution provider.

Validated device: [Innodisk EXEC-Q911](https://www.innodisk.com/en/products/computing/qualcomm-solution/exec-q911).

### Requirements

* [Innodisk EXEC-Q911](https://www.innodisk.com/en/products/computing/qualcomm-solution/exec-q911) (or a compatible Dragonwing device)
* An **Innodisk-provided Ubuntu image** flashed to the device — use it rather than the stock Qualcomm image so all IO keeps working (see [iQ-Studio](https://github.com/InnoIPA/iQ-Studio) for flashing/boot guides)
* Docker
* **Qualcomm AI Runtime (QAIRT) SDK** installed on the device (see [Prepare The Device](#0-prepare-the-device-qairt))
* EyePop dashboard access

### 0. Prepare The Device (QAIRT)

The runtime needs a **preinstalled QAIRT SDK** on the host. Use Innodisk's [iQ-Studio](https://github.com/InnoIPA/iQ-Studio) to boot the device and provision the BSP:

```sh
git clone https://github.com/InnoIPA/iQ-Studio.git
cd iQ-Studio && ./install.sh
```

Apply the new group membership without logging out:

```sh
newgrp docker
```

Point `QAIRT_SDK_ROOT` at your QAIRT install — the runtime mounts it into the container. Confirm the `lib/` tree exists (paths vary by QAIRT version and Hexagon target):

```sh
export QAIRT_SDK_ROOT=/opt/qcom/aistack/qairt/<version>
ls "$QAIRT_SDK_ROOT/lib/hexagon-v73/unsigned"
```

### 1. Get The Server Files From The Dashboard

Open `https://dashboard.eyepop.ai`, go to **My Servers**, and click **Add Server**. The dashboard provides `eyepop-instance.yml` and a Docker registry login command.

Save `eyepop-instance.yml` on the device (for example `~/eyepop/eyepop-instance.yml`). It looks like:

```yaml
eyepop-account-uuid: <your EyePop account UUID>
eyepop-api-key: <your EyePop API key>
instance-name: <your server name>
```

Make it readable by Docker:

```sh
chmod 644 eyepop-instance.yml
```

### 2. Log In To The Registry

Run the dashboard's Docker login command on the device:

```sh
printf '%s' '<registry key secret>' | docker login registry.eyepop.ai \
  -u '<registry key username>' \
  --password-stdin
```

The registry key secret is sensitive — keep it out of support tickets and logs.

### 3. Start The Runtime

From the directory containing `eyepop-instance.yml`:

```sh
docker run -d \
  --name eyepop-runtime \
  --restart unless-stopped \
  --privileged \
  --device /dev:/dev \
  -p 8080:8080 \
  --group-add "$(getent group fastrpc | cut -d: -f3)" \
  --group-add "$(getent group dmaheap | cut -d: -f3)" \
  -e ADSP_LIBRARY_PATH=/opt/qairt/lib/hexagon-v73/unsigned \
  -e LD_LIBRARY_PATH=/lib:/lib/aarch64-linux-gnu:/opt/qairt/lib/aarch64-oe-linux-gcc11.2:/lib.host:/lib.host/aarch64-linux-gnu \
  -v "$QAIRT_SDK_ROOT:/opt/qairt:ro" \
  -v /usr/lib:/lib.host:ro \
  -v "$PWD/eyepop-instance.yml:/etc/eyepop-instance.yml:ro" \
  registry.eyepop.ai/ai/runtime-qnn:latest
```

The device flags let the non-root runtime reach the Hexagon NPU: `--privileged`/`--device` expose the devices, the `fastrpc` and `dmaheap` host group IDs are resolved at run time, and QAIRT plus host libraries are mounted read-only at `/opt/qairt` and `/lib.host`. The `ADSP_LIBRARY_PATH`/`LD_LIBRARY_PATH` values match the EXEC-Q911 — adjust them if your QAIRT layout or Hexagon version differs.

### 4. Verify

```sh
curl http://127.0.0.1:8080/health   # health
curl http://127.0.0.1:8080/ready    # readiness
docker logs -f eyepop-runtime       # logs
```

First start takes a minute while the runtime registers; the first model run is slower while the model downloads and caches.

### Stop Or Update

```sh
docker stop eyepop-runtime && docker rm eyepop-runtime
```

To update, pull a newer tag and re-run step 3:

```sh
docker pull registry.eyepop.ai/ai/runtime-qnn:<tag>
```
