From fdce3e99eae45d5ba84b40bc95989851dfcad103 Mon Sep 17 00:00:00 2001
From: Olusegun Ajose <94995067+ajosegun@users.noreply.github.com>
Date: Tue, 18 Jul 2023 02:50:17 +0200
Subject: [PATCH] Adding Digital Ocean Deployment using Terraform (#148)

* Adding GCP Deployment Manager Template

* Adding GCP Deployment Manager Template

* Adding GCP Deployment Manager Template

* Update gcp/deployment/DEPLOY.md

Co-authored-by: David Blore <42894467+DavidBlore@users.noreply.github.com>

* Update gcp/deployment/DEPLOY.md

Co-authored-by: David Blore <42894467+DavidBlore@users.noreply.github.com>

* Update gcp/deployment/DEPLOY.md

Co-authored-by: David Blore <42894467+DavidBlore@users.noreply.github.com>

* Update DEPLOY.md

* Update DEPLOY.md

* Update DEPLOY.md

* Adding Digital Ocean Deployment using Terraform

* Adding Digital Ocean Deployment with Terraform

---------

Co-authored-by: David Blore <42894467+DavidBlore@users.noreply.github.com>
---
 digitalocean/terraform/DEPLOY.md     | 46 ++++++++++++++++++++++
 digitalocean/terraform/main.tf       | 52 ++++++++++++++++++++++++
 digitalocean/terraform/outputs.tf    |  4 ++
 digitalocean/terraform/user_data.tp1 | 59 ++++++++++++++++++++++++++++
 package.json                         |  2 +-
 5 files changed, 162 insertions(+), 1 deletion(-)
 create mode 100644 digitalocean/terraform/DEPLOY.md
 create mode 100644 digitalocean/terraform/main.tf
 create mode 100644 digitalocean/terraform/outputs.tf
 create mode 100644 digitalocean/terraform/user_data.tp1

diff --git a/digitalocean/terraform/DEPLOY.md b/digitalocean/terraform/DEPLOY.md
new file mode 100644
index 000000000..efcca3a49
--- /dev/null
+++ b/digitalocean/terraform/DEPLOY.md
@@ -0,0 +1,46 @@
+# How to deploy a private AnythingLLM instance on DigitalOcean using Terraform
+
+With a DigitalOcean account, you can easily deploy a private AnythingLLM instance using Terraform. This will create a URL that you can access from any browser over HTTP (HTTPS not supported). This single instance will run on your own keys, and they will not be exposed. However, if you want your instance to be protected, it is highly recommended that you set the `AUTH_TOKEN` and `JWT_SECRET` variables in the `docker/` ENV.
+
+[Refer to .env.example](../../docker/HOW_TO_USE_DOCKER.md) for data format.
+
+The output of this Terraform configuration will be:
+- 1 DigitalOcean Droplet
+- An IP address to access your application
+
+**Requirements**
+- An DigitalOcean  account with billing information
+- Terraform installed on your local machine
+  - Follow the instructions in the [official Terraform documentation](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) for your operating system.
+- `.env` file that is filled out with your settings and set up in the `docker/` folder
+
+
+## How to deploy on DigitalOcean
+Open your terminal and navigate to the `digitalocean/terraform` folder
+1. Replace the token value in the provider "digitalocean" block in main.tf with your DigitalOcean API token.
+2. Run the following commands to initialize Terraform, review the infrastructure changes, and apply them:
+    ```
+    terraform init  
+    terraform plan  
+    terraform apply  
+    ```
+Confirm the changes by typing yes when prompted.
+4. Once the deployment is complete, Terraform will output the public IP address of your droplet. You can access your application using this IP address.
+
+## How to deploy on DigitalOcean
+To delete the resources created by Terraform, run the following command in the terminal:
+`
+terraform destroy  
+`
+
+## Please read this notice before submitting issues about your deployment
+
+**Note:** 
+Your instance will not be available instantly. Depending on the instance size you launched with it can take anywhere from 10-20 minutes to fully boot up.
+
+If you want to check the instances progress, navigate to [your deployed instances](https://cloud.digitalocean.com/droplets) and connect to your instance via SSH in browser.
+
+Once connected run `sudo tail -f /var/log/cloud-init-output.log` and wait for the file to conclude deployment of the docker image.
+
+
+Additionally, your use of this deployment process means you are responsible for any costs of these Digital Ocean resources fully.
diff --git a/digitalocean/terraform/main.tf b/digitalocean/terraform/main.tf
new file mode 100644
index 000000000..ae6bd8a59
--- /dev/null
+++ b/digitalocean/terraform/main.tf
@@ -0,0 +1,52 @@
+terraform {
+  required_version = ">= 1.0.0"
+
+  required_providers {
+    digitalocean = {
+      source  = "digitalocean/digitalocean"
+      version = "~> 2.0"
+    }
+  }
+}
+
+provider "digitalocean" {  
+  # Add your DigitalOcean API token here  
+  token = "DigitalOcean API token"  
+}  
+
+  
+resource "digitalocean_droplet" "anything_llm_instance" {  
+  image  = "ubuntu-22-10-x64"  
+  name   = "anything-llm-instance"  
+  region = "nyc3"  
+  size   = "s-1vcpu-1gb"  
+  
+  user_data = templatefile("user_data.tp1", {   
+    env_content = local.formatted_env_content 
+  })
+}  
+
+locals {  
+  env_content = file("../../docker/.env")  
+  formatted_env_content = join("\n", [  
+    for line in split("\n", local.env_content) :  
+    line  
+    if !(  
+      (  
+        substr(line, 0, 1) == "#"  
+      ) ||  
+      (  
+        substr(line, 0, 3) == "UID"  
+      ) ||  
+      (  
+        substr(line, 0, 3) == "GID"  
+      ) ||  
+      (  
+        substr(line, 0, 11) == "CLOUD_BUILD"  
+      ) ||  
+      (  
+        line == ""  
+      )  
+    )  
+  ])  
+}
\ No newline at end of file
diff --git a/digitalocean/terraform/outputs.tf b/digitalocean/terraform/outputs.tf
new file mode 100644
index 000000000..2b6d5595a
--- /dev/null
+++ b/digitalocean/terraform/outputs.tf
@@ -0,0 +1,4 @@
+output "ip_address" {
+  value = digitalocean_droplet.anything_llm_instance.ipv4_address
+  description = "The public IP address of your droplet application."
+}
\ No newline at end of file
diff --git a/digitalocean/terraform/user_data.tp1 b/digitalocean/terraform/user_data.tp1
new file mode 100644
index 000000000..7e7451b38
--- /dev/null
+++ b/digitalocean/terraform/user_data.tp1
@@ -0,0 +1,59 @@
+#!/bin/bash  
+# check output of userdata script with sudo tail -f /var/log/cloud-init-output.log 
+  
+sudo apt-get update  
+sudo apt-get install -y docker.io  
+sudo usermod -a -G docker ubuntu
+  
+curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose  
+sudo chmod +x /usr/local/bin/docker-compose  
+sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose  
+  
+sudo systemctl enable docker  
+sudo systemctl start docker  
+  
+sudo apt-get install -y git  
+  
+git clone https://github.com/Mintplex-Labs/anything-llm.git /home/anything-llm  
+cd /home/anything-llm/docker  
+  
+cat >> .env << END
+${env_content}
+UID="1000"  
+GID="1000"  
+NO_DEBUG="true"  
+END
+  
+echo "Set .env file"  
+  
+cd ../frontend
+sudo rm -rf .env.production  
+  
+sudo cat >> .env.production << END
+GENERATE_SOURCEMAP=true  
+VITE_API_BASE="/api"  
+END
+  
+echo "Set .env.production file"  
+  
+cd ../docker  
+sudo docker-compose up -d --build  
+echo "Container ID: $(sudo docker ps --latest --quiet)"  
+  
+sudo docker container exec -u 0 -t $(sudo docker ps --latest --quiet) mkdir -p /app/server/storage /app/server/storage/documents /app/server/storage/vector-cache /app/server/storage/lancedb  
+echo "Placeholder folders in storage created."  
+  
+sudo docker container exec -u 0 -t $(sudo docker ps --latest --quiet) touch /app/server/storage/anythingllm.db  
+echo "SQLite DB placeholder set."  
+  
+sudo docker container exec -u 0 -t $(sudo docker ps --latest --quiet) chown -R anythingllm:anythingllm /app/collector /app/server  
+echo "File permissions corrected."  
+  
+export ONLINE=$(curl -Is http://localhost:3001/api/ping | head -n 1|cut -d$' ' -f2)  
+echo "Health check: $ONLINE"  
+  
+if [ "$ONLINE" = 200 ]; then  
+  echo "Running migrations..." && curl -Is http://localhost:3001/api/migrate | head -n 1 | cut -d$' ' -f2  
+fi  
+  
+echo "Setup complete! AnythingLLM instance is now online!"  
diff --git a/package.json b/package.json
index f51505fab..dba562032 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
     "prod:server": "cd server && yarn start",
     "prod:frontend": "cd frontend && yarn build",
     "generate:cloudformation": "node aws/cloudformation/generate.mjs",
-    "generate::gcp_deployment": "node gcp/deployment/generate.mjs"  
+    "generate::gcp_deployment": "node gcp/deployment/generate.mjs"
   },
   "private": false
 }
\ No newline at end of file