Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bf831dc
Add dockerfile
kowtom Jan 3, 2026
3531cad
Add helm chart
kowtom Jan 3, 2026
437f8e1
Pin package versions and reference tags
kowtom Jan 4, 2026
b413a4d
Merge remote-tracking branch 'origin/main' into feature/kubernetes-he…
kowtom Jan 6, 2026
a26288f
Ignore dependencies
kowtom Jan 6, 2026
2a4ee12
Update helm/gomodel/Chart.yaml
kowtom Jan 6, 2026
aca491f
Remove misleading comment
kowtom Jan 6, 2026
850f38d
Make it fail when neither TargetCPU nor TargetMemory is provided
kowtom Jan 6, 2026
d8b5933
Fail when invalid PDB configuration is provided
kowtom Jan 6, 2026
a472ac1
Add json scheme for validation
kowtom Jan 6, 2026
8ad61c1
Make secret configuration more dynamic
kowtom Jan 7, 2026
c525911
Use default user provided by distroless nonroot
kowtom Jan 7, 2026
0b1edd2
Get rid of the redundant gomodel directory in helm
kowtom Jan 8, 2026
205f677
Pin version and update redis
kowtom Jan 8, 2026
c11b6bd
Replace placeholder
kowtom Jan 8, 2026
9845aec
Add dockerignore
kowtom Jan 8, 2026
53154a8
Add validation for parentRef.name
kowtom Jan 8, 2026
e857e38
Update .dockerignore
SantiagoDePolonia Jan 14, 2026
cf02acd
Add todo
kowtom Jan 15, 2026
bee7cf5
Correct readme
kowtom Jan 15, 2026
b5eef50
Require redis url when cache type is redis
kowtom Jan 15, 2026
fd0b251
Add credentials validation for each provider
kowtom Jan 15, 2026
065167c
Remove local cache
kowtom Jan 15, 2026
fbe2fb4
Fix formatting
kowtom Jan 15, 2026
c792a7f
Allow empty redis url when the bitnami subchart is used
kowtom Jan 15, 2026
80072d1
Fix copying
kowtom Jan 15, 2026
d9a55be
Update paths in readme
kowtom Jan 15, 2026
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
70 changes: 70 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# ===================
# Git
# ===================
.git
.gitignore

# ===================
# Build artifacts
# ===================
bin/
gomodel
coverage.out

