diff --git a/helm/charts/nats-s3/Chart.yaml b/helm/charts/nats-s3/Chart.yaml new file mode 100644 index 00000000..74a6e8b5 --- /dev/null +++ b/helm/charts/nats-s3/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +version: 0.3.3 +appVersion: 1.4.2 +type: application +name: nats-s3 +description: S3-compatible object storage powered by NATS JetStream +maintainers: +- email: info@nats.io + name: Community Effort + url: https://github.com/wpnpeiris/nats-s3 diff --git a/helm/charts/nats-s3/README.md b/helm/charts/nats-s3/README.md new file mode 100644 index 00000000..a27e8cc1 --- /dev/null +++ b/helm/charts/nats-s3/README.md @@ -0,0 +1,149 @@ +# nats-s3 + +## TL;DR; + +``` +helm install -f my-values.yaml nats-s3 oci://ghcr.io/ashupednekar/charts/nats-s3 +``` + +## ⚙️ Configuration Overview + +The following example configurations can be set with `-f`. + +**Basic** + +```yaml +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" +replicaCount: 1 + +image: + repository: ghcr.io/wpnpeiris/nats-s3 + tag: latest + pullPolicy: IfNotPresent + +service: + type: NodePort + port: 5222 + targetPort: 5222 + nodePort: 30222 # Uncomment if using NodePort + +nats: + servers: "nats://nats:4222" + +auth: + # Enable authentication (disabled by default) + enabled: true + + # Use existing secret (takes precedence if set) + existingSecret: "" + + # Username/Password authentication + username: "natsadmin" + password: "natsadmin" +``` + +> Note: these username password values are subject to change in the future + +The chart is designed to make NATS S3 easily configurable through `values.yaml`. +Key configurable sections include: + +#### **General** +- **`nameOverride` / `fullnameOverride` / `namespaceOverride`** — Customize resource names and namespaces. +- **`replicaCount`** — Number of NATS S3 pod replicas to deploy. + +#### **Image** +- **`image.repository`** — Container image to use (default: `ghcr.io/wpnpeiris/nats-s3`). +- **`image.tag`** — Image tag (default: `latest`). +- **`image.pullPolicy`** — Kubernetes pull policy (`IfNotPresent`, `Always`, etc.). + +#### **Service** +- **`service.type`** — Kubernetes service type (`ClusterIP`, `NodePort`, etc.). +- **`service.port` / `service.targetPort`** — Define the external and internal ports for NATS S3. +- **`service.nodePort`** — Optional NodePort override (used if type is `NodePort`). + +#### **NATS Connection** +- **`nats.servers`** — Comma-separated list of NATS server URLs, e.g. `nats://nats:4222`. + +#### **Authentication** +- **`auth.enabled`** — Enables username/password authentication. +- **`auth.username` / `auth.password`** — Basic credentials for S3 access (used if `auth.enabled` is true). +- **`auth.existingSecret`** — Optionally reference an existing Kubernetes Secret containing credentials. + When set, this overrides inline username/password values. + +--- + +### 🚀 Example Usage + +```bash +helm repo add nats https://nats-io.github.io/k8s/helm/charts/ +helm install my-nats-s3 nats/nats-s3 -f my-values.yaml +``` + +Example `my-values.yaml`: + +```yaml +nats: + servers: "nats://nats:4222" + +auth: + enabled: true + username: "natsadmin" + password: "natsadmin" +``` + +--- + +### Usage + + +### Note +> The optional dependency for s3 in the nats chart is currently an oci dependency pointing to my ghcr artifact, can be changed to file once/if merged + +Right now, we need to cd into the nats chart and build the dependencies to pull in the s3 chart + +```bash +helm/charts/nats on  feat_s3 !? macbook +❯ helm dependency update +Hang tight while we grab the latest from your chart repositories... +...Successfully got an update from the "nats" chart repository +Update Complete. ⎈Happy Helming!⎈ +Error: could not retrieve list of tags for repository oci://ghcr.io/ashupe +dnekar/charts/nats-s3: GET "https://ghcr.io/v2/ashupednekar/charts/nats-s3 +/nats-s3/tags/list": response status code 404: name unknown: repository na +me not known to registry +helm/charts/nats on  feat_s3 !? macbook +❯ helm dependency update +Hang tight while we grab the latest from your chart repositories... +...Successfully got an update from the "nats" chart repository +Update Complete. ⎈Happy Helming!⎈ +Saving 1 charts +Downloading nats-s3 from repo oci://ghcr.io/ashupednekar/charts +Pulled: ghcr.io/ashupednekar/charts/nats-s3:0.1.0 +Digest: sha256:95b396a38241a050b20e589ecf87d6fb274bec0496d05fd9542e2af60a9 +063b4 +Deleting outdated charts +``` + +The chart can then be installed by enabling the `s3.enabled=true` value. + +```bash +❯ helm install nats . -f ~/Documents/nats.yaml --set s3.enabled=true +NAME: nats +LAST DEPLOYED: Tue Oct 28 11:03:37 2025 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +helm/charts/nats on  feat_s3 !? macbook +❯ k get po +NAME READY STATUS RESTARTS AGE +nats-0 1/1 Running 0 21s +nats-1 1/1 Running 0 21s +nats-2 1/1 Running 0 21s +nats-box-789cd4555d-9w2n2 1/1 Running 0 21s +nats-s3-84bb45c49b-x27gr 1/1 Running 2 (19s ago) 21s +pgo-85767cc986-d64p7 1/1 Running 1 (4d ago) 9d +helm/charts/nats on  feat_s3 !? macbook +❯ +``` diff --git a/helm/charts/nats-s3/templates/_helpers.tpl b/helm/charts/nats-s3/templates/_helpers.tpl new file mode 100644 index 00000000..4412418b --- /dev/null +++ b/helm/charts/nats-s3/templates/_helpers.tpl @@ -0,0 +1,90 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "nats-s3.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Expand the namespace of the chart. +*/}} +{{- define "nats-s3.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "nats-s3.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 "nats-s3.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "nats-s3.labels" -}} +helm.sh/chart: {{ include "nats-s3.chart" . }} +{{ include "nats-s3.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "nats-s3.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nats-s3.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "nats-s3.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "nats-s3.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Fix image keys for chart versions <= 0.13.1 +*/}} +{{- define "nats-s3.fixImage" -}} +{{- if .tagOverride }} +{{- $_ := set . "tag" .tagOverride }} +{{- $_ := unset . "tagOverride" }} +{{- end }} +{{- end }} + +{{/* +Print the image +*/}} +{{- define "nats-s3.image" -}} +{{- $image := printf "%s:%s" .repository .tag }} +{{- if .registry }} +{{- $image = printf "%s/%s" .registry $image }} +{{- end }} +{{- $image -}} +{{- end }} diff --git a/helm/charts/nats-s3/templates/deployment.yaml b/helm/charts/nats-s3/templates/deployment.yaml new file mode 100644 index 00000000..0893605d --- /dev/null +++ b/helm/charts/nats-s3/templates/deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nats-s3 + namespace: {{ .Values.namespaceOverride | default .Release.Namespace }} + labels: + app: nats-s3 + {{- include "nats-s3.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: nats-s3 + {{- include "nats-s3.selectorLabels" . | nindent 6 }} + strategy: {} + template: + metadata: + labels: + app: nats-s3 + {{- include "nats-s3.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: nats-s3 + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "--listen" + - "0.0.0.0:{{ .Values.service.targetPort }}" + - "--natsServers" + - "{{ .Values.nats.servers }}" + - "--s3.credentials" + - "/etc/nats-s3/credentials.json" + ports: + - containerPort: {{ .Values.service.targetPort }} + protocol: TCP + volumeMounts: + - name: credentials + mountPath: /etc/nats-s3 + readOnly: true + resources: {} + volumes: + - name: credentials + secret: + secretName: {{ .Values.auth.existingSecret | default "nats-s3-credentials" }} +status: {} diff --git a/helm/charts/nats-s3/templates/secret.yaml b/helm/charts/nats-s3/templates/secret.yaml new file mode 100644 index 00000000..09b989bb --- /dev/null +++ b/helm/charts/nats-s3/templates/secret.yaml @@ -0,0 +1,25 @@ +{{- if not .Values.auth.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: nats-s3-credentials + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "nats-s3.name" . }} + helm.sh/chart: {{ include "nats-s3.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +type: Opaque +stringData: + credentials.json: | + { + "credentials": [ + {{- if .Values.auth.enabled }} + { + "accessKey": {{ .Values.auth.username | quote }}, + "secretKey": {{ .Values.auth.password | quote }} + } + {{- end }} + ] + } +{{- end }} diff --git a/helm/charts/nats-s3/templates/service.yaml b/helm/charts/nats-s3/templates/service.yaml new file mode 100644 index 00000000..05b7fe67 --- /dev/null +++ b/helm/charts/nats-s3/templates/service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "nats-s3.fullname" . }} + namespace: {{ .Values.namespaceOverride | default .Release.Namespace }} + labels: + app: nats-s3 + {{- include "nats-s3.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: http + {{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + app: nats-s3 + {{- include "nats-s3.selectorLabels" . | nindent 4 }} diff --git a/helm/charts/nats-s3/values.yaml b/helm/charts/nats-s3/values.yaml new file mode 100644 index 00000000..10ba99d5 --- /dev/null +++ b/helm/charts/nats-s3/values.yaml @@ -0,0 +1,29 @@ +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" +replicaCount: 1 + +image: + repository: ghcr.io/wpnpeiris/nats-s3 + tag: latest + pullPolicy: IfNotPresent + +service: + type: NodePort + port: 5222 + targetPort: 5222 + nodePort: 30222 # Uncomment if using NodePort + +nats: + servers: "nats://nats:4222" + +auth: + # Enable authentication (disabled by default) + enabled: true + + # Use existing secret (takes precedence if set) + existingSecret: "" + + # Username/Password authentication + username: "natsadmin" + password: "natsadmin" diff --git a/helm/charts/nats/Chart.yaml b/helm/charts/nats/Chart.yaml index c065dfe3..ed4c44d1 100644 --- a/helm/charts/nats/Chart.yaml +++ b/helm/charts/nats/Chart.yaml @@ -13,3 +13,9 @@ maintainers: name: The NATS Authors url: https://github.com/nats-io icon: https://nats.io/img/nats-icon-color.png +dependencies: + - name: nats-s3 + version: 0.1.0 + repository: "oci://ghcr.io/ashupednekar/charts" + condition: s3.enabled + diff --git a/helm/charts/nats/values.yaml b/helm/charts/nats/values.yaml index ceb450a7..d2375428 100644 --- a/helm/charts/nats/values.yaml +++ b/helm/charts/nats/values.yaml @@ -688,3 +688,6 @@ natsBox: # {{ .Values.config.websocket.port }} # extraResources: [] + +s3: + enabled: false