Installation With Helm
Overview
This guide documents the process for installing Monad into a Kubernetes cluster using Helm. The primary installation method uses the Kubernetes Gateway API for ingress. If your cluster uses a traditional ingress controller instead, see Alternative: Ingress Controller at the end of this document.
Phase 1: Prerequisites
These must be installed before the Monad Helm chart can be deployed.
Authentication Provider
Monad supports local authentication, Auth0, and AWS Cognito, with Auth0 being the default.
Required Operators/Controllers
-
Victoria Metrics Operator
- Required for internal metrics and dashboards, deployed by Custom Resources from within the chart. This does not replace an observability stack like Prometheus, and all components expose endpoints for scraping by an observability platform.
- Installation: https://docs.victoriametrics.com/operator/
-
CloudNativePG (CNPG) - PostgreSQL operator
- Required unless you're using an external PostgreSQL instance
- Installation: https://cloudnative-pg.io/documentation/current/installation_upgrade/
Gateway or Ingress Controller
- Monad recommends using the Kubernetes Gateway API for ingress and will create HTTPRoute and TCPRoute resources automatically. You need a Gateway API implementation installed in your cluster (e.g., Traefik, Istio, Envoy Gateway, kgateway, or any other conformant implementation).
- Your implementation must support the experimental Gateway API channel, which includes
TCPRoute. - Installation varies by implementation. Refer to your implementation's documentation.
- This guide assumes the use of Gateway API, though alternatives for using an ingress controller are provided at the end of the document.
Create Namespace
Code
Phase 2: Create Required Secrets
These secrets must exist before installing the Helm chart. All secrets are created in the monad namespace.
1. License Secret
The Monad license is a TLS certificate. You should have received a license.crt file from Monad.
Code
2. Encryption Key Secret
Used for encrypting sensitive data within Monad. This is a base64-encoded random 32-byte key.
Code
3. Image Pull Secret
You should have received credentials from Monad support for accessing the images in Docker Hub. Configure those here as default-pull-secret (required name).
Code
4. Authentication Secrets
Using External Secrets Operator
If you're using an external secrets store, you'll need to either save your secrets with the property names found in values.yaml or update the values.yaml to match your secret property names.
Code
Not Using External Secrets Operator
If you're not using an External Secrets operator, you need to create secrets for authentication backend credentials. Below is an example file of key/value environment variable pairs that you can create a secret from.
Note: Some of these variables exist in two forms. Monad is migrating from variable names like AUTH0_CLIENT_ID to MONAD_AUTH_AUTH0_CLIENT_ID. The MONAD_-prefixed variables are the new names, and the old names will be deprecated in a future release. For current and future compatibility, use both until informed that the old names can be removed.
api.env
Code
Create the Secret api from the file:
Code
ui.env
Code
Create the secret ui from the file:
Code
Phase 3: Configure TLS
For the remainder of this guide we will be using monad.example.com as our example domain.
Monad requires two TLS certificates:
1. Gateway Certificate
Used by the Gateway to terminate HTTPS for all web traffic. This is a standard certificate for your Monad hostname (e.g., monad.example.com).
The Secret must be created in the same namespace as your Gateway resource (not the monad namespace). This is a Gateway API requirement: certificate secrets must be co-located with the Gateway that references them.
See TLS with cert-manager for instructions on creating this certificate automatically.
2. HTTP Input TLS Certificate
Monad's HTTP Input workload handles inputs such as Syslog that require direct TLS termination at the Pod level. This certificate is separate from the Gateway certificate and must be named http-input-tls in the monad namespace.
Syslog and other TCP-terminated inputs use the hostname with SNI for routing, with names like cef85707-4b6e-405a-aea9-3237d520e805.l4.monad.example.com. It should answer to both l4.monad.example.com and the wildcard domain *.l4.monad.example.com. You will also need a DNS record pointing *.l4.monad.example.com to the load balancer address that handles TCP traffic into your cluster.
The full FQDN that you use for L4 traffic doesn't have to be connected to the hostname that you use for Monad itself (such as *.l4.monad.example.com and monad.example.com). As long as the FQDN you choose lands on the Gateway and is routed to the correct Service, the Pod that receives it performs a handshake, retrieves the requested FQDN from SNI, and then uses the hostname portion to route to the corresponding pipeline.
See TLS with cert-manager for instructions on creating this certificate automatically.
Configure Your Gateway
Your Gateway resource needs an HTTPS listener that references the Gateway certificate Secret. The exact configuration depends on your implementation, but the Gateway API spec looks like:
Code
Refer to your Gateway implementation's documentation for how to configure listeners.
Phase 4: Configure values.yaml Overrides
Create a values-override.yaml file with the following configurations.
With Gateway API enabled, Monad's chart generates HTTPRoute resources automatically for all components. You do not need to configure ingress per-component — setting hostnames and routing at the top level is sufficient for all components to be reachable.
Code
The hostnames value replaces what previously required per-component BACKEND_URL environment variables and per-component ingress host configuration. Setting it once here propagates to all components automatically.
Phase 5: Install Monad
Log in to OCI Registry
Before you can pull the Helm chart, authenticate to the Docker registry:
Code
Note: Credentials are provided by Monad support. The login persists in ~/.docker/config.json.
Install with Custom Values
Code
You can perform upgrades of Monad using the same command above. Simply remove the --install directive to perform an upgrade.
Verify Installation
Some pods will initially come up in an Error state as they wait for the database to be ready. They should all be Running (or Completed) within a few minutes.
Code
Phase 6: Post-Installation
At this point, Monad should be up and running. Access it at your designated hostname.
Alternative Installation Options
TLS with cert-manager
If you're using cert-manager for certificate management, create a ClusterIssuer and two Certificate resources as described below.
ClusterIssuer
Code
Gateway Certificate
Create this in your Gateway's namespace (e.g., kube-system for Traefik on k3s):
Code
HTTP Input TLS Certificate
Create this in the monad namespace:
Code
External Postgres
If you want to use an external Postgres instance, you can disable the CloudNativePG operator and provide the connection details in the monad-db-app Secret.
Below is an example file you can create a Secret from. It uses the following values:
dbname: monaduser: monadpassword: somereallylongandcomplexpasswordhost: monad-db-rw.postgres / monad-db-rw.postgres.svc.cluster.local (default CNPG service structure for a database in thepostgresnamespace)port: 5432
Code
Create the Secret monad-db-app from the file:
Code
Disable the CloudNativePG operator in your values-override.yaml:
Code
Local Authentication
Local authentication creates an admin user of admin@monad.local and a random password. To activate this, remove the Auth0 and Cognito configuration from the api and ui secrets, and set MONAD_AUTH_TYPE to local for both components in your values-override.yaml:
Code
After completing the installation, retrieve the Secret with the username and password:
Code
This secret is only used to deliver credentials after installation and can be deleted after retrieval.
Local authentication does not allow the creation of more users than the local admin. If you wish to have multiple users, log in as the admin user and set up SSO from the Settings menu.
Ingress Controller
If your cluster uses a traditional Kubernetes Ingress resource rather than Gateway API, use the following values-override.yaml instead of the one in Phase 4. All other phases remain the same, except:
- The TLS certificate Secret should be created in the
monadnamespace instead of the Gateway namespace - Use
kubectl get ingress -n monadinstead ofkubectl get httproute -n monadto verify routing
Remove the routing and routes keys from the earlier example of values-override.yaml and add the following:
Code
The hostnames value at the top automatically configures backend URLs and the UI origin for all components. Per-component ingress.hosts configuration is handled by the chart defaults and does not need to be set explicitly.