Deploying with Helm
This guide walks you through deploying the Sendent for Outlook (cross-platform) on a Kubernetes cluster using Helm.
Prerequisites
A running Kubernetes cluster (v1.19 or later)
Helm installed on your local machine
kubectlconfigured to access your clusterA running Nextcloud instance
A domain name pointing to your cluster (e.g.,
outlook.example.com)
Step 1: Get the Helm Chart
Sendent maintains the Helm charts in our public GitHub repository. To get started, clone the repository from the following location: https://github.com/Sendent-B-V/sendent-container-helm-charts/tree/main/outlook-addin and follow the README instructions.
A cloud-hosted version of the Helm chart will be released soon, which will allow you to install it directly via helm install without needing to clone the repository first.
Step 2: Create your values file
Create a file called my-values.yaml with your configuration:
config: BASE_URL: https://outlook.example.com # your outlook domain DEFAULT_NEXTCLOUD_URL: https://nextcloud.example.com # your nextcloud domain MS_AUTH_TYPE: naa_silent # one of naa_silent, legacy_exchange MS_APP_ID: your-azure-app-id MS_TENANT_ID: your-azure-tenant-id
We recommend following this article to set up authentication.
Full configuration reference
Parameter | Description | Required | Default |
|---|---|---|---|
| Public URL where the add-in will be accessible | Yes |
|
| Nextcloud server URL | Yes |
|
| Authentication type: or | No (but recommended) |
|
| Azure App ID (required for | Conditional |
|
| Azure Tenant ID (required for non single-tenant apps) | Conditional |
|
| Comma-separated feature codes to disable (e.g., | No |
|
| Proxy placeholder URL | No |
|
| Auth log levels: | No |
|
Deployment parameters
Parameter | Description | Default |
|---|---|---|
| Number of prod replicas |
|
| Container image repository |
|
| Container image tag |
|
| Image pull policy |
|
| CPU request | - |
| Memory request | - |
| CPU limit | - |
| Memory limit | - |
| Node selector for pod scheduling |
|
| Pod tolerations |
|
| Pod affinity rules |
|
The add-in is stateless, so it can be scaled horizontally by increasing replicaCount:
replicaCount: 3
For production deployments, it is recommended to set resource requests and limits:
resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi
Step 3: Install the chart
To install the Helm chart, run
helm install sendent-outlook ./outlook-addin -f my-values.yaml
Verify the deployment is running:
kubectl get pods -l app.kubernetes.io/name=outlook-addin
You should see your pod(s) in Running status.
4: Expose the add-in
The chart creates a ClusterIP service on port 4300 by default. You need to expose this externally so Outlook can reach it. There are a few options depending on your cluster setup.
Option A: Ingress (recommended)
The chart can create an Ingress resource to expose the add-in externally. This requires an ingress controller (e.g. ingress-nginx) and cert-manager (for automatic TLS certificates).
Already have these? If your cluster already has an ingress controller and cert-manager with a ClusterIssuer configured, skip to the “Configure your DNS” step.
Install an Ingress controller (if not already present):
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx --create-namespace
Install cert-manager (if not already present):
helm repo add jetstack https://charts.jetstack.io helm install cert-manager jetstack/cert-manager \ --namespace cert-manager --create-namespace \ --set crds.enabled=true
Create a ClusterIssuer for Let’s Encrypt
Make sure to change the example email (Let’s Encrypt uses it for expiry notices).
# cluster-issue.yamlapiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: letsencrypt-prodspec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx
kubectl apply -f cluster-issuer.yaml
Configure your DNS
Retrieve the controller’s external IP:
kubectl get svc -n ingress-nginx
For example:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)ingress-nginx-controller LoadBalancer 10.10.10.10 140.10.10.10 80:32554/TCP,443:32677/TCP
Point your domain's A record at the ingress controller's external IP.
Update your values file with the ingress configuration
Finally, add the following to your values file:
ingress: enabled: true className: nginx # adjust to match your ingress controller annotations: cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - host: outlook.example.com paths: - path: / pathType: Prefix tls: - secretName: outlook-addin-tls hosts: - outlook.example.com
Adjust className, annotations, and tls to match your cluster's ingress setup.
Option B: Reverse proxy
If you prefer to manage routing outside of Kubernetes, keep the default ClusterIP service and point your existing reverse proxy (e.g., Nginx, Caddy) at the service. You can use kubectl port-forward to expose the service internally to your reverse proxy, and then configure it to serve https://outlook.example.com.
kubectl port-forward svc/sendent-outlook-outlook-addin 4300:4300
Step 5: Verify the deployment
Open https://outlook.example/manifest.xml in your browser. You should see the manifest XML. If this loads correctly, the deployment works and you can proceed to install the add-in in Outlook using this manifest URL.
Uninstalling
To uninstall the Helm chart, run
helm uninstall sendent-outlook
Troubleshooting
Check pod status:
kubectl get pods -l app.kubernetes.io/name=outlook-addin
View pod events and details:
kubectl describe pod -l app.kubernetes.io/name=outlook-addin
View application logs:
kubectl logs -l app.kubernetes.io/name=outlook-addin
If your pods are in CrashLoopBackOff, check the logs for configuration errors. The most common issues are missing BASE_URL or authentication configuration parameters.