Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion nginx-ssl/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ resource "nomad_job" "nginx-ssl" {
vars = {
dc = jsonencode([var.dc])
namespace = var.namespace
hosts = jsonencode(var.hosts)
docker_image = local.docker_image
docker_always_pull = jsonencode(local.docker_always_pull)
service_provider = var.service_provider
Expand Down
95 changes: 95 additions & 0 deletions ollama/input.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

///////////////////////////////////////////////////////////////////////////////
// VARIABLES

variable "dc" {
description = "data centers that the job is eligible to run in"
type = list(string)
}

variable "namespace" {
description = "namespace that the job runs in"
type = string
default = "default"
}

variable "enabled" {
type = bool
description = "If false, then no job is deployed"
default = true
}

variable "service_provider" {
description = "Service provider, either consul or nomad"
type = string
default = "nomad"
}

variable "service_name" {
description = "Service name"
type = string
default = "ollama"
}

variable "service_dns" {
description = "Service discovery DNS"
type = list(string)
default = []
}

variable "docker_tag" {
type = string
description = "Version of the docker image to use, defaults to latest"
default = "latest"
}

variable "docker_tag_webui" {
type = string
description = "Version of the docker image to use for webui, set to empty string to disable"
default = "main"
}

///////////////////////////////////////////////////////////////////////////////

variable "hosts" {
description = "List of hosts to deploy ollama on. If empty, one allocation will be created"
type = list(string)
default = []
}

variable "hosts_webui" {
description = "List of hosts to deploy webui on. If empty, one allocation will be created"
type = list(string)
default = []
}

variable "port" {
description = "Ollama port to expose"
type = number
default = 11434
}

variable "port_webui" {
description = "WebUI port to expose"
type = number
default = 11435
}

variable "data" {
description = "Persistent data path"
type = string
default = "ollama"
}

variable "devices" {
description = "Devices to expose"
type = list(string)
default = []
}

variable "openai_api_key" {
description = "OpenAI API Key"
type = string
sensitive = true
default = ""
}
6 changes: 6 additions & 0 deletions ollama/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

locals {
docker_image = "ollama/ollama:${var.docker_tag}"
docker_image_webui = var.docker_tag_webui == "" ? "" : "ghcr.io/open-webui/open-webui:${var.docker_tag_webui}"
docker_always_pull = var.docker_tag == "latest" ? true : false
}
26 changes: 26 additions & 0 deletions ollama/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

resource "nomad_job" "ollama" {
count = var.enabled ? 1 : 0
jobspec = file("${path.module}/nomad/ollama.hcl")

hcl2 {
allow_fs = true
vars = {
dc = jsonencode(var.dc)
namespace = var.namespace
docker_image = local.docker_image
docker_image_webui = local.docker_image_webui
docker_always_pull = jsonencode(local.docker_always_pull)
service_provider = var.service_provider
service_dns = jsonencode(var.service_dns)
service_name = var.service_name
hosts = jsonencode(var.hosts)
hosts_webui = jsonencode(var.hosts_webui)
port = var.port
port_webui = var.port_webui
data = var.data
devices = jsonencode(var.devices)
openai_api_key = var.openai_api_key
}
}
}
222 changes: 222 additions & 0 deletions ollama/nomad/ollama.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@

// ollama LLM
// Docker Image: ollama/ollama

///////////////////////////////////////////////////////////////////////////////
// VARIABLES

variable "dc" {
description = "data centers that the job is eligible to run in"
type = list(string)
}

variable "namespace" {
description = "namespace that the job runs in"
type = string
default = "default"
}

variable "service_provider" {
description = "Service provider, either consul or nomad"
type = string
default = "nomad"
}

variable "service_name" {
description = "Service name"
type = string
default = "ollama"
}

variable "service_dns" {
description = "Service discovery DNS"
type = list(string)
default = []
}

variable "docker_image" {
description = "Docker image"
type = string
default = "ollama/ollama:latest"
}

variable "docker_image_webui" {
description = "Docker image"
type = string
default = "ghcr.io/open-webui/open-webui:main"
}

variable "docker_always_pull" {
description = "Pull docker image on every job restart"
type = bool
default = false
}

///////////////////////////////////////////////////////////////////////////////

variable "hosts" {
description = "List of hosts to deploy on. If empty, one allocation will be created"
type = list(string)
default = []
}

variable "port" {
description = "Ollama port to expose"
type = number
default = 11434
}

variable "data" {
description = "Persistent data path"
type = string
default = ""
}

variable "devices" {
description = "Devices to expose"
type = list(string)
default = []
}

variable "hosts_webui" {
description = "List of hosts to deploy webui on. If empty, one allocation will be created"
type = list(string)
default = []
}

variable "port_webui" {
description = "WebUI port to expose"
type = number
default = 11435
}

variable "openai_api_key" {
description = "OpenAI API key"
type = string
default = ""
}

///////////////////////////////////////////////////////////////////////////////
// LOCALS

locals {
devices = [
for device in var.devices : {
host_path = device
container_path = device
}
]
volumes = compact([
var.data != "" ? format("%s:/root/.ollama", var.data) : null,
])
volumes_webui = compact([
var.data != "" ? format("%s:/app/backend/data", var.data) : null,
])
ollama_service = format("http://%s-http.%s.nomad.:%s", var.service_name, var.namespace, var.port)
}

///////////////////////////////////////////////////////////////////////////////
// JOB

job "ollama" {
type = "service"
datacenters = var.dc
namespace = var.namespace

update {
min_healthy_time = "10s"
healthy_deadline = "5m"
health_check = "task_states"
}

/////////////////////////////////////////////////////////////////////////////////

group "ollama" {
count = var.docker_image_webui == "" ? 0 : (length(var.hosts) == 0 ? 1 : length(var.hosts))

dynamic "constraint" {
for_each = length(var.hosts) == 0 ? [] : [join(",", var.hosts)]
content {
attribute = node.unique.name
operator = "set_contains_any"
value = constraint.value
}
}

network {
port "http" {
static = var.port
to = 11434
}
}

service {
tags = [var.service_name, "http"]
name = format("%s-%s", var.service_name, "http")
port = "http"
provider = var.service_provider
}

task "server" {
driver = "docker"

config {
image = var.docker_image
force_pull = var.docker_always_pull
ports = ["http"]
dns_servers = var.service_dns
volumes = local.volumes
devices = local.devices
}

} // task "server"
} // group "ollama"


/////////////////////////////////////////////////////////////////////////////////

group "ollama-webui" {
count = length(var.hosts_webui) == 0 ? 1 : length(var.hosts_webui)

dynamic "constraint" {
for_each = length(var.hosts_webui) == 0 ? [] : [join(",", var.hosts_webui)]
content {
attribute = node.unique.name
operator = "set_contains_any"
value = constraint.value
}
}

network {
port "http" {
static = var.port_webui
to = 8080
}
}

service {
tags = [var.service_name, "webui", "http"]
name = format("%s-webui-%s", var.service_name, "http")
port = "http"
provider = var.service_provider
}

task "server" {
driver = "docker"

env {
OLLAMA_BASE_URL = local.ollama_service
OPENAI_API_KEYS = var.openai_api_key
OPENAI_API_BASE_URLS = var.openai_api_key == "" ? "" : "https://api.openai.com/v1"
}

config {
image = var.docker_image_webui
force_pull = var.docker_always_pull
ports = ["http"]
dns_servers = var.service_dns
volumes = local.volumes
}
} // task "server"
} // group "ollama-webui"
} // job "ollama"
18 changes: 18 additions & 0 deletions ollama/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

output "enabled" {
value = var.enabled
}

output "service-http" {
value = {
name = format("%s-%s.%s.%s.", var.service_name, "http", var.namespace, "nomad")
port = var.port
}
}

output "service-webui-http" {
value = {
name = format("%s-webui-%s.%s.%s.", var.service_name, "http", var.namespace, "nomad")
port = var.port_webui
}
}
9 changes: 9 additions & 0 deletions ollama/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

terraform {
required_providers {
nomad = {
source = "hashicorp/nomad"
version = "~> 2.0.0"
}
}
}