# Installation modes

### Possible installation modes

The solution may be used two different ways:

* As a fully local solution
* As a distributed solution

The product is constituted of three elements:

* The server: it is unique and is necessary to make everything work together.
* The runners: they may be on the same machine as the server or not, they may be native or dockerized. They are required to run beLow's jobs in the contexts that you need: building your code, analysing your code, running your code, etc.
* The user interface (UI)

***

### Local solution

With this solution, everything is running on your machine and remains on your machine, except for authentication and licensing verification. Installing and running the local solution is very simple. Just follow the requirements and installation instructions for Linux or Windows, and the Getting started guide.

![Local solution scheme](/files/a45503a8a65937deb6f68d09074baf6db180ac79)

***

### Distributed solution

This solution allows you to run the server, runners and UI on different machines of the same network.

![Distributed solution scheme](/files/de002a55d4196111afc94add42452a79ad1e3a20)

In this section, we give the details on how to run the different required services on 3 machines, and make them work together:

* Server machine: hosts the central server part of the solution and exposes public APIs
* Runner machine: hosts a native runner
* UI machine: hosts the UI

For all three machines, make sure that you install everything that is needed on Linux or Windows. For what is next, we suppose that everything is correctly installed. If any command listed in this guide is not available in your terminal, please check your installation or contact WedoLow's support.

### Run the server

The server machine must be exposed to your users on their network. First decide the public endpoint for this server (numerical IP or DNS). Example used below: below-server.mycompany.org. We strongly advise protecting the server with HTTPS and using a reverse proxy to expose beLow server.

Create the following file if it does not exist yet:

{% tabs %}
{% tab title="Linux" %}

```bash
${HOME}/.config/wedolow/config.json
```

{% endtab %}

{% tab title="Windows" %}

```batch
%userprofile%\AppData\wedolow\config.json
```

{% endtab %}
{% endtabs %}

Fill this file with the following information (set `insecure` to `true` if you are using HTTP):

{% code title="config.json" %}

```json
{
    "core": {
        "s3": {
            "public_endpoint": "below-server.mycompany.org:19080",
            "insecure": false
        }
    }
}
```

{% endcode %}

{% tabs %}
{% tab title="Linux" %}
{% hint style="info" %}
To get current server configuration, run the following command:

```
belowctl-headless print-config
```

Any value of this configuration can be overriden in `config.json`file.
{% endhint %}
{% endtab %}

{% tab title="Windows" %}
{% hint style="info" %}
To get current server configuration, run the following command:

```
belowctl-headless-cli.exe print-config
```

Any value of this configuration can be overriden in `config.json`file.
{% endhint %}
{% endtab %}
{% endtabs %}

Once configured, you may now start the server. Docker service must be running and accessible:

{% tabs %}
{% tab title="Linux" %}

```
belowctl-headless server start
```

or to start in detached mode:

```
belowctl-headless server start -d
```

{% endtab %}

{% tab title="Windows" %}

```
belowctl-headless-cli.exe server start
```

or to start in detached mode:

```
belowctl-headless-cli.exe server start -d
```

{% endtab %}
{% endtabs %}

To check if server is running, run:

{% tabs %}
{% tab title="Linux" %}

```
belowctl-headless server status
```

{% endtab %}

{% tab title="Windows" %}

```
belowctl-headless-cli.exe server status
```

{% endtab %}
{% endtabs %}

which returns:

```json
{
  "state": "Running",
  "details": {
    "core": {
      "state": "Running",
      "docker_status": "Up 2 minutes (healthy)",
      "docker_state": "running"
    },
    "gateway": {
      "state": "Running",
      "docker_status": "Up 2 minutes",
      "docker_state": "running"
    },
    "minio": {
      "state": "Running",
      "docker_status": "Up 2 minutes (healthy)",
      "docker_state": "running"
    },
    "postgres": {
      "state": "Running",
      "docker_status": "Up 2 minutes (healthy)",
      "docker_state": "running"
    }
  }
}
```

To check if your server is accessible from a distant machine, you may try to contact the health endpoint from the main public API (to be adapted to your http scheme):

```bash
curl https://below-server.mycompany.org:18080/core/health
```

This should succeed with this kind of response:

```json
{
  "is_running": true,
  "build_information": {
    "date": "2024-11-22T09:44:43+0000",
    "git_hash": "21e87879b46995ac80b46c95765b974195bcd7f5",
    "version": "v1.5.5"
  },
  "services": [
    {
      "is_running": true,
      "name": "core"
    }
  ]
}
```

{% hint style="info" %}
Server services are run as Docker containers. Depending on your Docker configuration, services will continue to be available and running even after a reboot as long as you don't stop the server.
{% endhint %}

To stop the server, for instance for an update, run:

{% tabs %}
{% tab title="Linux" %}

```
belowctl-headless server stop
```

{% endtab %}

{% tab title="Windows" %}

```
belowctl-headless-cli.exe server stop
```

{% endtab %}
{% endtabs %}

### Add a runner

Runners are necessary to run jobs. There should at least be one declared and running in the whole system.

To register a runner, a token must be generated on the server machine by an administrator.

To do this, **on the server machine**, run the following command:

{% tabs %}
{% tab title="Linux" %}

```
belowctl-headless server get-registration-token --description "My first runner"
```

{% endtab %}

{% tab title="Windows" %}

```
belowctl-headless-cli.exe server get-registration-token --description "My first runner"
```

{% endtab %}
{% endtabs %}

This returns a token in the following form:

```json
{"token": "123XY"}
```

Remember this token.

**Get back to the runner machine**, where you must now configure, register and run the runner.

