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
13 changes: 13 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
PORT=3000
NODE_ENV=development

# Logging (structured JSON logging)
# LOG_LEVEL=info # debug | info | warn | error (default: info)
# LOG_FORMAT=text # json | text (default: json in production, text in development)

# MongoDB
# When using Docker Compose: mongodb://openthreads:openthreads@localhost:27017/openthreads
MONGODB_URI=mongodb://openthreads:openthreads@localhost:27017/openthreads
Expand Down Expand Up @@ -53,3 +57,12 @@ OPENTHREADS_BASE_URL=http://localhost:3000
# TRUST_JWS_ALGORITHM=RS256
# TRUST_PRIVATE_KEY_PATH=./keys/private.pem
# TRUST_PUBLIC_KEY_PATH=./keys/public.pem

# =============================================================================
# Observability (optional)
# =============================================================================

# OpenTelemetry — set OTEL_EXPORTER_OTLP_ENDPOINT to enable tracing
# OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
# OTEL_SERVICE_NAME=openthreads
# OTEL_SDK_DISABLED=false
53 changes: 53 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ─── Build stage ─────────────────────────────────────────────────────────────
FROM oven/bun:1.2 AS builder

WORKDIR /app

# Copy workspace manifests first for layer caching
COPY package.json bun.lockb* ./
COPY packages/core/package.json ./packages/core/
COPY packages/server/package.json ./packages/server/
COPY packages/storage/mongodb/package.json ./packages/storage/mongodb/
COPY packages/trust/package.json ./packages/trust/
COPY packages/channels/package.json ./packages/channels/
COPY packages/channels/discord/package.json ./packages/channels/discord/
COPY packages/channels/slack/package.json ./packages/channels/slack/
COPY packages/channels/telegram/package.json ./packages/channels/telegram/
COPY packages/channels/whatsapp/package.json ./packages/channels/whatsapp/

RUN bun install --frozen-lockfile

# Copy source
COPY tsconfig.base.json tsconfig.json ./
COPY packages ./packages

# Build the Next.js server
WORKDIR /app/packages/server
ENV NEXT_TELEMETRY_DISABLED=1
RUN bun run build

# ─── Production stage ─────────────────────────────────────────────────────────
FROM oven/bun:1.2-slim AS runner

WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000

RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs

# Copy built artifacts
COPY --from=builder /app/packages/server/.next/standalone ./
COPY --from=builder /app/packages/server/.next/static ./packages/server/.next/static
COPY --from=builder /app/packages/server/public ./packages/server/public 2>/dev/null || true

USER nextjs

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD bun -e "fetch('http://localhost:3000/api/health').then(r=>r.ok?process.exit(0):process.exit(1)).catch(()=>process.exit(1))"

CMD ["bun", "packages/server/server.js"]
21 changes: 21 additions & 0 deletions deploy/helm/openthreads/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: v2
name: openthreads
description: >
OpenThreads — a unified messaging gateway with human-in-the-loop support.
Bridges Slack, Discord, Telegram, WhatsApp, and other channels to any
HTTP-based agent or service via the A2H protocol.
type: application
version: 0.1.0
appVersion: "0.1.0"
keywords:
- openthreads
- a2h
- human-in-the-loop
- messaging
- webhook
home: https://github.com/deepducks/OpenThreads
sources:
- https://github.com/deepducks/OpenThreads
maintainers:
- name: DeepDucks
url: https://github.com/deepducks
60 changes: 60 additions & 0 deletions deploy/helm/openthreads/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "openthreads.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "openthreads.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart label.
*/}}
{{- define "openthreads.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels.
*/}}
{{- define "openthreads.labels" -}}
helm.sh/chart: {{ include "openthreads.chart" . }}
{{ include "openthreads.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels.
*/}}
{{- define "openthreads.selectorLabels" -}}
app.kubernetes.io/name: {{ include "openthreads.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
ServiceAccount name.
*/}}
{{- define "openthreads.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "openthreads.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
74 changes: 74 additions & 0 deletions deploy/helm/openthreads/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "openthreads.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- if .Values.metrics.annotations }}
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.service.port }}"
prometheus.io/path: "/api/metrics"
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "openthreads.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "openthreads.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
envFrom:
- secretRef:
name: {{ if .Values.existingSecret }}{{ .Values.existingSecret }}{{ else }}{{ include "openthreads.fullname" . }}{{ end }}
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
22 changes: 22 additions & 0 deletions deploy/helm/openthreads/templates/hpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "openthreads.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
35 changes: 35 additions & 0 deletions deploy/helm/openthreads/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "openthreads.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
15 changes: 15 additions & 0 deletions deploy/helm/openthreads/templates/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{- if not .Values.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
type: Opaque
stringData:
{{- range $key, $value := .Values.secrets }}
{{- if $value }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
{{- end }}
15 changes: 15 additions & 0 deletions deploy/helm/openthreads/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "openthreads.selectorLabels" . | nindent 4 }}
13 changes: 13 additions & 0 deletions deploy/helm/openthreads/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "openthreads.serviceAccountName" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}
Loading