diff --git a/activemq-helm-chart/Chart.yaml b/activemq-helm-chart/Chart.yaml
new file mode 100644
index 0000000000..b3c364e030
--- /dev/null
+++ b/activemq-helm-chart/Chart.yaml
@@ -0,0 +1,15 @@
+apiVersion: v2
+name: activemq
+description: A Helm chart for Apache ActiveMQ
+type: application
+version: 1.0.0
+appVersion: "latest"
+keywords:
+ - activemq
+ - message queue
+ - messaging
+home: https://activemq.apache.org
+sources:
+ - https://github.com/apache/activemq
+maintainers:
+ - name: activemq
\ No newline at end of file
diff --git a/activemq-helm-chart/README.md b/activemq-helm-chart/README.md
new file mode 100644
index 0000000000..a764417277
--- /dev/null
+++ b/activemq-helm-chart/README.md
@@ -0,0 +1,138 @@
+# ActiveMQ Helm Chart
+
+A Helm chart for deploying Apache ActiveMQ on Kubernetes.
+
+## Introduction
+
+This chart bootstraps an ActiveMQ deployment on a Kubernetes cluster using the Helm package manager.
+
+## Prerequisites
+
+- Kubernetes 1.19+
+- Helm 3.0+
+- PV provisioner support in the underlying infrastructure (if persistence is enabled)
+
+## Installing the Chart
+
+To install the chart with the release name `my-activemq`:
+
+```bash
+helm install my-activemq .
+```
+
+## Uninstalling the Chart
+
+To uninstall/delete the `my-activemq` deployment:
+
+```bash
+helm uninstall my-activemq
+```
+
+## Configuration
+
+The following table lists the configurable parameters of the ActiveMQ chart and their default values.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `replicaCount` | Number of replicas | `1` |
+| `image.repository` | ActiveMQ image repository | `apache/activemq-classic` |
+| `image.tag` | ActiveMQ image tag | `latest` |
+| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
+| `auth.username` | ActiveMQ admin username | `admin` |
+| `auth.password` | ActiveMQ admin password | `changeme` |
+| `service.type` | Kubernetes service type | `ClusterIP` |
+| `service.port` | OpenWire service port | `61616` |
+| `service.webConsolePort` | Web Console port | `8161` |
+| `persistence.enabled` | Enable persistence using PVC | `false` |
+| `persistence.storageClass` | PVC Storage Class | `""` |
+| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` |
+| `persistence.size` | PVC Storage Request | `8Gi` |
+| `resources.limits.cpu` | CPU limit | `1000m` |
+| `resources.limits.memory` | Memory limit | `2Gi` |
+| `resources.requests.cpu` | CPU request | `500m` |
+| `resources.requests.memory` | Memory request | `1Gi` |
+| `livenessProbe.enabled` | Enable liveness probe | `true` |
+| `readinessProbe.enabled` | Enable readiness probe | `true` |
+| `ingress.enabled` | Enable ingress | `false` |
+| `config.activemqXmlPath` | Path to custom activemq.xml file | `""` |
+| `config.jettyXmlPath` | Path to custom jetty.xml file | `""` |
+| `tls.enabled` | Enable TLS/SSL | `false` |
+| `tls.keystoreSecret` | Kubernetes secret containing broker.ks | `""` |
+| `tls.truststoreSecret` | Kubernetes secret containing broker.ts | `""` |
+| `tls.sslPort` | OpenWire SSL port | `61617` |
+| `tls.webConsoleSslPort` | Web Console SSL port | `8162` |
+
+## Accessing ActiveMQ
+
+### Web Console
+
+The ActiveMQ Web Console is accessible on port 8161. To access it locally:
+
+```bash
+kubectl port-forward svc/my-activemq 8161:8161
+```
+
+Then open http://localhost:8161 in your browser and login with the configured credentials.
+
+### OpenWire Connection
+
+Applications can connect to ActiveMQ on port 61616 using the service name:
+
+```
+tcp://my-activemq:61616
+```
+
+## Custom Configuration
+
+To use custom configuration files, place your files in the chart directory and specify the paths:
+
+```yaml
+config:
+ activemqXmlPath: "my-activemq.xml"
+ jettyXmlPath: "my-jetty.xml"
+```
+
+## Persistence
+
+The ActiveMQ image stores data at the `/opt/apache-activemq/data` path of the container.
+
+By default, the chart mounts a Persistent Volume at this location. The volume is created using dynamic volume provisioning.
+
+## TLS Configuration
+
+To enable TLS/SSL connections, you need to create Kubernetes secrets containing your keystore and truststore files.
+
+### Generate Test Certificates (for development)
+
+```bash
+# Generate keystore
+keytool -genkey -alias broker -keyalg RSA -keystore broker.ks \
+ -storepass changeit -keypass changeit \
+ -dname "CN=localhost, OU=Test, O=Test, L=Test, ST=Test, C=US"
+
+# Export certificate
+keytool -export -alias broker -keystore broker.ks \
+ -file broker.cert -storepass changeit
+
+# Create truststore
+keytool -import -alias broker -keystore broker.ts \
+ -file broker.cert -storepass changeit
+```
+
+### Create Kubernetes Secrets
+
+```bash
+kubectl create secret generic activemq-keystore --from-file=broker.ks
+kubectl create secret generic activemq-truststore --from-file=broker.ts
+```
+
+### Install with TLS Enabled
+
+```bash
+helm install my-activemq . \
+ --set tls.enabled=true \
+ --set tls.keystoreSecret=activemq-keystore \
+ --set tls.truststoreSecret=activemq-truststore
+```
+
+**Note:** When TLS is enabled, only SSL/TLS ports are exposed. Non-TLS ports are not available.
\ No newline at end of file
diff --git a/activemq-helm-chart/activemq_sample.xml b/activemq-helm-chart/activemq_sample.xml
new file mode 100644
index 0000000000..9f32bd90f5
--- /dev/null
+++ b/activemq-helm-chart/activemq_sample.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+ file:${activemq.conf}/credentials.properties
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/activemq-helm-chart/templates/NOTES.txt b/activemq-helm-chart/templates/NOTES.txt
new file mode 100644
index 0000000000..cf84715dd2
--- /dev/null
+++ b/activemq-helm-chart/templates/NOTES.txt
@@ -0,0 +1,39 @@
+1. Get the ActiveMQ Web Console URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "activemq.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo {{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://$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 of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "activemq.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "activemq.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo {{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://$SERVICE_IP:{{ if .Values.tls.enabled }}{{ .Values.tls.webConsoleSslPort }}{{ else }}{{ .Values.service.webConsolePort }}{{ end }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "activemq.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[1].containerPort}")
+ echo "Visit {{ if .Values.tls.enabled }}https://127.0.0.1:{{ .Values.tls.webConsoleSslPort }}{{ else }}http://127.0.0.1:{{ .Values.service.webConsolePort }}{{ end }} to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME {{ if .Values.tls.enabled }}{{ .Values.tls.webConsoleSslPort }}{{ else }}{{ .Values.service.webConsolePort }}{{ end }}:$CONTAINER_PORT
+{{- end }}
+
+2. Login credentials:
+ Username: {{ .Values.auth.username }}
+ Password: {{ .Values.auth.password }}
+
+3. To connect to ActiveMQ from applications:
+{{- if .Values.tls.enabled }}
+ Connection URL: ssl://{{ include "activemq.fullname" . }}:{{ .Values.tls.sslPort }}
+{{- else }}
+ Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }}
+{{- end }}
+
+{{- if .Values.tls.enabled }}
+4. TLS is enabled. Ensure you have created the required secrets:
+ - Keystore secret: {{ .Values.tls.keystoreSecret }}
+ - Truststore secret: {{ .Values.tls.truststoreSecret }}
+{{- end }}
\ No newline at end of file
diff --git a/activemq-helm-chart/templates/_helpers.tpl b/activemq-helm-chart/templates/_helpers.tpl
new file mode 100644
index 0000000000..8427364191
--- /dev/null
+++ b/activemq-helm-chart/templates/_helpers.tpl
@@ -0,0 +1,49 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "activemq.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+*/}}
+{{- define "activemq.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 name and version as used by the chart label.
+*/}}
+{{- define "activemq.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "activemq.labels" -}}
+helm.sh/chart: {{ include "activemq.chart" . }}
+{{ include "activemq.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "activemq.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "activemq.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
\ No newline at end of file
diff --git a/activemq-helm-chart/templates/configmap.yaml b/activemq-helm-chart/templates/configmap.yaml
new file mode 100644
index 0000000000..4d44407b38
--- /dev/null
+++ b/activemq-helm-chart/templates/configmap.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "activemq.fullname" . }}-config
+ labels:
+ {{- include "activemq.labels" . | nindent 4 }}
+data:
+ users.properties: |
+ {{ .Values.auth.username }}={{ .Values.auth.password }}
+ groups.properties: |
+ admins={{ .Values.auth.username }}
+ {{- if .Values.config.activemqXmlPath }}
+ activemq.xml: |
+{{ .Files.Get .Values.config.activemqXmlPath | indent 4 }}
+ {{- end }}
+ {{- if .Values.config.jettyXmlPath }}
+ jetty.xml: |
+{{ .Files.Get .Values.config.jettyXmlPath | indent 4 }}
+ {{- end }}
\ No newline at end of file
diff --git a/activemq-helm-chart/templates/service.yaml b/activemq-helm-chart/templates/service.yaml
new file mode 100644
index 0000000000..2e421e3657
--- /dev/null
+++ b/activemq-helm-chart/templates/service.yaml
@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "activemq.fullname" . }}
+ labels:
+ {{- include "activemq.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ {{- if not .Values.tls.enabled }}
+ - name: openwire
+ port: {{ .Values.service.port }}
+ targetPort: openwire
+ protocol: TCP
+ - name: webconsole
+ port: {{ .Values.service.webConsolePort }}
+ targetPort: webconsole
+ protocol: TCP
+ {{- else }}
+ - name: openwire-ssl
+ port: {{ .Values.tls.sslPort }}
+ targetPort: openwire-ssl
+ protocol: TCP
+ - name: webconsole-ssl
+ port: {{ .Values.tls.webConsoleSslPort }}
+ targetPort: webconsole-ssl
+ protocol: TCP
+ {{- end }}
+ selector:
+ {{- include "activemq.selectorLabels" . | nindent 4 }}
\ No newline at end of file
diff --git a/activemq-helm-chart/templates/statefulset.yaml b/activemq-helm-chart/templates/statefulset.yaml
new file mode 100644
index 0000000000..60d2d292bb
--- /dev/null
+++ b/activemq-helm-chart/templates/statefulset.yaml
@@ -0,0 +1,136 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ include "activemq.fullname" . }}
+ labels:
+ {{- include "activemq.labels" . | nindent 4 }}
+spec:
+ serviceName: {{ include "activemq.fullname" . }}
+ replicas: {{ .Values.replicaCount }}
+ selector:
+ matchLabels:
+ {{- include "activemq.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ annotations:
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "activemq.selectorLabels" . | nindent 8 }}
+ spec:
+ containers:
+ - name: activemq
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ {{- if not .Values.tls.enabled }}
+ - name: openwire
+ containerPort: 61616
+ protocol: TCP
+ - name: webconsole
+ containerPort: 8161
+ protocol: TCP
+ {{- else }}
+ - name: openwire-ssl
+ containerPort: {{ .Values.tls.sslPort }}
+ protocol: TCP
+ - name: webconsole-ssl
+ containerPort: {{ .Values.tls.webConsoleSslPort }}
+ protocol: TCP
+ {{- end }}
+ {{- if .Values.livenessProbe.enabled }}
+ livenessProbe:
+ tcpSocket:
+ port: {{ if .Values.tls.enabled }}openwire-ssl{{ else }}openwire{{ end }}
+ initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
+ failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
+ successThreshold: {{ .Values.livenessProbe.successThreshold }}
+ {{- end }}
+ {{- if .Values.readinessProbe.enabled }}
+ readinessProbe:
+ tcpSocket:
+ port: {{ if .Values.tls.enabled }}openwire-ssl{{ else }}openwire{{ end }}
+ initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
+ failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
+ successThreshold: {{ .Values.readinessProbe.successThreshold }}
+ {{- end }}
+ volumeMounts:
+ - name: data
+ mountPath: /opt/apache-activemq/data
+ - name: config
+ mountPath: /opt/apache-activemq/conf/users.properties
+ subPath: users.properties
+ - name: config
+ mountPath: /opt/apache-activemq/conf/groups.properties
+ subPath: groups.properties
+ {{- if .Values.config.activemqXmlPath }}
+ - name: config
+ mountPath: /opt/apache-activemq/conf/activemq.xml
+ subPath: activemq.xml
+ {{- end }}
+ {{- if .Values.config.jettyXmlPath }}
+ - name: config
+ mountPath: /opt/apache-activemq/conf/jetty.xml
+ subPath: jetty.xml
+ {{- end }}
+ {{- if .Values.tls.enabled }}
+ - name: keystore
+ mountPath: /opt/apache-activemq/conf/broker.ks
+ subPath: broker.ks
+ readOnly: true
+ - name: truststore
+ mountPath: /opt/apache-activemq/conf/broker.ts
+ subPath: broker.ts
+ readOnly: true
+ {{- end }}
+ {{- with .Values.resources }}
+ resources:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ volumes:
+ - name: config
+ configMap:
+ name: {{ include "activemq.fullname" . }}-config
+ {{- if .Values.tls.enabled }}
+ - name: keystore
+ secret:
+ secretName: {{ .Values.tls.keystoreSecret }}
+ - name: truststore
+ secret:
+ secretName: {{ .Values.tls.truststoreSecret }}
+ {{- end }}
+ {{- if not .Values.persistence.enabled }}
+ - name: data
+ emptyDir: {}
+ {{- end }}
+ {{- if .Values.persistence.enabled }}
+ volumeClaimTemplates:
+ - metadata:
+ name: data
+ spec:
+ accessModes:
+ - {{ .Values.persistence.accessMode | quote }}
+ {{- if .Values.persistence.storageClass }}
+ storageClassName: {{ .Values.persistence.storageClass | quote }}
+ {{- end }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size | quote }}
+ {{- end }}
\ No newline at end of file
diff --git a/activemq-helm-chart/values.yaml b/activemq-helm-chart/values.yaml
new file mode 100644
index 0000000000..5b95b600e1
--- /dev/null
+++ b/activemq-helm-chart/values.yaml
@@ -0,0 +1,78 @@
+replicaCount: 1
+
+image:
+ repository: apache/activemq-classic
+ tag: "latest"
+ pullPolicy: IfNotPresent
+
+nameOverride: ""
+fullnameOverride: ""
+
+auth:
+ username: admin
+ password: changeme
+
+config:
+ activemqXmlPath: ""
+ jettyXmlPath: ""
+
+service:
+ type: ClusterIP
+ port: 61616
+ webConsolePort: 8161
+
+persistence:
+ enabled: false
+ storageClass: ""
+ accessMode: ReadWriteOnce
+ size: 8Gi
+
+resources:
+ limits:
+ cpu: 1000m
+ memory: 2Gi
+ requests:
+ cpu: 500m
+ memory: 1Gi
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+podAnnotations: {}
+
+livenessProbe:
+ enabled: true
+ initialDelaySeconds: 120
+ periodSeconds: 30
+ timeoutSeconds: 20
+ failureThreshold: 6
+ successThreshold: 1
+
+readinessProbe:
+ enabled: true
+ initialDelaySeconds: 60
+ periodSeconds: 30
+ timeoutSeconds: 20
+ failureThreshold: 3
+ successThreshold: 1
+
+ingress:
+ enabled: false
+ className: ""
+ annotations: {}
+ hosts:
+ - host: activemq.local
+ paths:
+ - path: /
+ pathType: Prefix
+ tls: []
+
+tls:
+ enabled: false
+ keystoreSecret: "activemq-keystore" # kubectl create secret generic activemq-keystore --from-file=broker.ks=
+ truststoreSecret: "activemq-truststore" # kubectl create secret generic activemq-truststore --from-file=broker.ts=
+ sslPort: 61617
+ webConsoleSslPort: 8162
\ No newline at end of file