# GCP

The Relay Server is the plumbing that all MPC communication goes through. It is built in a way that it is completely untrusted and so the MPC SDKs and MPC Vertex will encrypt all data before sending it through the Relay.
To deploy the Relay server on your cloud environment please read the guide below.

## Architecture

The self-hosted solution comes in two forms: a dedicated [Terraform module](https://developer.hashicorp.com/terraform/intro) per cloud provider, and a general use [Helm chart](https://helm.sh/docs/topics/charts/). Both should be run on your organization's computing infrastructure.
We recommend you first look at our example Terraform module and modify it according to your organization's needs.

## Requirements

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

1. The `terraform` [CLI](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli).
2. The `gcloud` CLI tool for GCP. Make sure the following are true:
   1. You are **logged in** (i.e `gcloud auth application-default login` - notice this is different from `gcloud auth login`).
   2. Your account has permissions to **create resources** (such as GKE clusters, load balancers, key rings, etc...).
   3. You enabled the relevant APIs in your GCP project (e.g. "Cloud Key Management Service (KMS) API", "Kubernetes Engine API", etc...).

In addition, this guide assumes you're running the provided example Terraform module as the root module (although most steps are applicable when running it as a submodule as well).

## Installation Process

The installation process consists of the following steps:

1. Collecting installation parameters
2. Obtaining a TLS certificate
3. Setting a preconfigured API key
4. Obtaining the Terraform module
5. Applying the Terraform module
6. Setting the DNS record to `URL_ENDPOINT`
7. Modify existing code

### 1. Collecting Parameters

At this step you should collect the following pieces of information, listed down below.
At the end of each bullet we put in parentheses a capitalized name which will be used to refer to the value being set throughout the rest of this guide.

1. The endpoint URL that you wish to host your relay server at (`URL_ENDPOINT`).
2. The Sodot Artifactory user and token which provide access to the **Terraform modules, Helm charts, and Docker images** (`ARTIFACTORY_USER` and `ARTIFACTORY_TOKEN`). You can obtain these by following the [Obtaining Credentials](/relay-server/obtaining-artifacts-credentials) guide.

### 2. Obtaining a TLS Certificate

You should obtain a TLS certificate for the `URL_ENDPOINT` domain via GCP Certificate Manager, using **Classic Certificates**. The certificate can either be requested or imported from an existing certificate.
We will need the unique name of your certificate (`TLS_CERT_NAME`).

### 3. Setting a Preconfigured API Key

When setting up your relay server, you should configure an API key.
This is done by passing the `relay_api_key` variable to the `terraform apply` invocation (more on that below).

The `relay_api_key` value is encoded as `KEY,NAME` where `KEY` is the base64url encoding (not plain base64) of a 16-byte value and `NAME` is the name of the API key.

:::info[Example]
To set a 16-byte API key with the following hexadecimal representation: `00112233445566778899aabbccddeeff` with the name `AdminKey` pass `relay_api_key=ABEiM0RVZneImaq7zN3u_w==,AdminKey` when invoking `terraform apply`.
:::

:::tip
A hexadecimal string can be base64url-encoded in bash-like shells using the following command.

```bash
$ echo -n '00112233445566778899aabbccddeeff' | xxd -r -p | base64 | tr '+/' '-_'
ABEiM0RVZneImaq7zN3u_w==
```
:::

### 4. Obtaining the Terraform Module

You can consume the **Relay Server** Terraform module from the Sodot private registry in one of two ways:

#### A. Use the module directly from the registry

First, you'll need to log in to the Sodot Terraform module registry using the credentials you obtained in the previous step.

```bash
terraform login repo.sodot.dev
```

Then, you can use the module directly from the registry by adding it to your Terraform configuration.
Add the following block to your `main.tf` (or similar) and run `terraform init`. Terraform will pull the module from your JFrog Artifactory registry at runtime.

```hcl
module "relay" {
  source  = "repo.sodot.dev/sodot-terraform-modules__sodot/relay/google"
  ...
}
```

#### B. Download the raw Terraform module to customize it

1. Fetch the desired release (replace `<VERSION>` with a tag such as `v1.3.12`):

   ```bash
   curl -u "<ARTIFACTORY_USER>:<ARTIFACTORY_TOKEN>" \
     -O "https://repo.sodot.dev/artifactory/sodot-terraform-modules/sodot/relay/google/<VERSION>.zip"
   ```

   Alternatively, you can use the Artifactory GUI instead.<br /><br />

2. Unzip and make it your root module:

   ```bash
   unzip <VERSION>.zip -d relay
   cd relay
   ```

### 5. Applying the Terraform Module to Your Cloud Environment

Setting up the Relay infrastructure is done with `terraform apply` (after `terraform init`).
Where you run those commands depends on the option you chose in [Obtaining the Terraform Module](#4-obtaining-the-terraform-module).

#### Configuring Terraform

The module’s inputs are declared in `variables.tf` and have sensible defaults where appropriate.
You **must** supply the following variables when invoking **both** `terraform apply` and `terraform destroy`:

* `location` - the GCP region in which to create resources.
* `project_id` - your GCP **project ID**.
* `artifactory_user` - JFrog Artifactory username (`<ARTIFACTORY_USER>`).
* `artifactory_token` - JFrog Artifactory API token (`<ARTIFACTORY_TOKEN>`).
* `relay_helm_version` - the Helm chart version for the Relay deployment (for example: `4.0.1`).
* `relay_api_key` - the key set in [Setting a Preconfigured API Key](#3-setting-a-preconfigured-api-key).
* `ssl_certificate_name` - the certificate name (`TLS_CERT_NAME`) from [Obtaining a TLS Certificate](#2-obtaining-a-tls-certificate).
* `relay_dns_address` - the public DNS name that will point to the Relay.

If you chose to download the zip, run this terraform command from the root module directory:

```bash
terraform init

terraform apply \
  -var "location=us-central1" \
  -var "project_id=my-project" \
  -var "ssl_certificate_name=my-tls-cert" \
  -var "artifactory_user=a_user" \
  -var "artifactory_token=XXXXXXXXXXX" \
  -var "relay_helm_version=4.0.1" \
  -var "relay_dns_address=my-relay.example.com" \
  -var "relay_api_key=ABEiM0RVZneImaq7zN3u_w==,AdminKey"
```

If not and you chose to use the module directly from the registry, run the same command from the root module directory which references `module "relay"`.

### 6. Setting the DNS Record for `URL_ENDPOINT` to Point to the Relay Server

After running `terraform apply` successfully, the resulting external IP address to the internal load-balancer will be outputted under the name `ingress_ip`.

After getting the external IP address of your Relay Server, you will need to create an A record for `URL_ENDPOINT` that points to that address (you can also use an A-alias record to point directly at the load balancer object).
Then, at `https://URL_ENDPOINT` you will be able to communicate with your Relay server.

To verify, you can run:

```bash
curl -H "Authorization: Bearer <RELAY_API_KEY>" https://URL_ENDPOINT/create_room/2
```

Note that `<RELAY_API_KEY>` here is only the `KEY` portion of the `relay_api_key` value, without the `,NAME` suffix (for the example above: `ABEiM0RVZneImaq7zN3u_w==`).

Which should yield a new room ID string if a Relay Server is configured behind the address correctly.

### 7. Modify Existing Code

By default, the `Ecdsa`,`Ed25519`,`StatefulEcdsa` and `StatefulEd25519` classes are routed to a Sodot owned Relay Server. This can be changed by supplying an additional parameter specifying the URL of the on-prem Relay Server.

For instance, consider the `const ecdsa = new Ecdsa()` constructor call.
Calling it should now be made with the extra parameter of `URL_ENDPOINT` like so:

```typescript
const ecdsa = new Ecdsa(URL_ENDPOINT);
```

The same holds for the calling to any of the following constructors as well:

```typescript
const ed25519 = new Ed25519(URL_ENDPOINT);
const ecdsa = new StatefulEcdsa(URL_ENDPOINT);
const ed25519 = new StatefulEd25519(URL_ENDPOINT);
```

More information can be reviewed in the API references for each of the different classes.

* [`new Ecdsa()`](/web/api-ref/classes/Ecdsa#new-ecdsa)
* [`new Ed25519()`](/web/api-ref/classes/Ed25519#new-ed25519)
* [`new StatefulEcdsa()`](/rn/api-ref/classes/StatefulEcdsa#new-statefulecdsa) (React Native SDK)
* [`new StatefulEd25519()`](/rn/api-ref/classes/StatefulEd25519#new-statefuled25519) (React Native SDK)
