---
title: "Distributed installation"
description: "Run DrowAI Management and Runner services on separate Linux hosts."
section: "Setup"
updated: 2026-07-10
tags: ["installation","setup","docker","runner","distributed"]
source: "/user-guide/distributed-installation"
---

# Distributed installation

Run DrowAI Management and Runner services on separate Linux hosts.

Distributed uses two Linux hosts:

- The **Management host** runs PostgreSQL, the API, and the web UI.
- The **Runner host** runs the Runner and all Kali task containers.

The Runner makes an outbound connection to Management. Management does not need
Docker access to the Runner host and does not provide a local execution
fallback.

## 1. Start Management

On the Management host:

```bash
git clone https://github.com/quareth/drowAI.git
cd drowAI
docker compose --project-directory . \
  -f deploy/cloud/control-plane.yml \
  up -d --build
```

Check the services:

```bash
docker compose --project-directory . \
  -f deploy/cloud/control-plane.yml \
  ps
```

By default, the Distributed web UI is available at:

```text
http://<management-address>
```

Allow Runner hosts and operator browsers to reach the Management web port. The
default is HTTP port `80`; use HTTPS port `443` when you place Management behind
a trusted TLS reverse proxy. PostgreSQL port `5432` and the direct backend port
`8000` are not the product-facing Runner endpoint and should not be exposed to
untrusted networks.

## 2. Complete Management setup

Open the Management URL. On a fresh installation, DrowAI opens the setup wizard
automatically. If the wizard does not open, go to:

```text
http://<management-address>/setup
```

The wizard asks for:

- The database password DrowAI should use after bootstrap.
- The initial administrator username, email, and password.
- The display timezone.
- The name of the default Runner Site.

Configure an AI provider and model after signing in under **Settings -> API**.

Distributed setup creates the default Runner Site record, but no Runner is
bundled with Management. A waiting status is expected until the Runner package
is installed on the second host.

## 3. Confirm the Management URL

Go to **Settings -> Runner Sites**. Confirm that **Management URL** is the
browser-facing origin that the Runner host can reach, for example:

```text
http://192.168.50.130
https://drowai.example.com
http://management.example.test:8080
```

From the Runner host, verify reachability before downloading the package:

```bash
curl -f http://<management-address>/api/health
```

## 4. Download the Runner package

In **Settings -> Runner Sites**, find the default site created by setup and
select its **Download Package** button.

Do not select **Create New Runner Site Package** for the first Runner. That
action is only for adding a separate Runner Site. Reusing the existing site's
download button avoids duplicate sites.

The archive contains one-time enrollment material. Treat it as sensitive, do
not commit it to source control, and move it to the Runner host promptly. If the
enrollment expires or has already been used, download a fresh package from the
same Runner Site.

For example, from the computer where the browser saved the package:

```bash
scp drowai-runner-site-*.tar.gz <runner-user>@<runner-address>:~
```

## 5. Start the Runner

On the Runner host, in the directory containing the downloaded archive:

```bash
tar xzf drowai-runner-site-*.tar.gz
cd drowai-runner-site
docker compose up -d --build
```

The package builds the Runner image, publishes the packaged enrollment into its
active configuration, exchanges the one-time enrollment for durable Runner
credentials, and connects to Management. The correct Kali runtime image is
selected for the Runner host's CPU architecture and is pulled when needed.

Check the Runner:

```bash
docker compose ps
docker compose logs runner --tail=200
```

## 6. Verify end-to-end execution

Return to **Settings -> Runner Sites** in Management. The site should show one
registered Runner and then **Ready 1/1** when its live connection is available.

Create and start a small test task. On the Runner host, confirm that the task
container appears alongside `drowai-runner`:

```bash
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
```

The task container must appear on the Runner host, not the Management host.
This confirms that task runtime work is using the required Runner path.

## Stop or update Distributed

On the Management host, stop without deleting data:

```bash
docker compose --project-directory . \
  -f deploy/cloud/control-plane.yml \
  down
```

On the Runner host:

```bash
cd drowai-runner-site
docker compose down
```

To update Management, pull the new repository version and run the Management
`up -d --build` command again. Generate a fresh Runner package from Management
when the Runner software changes, then replace the extracted package directory
on the Runner host and rebuild it.

## Reset a Runner host completely

Ordinary container recreation keeps durable Runner credentials under
`/var/lib/drowai`. This is intentional. Removing containers or Docker volumes
alone does not erase those credentials.

To intentionally enroll the host from scratch, stop the package and delete its
persistent Runner state:

```bash
cd drowai-runner-site
docker compose down --remove-orphans
cd ..
sudo rm -rf /var/lib/drowai
rm -rf drowai-runner-site
```

Then download a **fresh** package for the intended Runner Site, extract it, and
start it again. Do not reuse a package whose one-time enrollment was already
consumed.

## Reset Management completely

This permanently deletes Management's database, generated secrets, users,
setup state, and Runner Site records:

```bash
docker compose --project-directory . \
  -f deploy/cloud/control-plane.yml \
  down --volumes --remove-orphans
```

Reset each Runner host separately before enrolling it into the new Management
installation. Old durable Runner credentials belong to the deleted Management
database and cannot register with the replacement installation.
