# Multi-VM (Ubuntu)

This article provides step-by-step instructions for the fresh deployment of the Edgi Data Service and Edgi Insight Service, along with the required configuration updates to the OvalEdge UI and Job Services, in a multi-VM Ubuntu environment.

Each Edgi service is implemented as a Python application managed using Poetry and integrated with an existing OvalEdge on-premises installation.

## Purpose

The purpose of this article is to provide clear, structured guidance for the fresh deployment of the Edgi Data Service and Edgi Insight Service in a multi-VM Ubuntu environment.&#x20;

It outlines the prerequisites, software dependencies, network and port configurations, installation steps, service setup, and validation procedures required to successfully integrate askEdgi with an existing OvalEdge on-premises installation.

## Prerequisites

Before starting the installation, ensure the following:

**System Access**

* Ubuntu Linux (LTS recommended)
* User account with sudo privileges

**Application Requirements**

* OvalEdge application is installed and running in a multi-VM setup
* MySQL database is accessible
* Elasticsearch is installed and running

**Software Requirements**

The following software is required on the Edgi service VMs:

* Python 3.13.x
* Poetry 2.1.3

{% hint style="info" %}
Do not remove or overwrite the system default Python version. Doing so may break system utilities and the apt package manager.
{% endhint %}

### Network and Port Requirements

Open the following inbound ports to allow communication between OvalEdge and Edgi services.

<table><thead><tr><th width="118">Port</th><th width="185">Service</th><th>Purpose</th></tr></thead><tbody><tr><td>8001</td><td>Edgi Data Service</td><td>Communication between Edgi Data Service and OvalEdge</td></tr><tr><td>8000</td><td>Edgi Insight Service</td><td>Communication between Edgi Insight Service and OvalEdge</td></tr><tr><td>9200</td><td>Elasticsearch</td><td>Communication between Edgi services and Elasticsearch</td></tr><tr><td>3306</td><td>MySQL</td><td>Communication between Edgi services and MySQL</td></tr></tbody></table>

**Firewall Rules**

* Open ports **8000** and **8001** inbound on the Edgi VM security group, allowing access from OvalEdge VMs.
* Open port **9200** inbound on the Elasticsearch security group, allowing access from Edgi VMs.
* Open port **3306** inbound on the MySQL security group, allowing access from Edgi VMs.

## Installation Steps

#### Python 3.13

1. Add Required Repositories.

   ```
   sudo apt install software-properties-common -y
   sudo add-apt-repository ppa:deadsnakes/ppa -y
   sudo apt update
   ```
2. Verify Existing Python Version.

   ```
   python3 --version
   ```
3. If the version is below 3.13.x, install Python 3.13:

   ```
   sudo apt install -y python3.13
   ```

   \
   Sample Reference Screenshot:

   <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FerkHFjuHn375ThMCrnG6%2Funknown.png?alt=media&#x26;token=b4bec993-f5ed-48bc-a8ba-6784d11afda1" alt="" width="563"><figcaption></figcaption></figure></div>
4. Configure Python Alternatives.

   ```
   sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
   sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.13 2
   sudo update-alternatives --config python3
   ```

   \
   Sample Reference Screenshot:

   <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FduLUumGyfZytHtblHn2X%2Funknown.png?alt=media&#x26;token=88bae731-46d7-4887-95d5-6897959798ea" alt="" width="563"><figcaption></figcaption></figure></div>
5. Verify Python Version.

   ```
   python3 --version
   ```

There are two alternatives: python3 (providing /usr/bin/python3).

<table><thead><tr><th width="114">Selection</th><th width="194">Path</th><th width="119">Priority</th><th>Status</th></tr></thead><tbody><tr><td>*0</td><td>/usr/bin/python3.10</td><td>1</td><td>auto mode</td></tr><tr><td>1</td><td>/usr/bin/python3.10</td><td>1</td><td>manual mode</td></tr><tr><td>2</td><td>/usr/bin/python3.13</td><td>2</td><td>manual mode</td></tr></tbody></table>

#### Poetry Installation (Version 2.1.3)

1. Run the following commands.

   ```
   curl -sSL https://install.python-poetry.org | python3 - --version 2.1.3
   echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
   source ~/.bashrc
   poetry --version
   ```

