Helm Chart Airgapped Deployment

Helm Chart Airgapped Deployment Guide

This guide covers deploying Rocket.Chat with MongoDB and Monitoring in an airgapped environment using Hauler to collect, package, and transfer all required artifacts.

LOW SIDE (Internet)                      HIGH SIDE (Airgapped)
-----------------------                  ----------------------
1. Sync artifacts with Hauler            4. Load artifacts into Hauler store
2. Save to transportable archive         5. Copy to internal registry
3. Transfer via approved media --------> 6. Deploy with registry override

Prerequisites

Low Side (Internet-Connected):

  • Hauler installed
  • helm CLI installed

High Side (Airgapped):

  • Hauler installed
  • helm CLI installed
  • kubectl configured for your cluster
  • Container registry accessible from Kubernetes cluster

Note: This guide was tested with Hauler v1.4.1

Part 1: Export Artifacts (Low Side)

Step 1: Create Hauler Manifest

Create a file named rocketchat-airgap-manifest.yaml:

apiVersion: content.hauler.cattle.io/v1
kind: Charts
metadata:
  name: rocketchat-airgap-charts
spec:
  charts:
    - name: rocketchat
      repoURL: https://rocketchat.github.io/helm-charts
      version: 6.32.1
      add-images: true
      add-dependencies: true

    - name: monitoring
      repoURL: https://rocketchat.github.io/helm-charts
      version: 0.0.14
      add-images: true
      add-dependencies: true

    - name: mongodb-kubernetes
      repoURL: https://mongodb.github.io/helm-charts
      version: 1.7.0
      add-images: true

---
# Rocket.Chat runtime images - not needed if using the same version as the chart
# as the sync will automatically discover these images. Include explicitly if
# deploying a different version than what the chart specifies.
apiVersion: content.hauler.cattle.io/v1
kind: Images
metadata:
  name: rocketchat-runtime-images
  annotations:
    hauler.dev/platform: linux/amd64
spec:
  images:
    - name: registry.rocket.chat/rocketchat/rocket.chat:8.1.0
    - name: docker.io/rocketchat/presence-service:8.1.0
    - name: docker.io/rocketchat/ddp-streamer-service:8.1.0
    - name: docker.io/rocketchat/account-service:8.1.0
    - name: docker.io/rocketchat/authorization-service:8.1.0
    - name: docker.io/library/nats:2.12-alpine
    - name: docker.io/natsio/nats-box:0.19.2
    - name: docker.io/natsio/nats-server-config-reloader:0.21.1
    - name: docker.io/natsio/prometheus-nats-exporter:0.18.0

---
# MongoDB runtime images - these are deployed by the MongoDBCommunity CR,
# not the operator's Helm chart, so they must be listed explicitly.
apiVersion: content.hauler.cattle.io/v1
kind: Images
metadata:
  name: mongodb-runtime-images
  annotations:
    hauler.dev/platform: linux/amd64
spec:
  images:
    - name: quay.io/mongodb/mongodb-community-server:8.0.4-ubi8
    - name: quay.io/mongodb/mongodb-agent:108.0.2.8729-1

Note: The add-images: true flag extracts all container images referenced in the Helm charts. The runtime image sections allow you to explicitly specify versions if deploying different versions than what the charts reference.

Step 2: Sync Artifacts

hauler store sync -f rocketchat-airgap-manifest.yaml

This downloads all Helm charts and container images to the local Hauler store.

Step 3: Verify Store Contents

hauler store info

Step 4: Save to Archive

hauler store save -f rocketchat-airgap.tar.zst

Part 2: Transfer to High Side

Transfer the following files to the airgapped environment using your organization’s approved transfer method:

File Size Description
rocketchat-airgap.tar.zst ~5-8 GB Compressed archive containing all charts and images
hauler binary ~50 MB Hauler CLI (if not already installed on high side)
Values files (.yaml) < 1 MB Your customized Helm values files

Included Artifacts

Helm Charts:

Chart Version
rocketchat 6.32.1
monitoring 0.0.14
mongodb-kubernetes 1.7.0
kube-prometheus-stack 75.9.0
grafana-operator v5.18.0
loki 6.49.0
mongodb (dependency) 13.18.5
postgresql (dependency) 15.5.38
nats (dependency) 0.15.1

