---
sidebar_position: 20
title: Google Cloud Platform
---

Before deploying the application, you must first provision a kubernetes cluster with the relevant credentials. There are no exotic requirements for this cluster and to date, it has be able to run on an auto pilot GKE cluster without issue.

A Switchboard oracle can be run on any cloud provider who offers kubernetes services but this guide will currently be focused on Google Cloud. Feel free to contribute to our documentation if you are running an oracle on another provider. Here's some extra reading to learn more about kubernetes:

- [What is Kubernetes?](https://cloud.google.com/learn/what-is-kubernetes)
- [Kubernetes Engine Quickstart](https://cloud.google.com/kubernetes-engine/docs/quickstart)

## Requirements

### Switchboard Helm Charts

The repo below contains the kubernetes manifest to streamline the deployment. Clone the repo below to get started:

```bash
git clone https://github.com/switchboard-xyz/switchboard-v2
cd switchboard-v2/oracles/helm-deployment
```

### gcloud SDK

You will need to install the google cloud SDK and have a Google Cloud Platform account

- [Install gcloud SDK](https://cloud.google.com/sdk/docs/install)
- [Google Cloud Platform Registration](https://console.cloud.google.com/freetrial/signup/tos)

Verify it installed correctly with the following command:

```bash
gcloud --version
```

### Grafana Domain Name

You will need a domain name to point your grafana instance at to monitor your oracle's metrics. During setup, you will create an external IP, which you will need to add to your domains DNS records. Finally we will provision a TLS certificate for your domain for enhanced security.

## Environment

You will need to collect the following environment variables to inject into the helm charts before deploying to Google Cloud Project. If you chose to use the automated deployment, an env file will be populated with most of these variables populated.

<details>

<summary>
  <b>GCP Environment Variables</b>
</summary>

<table>
  <thead>
    <tr>
      <th>Env Variable</th>
      <th>Definition</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CLUSTER</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - String (devnet / mainnet-beta)
        <br />
        <b>Description</b> - Solana cluster you will be running an oracle on
        (mainnet-beta/devnet)
      </td>
    </tr>
    <tr>
      <td>RPC_URL</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - URL
        <br />
        <b>Description</b> - Solana RPC URL that must be capable of supporting
        websockets. The default RPC pools should be avoided at all cost as you
        will quickly hit the rate limits and risk being slashed
      </td>
    </tr>
    <tr>
      <td>WS_URL</td>
      <td>
        <b>
          <u>Optional</u>
        </b>
        <br />
        <b>Type</b> - URL
        <br />
        <b>Default</b> - RPC_URL
        <br />
        <b>Description</b> - Websocket URL to connect to a Solana RPC server. If
        not provided, oracle will fallback to RPC_URL
      </td>
    </tr>
    <tr>
      <td>BACKUP_MAINNET_RPC</td>
      <td>
        <b>
          <u>Optional</u>
        </b>
        <br />
        <b>Type</b> - URL
        <br />
        <b>Default</b> - https://api.mainnet-beta.solana.com
        <br />
        <b>Description</b> - Backup RPC URL in case of network congestion
      </td>
    </tr>
    <tr>
      <td>ORACLE_KEY</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - Public Key
        <br />
        <b>Description</b> - Public key of the oracle account that has been
        granted permissions to use an oracle queue <br />
      </td>
    </tr>
    <tr>
      <td>HEARTBEAT_INTERVAL</td>
      <td>
        <b>
          <u>Optional</u>
        </b>
        <br />
        <b>Type</b> - Number (seconds)
        <br />
        <b>Default</b> - 15
        <br />
        <b>Description</b> - Seconds between oracle heartbeats. Queues have
        different oracle heartbeat requirements. Recommended value is 15
      </td>
    </tr>
    <tr>
      <td>SERVICE_ACCOUNT_BASE64</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - Base64 encoded JSON file
        <br />
        <b>Description</b> - Base64 encoded JSON file containing the private key
        for your service account that has access to your google secret keypair
        and config bucket
      </td>
    </tr>
    <tr>
      <td>GOOGLE_PAYER_SECRET_PATH</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - GCP Resource Path
        <br />
        <b>Description</b> - Google cloud resource to manage your keypair
        securely.
      </td>
    </tr>
    <tr>
      <td>GCP_CONFIG_BUCKET</td>
      <td>
        <b>
          <u>Optional</u>
        </b>
        <br />
        <b>Type</b> - GCP Resource Path
        <br />
        <b>Default</b> - oracle-configs:configs.json
        <br />
        <b>Description</b> - Contains API keys for private API endpoints
      </td>
    </tr>
    <tr>
      <td>EXTERNAL_IP</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - IPv4 Address
        <br />
        <b>Description</b> - IP Address where your grafana instance will be
        hosted to view metrics and oracle operating status
      </td>
    </tr>
    <tr>
      <td>GRAFANA_HOSTNAME</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - Fully Qualified Domain Name
        <br />
        <b>Description</b> - Hostname where your grafana instance will point to
      </td>
    </tr>
    <tr>
      <td>GRAFANA_ADMIN_PASSWORD</td>
      <td>
        <b>
          <u>Optional</u>
        </b>
        <br />
        <b>Type</b> - String / Password
        <br />
        <b>Default</b> - Sbv2K8sPassword123@
        <br />
        <b>Description</b> - Password to admin account that allows access to
        your grafana instance. You can set this to whatever value you want.
        <br />
      </td>
    </tr>
    <tr>
      <td>GRAFANA_TLS_CRT</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - Base64 encoded CRT file
        <br />
        <b>Description</b> - Base64 encoded string of your TLS certificate to
        secure your grafana instance
      </td>
    </tr>
    <tr>
      <td>GRAFANA_TLS_KEY</td>
      <td>
        <b>
          <u>Required</u>
        </b>
        <br />
        <b>Type</b> - Base64 encoded private key file
        <br />
        <b>Description</b> - Base64 encoded string of the private key used to
        create your TLS certificate
      </td>
    </tr>
  </tbody>
</table>

</details>

## Setup

The `oracles/helm-deployment` directory in the [Switchboard-V2 SDK](https://github.com/switchboard-xyz/switchboard-v2) contains a bash script to walk through the GCP setup and output the required variables to an env file. This script is provided as a convenience tool, you should understand all of the commands in the script before running. To automate the GCP setup, run the following command:

```bash
./setup-gcloud.sh PROJECTNAME

# ./setup-gcloud.sh Sbv2-Devnet-Oracle
```

- `PROJECTNAME` will be the name of your GCP project and must contain no spaces or special characters

The script will walk-through the google cloud setup, create your gcp project, add your oracle keypair as a secret, create a service account and give it access to your keypair, then spin up a kubernetes cluster. The script will periodically prompt you for more information.

Upon completion you will have a file `PROJECTNAME.env` containing:

- PROJECT
- DEFAULT_REGION
- DEFAULT_ZONE
- CLUSTER_NAME
- EXTERNAL_IP
- SECRET_NAME
- GOOGLE_PAYER_SECRET_PATH
- GCP_CONFIG_BUCKET
- SERVICE_ACCOUNT_EMAIL
- SERVICE_ACCOUNT_BASE64

You will need to manually add:

- CLUSTER
- RPC_URL
- BACKUP_MAINNET_RPC
- ORACLE_KEY
- GRAFANA_HOSTNAME
- GRAFANA_ADMIN_PASSWORD
- GRAFANA_TLS_CRT
- GRAFANA_TLS_KEY

<details>
    <summary><b>Manual GCP Setup Steps</b></summary>

<b>Login</b>

Login to your google cloud account:

```bash
gcloud auth login
```

<b>Project</b>

Create a new project

```bash
gcloud projects create switchboard-oracle-cluster --name="Switchboard Oracle"
```

Set it as your default project

```bash
gcloud config set project switchboard-oracle-cluster
```

[Google - gcloud projects create](https://cloud.google.com/sdk/gcloud/reference/projects/create)

<b>gCloud Config</b>

Set the default zone using [list of regions and zones](https://cloud.google.com/compute/docs/regions-zones#available)

```bash
gcloud config set compute/zone us-west1-a # replace with your closest region
```

Set the default region using [list of regions and zones](https://cloud.google.com/compute/docs/regions-zones#available)

```bash
gcloud config set compute/region us-west1 # replace with your closest region
```

[Google - Set default settings for the gcloud tool](https://cloud.google.com/kubernetes-engine/docs/quickstart#autopilot)

<b>Billing</b>

You will need to enable billing for the project before enabling any services:

- https://console.cloud.google.com/billing/enable?project=switchboard-oracle-cluster

[Google - APIs and billing](https://support.google.com/googleapi/answer/6158867?hl=en)

<b>Services</b>

Enable the relevant services:

```bash
gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com
gcloud services enable iamcredentials.googleapis.com
gcloud services enable secretmanager.googleapis.com
```

<b>External IP</b>

You will need to reserve a static IP address for your grafana instance

```bash
gcloud compute addresses create load-balancer --project=switchboard-oracle-cluster
gcloud compute addresses list
# NAME           ADDRESS/RANGE
# load-balancer  123.123.123.123 ($LOADBALANCER_IP)
```

This will be your `$EXTERNAL_IP`

[Google - Reserve a new static external IP address](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#reserve_new_static)

<b>Service Account</b>

You will need to create a service account to access our resources.

```bash
gcloud iam service-accounts create svc-account --display-name="Oracle Service Account"
gcloud iam service-accounts list
```

Now save it to our filesystem

```bash
gcloud iam service-accounts keys create secrets/svc-account.json  --iam-account=svc-account@switchboard-oracle-cluster.iam.gserviceaccount.com
```

Now convert the json file to a base64 string to store in `$SERVICE_ACCOUNT_BASE64`

```bash
base64 secrets/svc-account.json
```

[Google - Creating service account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)

<b>OraclePayerSecret</b>

You will need to store your solana keypair in Google Secret Manager for enhanced security. If you are using another keypair replace `--data-file` with your relevant path.

```bash
gcloud secrets create oracle-payer-secret --replication-policy="automatic"  --data-file=secrets/authority-keypair.json
```

You can view your `$GOOGLE_PAYER_SECRET_PATH` in the [GCP console](https://console.cloud.google.com/security/secret-manager/secret/oracle-payer-secret/versions&project=switchboard-oracle-cluster) or by running the command

```bash
echo "$(gcloud secrets list --uri --filter=oracle-payer-secret | \
cut -c41- | tr -d '\n')/versions/latest"
```

[Google - Creating a secret](https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets)

<b>Storage Bucket</b>

You can create a GCP storage bucket to store API keys. The following command will create a new storage bucket and give your service account permissions to read from it. You will need to use a unique name as storage bucket names are global to the entire GCP platform.

```bash
gsutil mb -p switchboard-oracle-cluster -l us-west1 gs://switchboard-oracle-cluster-bucket
gsutil iam ch serviceAccount:svc-account@switchboard-oracle-cluster.iam.gserviceaccount.com:legacyBucketReader gs://switchboard-oracle-cluster-bucket
gsutil ls
# gs://switchboard-oracle-cluster-bucket/
```

You can view your `$GCP_CONFIG_BUCKET` by running the command

```bash
echo "$(gsutil ls | grep 'switchboard-oracle-cluster-bucket' | \
sed -e 's/.*gs:\/\/\(.*\)\/.*/\1/' ):configs.json"
# switchboard-oracle-cluster-bucket:configs.json
```

[Google - Create storage buckets](https://cloud.google.com/storage/docs/creating-buckets#storage-create-bucket-gsutil)

<b>Kubernetes Cluster</b>

Finally you will need to create a new kubernetes cluster

```bash
gcloud container clusters create-auto switchboard-cluster \
--service-account=svc-account@switchboard-oracle-cluster.iam.gserviceaccount.com \
--region us-west1
```

then connect to it and store your credentials in your gCloud config

```bash
gcloud container clusters get-credentials switchboard-cluster \
--project switchboard-oracle-cluster \
--region us-west1
```

:::note
Remember to update the region to the same region you used for your static IP.
:::

[Google - Create a GKE cluster](https://cloud.google.com/kubernetes-engine/docs/quickstart#autopilot)

<b>Wrapping Up</b>

You should now have an `PROJECTNAME.env` file containing

- EXTERNAL_IP
- GOOGLE_PAYER_SECRET_PATH
- GCP_CONFIG_BUCKET
- SERVICE_ACCOUNT_BASE64

You will need to manually add:

- CLUSTER
- RPC_URL
- BACKUP_MAINNET_RPC
- ORACLE_KEY
- GRAFANA_HOSTNAME
- GRAFANA_ADMIN_PASSWORD
- GRAFANA_TLS_CRT
- GRAFANA_TLS_KEY

</details>

## Grafana

Grafana is a visualization tool to view your cluster's metrics. While this step is optional, it is recommended if you have no other monitoring or metric suite in place.

### Domain Name

You will need a domain name to host your grafana instance. In your domain management tool, add a DNS A record with a value of `$EXTERNAL_IP`.

This value will be your `$GRAFANA_HOSTNAME` (i.e. grafana.switchboard.com) and will be used to provision a TLS certificate.

### TLS Certificate

The following steps will walk you through provisioning a TLS certificate for your domain from letsencrypt. The [helm-manifest repo](https://github.com/switchboard-xyz/helm-manifests) contains a script to walk through creating the neccessary keys and certificate signing request (CSR).

```bash
./setup-grafana.sh PROJECTNAME DOMAIN EMAIL
```

- PROJECTNAME is the name of the env file to store variables
- DOMAIN is your $GRAFANA_HOSTNAME from above
- EMAIL is the email you will use for your certificate signing request

When the necessary keys and CSR are generated, head over to [gethttpsforfree.com](https://gethttpsforfree.com.com) and walk through their steps to sign your certificate. Save the final output to the filename given by the script, then rerun the script. The script will save the env variables to `PROJECTNAME.env` and also output them to the console.

Your `PROJECTNAME.env` file should now contain

- GRAFANA_HOSTNAME
- GRAFANA_ADMIN_PASSWORD (You can set this to whatever value you want)
- GRAFANA_TLS_CRT
- GRAFANA_TLS_KEY

## Deploy

After completing the steps on this page you should have a `PROJECTNAME.env` file with each of the required variables defined. See [Google Cloud / Environment](#environment) for a list of all required variables that must be set.

Run the following command to build the helm charts with your environment variables injected into the manifests:

```bash
./build-helm.sh PROJECTNAME
```

### Deploy Helm Charts

Run the command

```bash
./deploy-helm.sh PROJECTNAME
```

When complete, you should see your cluster running in the Google Cloud Console.

[Google - Observing your GKE clusters](https://cloud.google.com/stackdriver/docs/solutions/gke/observing)

### Update

If necessary, rebuild the charts to update any environment variables:

```bash
./build-helm.sh PROJECTNAME
```

then redeploy the helm charts:

```bash
./deploy-helm.sh PROJECTNAME
```