### Directory Preparation

1. Create separate directories for the Edgi services (edgi\_data and edgi\_insight):

   ```
   mkdir -p /home/ovaledge/edgi_data
   mkdir -p /home/ovaledge/edgi_insight
   ```

   \
   Sample Reference Screenshot:

   <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FGl30uCgJ0Q4JQUFH0MkO%2Funknown.png?alt=media&#x26;token=4ffcfe4d-79c1-4815-9379-baf185bc7106" alt="" width="563"><figcaption></figcaption></figure></div>

### Edgi Data Service Deployment

1. Create Required Directories.

   ```
   cd /home/ovaledge/edgi_data
   mkdir logs dbfolder
   touch .env
   ```

   Sample Reference screenshot:

   <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FZFBTLt4liSRRZG3z7Dcf%2Funknown.png?alt=media&#x26;token=fdabaa90-26a5-4b30-a62f-a2ac15d63041" alt="" width="563"><figcaption></figcaption></figure></div>

2. Configure Environment Variables.
   1. Edit the .env file:

      ```
      # VM Configuration
      DEPLOYMENT_TYPE=vm
      ENV=production
      # MySQL Configuration
      mysql_url=jdbc:mysql://<MYSQL_HOST>:3306/ovaledgedb?useUnicode=true&character_set_server=utf8mb4&useSSL=false&allowPublicKeyRetrieval=true
      mysql_user=<MYSQL_USERNAME>
      mysql_password=<MYSQL_PASSWORD>
      # Workspace Configuration
      WORKSPACE_PROJECT_ID=0001
      WORKSPACE_USER=unknown
      # Logging
      LOG_PATH=/home/ovaledge/edgi_data/logs
      LOG_MODE=INFO
      # DuckDB
      DB_FOLDER=/home/ovaledge/edgi_data/dbfolder
      # Connection Pooling
      MYSQL_POOL=10
      MYSQL_POOL_NAME=ovaledge_pool
      # Service Port
      APP_PORT=8001
      # Optional
      OVALEDGE_RECIPE_CONNECTION_ID=-1
      ```

      \
      Sample Reference screenshot:

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FrXFT0zIGhpkDqB2Googd%2Funknown.png?alt=media&#x26;token=bb4f48af-d1d9-4d39-9c44-e8c1c10b3c90" alt=""><figcaption></figcaption></figure>

3. Download and Extract Package.
   1. Download the Edgi Data Service package (provided by DevOps) and extract it:

      ```
      tar -xvf edgi-data.tar.gz
      ```

      \
      Sample Reference Screenshots:

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2F3wW5X4aAbIAa6BRk9HTl%2Funknown.png?alt=media&#x26;token=8b777d28-05f4-4790-a929-da1e9877ab83" alt=""><figcaption></figcaption></figure>

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FGEwPU9wrogYVKqmQSRkO%2Funknown.png?alt=media&#x26;token=71f2e93e-3c25-4c19-b1a6-2716c0a3b2ad" alt=""><figcaption></figcaption></figure>

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2F6u1frsFilYgeGIBaJ25O%2Funknown.png?alt=media&#x26;token=49103988-2103-4cce-b59a-787efd196c20" alt=""><figcaption></figcaption></figure>

4. Install Dependencies.
   1. Run the following command from the directory containing pyproject.toml:

      ```
      poetry install
      ```

      \
      Sample Reference Screenshots:

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FUso1gmq7zqyUsOPDeUge%2Funknown.png?alt=media&#x26;token=a41de7b7-4f1f-4240-be1c-8fd8efb27510" alt=""><figcaption></figcaption></figure>

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FtcCjJsEv91n2WcHNNVAw%2Funknown.png?alt=media&#x26;token=43e2be2c-63af-489b-b023-f9dad32cfcee" alt=""><figcaption></figcaption></figure>

5. Validate Service Startup.

   ```
   poetry run service
   ```

   \
   Sample Reference Screenshot:

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FsBtJEnlb3jVpPhC3LGO3%2Funknown.png?alt=media&#x26;token=5879d8b5-7142-413a-8fa4-f52e937cd929" alt=""><figcaption></figcaption></figure>

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Verify that the service starts successfully, then stop it using Ctrl+C.</p></div>

