From 7499b69a9818637f9cfa8992b0005c521b7cfdce Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Sat, 13 Jan 2024 13:03:24 +0100 Subject: [PATCH] Add Terraform provisioning on DigitalOcean --- .gitignore | 9 ++++++++- .terraform.lock.hcl | 26 ++++++++++++++++++++++++ README.md | 26 ++++++++++++++++++++++-- cloud-config.yaml | 49 +++++++++++++++++++++++++++++++++++++++++++++ config.yaml | 2 +- docker-compose.yaml | 2 +- example.env | 3 +++ main.tf | 46 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 .terraform.lock.hcl create mode 100644 cloud-config.yaml create mode 100644 main.tf diff --git a/.gitignore b/.gitignore index 9657e68..a36d9d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ +# Bot .env -.build/ \ No newline at end of file +.build/ + +# Terraform +.terraform/ +terraform.tfstate +terraform.tfstate.backup +values.auto.tfvars \ No newline at end of file diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..9244a4f --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,26 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/digitalocean/digitalocean" { + version = "2.34.1" + constraints = "~> 2.0" + hashes = [ + "h1:iRyhFUfKnDRWx75+alSOEtdS0BtNUkrvLusC15s34eo=", + "zh:022d4c97af3d022d4e3735a81c6a7297aa43c3b28a8cecaa0ff58273a5677e2e", + "zh:1922f86d5710707eb497fbebcb1a1c5584c843a7e95c3900d750d81bd2785204", + "zh:1b7ab7c67a26c399eb5aa8a7a695cb59279c6a1a562ead3064e4a6b17cdacabe", + "zh:1dc666faa2ec0efc32329b4c8ff79813b54741ef1741bc42d90513e5ba904048", + "zh:220dec61ffd9448a91cca92f2bc6642df10db57b25d3d27036c3a370e9870cb7", + "zh:262301545057e654bd6193dc04b01666531fccfcf722f730827695098d93afa7", + "zh:63677684a14e6b7790833982d203fb2f84b105ad6b9b490b3a4ecc7043cdba81", + "zh:67a2932227623073aa9431a12916b52ce1ccddb96f9a2d6cdae2aaf7558ccbf8", + "zh:70dfc6ac33ee140dcb29a971df7eeb15117741b5a75b9f8486c5468c9dd28f24", + "zh:7e3b3b62754e86442048b4b1284e10807e3e58f417e1d59a4575dd29ac6ba518", + "zh:7e6fe662b1e283ad498eb2549d0c2260b908ab5b848e05f84fa4acdca5b4d5ca", + "zh:9c554170f20e659222896533a3a91954fb1d210eea60de05aea803b36d5ccd5d", + "zh:ad2f64d758bd718eb39171f1c31219900fd2bfb552a14f6a90b18cfd178a74b4", + "zh:cfce070000e95dfe56a901340ac256f9d2f84a73bf62391cba8a8e9bf1f857e0", + "zh:d5ae30eccd53ca7314157e62d8ec53151697ed124e43b24b2d16c565054730c6", + "zh:fbe5edf5337adb7360f9ffef57d02b397555b6a89bba68d1b60edfec6e23f02c", + ] +} diff --git a/README.md b/README.md index 3059896..424a7f1 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,13 @@ More information: - Solana RPC Endpoint - Solana Private Key for signing transactions - Jito Private Key for auth to block engine API (optional) +- Terraform (optional) +- DigitalOcean API Key (optional) Drift account is setup according to: https://docs.drift.trade/keeper-bots. The account can also be set up using the trading app: https://app.drift.trade/. -## Setup +## Configure Create .env file from example and configure all environment variables. @@ -27,9 +29,11 @@ Create .env file from example and configure all environment variables. cp example.env .env ``` +Adjust `config.yaml` as you please. + ## Build -Clone the keeper-bots repository and build the Docker image. +Clone the [keeper-bots-v2](https://github.com/drift-labs/keeper-bots-v2/) repository and build the Docker image. ``` ./ctl.sh image build @@ -43,6 +47,24 @@ Run the bot. docker compose up ``` +## Deploy + +Provision a DigitalOcean Droplet and deploy Keeper Bot with current configuration (.env and config.yaml). +By default ~/.ssh/id_rsa.pub is added to DigitalOcean and the Droplet. + +``` +terraform init +terraform apply +``` + +Wait until Droplet is up and the `droplet_ip` is printed. You may connect to the Droplet using + +``` +ssh root@droplet_ip +``` + +In case somethin went wrong with the provisioning, check the cloud-init-output log at `/var/log/cloud-init-output.log`. + ## Metrics The bot exposes Prometheus metrics that are automatically scraped. diff --git a/cloud-config.yaml b/cloud-config.yaml new file mode 100644 index 0000000..4e6bd57 --- /dev/null +++ b/cloud-config.yaml @@ -0,0 +1,49 @@ +#cloud-config +groups: + - ubuntu: [root,sys] + - docker + - bot + +users: + - default + - name: keeper + gecos: keeper + shell: /bin/bash + primary_group: bot + sudo: ALL=(ALL) NOPASSWD:ALL + groups: users, admin, docker + lock_passwd: false + +packages: + - apt-transport-https + - ca-certificates + - curl + - gnupg-agent + - software-properties-common + - chrony + - docker.io + - docker-compose + +ntp: + enabled: true + ntp_client: chrony + servers: + - ${ntp_server} + +runcmd: + - git clone https://github.com/0x1d/drift-keeper /app/bot + - mv /app/.env /app/bot/.env + - mv /app/config.yaml /app/bot/config.yaml + - cd /app/bot && docker-compose up -d + +write_files: + - path: /app/.env + encoding: b64 + owner: root:root + permissions: '0750' + content: ${env_file} + - path: /app/config.yaml + encoding: b64 + owner: root:root + permissions: '0750' + content: ${config_file} \ No newline at end of file diff --git a/config.yaml b/config.yaml index 7197387..096755e 100644 --- a/config.yaml +++ b/config.yaml @@ -36,7 +36,7 @@ global: eventSubscriberPollingInterval: 5000 bulkAccountLoaderPollingInterval: 5000 - useJito: false + useJito: true jitoBlockEngineUrl: jitoAuthPrivateKey: diff --git a/docker-compose.yaml b/docker-compose.yaml index c6bbae5..422f59a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -34,7 +34,7 @@ services: restart: unless-stopped environment: - GF_SECURITY_ADMIN_USER=admin - - GF_SECURITY_ADMIN_PASSWORD=grafana + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} volumes: - ./grafana/provisioning:/etc/grafana/provisioning - ./grafana/dashboards:/var/lib/grafana/dashboards diff --git a/example.env b/example.env index faaf2ab..1382b02 100644 --- a/example.env +++ b/example.env @@ -4,6 +4,9 @@ DOCKER_IMAGE=wirelos/drift-keeper:mainnet-beta # Shell Utils WALLET_ADDRESS=h5XjtA..... +# Grafana Settings +GRAFANA_ADMIN_PASSWORD=grafana + # Drift Config ENV=mainnet-beta ENDPOINT=https://solana-mainnet.rpc.extrnode.com/your-api-key diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..ade5027 --- /dev/null +++ b/main.tf @@ -0,0 +1,46 @@ +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "~> 2.0" + } + } +} + +variable "do_token" {} +variable "config" { + default = { + ntp_server = "ntp.amsterdam.jito.wtf" + docker_image = "wirelos/drift-keeper:mainnet-beta" + } +} + +provider "digitalocean" { + token = var.do_token +} + +locals { + user_data = templatefile("cloud-config.yaml", { + ntp_server = var.config.ntp_server + env_file = base64encode(file(".env")) + config_file = base64encode(file("config.yaml")) + }) +} + +resource "digitalocean_ssh_key" "default" { + name = "Keeper Key" + public_key = file("~/.ssh/id_rsa.pub") +} + +resource "digitalocean_droplet" "keeper" { + image = "ubuntu-23-10-x64" + name = "drift-keeper" + region = "ams3" + size = "s-1vcpu-1gb-intel" + ssh_keys = [digitalocean_ssh_key.default.fingerprint] + user_data = local.user_data +} + +output "droplet_ip" { + value = digitalocean_droplet.keeper.ipv4_address +} \ No newline at end of file