├── .devcontainer └── devcontainer.json ├── .gitignore ├── LICENSE ├── README.md ├── db.tf ├── network.tf ├── openai.tf ├── outputs.tf ├── providers.tf ├── resource_group.tf ├── strings.tf ├── terraform.tfvars.sample ├── variables.tf └── webapps.tf /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu 3 | { 4 | "name": "libre_chat_deploy", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/base:jammy", 7 | "features": { 8 | "ghcr.io/devcontainers/features/azure-cli:1": {}, 9 | "ghcr.io/devcontainers/features/terraform:1": {} 10 | // "ghcr.io/devcontainers/features/dotnet:1": {}, 11 | // "ghcr.io/devcontainers/features/docker-in-docker:2": {}, 12 | // "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {} 13 | }, 14 | "customizations": { 15 | "vscode": { 16 | "extensions": [ 17 | "HashiCorp.terraform", 18 | "ms-azuretools.vscode-azureterraform", 19 | "ms-vscode.vscode-node-azure-pack", 20 | "ms-kubernetes-tools.vscode-kubernetes-tools", 21 | "ms-kubernetes-tools.vscode-aks-tools" 22 | ] 23 | } 24 | } 25 | 26 | // Features to add to the dev container. More info: https://containers.dev/features. 27 | // "features": {}, 28 | 29 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 30 | // "forwardPorts": [], 31 | 32 | // Use 'postCreateCommand' to run commands after the container is created. 33 | // "postCreateCommand": "uname -a", 34 | 35 | // Configure tool-specific properties. 36 | // "customizations": {}, 37 | 38 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 39 | // "remoteUser": "root" 40 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alex Balasch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibreChatAzureDeployment 2 | A Terraform setup to deploy [LibreChat](https://github.com/danny-avila/LibreChat) to Azure and setup all the necessary services. 3 | 4 | # Azure Deployment Instructions 5 | 6 | ## Prerequisites 7 | 8 | You must have an existing Azure subscription for this to work. 9 | 10 | ## Steps 11 | 12 | 1. **Clone the repository.** 13 | 14 | 2. **Open in VS-Code Devcontainer.** 15 | 16 | 3. **[Optional] Configure Deployment:** 17 | * Edit `terraform.tfvars` to customize your deployment. 18 | * You can for example set the `MONGO_URI` which is the connection string to your MongoDB. A fast and simple solution for that is a free cloud instance, like setting up an [Atlas Instance](https://github.com/danny-avila/LibreChat/blob/main/docs/install/mongodb.md). By default a CosmosDB instance is set up automatically. 19 | 20 | 4. **Azure Login:** Open the Terminal inside of VS-Code, and run the command `az login`. 21 | 22 | 5. **Terraform Initialization:** In the Terminal inside of VS-Code, run the command `terraform init`. 23 | 24 | 6. **Apply Terraform Configuration:** In the Terminal inside of VS-Code, run the command `terraform apply`. 25 | 26 | 7. **Open LibreChat:** After finishing, terraform shows the outputs in the terminal. Open the Url of "libre_chat_url" (it might take some minutes until everything has booted) 27 | ## Teardown 28 | 29 | To tear down your Azure resources, run the command `terraform destroy` in the Terminal inside of VS-Code. 30 | 31 | -------------------------------------------------------------------------------- /db.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_cosmosdb_account" "librechat" { 2 | name = "librechatdb${random_string.random_postfix.result}" 3 | resource_group_name = azurerm_resource_group.this.name 4 | location = azurerm_resource_group.this.location 5 | offer_type = "Standard" 6 | kind = "MongoDB" 7 | enable_automatic_failover = false 8 | enable_free_tier = var.use_cosmosdb_free_tier 9 | 10 | 11 | consistency_policy { 12 | consistency_level = "BoundedStaleness" 13 | max_interval_in_seconds = 10 14 | max_staleness_prefix = 200 15 | } 16 | 17 | geo_location { 18 | location = azurerm_resource_group.this.location 19 | failover_priority = 0 20 | } 21 | capabilities { 22 | name = "MongoDBv3.4" 23 | } 24 | capabilities { 25 | name = "EnableServerless" 26 | } 27 | capabilities { 28 | name = "EnableMongo" 29 | } 30 | 31 | virtual_network_rule { 32 | id = azurerm_subnet.librechat_subnet.id 33 | } 34 | 35 | # enable_multiple_write_locations = false 36 | is_virtual_network_filter_enabled = true 37 | public_network_access_enabled = true 38 | } 39 | -------------------------------------------------------------------------------- /network.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_virtual_network" "librechat_network" { 2 | name = "librechat_network" 3 | address_space = ["10.0.0.0/16"] 4 | location = azurerm_resource_group.this.location 5 | resource_group_name = azurerm_resource_group.this.name 6 | } 7 | 8 | resource "azurerm_subnet" "librechat_subnet" { 9 | name = "librechat_subnet" 10 | resource_group_name = azurerm_resource_group.this.name 11 | virtual_network_name = azurerm_virtual_network.librechat_network.name 12 | address_prefixes = ["10.0.1.0/24"] 13 | 14 | service_endpoints = ["Microsoft.AzureCosmosDB", "Microsoft.Web"] 15 | 16 | delegation { 17 | name = "delegation" 18 | service_delegation { 19 | name = "Microsoft.Web/serverFarms" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /openai.tf: -------------------------------------------------------------------------------- 1 | module "openai" { 2 | # application_name = "openai_service_librechat" 3 | source = "Azure/openai/azurerm" 4 | version = "0.1.1" 5 | resource_group_name = azurerm_resource_group.this.name 6 | location = azurerm_resource_group.this.location 7 | public_network_access_enabled = true 8 | # private_endpoint = { 9 | # "pe_endpoint" = { 10 | # private_dns_entry_enabled = true 11 | # dns_zone_virtual_network_link = "dns_zone_link_openai" 12 | # is_manual_connection = false 13 | # name = "openai_pe" 14 | # private_service_connection_name = "openai_pe_connection" 15 | # subnet_name = "subnet0" 16 | # vnet_name = module.vnet.vnet_name 17 | # vnet_rg_name = azurerm_resource_group.this.name 18 | # } 19 | # } 20 | deployment = var.deployments 21 | depends_on = [ 22 | azurerm_resource_group.this, 23 | # module.vnet 24 | ] 25 | } 26 | 27 | 28 | # resource "azurerm_cognitive_account" "openai" { 29 | # name = "openai_service_librechat" 30 | # location = azurerm_resource_group.this.location 31 | # resource_group_name = azurerm_resource_group.this.name 32 | # kind = "OpenAI" 33 | # # custom_subdomain_name = var.custom_subdomain_name 34 | # sku_name = "S0" 35 | # public_network_access_enabled = var.public_network_access_enabled 36 | # # tags = var.tags 37 | 38 | # private_endpoint = { 39 | # "pe_endpoint" = { 40 | # private_dns_entry_enabled = true 41 | # dns_zone_virtual_network_link = "dns_zone_link_openai" 42 | # is_manual_connection = false 43 | # name = "openai_pe" 44 | # private_service_connection_name = "openai_pe_connection" 45 | # subnet_name = "subnet0" 46 | # vnet_name = module.vnet.vnet_name 47 | # vnet_rg_name = azurerm_resource_group.this.name 48 | # } 49 | # } 50 | 51 | # # identity { 52 | # # type = "SystemAssigned" 53 | # # } 54 | 55 | # # lifecycle { 56 | # # ignore_changes = [ 57 | # # tags 58 | # # ] 59 | # # } 60 | # } 61 | 62 | # resource "azurerm_cognitive_deployment" "deployment" { 63 | # for_each = {for deployment in var.deployments: deployment.name => deployment} 64 | 65 | # name = each.key 66 | # cognitive_account_id = azurerm_cognitive_account.openai.id 67 | 68 | # model { 69 | # format = "OpenAI" 70 | # name = each.value.model.name 71 | # version = each.value.model.version 72 | # } 73 | 74 | # scale { 75 | # type = "Standard" 76 | # } 77 | # } 78 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | # output "mongo_connection_string" { 2 | # description = "Connection string for the MongoDB" 3 | # value = azurerm_cosmosdb_account.librechat.connection_strings[0] 4 | # sensitive = true 5 | # } 6 | 7 | output "ressource_group_name" { 8 | description = "name of the created ressource group" 9 | value = azurerm_resource_group.this.name 10 | } 11 | 12 | output "libre_chat_url" { 13 | value = "${azurerm_linux_web_app.librechat.name}.azurewebsites.net" 14 | } 15 | 16 | output "meilisearch_url" { 17 | value = "${azurerm_linux_web_app.meilisearch.name}.azurewebsites.net" 18 | } 19 | 20 | output "azure_openai_api_key" { 21 | value = module.openai.openai_primary_key 22 | sensitive = true 23 | } 24 | 25 | output "azure_openai_endpoint" { 26 | value = module.openai.openai_endpoint 27 | sensitive = true 28 | } 29 | 30 | 31 | # output "meilisearch_master_key" { 32 | # description = "MeiliSearch Master Key" 33 | # value = random_string.meilisearch_master_key 34 | # } 35 | -------------------------------------------------------------------------------- /providers.tf: -------------------------------------------------------------------------------- 1 | # Azure provider version 2 | terraform { 3 | required_version = ">= 1.3.0" 4 | 5 | required_providers { 6 | azurerm = { 7 | source = "hashicorp/azurerm" 8 | version = "~> 3.0, < 4.0" 9 | } 10 | random = { 11 | source = "hashicorp/random" 12 | version = "3.3.2" 13 | } 14 | } 15 | } 16 | 17 | provider "azurerm" { 18 | features {} 19 | } 20 | 21 | provider "random" {} -------------------------------------------------------------------------------- /resource_group.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_resource_group" "this" { 2 | name = "rg-librechat-${random_string.random_postfix.result}" 3 | location = var.location 4 | } -------------------------------------------------------------------------------- /strings.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "random_string" "random_postfix" { 3 | length = 8 4 | lower = true 5 | upper = false 6 | special = false 7 | } 8 | 9 | resource "random_string" "jwt_secret" { 10 | length = 64 11 | lower = true 12 | upper = false 13 | special = false 14 | } 15 | 16 | resource "random_string" "jwt_refresh_secret" { 17 | length = 64 18 | lower = true 19 | upper = false 20 | special = false 21 | } 22 | 23 | resource "random_string" "creds_key" { 24 | length = 64 25 | lower = true 26 | upper = false 27 | special = false 28 | } 29 | 30 | resource "random_string" "creds_iv" { 31 | length = 32 32 | lower = true 33 | upper = false 34 | special = false 35 | } 36 | 37 | resource "random_string" "meilisearch_master_key" { 38 | length = 20 39 | special = false 40 | } 41 | 42 | resource "random_string" "mongo_root_password" { 43 | length = 32 44 | lower = true 45 | upper = false 46 | special = false 47 | } -------------------------------------------------------------------------------- /terraform.tfvars.sample: -------------------------------------------------------------------------------- 1 | location = "region_name" # for e.g. australiaeast 2 | app_title = "librechat" 3 | openai_key = "" 4 | chatgpt_token = "user_provided" 5 | anthropic_api_key = "user_provided" 6 | bingai_token = "user_provided" 7 | palm_key = "user_provided" 8 | app_service_sku_name = "B1" 9 | mongo_uri = "" 10 | use_cosmosdb_free_tier = true 11 | 12 | deployments = { 13 | "gpt-35-turbo" = { 14 | name = "gpt-35-turbo" 15 | rai_policy_name = "Microsoft.Default" 16 | model_name = "gpt-35-turbo" 17 | model_format = "OpenAI" 18 | model_version = "0613" 19 | scale_type = "Standard" 20 | } 21 | "gpt-35-turbo-16k" = { 22 | name = "gpt-35-turbo-16k" 23 | rai_policy_name = "Microsoft.Default" 24 | model_name = "gpt-35-turbo-16k" 25 | model_format = "OpenAI" 26 | model_version = "0613" 27 | scale_type = "Standard" 28 | } 29 | "gpt-4" = { 30 | name = "gpt-4" 31 | rai_policy_name = "Microsoft.Default" 32 | model_name = "gpt-4" 33 | model_format = "OpenAI" 34 | model_version = "0613" 35 | scale_type = "Standard" 36 | } 37 | "gpt-4-32k" = { 38 | name = "gpt-4-32k" 39 | rai_policy_name = "Microsoft.Default" 40 | model_name = "gpt-4-32k" 41 | model_format = "OpenAI" 42 | model_version = "0613" 43 | scale_type = "Standard" 44 | } 45 | "text-embedding-ada-002" = { 46 | name = "text-embedding-ada-002" 47 | rai_policy_name = "Microsoft.Default" 48 | model_name = "text-embedding-ada-002" 49 | model_format = "OpenAI" 50 | model_version = "2" 51 | scale_type = "Standard" 52 | } 53 | } 54 | 55 | azure_openai_api_deployment_name = "" 56 | azure_openai_api_completions_deployment_name = "" 57 | azure_openai_api_version = "2024-02-01" 58 | azure_openai_api_embeddings_deployment_name = "" 59 | public_network_access_enabled = false 60 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "location" { 2 | description = "The location where all resources will be deployed" 3 | default = "australiaeast" 4 | } 5 | 6 | variable "app_title" { 7 | description = "The title that librechat will display" 8 | default = "librechat" 9 | } 10 | 11 | variable "openai_key" { 12 | description = "OpenAI API Key" 13 | default = "" 14 | sensitive = true 15 | } 16 | 17 | variable "chatgpt_token" { 18 | description = "ChatGPT Token" 19 | default = "user_provided" 20 | sensitive = true 21 | } 22 | 23 | variable "anthropic_api_key" { 24 | description = "Anthropic API Key" 25 | default = "user_provided" 26 | sensitive = true 27 | } 28 | 29 | variable "bingai_token" { 30 | description = "BingAI Token" 31 | default = "user_provided" 32 | sensitive = true 33 | } 34 | 35 | variable "palm_key" { 36 | description = "PaLM Key" 37 | default = "user_provided" 38 | sensitive = true 39 | } 40 | 41 | variable "app_service_sku_name" { 42 | description = "size of the VM that runs the librechat app. F1 is free but limited to 1h per day." 43 | default = "B1" 44 | } 45 | 46 | variable "mongo_uri" { 47 | description = "Connection string for the mongodb" 48 | default = "" 49 | sensitive = true 50 | } 51 | 52 | variable "use_cosmosdb_free_tier" { 53 | description = "Flag to enable/disable free tier of cosmosdb. This needs to be false if another instance already uses free tier." 54 | default = true 55 | } 56 | 57 | variable "deployments" { 58 | description = "(Optional) Specifies the deployments of the Azure OpenAI Service" 59 | type = map(object({ 60 | name = string 61 | rai_policy_name = string 62 | model_format = string 63 | model_name = string 64 | model_version = string 65 | scale_type = string 66 | })) 67 | default = { 68 | "gpt-35-turbo" = { 69 | name = "gpt-35-turbo" 70 | rai_policy_name = "Microsoft.Default" 71 | model_name = "gpt-35-turbo" 72 | model_format = "OpenAI" 73 | model_version = "0613" 74 | scale_type = "Standard" 75 | }, 76 | "gpt-35-turbo-16k" = { 77 | name = "gpt-35-turbo-16k" 78 | rai_policy_name = "Microsoft.Default" 79 | model_name = "gpt-35-turbo-16k" 80 | model_format = "OpenAI" 81 | model_version = "0613" 82 | scale_type = "Standard" 83 | }, 84 | # "gpt-35-turbo-1106" = { 85 | # name = "gpt-35-turbo-1106" 86 | # rai_policy_name = "Microsoft.Default" 87 | # model_name = "gpt-35-turbo" 88 | # model_format = "OpenAI" 89 | # model_version = "1106" 90 | # scale_type = "Standard" 91 | # }, 92 | "gpt-4" = { 93 | name = "gpt-4" 94 | rai_policy_name = "Microsoft.Default" 95 | model_name = "gpt-4" 96 | model_format = "OpenAI" 97 | model_version = "0613" 98 | scale_type = "Standard" 99 | }, 100 | "gpt-4-32k" = { 101 | name = "gpt-4-32k" 102 | rai_policy_name = "Microsoft.Default" 103 | model_name = "gpt-4-32k" 104 | model_format = "OpenAI" 105 | model_version = "0613" 106 | scale_type = "Standard" 107 | }, 108 | # "gpt-4-1106-preview" = { 109 | # name = "gpt-4-1106-preview" 110 | # rai_policy_name = "Microsoft.Default" 111 | # model_name = "gpt-4" 112 | # model_format = "OpenAI" 113 | # model_version = "1106-Preview" 114 | # scale_type = "Standard" 115 | # }, 116 | # "gpt-4-vision-preview" = { 117 | # name = "gpt-4-vision-preview" 118 | # rai_policy_name = "Microsoft.Default" 119 | # model_name = "gpt-4" 120 | # model_format = "OpenAI" 121 | # model_version = "vision-preview" 122 | # scale_type = "Standard" 123 | # }, 124 | "text-embedding-ada-002" = { 125 | name = "text-embedding-ada-002" 126 | rai_policy_name = "Microsoft.Default" 127 | model_name = "text-embedding-ada-002" 128 | model_format = "OpenAI" 129 | model_version = "2" 130 | scale_type = "Standard" 131 | }, 132 | } 133 | } 134 | 135 | variable "azure_openai_api_deployment_name" { 136 | description = "(Optional) The deployment name of your Azure OpenAI API; if deployments.chat_model.name is defined, the default value is that value." 137 | default = "" 138 | } 139 | 140 | variable "azure_openai_api_completions_deployment_name" { 141 | description = "(Optional) The deployment name for completion; if deployments.chat_model.name is defined, the default value is that value." 142 | default = "" 143 | } 144 | 145 | variable "azure_openai_api_version" { 146 | description = "The version of your Azure OpenAI API" 147 | default = "2024-02-01" 148 | } 149 | 150 | variable "azure_openai_api_embeddings_deployment_name" { 151 | description = "(Optional) The deployment name for embedding; if deployments.embedding_model.name is defined, the default value is that value." 152 | default = "" 153 | } 154 | 155 | variable "public_network_access_enabled" { 156 | description = "(Optional) Specifies whether public network access is allowed for the Azure OpenAI Service" 157 | type = bool 158 | default = false 159 | } 160 | -------------------------------------------------------------------------------- /webapps.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_service_plan" "librechat" { 2 | name = "librechat-asp${random_string.random_postfix.result}" 3 | location = azurerm_resource_group.this.location 4 | resource_group_name = azurerm_resource_group.this.name 5 | os_type = "Linux" 6 | 7 | sku_name = var.app_service_sku_name 8 | } 9 | 10 | resource "azurerm_linux_web_app" "librechat" { 11 | name = "librechatapp${random_string.random_postfix.result}" 12 | location = azurerm_resource_group.this.location 13 | resource_group_name = azurerm_resource_group.this.name 14 | service_plan_id = azurerm_service_plan.librechat.id 15 | public_network_access_enabled = true 16 | https_only = true 17 | 18 | site_config { 19 | minimum_tls_version = "1.2" 20 | 21 | } 22 | 23 | logs { 24 | http_logs { 25 | file_system { 26 | retention_in_days = 7 27 | retention_in_mb = 35 28 | } 29 | } 30 | application_logs { 31 | file_system_level = "Information" 32 | } 33 | } 34 | 35 | app_settings = { 36 | #==================================================# 37 | # Server Configuration # 38 | #==================================================# 39 | 40 | APP_TITLE = var.app_title 41 | # CUSTOM_FOOTER="My custom footer" 42 | HOST = "0.0.0.0" 43 | PORT = 80 44 | 45 | MONGO_URI = azurerm_cosmosdb_account.librechat.connection_strings[0] 46 | 47 | DOMAIN_CLIENT = "http://localhost:3080" 48 | DOMAIN_SERVER = "http://localhost:3080" 49 | 50 | #===============# 51 | # Debug Logging # 52 | #===============# 53 | DEBUG_LOGGING = true 54 | DEBUG_CONSOLE = false 55 | 56 | #=============# 57 | # Permissions # 58 | #=============# 59 | 60 | # UID=1000 61 | # GID=1000 62 | 63 | #===================================================# 64 | # Endpoints # 65 | #===================================================# 66 | 67 | ENDPOINTS = "azureOpenAI" #openAI,azureOpenAI,bingAI,chatGPTBrowser,google,gptPlugins,anthropic 68 | 69 | # PROXY= 70 | 71 | #============# 72 | # Anthropic # 73 | #============# 74 | 75 | # ANTHROPIC_API_KEY = "user_provided" 76 | # ANTHROPIC_MODELS = "claude-1,claude-instant-1,claude-2" 77 | # ANTHROPIC_REVERSE_PROXY= 78 | 79 | #============# 80 | # Azure # 81 | #============# 82 | 83 | AZURE_API_KEY = module.openai.openai_primary_key 84 | AZURE_OPENAI_MODELS = "gpt-3.5-turbo,gpt-4" 85 | # AZURE_OPENAI_DEFAULT_MODEL = "gpt-3.5-turbo" 86 | # PLUGINS_USE_AZURE = true 87 | 88 | AZURE_USE_MODEL_AS_DEPLOYMENT_NAME = true 89 | 90 | AZURE_OPENAI_API_INSTANCE_NAME = split("//", split(".", module.openai.openai_endpoint)[0])[1] 91 | # AZURE_OPENAI_API_DEPLOYMENT_NAME = 92 | AZURE_OPENAI_API_VERSION = var.azure_openai_api_version 93 | # AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME = 94 | # AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME = 95 | 96 | #============# 97 | # BingAI # 98 | #============# 99 | 100 | BINGAI_TOKEN = var.bingai_token 101 | # BINGAI_HOST = "https://cn.bing.com" 102 | 103 | #============# 104 | # ChatGPT # 105 | #============# 106 | 107 | CHATGPT_TOKEN = var.chatgpt_token 108 | CHATGPT_MODELS = "text-davinci-002-render-sha" 109 | # CHATGPT_REVERSE_PROXY = "" 110 | 111 | #============# 112 | # Google # 113 | #============# 114 | 115 | GOOGLE_KEY = "user_provided" 116 | # GOOGLE_MODELS="gemini-pro,gemini-pro-vision,chat-bison,chat-bison-32k,codechat-bison,codechat-bison-32k,text-bison,text-bison-32k,text-unicorn,code-gecko,code-bison,code-bison-32k" 117 | # GOOGLE_REVERSE_PROXY= "" 118 | 119 | #============# 120 | # OpenAI # 121 | #============# 122 | 123 | # OPENAI_API_KEY = var.openai_key 124 | # OPENAI_MODELS = "gpt-3.5-turbo-1106,gpt-4-1106-preview,gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314,gpt-4-0613" 125 | 126 | DEBUG_OPENAI = false 127 | 128 | # TITLE_CONVO = false 129 | # OPENAI_TITLE_MODEL = "gpt-3.5-turbo" 130 | 131 | # OPENAI_SUMMARIZE = true 132 | # OPENAI_SUMMARY_MODEL = "gpt-3.5-turbo" 133 | 134 | # OPENAI_FORCE_PROMPT = true 135 | 136 | # OPENAI_REVERSE_PROXY = "" 137 | 138 | #============# 139 | # OpenRouter # 140 | #============# 141 | 142 | # OPENROUTER_API_KEY = 143 | 144 | #============# 145 | # Plugins # 146 | #============# 147 | 148 | # PLUGIN_MODELS = "gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,gpt-4,gpt-4-0314,gpt-4-0613" 149 | 150 | DEBUG_PLUGINS = true 151 | 152 | CREDS_KEY = random_string.creds_key.result 153 | CREDS_IV = random_string.creds_iv.result 154 | 155 | # Azure AI Search 156 | #----------------- 157 | # AZURE_AI_SEARCH_SERVICE_ENDPOINT= 158 | # AZURE_AI_SEARCH_INDEX_NAME= 159 | # AZURE_AI_SEARCH_API_KEY= 160 | 161 | # AZURE_AI_SEARCH_API_VERSION= 162 | # AZURE_AI_SEARCH_SEARCH_OPTION_QUERY_TYPE= 163 | # AZURE_AI_SEARCH_SEARCH_OPTION_TOP= 164 | # AZURE_AI_SEARCH_SEARCH_OPTION_SELECT= 165 | 166 | # DALL·E 3 167 | #---------------- 168 | # DALLE_API_KEY= 169 | # DALLE3_SYSTEM_PROMPT="Your System Prompt here" 170 | # DALLE_REVERSE_PROXY= 171 | 172 | # Google 173 | #----------------- 174 | # GOOGLE_API_KEY= 175 | # GOOGLE_CSE_ID= 176 | 177 | # SerpAPI 178 | #----------------- 179 | # SERPAPI_API_KEY= 180 | 181 | # Stable Diffusion 182 | #----------------- 183 | # SD_WEBUI_URL=http://host.docker.internal:7860 184 | 185 | # WolframAlpha 186 | #----------------- 187 | # WOLFRAM_APP_ID= 188 | 189 | # Zapier 190 | #----------------- 191 | # ZAPIER_NLA_API_KEY= 192 | 193 | #==================================================# 194 | # Search # 195 | #==================================================# 196 | 197 | SEARCH = true 198 | MEILI_NO_ANALYTICS = true 199 | MEILI_HOST = "${azurerm_linux_web_app.meilisearch.name}.azurewebsites.net" 200 | # MEILI_HTTP_ADDR=0.0.0.0:7700 201 | MEILI_MASTER_KEY = random_string.meilisearch_master_key.result 202 | 203 | #===================================================# 204 | # User System # 205 | #===================================================# 206 | 207 | #========================# 208 | # Moderation # 209 | #========================# 210 | 211 | BAN_VIOLATIONS = true 212 | BAN_DURATION = 1000 * 60 * 60 * 2 213 | BAN_INTERVAL = 20 214 | 215 | LOGIN_VIOLATION_SCORE = 1 216 | REGISTRATION_VIOLATION_SCORE = 1 217 | CONCURRENT_VIOLATION_SCORE = 1 218 | MESSAGE_VIOLATION_SCORE = 1 219 | NON_BROWSER_VIOLATION_SCORE = 20 220 | 221 | LOGIN_MAX = 7 222 | LOGIN_WINDOW = 5 223 | REGISTER_MAX = 5 224 | REGISTER_WINDOW = 60 225 | 226 | LIMIT_CONCURRENT_MESSAGES = true 227 | CONCURRENT_MESSAGE_MAX = 2 228 | 229 | LIMIT_MESSAGE_IP = true 230 | MESSAGE_IP_MAX = 40 231 | MESSAGE_IP_WINDOW = 1 232 | 233 | LIMIT_MESSAGE_USER = false 234 | MESSAGE_USER_MAX = 40 235 | MESSAGE_USER_WINDOW = 1 236 | 237 | #========================# 238 | # Balance # 239 | #========================# 240 | 241 | CHECK_BALANCE = false 242 | 243 | #========================# 244 | # Registration and Login # 245 | #========================# 246 | 247 | ALLOW_EMAIL_LOGIN = true 248 | ALLOW_REGISTRATION = true 249 | ALLOW_SOCIAL_LOGIN = false 250 | ALLOW_SOCIAL_REGISTRATION = false 251 | 252 | SESSION_EXPIRY = 1000 * 60 * 15 253 | REFRESH_TOKEN_EXPIRY = (1000 * 60 * 60 * 24) * 7 254 | 255 | JWT_SECRET = random_string.jwt_secret.result 256 | JWT_REFRESH_SECRET = random_string.jwt_refresh_secret.result 257 | 258 | # Discord 259 | # DISCORD_CLIENT_ID= 260 | # DISCORD_CLIENT_SECRET= 261 | # DISCORD_CALLBACK_URL=/oauth/discord/callback 262 | 263 | # Facebook 264 | # FACEBOOK_CLIENT_ID= 265 | # FACEBOOK_CLIENT_SECRET= 266 | # FACEBOOK_CALLBACK_URL=/oauth/facebook/callback 267 | 268 | # GitHub 269 | # GITHUB_CLIENT_ID= 270 | # GITHUB_CLIENT_SECRET= 271 | # GITHUB_CALLBACK_URL=/oauth/github/callback 272 | 273 | # Google 274 | # GOOGLE_CLIENT_ID= 275 | # GOOGLE_CLIENT_SECRET= 276 | # GOOGLE_CALLBACK_URL=/oauth/google/callback 277 | 278 | # OpenID 279 | # OPENID_CLIENT_ID= 280 | # OPENID_CLIENT_SECRET= 281 | # OPENID_ISSUER= 282 | # OPENID_SESSION_SECRET= 283 | # OPENID_SCOPE="openid profile email" 284 | # OPENID_CALLBACK_URL=/oauth/openid/callback 285 | 286 | # OPENID_BUTTON_LABEL= 287 | # OPENID_IMAGE_URL= 288 | 289 | #========================# 290 | # Email Password Reset # 291 | #========================# 292 | 293 | # EMAIL_SERVICE= 294 | # EMAIL_HOST= 295 | # EMAIL_PORT=25 296 | # EMAIL_ENCRYPTION= 297 | # EMAIL_ENCRYPTION_HOSTNAME= 298 | # EMAIL_ALLOW_SELFSIGNED= 299 | # EMAIL_USERNAME= 300 | # EMAIL_PASSWORD= 301 | # EMAIL_FROM_NAME= 302 | # EMAIL_FROM=noreply@librechat.ai 303 | 304 | #==================================================# 305 | # Others # 306 | #==================================================# 307 | # You should leave the following commented out # 308 | 309 | # NODE_ENV= 310 | 311 | # REDIS_URI= 312 | # USE_REDIS= 313 | 314 | # E2E_USER_EMAIL= 315 | # E2E_USER_PASSWORD= 316 | 317 | #=============================================================# 318 | # Azure App Service Configuration # 319 | #=============================================================# 320 | 321 | WEBSITE_RUN_FROM_PACKAGE = "1" 322 | DOCKER_REGISTRY_SERVER_URL = "https://index.docker.io" 323 | WEBSITES_ENABLE_APP_SERVICE_STORAGE = false 324 | DOCKER_ENABLE_CI = false 325 | WEBSITES_PORT = 80 326 | PORT = 80 327 | DOCKER_CUSTOM_IMAGE_NAME = "ghcr.io/danny-avila/librechat-dev-api:latest" 328 | NODE_ENV = "production" 329 | } 330 | virtual_network_subnet_id = azurerm_subnet.librechat_subnet.id 331 | 332 | depends_on = [azurerm_linux_web_app.meilisearch, azurerm_cosmosdb_account.librechat, module.openai] 333 | # depends_on = [azurerm_linux_web_app.meilisearch] 334 | } 335 | 336 | # Deploy code from a public GitHub repo 337 | # resource "azurerm_app_service_source_control" "sourcecontrol" { 338 | # app_id = azurerm_linux_web_app.librechat.id 339 | # repo_url = "https://github.com/danny-avila/LibreChat" 340 | # branch = "main" 341 | # type = "Github" 342 | 343 | # # use_manual_integration = true 344 | # # use_mercurial = false 345 | # depends_on = [ 346 | # azurerm_linux_web_app.librechat, 347 | # ] 348 | # } 349 | 350 | # resource "azurerm_app_service_virtual_network_swift_connection" "librechat" { 351 | # app_service_id = azurerm_linux_web_app.librechat.id 352 | # subnet_id = module.vnet.vnet_subnets_name_id["subnet0"] 353 | 354 | # depends_on = [ 355 | # azurerm_linux_web_app.librechat, 356 | # module.vnet 357 | # ] 358 | # } 359 | 360 | #TODO: privately communicate between librechat and meilisearch, right now it is via public internet 361 | resource "azurerm_linux_web_app" "meilisearch" { 362 | name = "meilisearchapp${random_string.random_postfix.result}" 363 | location = azurerm_resource_group.this.location 364 | resource_group_name = azurerm_resource_group.this.name 365 | service_plan_id = azurerm_service_plan.librechat.id 366 | 367 | app_settings = { 368 | WEBSITES_ENABLE_APP_SERVICE_STORAGE = false 369 | 370 | MEILI_MASTER_KEY = random_string.meilisearch_master_key.result 371 | MEILI_NO_ANALYTICS = true 372 | 373 | DOCKER_REGISTRY_SERVER_URL = "https://index.docker.io" 374 | WEBSITES_ENABLE_APP_SERVICE_STORAGE = false 375 | DOCKER_ENABLE_CI = false 376 | WEBSITES_PORT = 7700 377 | PORT = 7700 378 | DOCKER_CUSTOM_IMAGE_NAME = "getmeili/meilisearch:latest" 379 | } 380 | 381 | site_config { 382 | always_on = "true" 383 | ip_restriction { 384 | virtual_network_subnet_id = azurerm_subnet.librechat_subnet.id 385 | priority = 100 386 | name = "Allow from LibreChat subnet" 387 | action = "Allow" 388 | } 389 | } 390 | 391 | logs { 392 | http_logs { 393 | file_system { 394 | retention_in_days = 7 395 | retention_in_mb = 35 396 | } 397 | } 398 | application_logs { 399 | file_system_level = "Information" 400 | } 401 | } 402 | 403 | # identity { 404 | # type = "SystemAssigned" 405 | # } 406 | 407 | } 408 | --------------------------------------------------------------------------------