6. Configure systemd Service
   1. Identify the Poetry binary path:

      ```
      which poetry
      ```

      \
      Sample Reference Screenshot:

      <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FzPVlAZRONT4b9Rl5nsAH%2Funknown.png?alt=media&#x26;token=7024728d-4d12-4046-86fb-2eaaf6509f4d" alt="" width="563"><figcaption></figcaption></figure></div>

   2. Create the service file:

      ```
      sudo vim /etc/systemd/system/data.service
      ```

      ```
      [Unit]
      Description=Edgi Data Service
      After=network.target
      [Service]
      User=ovaledge
      WorkingDirectory=/home/ovaledge/edgi_data
      ExecStartPre=/home/ovaledge/.local/bin/poetry install
      ExecStart=/home/ovaledge/.local/bin/poetry run service
      Restart=always
      StandardOutput=append:/home/ovaledge/edgi_data/logs/edgi-data.log
      StandardError=append:/home/ovaledge/edgi_data/logs/edgi-data.log
      Environment="PATH=/home/ovaledge/.local/bin:/usr/local/bin:/usr/bin"
      [Install]
      WantedBy=multi-user.target
      ```

7. Manage the Service.

   ```
   sudo systemctl daemon-reload
   sudo systemctl start data.service
   sudo systemctl enable data.service
   sudo systemctl status data.service
   ```

   \
   **Service Management Commands**

   | Reload Service | systemctl daemon-reload       |
   | -------------- | ----------------------------- |
   | Start Service  | systemctl start data.service  |
   | Enable Service | systemctl enable data.service |
   | Check Status   | systemctl status data.service |

### Edgi Insight Service Deployment

1. Create Required Directories.

   ```
   cd /home/ovaledge/edgi_insight
   mkdir logs docu dbfolder storefolder
   touch .env
   ```

   \
   Sample Reference Screenshot:

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FohyDGGE02HAueJJBqFtI%2Funknown.png?alt=media&#x26;token=c45949c1-f584-42ff-b567-c7c70df7f723" alt=""><figcaption></figcaption></figure>

2. Configure Environment Variables.

   ```
   # VM Configuration
   DEPLOYMENT_TYPE=vm
   ENV=production
   # MySQL
   mysql_url=jdbc:mysql://<MYSQL_HOST>:3306/ovaledgedb?useUnicode=true&character_set_server=utf8mb4&useSSL=false&allowPublicKeyRetrieval=true
   mysql_user=<MYSQL_USERNAME>
   mysql_password=<MYSQL_PASSWORD>
   # Workspace
   WORKSPACE_PROJECT_ID=0001
   WORKSPACE_USER=unknown
   # Logging
   LOG_PATH=/home/ovaledge/edgi_insight/logs
   LOG_MODE=DEBUG
   EDGI_DEBUG_MODE=False
   # Elasticsearch
   es_host=<ELASTICSEARCH_HOST>
   es_port=9200
   es_username=elastic
   es_password=<ELASTIC_PASSWORD>
   es_protocol=http
   # Workspace Discovery
   EDGI_WORKSPACE_DISCOVERY=static
   EDGI_WORKSPACE_HOST=localhost
   EDGI_WORKSPACE_PORT=8001
   # Storage Paths
   DB_FOLDER=/home/ovaledge/edgi_insight/dbfolder
   DOCS_FOLDER=/home/ovaledge/edgi_insight/docu
   STORE_FOLDER=/home/ovaledge/edgi_insight/storefolder
   ```

   \
   Sample Reference Screenshot:

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2Fsvo0tQpqWIOD2qIWhPF0%2Funknown.png?alt=media&#x26;token=59d9b018-a204-461f-a5c6-ddc38d62e1a1" alt=""><figcaption></figcaption></figure>

3. Install and Validate.

   ```
   poetry install
   poetry run service
   ```

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Stop the service using Ctrl+C after validation.</p></div>