# ===================
# Tests
# ===================
tests/
**/*_test.go

# ===================
# Documentation
# ===================
*.md
LICENSE

# ===================
# CI/CD & Release
# ===================
.github/
.goreleaser.yaml

# ===================
# Development tooling
# ===================
.golangci.yml
.pre-commit-config.yaml
Makefile

# ===================
# Docker & Kubernetes
# ===================
Dockerfile
.dockerignore
docker-compose.yaml
helm/
prometheus.yml

# ===================
# IDE & Editor configs
# ===================
.claude/
.vscode/
.idea/
*.swp
*.swo
*~

# ===================
# Environment & Secrets
# ===================
.env
.env.*

# ===================
# Miscellaneous
# ===================
.cache/
*.bck.yml
repomix-output.*
session-*.md
Comment thread
SantiagoDePolonia marked this conversation as resolved.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
/*.bck.yml
/repomix-output.*
/coverage.out

# Helm chart dependencies
**/charts/*.tgz
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Build stage
FROM golang:1.24-alpine3.23 AS builder

WORKDIR /app

# Install ca-certificates for HTTPS requests
RUN apk add --no-cache ca-certificates=20251003-r0

# Download dependencies first for better layer caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source and build
COPY . .
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
kowtom marked this conversation as resolved.
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /gomodel ./cmd/gomodel
Comment thread
kowtom marked this conversation as resolved.

# Runtime stage
FROM gcr.io/distroless/static-debian12:nonroot
Comment thread
kowtom marked this conversation as resolved.

# Copy binary and ca-certificates
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /gomodel /gomodel
COPY --from=builder /app/config/*.yaml /app/config/

WORKDIR /app

EXPOSE 8080

ENTRYPOINT ["/gomodel"]
Comment thread
SantiagoDePolonia marked this conversation as resolved.
6 changes: 6 additions & 0 deletions helm/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dependencies:
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
version: 24.1.0
digest: sha256:46e96c6627f431805f1ded87a1d15a25c3aaf648a1242343f52b8c6a51e2cb2f
generated: "2026-01-08T06:38:01.742616425+01:00"
30 changes: 30 additions & 0 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: v2
name: gomodel
description: High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, xAI)
type: application
version: 0.1.0
appVersion: "1.0.0"

keywords:
- llm
- ai
- gateway
- openai
- anthropic
- gemini
- groq
- xai
- proxy

home: https://github.com/ENTERPILOT/GOModel
sources:
- https://github.com/ENTERPILOT/GOModel

maintainers:
- name: GOModel Team
Comment thread
SantiagoDePolonia marked this conversation as resolved.

dependencies:
- name: redis
version: "^24.0.0"
repository: oci://registry-1.docker.io/bitnamicharts
condition: redis.enabled
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
kowtom marked this conversation as resolved.
144 changes: 144 additions & 0 deletions helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# GOModel Helm Chart

High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, xAI).

## Prerequisites

- Kubernetes 1.29+ (for Gateway API v1 support)
- Helm 3.x
- (Optional) Prometheus Operator for ServiceMonitor support

## Installation

### Add the Helm repository (if published)

```bash
helm repo add gomodel https://your-org.github.io/gomodel
helm repo update
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

### Install from local chart

```bash
# Basic install with OpenAI
helm install gomodel ./helm \
-n gomodel --create-namespace \
--set providers.openai.enabled=true \
--set providers.openai.apiKey="sk-..."

# Multi-provider setup with Redis cache
helm install gomodel ./helm \
-n gomodel --create-namespace \
--set providers.openai.enabled=true \
--set providers.openai.apiKey="sk-..." \
--set providers.anthropic.enabled=true \
--set providers.anthropic.apiKey="sk-ant-..." \
--set redis.enabled=true

# Using existing secrets (GitOps-friendly)
helm install gomodel ./helm \
-n gomodel --create-namespace \
--set providers.existingSecret="llm-api-keys" \
--set providers.openai.enabled=true \
--set providers.anthropic.enabled=true
```

## Configuration

### Key Values

| Parameter | Description | Default |
|-----------|-------------|---------|
| `replicaCount` | Number of replicas | `2` |
| `image.repository` | Image repository | `enterpilot/gomodel` |
| `image.tag` | Image tag | `""` (uses appVersion) |
Comment thread
SantiagoDePolonia marked this conversation as resolved.
| `server.port` | Server port | `8080` |
| `server.bodySizeLimit` | Max request body size | `"10M"` |
| `auth.masterKey` | Master key for auth | `""` |
| `auth.existingSecret` | Existing secret for auth | `""` |
| `providers.existingSecret` | Existing secret for API keys | `""` |
| `providers.openai.enabled` | Enable OpenAI | `false` |
| `providers.anthropic.enabled` | Enable Anthropic | `false` |
| `providers.gemini.enabled` | Enable Gemini | `false` |
| `providers.groq.enabled` | Enable Groq | `false` |
| `providers.xai.enabled` | Enable xAI | `false` |
| `cache.type` | Cache type (local/redis) | `"redis"` |
| `redis.enabled` | Deploy Redis subchart | `true` |
| `metrics.enabled` | Enable Prometheus metrics | `true` |
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor | `false` |
| `ingress.enabled` | Enable Ingress | `false` |
| `gateway.enabled` | Enable Gateway API HTTPRoute | `false` |
| `autoscaling.enabled` | Enable HPA | `false` |

### Using Existing Secrets

Create a secret with your API keys:

```yaml
apiVersion: v1
kind: Secret
metadata:
name: llm-api-keys
type: Opaque
stringData:
OPENAI_API_KEY: "sk-..."
ANTHROPIC_API_KEY: "sk-ant-..."
GEMINI_API_KEY: "..."
```

Then reference it:

```bash
helm install gomodel ./helm \
--set providers.existingSecret="llm-api-keys" \
--set providers.openai.enabled=true
```

### Ingress Example

```yaml
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: gomodel.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: gomodel-tls
hosts:
- gomodel.example.com
```

### Gateway API Example

```yaml
gateway:
enabled: true
parentRef:
name: my-gateway
namespace: gateway-system
hostnames:
- gomodel.example.com
```

## Upgrading

```bash
helm upgrade gomodel ./helm -n gomodel -f values.yaml
```

## Uninstalling

```bash
helm uninstall gomodel -n gomodel
```

# Todo

- Add a values-demo.yaml file with a demo setup ready to run
- Consider adding prometheus + grafana stack as an optional subchart
- Add an example for production-ready redis configuration with persistence and authentication enabled
57 changes: 57 additions & 0 deletions helm/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Thank you for installing {{ .Chart.Name }}!

Your release is named: {{ .Release.Name }}

To get the application URL:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ (first $host.paths).path }}
{{- end }}
{{- else if .Values.gateway.enabled }}
Configure your Gateway to route traffic to the service.
Service: {{ include "gomodel.fullname" . }}:{{ .Values.service.port }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gomodel.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status with: kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "gomodel.fullname" . }}
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "gomodel.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "gomodel.fullname" . }} 8080:{{ .Values.service.port }}
echo "Visit http://127.0.0.1:8080 to use the API"
{{- end }}

{{- if not .Values.auth.masterKey }}
{{- if not .Values.auth.existingSecret }}

⚠️ WARNING: No authentication configured!
The gateway is running in UNSAFE MODE without authentication.
Set auth.masterKey or auth.existingSecret for production use.
{{- end }}
{{- end }}

{{- $enabledProviders := list }}
{{- if .Values.providers.openai.enabled }}{{ $enabledProviders = append $enabledProviders "openai" }}{{ end }}
{{- if .Values.providers.anthropic.enabled }}{{ $enabledProviders = append $enabledProviders "anthropic" }}{{ end }}
{{- if .Values.providers.gemini.enabled }}{{ $enabledProviders = append $enabledProviders "gemini" }}{{ end }}
{{- if .Values.providers.groq.enabled }}{{ $enabledProviders = append $enabledProviders "groq" }}{{ end }}
{{- if .Values.providers.xai.enabled }}{{ $enabledProviders = append $enabledProviders "xai" }}{{ end }}

{{- if eq (len $enabledProviders) 0 }}

⚠️ WARNING: No providers enabled!
Enable at least one provider (e.g., providers.openai.enabled=true)
{{- else }}

Enabled providers: {{ join ", " $enabledProviders }}
{{- end }}

To check the logs:
kubectl logs --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "gomodel.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -f

To test the health endpoint:
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "gomodel.fullname" . }} 8080:{{ .Values.service.port }} &
curl http://127.0.0.1:8080/health
Comment thread
kowtom marked this conversation as resolved.
Loading