# Local Dev Environment

In this guide, we will walk you through the process of setting up a development environment for Sodot Exchange API Vault.

## Architecture Overview

The Exchange API Vault is designed to provide a secure and scalable environment for managing your trading and custodian API keys using Multi-Party Computation (MPC) technology.

The deployment consists of the following services:

1. Three [Vertex](/vertex/overview) servers that work together as a cluster to securely store and manage your API keys.
2. A [Relay](/relay-server/relay_gcp) Server that facilitates secure communication between your applications and the Vertex cluster.
3. A Kubernetes pod that serves the management UI of the Exchange API Vault.
4. The required databases and networking components required to support the above services (in this case, a docker volume for each Vertex server to store its data as well as a Postgres instance for the audit log).

The purpose of this guide is to allow you to run a full setup **locally**, with minimal resources and effort, so you can start to integrate with it using your code without the need to deploy it to a cloud provider.
While this setup is not intended for production use, it provides a convenient way to test and develop against the Exchange API Vault and defines the same architecture and APIs used in production deployments.

## Requirements

Before starting the setup process, make sure you have the following installed:

* Docker - [Install Docker](https://docs.docker.com/get-docker/)

## Setup Process

The setup process is made of the following steps:

1. [Login to the Sodot Docker Registry using the JFROG Artifactory](#docker-login)
2. [Collect the required UI authentication parameters](#ui-auth-params)
3. [Run the full setup using Docker Compose](#docker-compose-setup)

### 1. Login to Sodot Docker Registry

To log in to the Sodot Docker Registry, you will need to obtain a Docker registry token from the JFROG Artifactory.
You can follow the instructions in the [Obtaining Credentials](/exchange-api-vault/obtaining-artifacts-credentials) guide to obtain your token and log in to the Docker registry.

You may test your login by running:

```bash
docker pull repo.sodot.dev/sodot-docker-oci/vertex-exchange-api-vault:<VERSION> # Replace <VERSION> with the desired version (e.g., 1.15.3)
```

### 2. Collect the required UI authentication parameters

To enable authentication for the Exchange API Vault UI, you will need to create 3 Applications and collect the following parameters:

* Client ID (for each of the 3 applications)
* Tenant ID (only used for Entra ID)
* Redirect URI

You can follow the instructions in [Entra ID Authentication Setup](/exchange-api-vault/deployment/sso-configuration/entra-id) guide to create the Entra ID Applications and collect the required parameters or [Google ID Authentication Setup](/exchange-api-vault/deployment/sso-configuration/google-auth).

:::info
You may use the three production Applications if you have one already set up.
:::

### 3. Running the full setup using Docker Compose

To run the MPC Cluster and Relay server using Docker Compose, you will first need to create a `docker-compose.yml` file with the following content:

:::details[docker-compose.yml]
```yaml
services:
  vertex-1:
    image: repo.sodot.dev/sodot-docker-oci/vertex-exchange-api-vault:1.15.3
    restart: always
    env_file: eav.env
    environment:
      - VERTEX_AZURE_CLIENT_ID=df05359c-e72e-46a6-ba32-000000000000
    ports:
      - "9001:8080"
    volumes:
      - vertex-1-db:/app/db/
    healthcheck:
      test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8080/health" ]
    depends_on:
      audit-log-db:
        condition: service_healthy

  vertex-2:
    image: repo.sodot.dev/sodot-docker-oci/vertex-exchange-api-vault:1.15.3
    restart: always
    env_file: eav.env
    environment:
      - VERTEX_AZURE_CLIENT_ID=48662519-2747-4bfb-9726-000000000000
    ports:
      - "9002:8080"
    volumes:
      - vertex-2-db:/app/db/
    healthcheck:
      test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8080/health" ]
    depends_on:
      audit-log-db:
        condition: service_healthy

  vertex-3:
    image: repo.sodot.dev/sodot-docker-oci/vertex-exchange-api-vault:1.15.3
    restart: always
    env_file: eav.env
    environment:
      - VERTEX_AZURE_CLIENT_ID=f865914e-66f8-4269-809a-000000000000
    ports:
      - "9003:8080"
    volumes:
      - vertex-3-db:/app/db/
    healthcheck:
      test: [ "CMD", "wget", "--spider", "-q", "http://localhost:8080/health" ]
    depends_on:
      audit-log-db:
        condition: service_healthy


  setup-script:
    image: repo.sodot.dev/sodot-docker-oci/eav-setup:1.0.0
    env_file:
      - eav.env
    depends_on:
      vertex-1:
        condition: service_healthy
      vertex-2:
        condition: service_healthy
      vertex-3:
        condition: service_healthy

  audit-log-db:
    image: postgres:17-alpine
    restart: always
    environment:
      POSTGRES_USER: vertex
      POSTGRES_PASSWORD: vertex
      POSTGRES_DB: audit_log
    volumes:
      - audit-log-db:/var/lib/postgresql/data
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U vertex -d audit_log" ]

  relay:
    image: repo.sodot.dev/sodot-docker-oci/sodot-relay-server:3.1.16
    restart: always
    environment:
      RUST_LOG: debug
    command:
      - /sodot-relay-server
      - --insecure-api-keys-not-enforced
      - --listen
      - 0.0.0.0:80

  ui:
    image: repo.sodot.dev/sodot-docker-oci/eav-ui:1.15.3
    restart: always
    ports:
      - "3000:3000"
    env_file:
      - eav.env
    depends_on:
      - setup-script

volumes:
  vertex-1-db:
  vertex-2-db:
  vertex-3-db:
  audit-log-db:

```
:::

Then, create a `eav.env` file with the following content:\
Please **replace the placeholder values** in the **Entra ID Authentication Configuration** section with your own values.\
Set your own email as the `ADMIN_EMAIL` for the admin user to be created.

***Note:*** Please set the `VERTEX_AZURE_CLIENT_ID` environment variable in each Vertex service definition in the `docker-compose.yml` file accordingly, as well as set the `CLIENT_ID_X` variables in the `eav.env` file.

:::details[eav.env]
```bash
# MPC Cluster Vertex Service Configuration
RUST_LOG=info # Change to `debug` for more verbose logging
VERTEX_LISTEN_ADDR=0.0.0.0:8080 # Address and port for the Vertex to listen on, this port is mapped in docker-compose.yml
VERTEX_ADMIN_TOKEN=super_user # Replace with your own secret token to access the Vertex REST API as an administrator
VERTEX_HTTP=true # Listen on HTTP
VERTEX_RELAY_ADDRESS=relay # The relay service name defined in the docker-compose.yml
VERTEX_RELAY_API_KEY=aaaa # The relay is configured to not enforce API keys, so you can use any value here
VERTEX_SQLITE=sqlite:///app/db/vertex.db?mode=rwc # SQLite database file for the Vertex
VERTEX_AUDIT_POSTGRES=postgres://vertex:vertex@audit-log-db/audit_log # A shared PostgreSQL database for audit trails from all vertices
VERTEX_BASIC_ENCRYPTION_KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # 32 bytes hex encoded key to encrypt/decrypt DB keys
DANGEROUS_CONTACT_RELAY_NO_TLS=true # Disable TLS for Relay communication (not recommended for production use)

# UI Configuration
CLUSTER_NAME=sodot-cluster
VERTEX_ADDRESS_0=http://localhost:9001
VERTEX_ADDRESS_1=http://localhost:9002
VERTEX_ADDRESS_2=http://localhost:9003


# Entra ID Authentication Configuration
ADMIN_EMAIL=admin@example.com # Email of the UI admin user to be created
AZURE_LOGIN=true # Tells the UI to use Entra ID login (set GOOGLE_LOGIN=true instead when using Google authentication)
CLIENT_ID_0=df05359c-e72e-46a6-ba32-000000000000 # Replace with your own Entra ID Application (Client) ID 0
CLIENT_ID_1=48662519-2747-4bfb-9726-000000000000 # Replace with your own Entra ID Application (Client) ID 1
CLIENT_ID_2=f865914e-66f8-4269-809a-000000000000 # Replace with your own Entra ID Application (Client) ID 2
REDIRECT_URI=http://localhost:3000/auth/callback
TENANT_ID=df05359c-e72e-46a6-ba32-000000000000 # Replace with your own Entra ID Tenant ID
VERTEX_TENANT_ID=df05359c-e72e-46a6-ba32-000000000000 # Replace with your own Entra ID Tenant ID
VERTEX_ENABLED_AUTH_METHODS=classic_api_key,entra_id_ui # Enable Entra ID for UI authentication and classic API key authentication used for signing
```
:::

Then, run the following command to start everything:

```bash
docker compose up -d
```

Wait for a few minutes for all services to start up and initialize. You can check the logs of the services using:

```bash
docker compose logs -f
```

In case you want to run a clean local setup, you can stop and remove all containers and **volumes** using:

```bash
docker compose down -v
```

## Next Steps

Now that you've set up the local environment, you can access the Exchange API Vault UI at [`http://localhost:3000`](http://localhost:3000).\
You may also access the Vertex instances via direct API at `http://localhost:9001`, `http://localhost:9002`, and `http://localhost:9003`.\
An admin user with the token you provided in the `VERTEX_ADMIN_TOKEN` environment variable will be created automatically.

:::info[Permissions]
Note that the admin user you've set up has **no import permissions** by default. You will need to grant the admin user the required permissions to manage API keys via the Users screen in the UI if you plan to use the admin user for API key management.
:::

## Production Deployment

For a production deployment, you can follow the deployment guide of the supported cloud providers:

* [AWS](/exchange-api-vault/deployment/aws)
* [GCP](/exchange-api-vault/deployment/gcp)
* [Azure](/vertex/deployment/vertex_azure)