Container Images - Rocket.Chat & Dependencies:

Image Tag
registry.rocket.chat/rocketchat/rocket.chat 8.1.0
rocketchat/presence-service 8.1.0
rocketchat/ddp-streamer-service 8.1.0
rocketchat/account-service 8.1.0
rocketchat/authorization-service 8.1.0
library/nats 2.12-alpine
natsio/nats-box 0.19.2
natsio/nats-server-config-reloader 0.21.1
natsio/prometheus-nats-exporter 0.18.0

Container Images - MongoDB:

Image Tag
Quay 1.7.0
Quay 8.0.4-ubi8
Quay 108.0.2.8729-1

Container Images - Monitoring:

Image Tag
Quay v0.83.0
Quay v3.4.2
Quay v0.28.1
Quay v1.9.1
registry.k8s.io/kube-state-metrics/kube-state-metrics v2.16.0
Package grafana-operator · GitHub v5.18.0
grafana/grafana 12.0.2
grafana/loki 3.6.3
grafana/rollout-operator v0.32.0
kiwigrid/k8s-sidecar 1.30.9
otel/opentelemetry-collector-contrib 0.143.0
nginxinc/nginx-unprivileged 1.29-alpine
Quay RELEASE.2024-12-18T13-15-44Z
Quay RELEASE.2024-11-21T17-21-54Z

Part 3: Import Artifacts (High Side)

Step 1: Load Archive

hauler store load -f rocketchat-airgap.tar.zst

Step 2: Copy to Registry

hauler store copy --destination registry://<your-registry>:<port>

# Example:
hauler store copy --destination registry://registry.internal.local:5000

Part 4: Deploy Rocket.Chat

Step 1: Configure Registry Override

Create values files with your internal registry. Replace registry.internal.local:5000 with your registry address.

mongodb-operator-values.yaml:

global:
  imageRegistry: registry.internal.local:5000

operator:
  tolerations:
    - key: "dedicated"
      operator: "Equal"
      value: "rocketchat"
      effect: "NoSchedule"
  nodeSelector:
    dedicated: rocketchat

registry:
  operator: registry.internal.local:5000/mongodb
  database: registry.internal.local:5000/mongodb
  initDatabase: registry.internal.local:5000/mongodb
  agent: registry.internal.local:5000/mongodb
  versionUpgradeHook: registry.internal.local:5000/mongodb
  readinessProbe: registry.internal.local:5000/mongodb

monitoring-values.yaml:

global:
  imageRegistry: registry.internal.local:5000
  tolerations: &tolerations
    - key: "dedicated"
      operator: "Equal"
      value: "rocketchat"
      effect: "NoSchedule"
  nodeSelector: &nodeSelector
    dedicated: rocketchat

opentelemetryCollector:
  image:
    registry: registry.internal.local:5000/otel/opentelemetry-collector-contrib

operator:
  prometheusOperator:
    image:
      registry: registry.internal.local:5000
    prometheusConfigReloader:
      image:
        registry: registry.internal.local:5000
    tolerations: *tolerations
    nodeSelector: *nodeSelector
  prometheus:
    prometheusSpec:
      image:
        registry: registry.internal.local:5000
      tolerations: *tolerations
      nodeSelector: *nodeSelector
  kube-state-metrics:
    image:
      registry: registry.internal.local:5000
    tolerations: *tolerations
    nodeSelector: *nodeSelector
  prometheus-node-exporter:
    image:
      registry: registry.internal.local:5000
    tolerations: *tolerations
    nodeSelector: *nodeSelector

grafana:
  image:
    repository: registry.internal.local:5000/grafana/grafana-operator
  tolerations: *tolerations
  nodeSelector: *nodeSelector

loki:
  loki:
    image:
      registry: registry.internal.local:5000
  gateway:
    image:
      registry: registry.internal.local:5000
  singleBinary:
    tolerations: *tolerations
    nodeSelector: *nodeSelector
  chunksCache:
    enabled: false
  resultsCache:
    enabled: false

rocketchat-values.yaml:

