DEV Community

Cover image for Node-RED Kubernetes Deployment & Password Management Guide
Durrell Gemuh
Durrell Gemuh

Posted on

Node-RED Kubernetes Deployment & Password Management Guide

Deploying Node-RED on Kubernetes is a powerful way to run your low-code workflows at scale. In this guide, I’ll walk you through a streamlined setup on GKE (Google Kubernetes Engine), including secure password management best practices.

Prerequisites

  • Kubernetes cluster (GKE) with kubectl configured
  • Node-RED Docker image: nodered/node-red:4.0.8
  • (Optional) Static IP and ManagedCertificate for HTTPS (GKE Ingress)
  1. Initial Deployment

1.1 Deploy Node-RED Deployment (deployment.yml)

apiVersion: apps/v1 kind: Deployment metadata: name: node-red namespace: <namespace> labels: app: node-red spec: replicas: 1 selector: matchLabels: app: node-red template: metadata: labels: app: node-red spec: securityContext: fsGroup: 1000 containers: - name: nodered image: nodered/node-red:4.0.8 args: ["--settings", "/config/settings.js"] env: - name: NODE_OPTIONS value: "--trace-warnings" ports: - containerPort: 1880 securityContext: runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false resources: limits: memory: "512Mi" cpu: "500m" requests: memory: "256Mi" cpu: "250m" livenessProbe: httpGet: path: / port: 1880 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: / port: 1880 initialDelaySeconds: 5 periodSeconds: 5 volumeMounts: - name: node-red-storage mountPath: /data - name: node-red-settings mountPath: /config/settings.js subPath: settings.js volumes: - name: node-red-storage persistentVolumeClaim: claimName: node-red-pvc - name: node-red-settings configMap: name: node-red-settings 
Enter fullscreen mode Exit fullscreen mode

Deploy:
kubectl apply -f deployment.yml -n <namespace>

1.2 Create ConfigMap (configmap.yml)
Note: Leave the password blank for now; you will generate it inside the pod.

apiVersion: v1 kind: ConfigMap metadata: name: node-red-settings namespace: <namespace> data: settings.js: | module.exports = { httpAdminRoot: '/', httpNodeRoot: '/', userDir: '/data', flowFile: 'flows.json', credentialSecret: 'yzM0ol6Zn5kd1234', adminAuth: { type: "credentials", users: [{ username: "admin", password: "", permissions: "*" }] }, uiPort: process.env.PORT || 1880, mqttReconnectTime: 15000, serialReconnectTime: 15000, debugMaxLength: 1000, functionGlobalContext: {}, exportGlobalContextKeys: false, logging: { console: { level: "info", metrics: false, audit: false } }, editorTheme: { projects: { enabled: false } } }; 
Enter fullscreen mode Exit fullscreen mode

Apply:
kubectl apply -f configmap.yml -n <namespace>

1.3 Expose Service (service.yml)

apiVersion: v1 kind: Service metadata: name: node-red-service namespace: <namespace> labels: app: node-red spec: type: ClusterIP ports: - port: 1880 targetPort: 1880 protocol: TCP name: http selector: app: node-red 
Enter fullscreen mode Exit fullscreen mode

Apply:
kubectl apply -f service.yml -n <namespace>

1.4 Create Persistent Volume Claim (pvc.yml)

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: node-red-pvc namespace: <namespace> labels: app: node-red spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi 
Enter fullscreen mode Exit fullscreen mode

Apply it with:
kubectl apply -f pvc.yml -n <namespace>

1.5 Optional: Ingress & HTTPS (ingress.yml)

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: node-red-ingress namespace: <namespace> labels: app: node-red annotations: kubernetes.io/ingress.class: "gce" kubernetes.io/ingress.global-static-ip-name: "node-red" ingress.gcp.kubernetes.io/pre-shared-cert: "mcrt-b7f0d81d-9c86-4731-b38f-111c1a486a44" nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/rewrite-target: / cloud.google.com/backend-config: '{"default": "node-red-backendconfig"}' spec: rules: - host: node-red.dev.c1conversations.io http: paths: - path: /* pathType: ImplementationSpecific backend: service: name: node-red-service port: number: 1880 
Enter fullscreen mode Exit fullscreen mode

Apply:
kubectl apply -f ingress.yml -n <namespace>

1.6 Horizontal Pod Autoscaler (hpa.yml)

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: node-red-hpa namespace: <namespace> labels: app: node-red spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: node-red minReplicas: 1 maxReplicas: 3 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 
Enter fullscreen mode Exit fullscreen mode

Apply:
kubectl apply -f hpa.yml -n <namespace>

1.7 BackendConfig (backend.yml)

apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: node-red-backendconfig namespace: <namespace> spec: healthCheck: checkIntervalSec: 10 timeoutSec: 5 healthyThreshold: 1 unhealthyThreshold: 3 type: HTTP requestPath: / port: 1880 
Enter fullscreen mode Exit fullscreen mode

Apply:
kubectl apply -f backend.yml -n <namespace>

  1. Generate Password Inside the Pod After deployment is ready, generate a hashed password inside the pod:
kubectl get pods -n <namespace> kubectl exec -it <node-red-pod> -n <namespace> -- node-red admin hash-pw 
Enter fullscreen mode Exit fullscreen mode

Enter your desired password when prompted. Copy the generated bcrypt hash.

  1. Update ConfigMap with Hashed Password Edit the ConfigMap: kubectl edit configmap node-red-settings -n <namespace>

Paste the bcrypt hash under:

js adminAuth: { users: [{ username: "admin", password: "<bcrypt-hash-here>", permissions: "*" }] } 
Enter fullscreen mode Exit fullscreen mode
  1. Restart Node-RED Pod
    Delete the pod to reload the updated ConfigMap and password:
    kubectl delete pod <node-red-pod> -n <namespace>
    Kubernetes will recreate it automatically. Log in to the Node-RED UI with your new password.

  2. Changing Password in the Future
    Exec into the pod again and generate a new hash:
    kubectl exec -it <node-red-pod> -n <namespace> -- node-red admin hash-pw
    Update the ConfigMap with the new hash.
    Delete the pod to reload the ConfigMap.
    Node-RED will pick up the new password immediately.

  3. Notes & Best Practices
    Always generate bcrypt hashes inside the running pod to match Node.js versions and environment, ensuring compatibility.

Never hardcode plain-text passwords in ConfigMaps. Always store hashed passwords.

The credentialSecret encrypts flow credentials (like MQTT passwords). Changing it requires regenerating flows_cred.json.

Deploying Node-RED on Kubernetes with secure password practices helps you scale workflows without sacrificing security. Happy automating!

If you found this guide helpful or have questions, feel free to leave a comment!

Top comments (0)