Create a directory where you want, e.g. called `below-runner` .

Inside this directory, create a file called `config.json` , with the following content:

{% tabs %}
{% tab title="Linux" %}

```json
{
  "version": "1.0.0",
  "dev_mode": false,
  "runner_mode": "local",
  "db": {
    "path": "/path/to/runner/runner-local.db"
  },
  "log": {
    "file": "/path/to/runner/logs.txt",
    "level": "info"
  },
  "core": {
    "url": "https://below-server.mycompany.org:18081/corerunner"
  },
  "s3": {
    "endpoint": "below-server.mycompany.org:19080",
    "endpoint_orchestrator": "below-server.mycompany.org:19080",
    "insecure": false,
    "region": "fr-par"
  },
  "orchestrator": {
    "local": {
      "exec_path": "/usr/local/bin/below-orchestrator",
      "llvm_mca_exec_path": "/usr/local/bin/below-llvm-mca",
      "clang_resource_dir": "/usr/local/lib/below-clang",
      "arm_none_eabi_include_dir": "/usr/local/arm-none-eabi/include"
    }
  },
  "workers": {
    "job_concurrency": 1,
    "job_fetch_period": "3s",
    "job_status_update_period": "1s"
  }
}
```

Replace `/path/to/runner` with the absolute path of the `runner` directory you just created. Also adapt the public URL of the server where it appears (`below-server.mycompany.org`), the http scheme and `insecure field`.
{% endtab %}

{% tab title="Windows" %}

```json
{
  "version": "1.0.0",
  "dev_mode": false,
  "runner_mode": "local",
  "db": {
    "path": "C:\\path\\to\\runner\\runner-local.db"
  },
  "log": {
    "file": "C:\\path\\to\\runner\\logs.txt",
    "level": "info"
  },
  "core": {
    "url": "https://below-server.mycompany.org:18081/corerunner"
  },
  "s3": {
    "endpoint": "below-server.mycompany.org:19080",
    "endpoint_orchestrator": "below-server.mycompany.org:19080",
    "insecure": false,
    "region": "fr-par"
  },
  "orchestrator": {
    "local": {
      "exec_path": "below-orchestrator.exe",
      "llvm_mca_exec_path": "below-llvm-mca.exe",
      "clang_resource_dir": "C:\\Program Files\\beLow\\runner\\clang",
      "arm_none_eabi_include_dir": "C:\\Program Files\\beLow\\runner\\arm-none-eabi\\include"
    }
  },
  "workers": {
    "job_concurrency": 1,
    "job_fetch_period": "3s",
    "job_status_update_period": "1s"
  }
}
```

Replace `C:\\path\\to\\runner` with the absolute path of the `runner` directory you just created. Also adapt the public URL of the server where it appears (`below-server.mycompany.org`), the http scheme and `insecure field`.
{% endtab %}
{% endtabs %}

You may already theck that the runner is succesfully contacting the server by running in a terminal:

{% tabs %}
{% tab title="Linux" %}

```
below-runner runner -c /path/to/runner/config.json is-registered
```

{% endtab %}

{% tab title="Windows" %}

```
below-runner.exe runner -c C:\path\to\runner\config.json is-registered
```

{% endtab %}
{% endtabs %}

The command should run with no error and print:

```json
{
  "registered": false,
  "registration_update_required": true,
  "runner": null
}
```

You may now register the runner using the token you got on server side:

{% tabs %}
{% tab title="Linux" %}

```
below-runner runner -c /path/to/runner/config.json register "123XY"
```

{% endtab %}

{% tab title="Windows" %}

```
below-runner.exe runner -c C:\path\to\runner\config.json register "123XY"
```

{% endtab %}
{% endtabs %}

If command succeeds, your runner is successfully registered to server.

Now, you can run your runner the following way:

{% tabs %}
{% tab title="Linux" %}

```
below-runner runner -c /path/to/runner/config.json start --self-update
```

{% endtab %}

{% tab title="Windows" %}

```
below-runner.exe runner -c C:\path\to\runner\config.json start --self-update
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
It is currently not possible yet to run the runner in detached mode. To run it as a service, please use the recommended way for your OS, e.g using [systemd](https://linuxhandbook.com/create-systemd-services/) for compatible Linux distributions, or creating a [Windows service](https://learn.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer). The easiest way for now is to let the runner command active in a minimized terminal.
{% endhint %}

To stop the runner gracefully, send a termination signal to the running command (CTRL+C in the terminal for instance).

### Limitations

In the product, when starting a new version for a project, you may choose between two modes:

* Copy mode
* Local mode

<figure><img src="/files/nd6txeQsUUvlfUMc6ZmN" alt=""><figcaption><p>Choosing between Copy mode or Local mode</p></figcaption></figure>

When beLow is fully installed on a unique machine, Local mode always works.

However, in distributed mode, Local mode only works if the jobs are run on the same machine as the UI. The following pattern will **not work** then:

* If you choose a build platform which is not compatible with the local runner
* If you choose a target platform which is not compatible with the local runner, in *dynamic auto* analysis mode
* If you choose any of both platforms described above that are also available on a distant runner. In this case, you may use the ***tags*** system while selecting the platforms, to target the local runner. To do so, when registering a new runner, you may add `--tag <your-tag>` (repeatable) in the registration command to add custom tags that you can identify, or use auto-generated tags such as `hostname:<your-machine-hostname>` tag.

<figure><img src="/files/ny2rRp6Wz1iVgmwrSE10" alt=""><figcaption><p>Forcing the usage of your local runner by hostname selection</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wedolow.com/documentation/below/installation-guide/installation-modes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