global:
  imageRegistry: registry.internal.local:5000
  tolerations: &tolerations
    - key: "dedicated"
      operator: "Equal"
      value: "rocketchat"
      effect: "NoSchedule"
  nodeSelector: &nodeSelector
    dedicated: rocketchat

image:
  repository: rocketchat/rocket.chat
  pullPolicy: IfNotPresent

microservices:
  enabled: true
  presence:
    image:
      repository: rocketchat/presence-service
  ddpStreamer:
    image:
      repository: rocketchat/ddp-streamer-service
  account:
    image:
      repository: rocketchat/account-service
  authorization:
    image:
      repository: rocketchat/authorization-service

nats:
  nats:
    image: registry.internal.local:5000/library/nats:2.12-alpine
  natsbox:
    image: registry.internal.local:5000/natsio/nats-box:0.19.2
  reloader:
    image: registry.internal.local:5000/natsio/nats-server-config-reloader:0.21.1
  exporter:
    image: registry.internal.local:5000/natsio/prometheus-nats-exporter:0.18.0
  tolerations: *tolerations
  nodeSelector: *nodeSelector

mongodb:
  enabled: false

host: <your-domain.com>

ingress:
  enabled: true
  ingressClassName: traefik
  tls:
    - secretName: rocketchat-tls
      hosts:
        - <your-domain.com>

extraEnv:
  - name: OVERWRITE_SETTING_Show_Setup_Wizard
    value: "completed"
  - name: OVERWRITE_SETTING_Enterprise_License
    value: |
      <YOUR-LICENSE-KEY>

externalMongodbUrl: "mongodb://rocketchat:<password>@mongodb-0.mongodb-svc.rocketchat.svc.cluster.local:27017/rocketchat?authSource=rocketchat&replicaSet=mongodb"

Image Path Note: When using global.imageRegistry, image repositories should NOT include the original registry prefix. The chart prepends global.imageRegistry automatically:

  • global.imageRegistry: registry.internal.local:5000
  • image.repository: rocketchat/rocket.chat
  • Result: registry.internal.local:5000/rocketchat/rocket.chat

Custom CA Certificate (Optional)

If Rocket.Chat needs to trust a custom CA:

kubectl create configmap custom-ca-certs --from-file=ca-certificates.crt=path/to/your-ca.crt -n rocketchat

Then add to rocketchat-values.yaml:

extraEnv:
  - name: NODE_EXTRA_CA_CERTS
    value: /etc/ssl/certs/custom-ca/ca-certificates.crt

extraVolumes:
  - name: custom-ca-certs
    configMap:
      name: custom-ca-certs

extraVolumeMounts:
  - name: custom-ca-certs
    mountPath: /etc/ssl/certs/custom-ca
    readOnly: true

Step 2: Install Helm Charts

helm install mongodb-kubernetes-operator oci://registry.internal.local:5000/mongodb/mongodb-kubernetes -n rocketchat -f mongodb-operator-values.yaml

helm install monitoring oci://registry.internal.local:5000/rocketchat/helm-monitoring -n rocketchat -f monitoring-values.yaml

helm install rocketchat oci://registry.internal.local:5000/rocketchat/helm-rocketchat -n rocketchat -f rocketchat-values.yaml

Step 3: Verify Deployment

kubectl get pods -n rocketchat

All pods should reach Running status and pull images from your internal registry.

Troubleshooting

Images Not Found

If pods fail to pull images:

  1. Verify the image exists in your registry
  2. Check for registry authentication issues with kubectl get events -n rocketchat
  3. Ensure imagePullSecrets is configured if your registry requires authentication:
    imagePullSecrets:
      - name: registry-credentials
    

Double Registry Prefix Error

If you see errors like Failed to pull image "registry.internal.local:5000/registry.rocket.chat/rocketchat/rocket.chat":

The chart prepends global.imageRegistry to the repository path. Remove the registry prefix from image.repository:

# Wrong - causes double prefix
image:
  repository: registry.rocket.chat/rocketchat/rocket.chat

# Correct
image:
  repository: rocketchat/rocket.chat

Hauler Store Issues

If hauler store sync fails:

  1. Check network connectivity to registries
  2. Verify authentication for private registries: hauler login <registry> -u <username> -p <password>
  3. Check disk space - the store can grow large

References