4. Configure systemd Service.

   ```
   sudo vim /etc/systemd/system/insight.service
   [Unit]
   Description=Edgi Insight Service
   After=network.target
   [Service]
   User=ovaledge
   WorkingDirectory=/home/ovaledge/edgi_insight
   ExecStartPre=/home/ovaledge/.local/bin/poetry install
   ExecStart=/home/ovaledge/.local/bin/poetry run service
   Restart=always
   StandardOutput=append:/home/ovaledge/edgi_insight/logs/edgi-insight.log
   StandardError=append:/home/ovaledge/edgi_insight/logs/edgi-insight.log
   Environment="PATH=/home/ovaledge/.local/bin:/usr/local/bin:/usr/bin"
   [Install]
   WantedBy=multi-user.target
   ```

5. Manage the Service.

   ```
   sudo systemctl daemon-reload
   sudo systemctl start insight.service
   sudo systemctl enable insight.service
   sudo systemctl status insight.service
   ```

### OvalEdge Configuration Updates

#### Oasis Configuration

1. Update the following properties in the oasis configuration file:

   ```
   oe.edgi.enabled=true
   oe.edgi.credential.type=static
   oe.edgi.workspace.host=<EDGI_DATA_HOST>
   oe.edgi.workspace.port=8001
   oe.edgi.insight.service.host=<EDGI_INSIGHT_HOST>
   oe.edgi.insight.service.port=8000
   ```

   \
   Sample Reference Screenshot:

   <div align="left"><figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FWD41VfJIhBGnsTynjSIr%2Funknown.png?alt=media&#x26;token=48df74f4-1153-4209-b360-0c20c1c968b4" alt="" width="307"><figcaption></figcaption></figure></div>

{% hint style="info" %}
Restart Tomcat after saving the changes.
{% endhint %}

#### OvalEdge UI Configuration

1. Log in to the OvalEdge application.

2. Validate the MySQL connector (ID: -1) and complete crawl and profiling.

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FQOUsN6kVXLIUelQYELnq%2Fimage.png?alt=media&#x26;token=4c1a770d-6331-4883-8e2a-a4c2a50d998a" alt=""><figcaption></figcaption></figure>

   <br>

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FYkeI7H1ttn3XLROAzEsX%2Fimage.png?alt=media&#x26;token=ad9da9e9-483c-482a-bb37-0eebdcddc4e2" alt=""><figcaption></figcaption></figure>

3. Navigate to System Settings → AI and update the following settings:
   1. askedgi.edition = metadata analytics
   2. Askedgiplus.enable = true
   3. askedgi.ovaledge.recipe.connection.id = -1 (MySQL connector ID)

      <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FbIz7gh3ckoDVe7QkTmza%2Fimage.png?alt=media&#x26;token=7a5df4e6-22dc-4d13-a597-d5bec8585c54" alt=""><figcaption></figcaption></figure>

4. Update ai.config with the key provided by the DevOps team.

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FOut9HliPeHsLMLi8bzvG%2Fimage.png?alt=media&#x26;token=a09a45e2-9542-4fb4-9d6c-1b38d0510bc4" alt=""><figcaption></figcaption></figure>

5. Log out and log back in to apply the changes.

### Validation

1. Navigate to the AskEdgi feature.
2. Wait for workspace initialization.

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2F5nFOVL9vBpLT3pqHMpj3%2Fimage.png?alt=media&#x26;token=8e8b1132-8fa9-4aa9-87b3-11e93e2e2d89" alt=""><figcaption></figcaption></figure>
3. Open the catalog and add a schema.

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FO22RRYHMK3bVG8hKYiml%2Fimage.png?alt=media&#x26;token=88f83473-995d-4017-b395-813d6e9b436c" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FdeSZU9tp3EiN4GmAzVvT%2Fimage.png?alt=media&#x26;token=4e903489-2770-4c3e-8b67-1ea7af63ce86" alt=""><figcaption></figcaption></figure>
4. Verify data access.

   <figure><img src="https://4123149314-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FztcvwwOJCeaE1n6oHp4C%2Fuploads%2FxCXaPhg4RNSgKNvrUgpO%2Fimage.png?alt=media&#x26;token=9314e700-cec2-4b24-8e0b-edda575088c4" alt=""><figcaption></figcaption></figure>
5. Use the search bar to query metadata and validate results.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Successful responses confirm that the deployment is complete.</p></div>

***

Copyright © 2026, OvalEdge LLC, Peachtree Corners, GA, USA.
