From d56ec33b77b77d604bcdffdc5dcbad1673caf257 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Wed, 29 Oct 2025 01:20:55 +0100 Subject: [PATCH] build: update helm chart --- helm/nextcloud-mcp-server/.helmignore | 31 ++ helm/nextcloud-mcp-server/README.md | 375 ++++++++++++++++++ helm/nextcloud-mcp-server/templates/NOTES.txt | 69 ++++ 3 files changed, 475 insertions(+) create mode 100644 helm/nextcloud-mcp-server/.helmignore create mode 100644 helm/nextcloud-mcp-server/README.md create mode 100644 helm/nextcloud-mcp-server/templates/NOTES.txt diff --git a/helm/nextcloud-mcp-server/.helmignore b/helm/nextcloud-mcp-server/.helmignore new file mode 100644 index 0000000..09e0e09 --- /dev/null +++ b/helm/nextcloud-mcp-server/.helmignore @@ -0,0 +1,31 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# CI/CD +.github/ +.gitlab-ci.yml +.circleci/ +# Documentation +*.md +!Chart.yaml +!values.yaml diff --git a/helm/nextcloud-mcp-server/README.md b/helm/nextcloud-mcp-server/README.md new file mode 100644 index 0000000..1dea9db --- /dev/null +++ b/helm/nextcloud-mcp-server/README.md @@ -0,0 +1,375 @@ +# Nextcloud MCP Server Helm Chart + +This Helm chart deploys the Nextcloud MCP (Model Context Protocol) Server on a Kubernetes cluster, enabling AI assistants to interact with your Nextcloud instance. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ +- A running Nextcloud instance (accessible from the Kubernetes cluster) +- Nextcloud credentials (username/password for basic auth OR OAuth client for OAuth mode) + +## Installation + +### Quick Start with Basic Authentication + +```bash +# Install with basic auth (recommended for most users) +helm install nextcloud-mcp ./helm/nextcloud-mcp-server \ + --set nextcloud.host=https://cloud.example.com \ + --set auth.basic.username=myuser \ + --set auth.basic.password=mypassword +``` + +### Using a values file + +Create a `custom-values.yaml` file: + +```yaml +nextcloud: + host: https://cloud.example.com + +auth: + mode: basic + basic: + username: myuser + password: mypassword + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi +``` + +Install with your custom values: + +```bash +helm install nextcloud-mcp ./helm/nextcloud-mcp-server -f custom-values.yaml +``` + +### OAuth Authentication Mode (Experimental) + +**Warning:** OAuth mode is experimental and requires patches to the Nextcloud `user_oidc` app. See the [Authentication Guide](https://github.com/cbcoutinho/nextcloud-mcp-server#authentication) for details. + +```yaml +nextcloud: + host: https://cloud.example.com + mcpServerUrl: https://mcp.example.com + publicIssuerUrl: https://cloud.example.com + +auth: + mode: oauth + oauth: + # Optional: provide pre-registered client credentials + # If not provided, will use Dynamic Client Registration + clientId: "your-client-id" + clientSecret: "your-client-secret" + persistence: + enabled: true + size: 100Mi + +ingress: + enabled: true + className: nginx + hosts: + - host: mcp.example.com + paths: + - path: / + pathType: Prefix + tls: + - secretName: nextcloud-mcp-tls + hosts: + - mcp.example.com +``` + +## Configuration + +### Key Configuration Parameters + +#### Nextcloud Connection + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `nextcloud.host` | URL of your Nextcloud instance | `""` | +| `nextcloud.mcpServerUrl` | MCP server URL for OAuth callbacks (OAuth only) | `""` | +| `nextcloud.publicIssuerUrl` | Public issuer URL for OAuth (OAuth only) | `""` | + +#### Authentication + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `auth.mode` | Authentication mode: `basic` or `oauth` | `basic` | +| `auth.basic.username` | Nextcloud username (basic auth) | `""` | +| `auth.basic.password` | Nextcloud password (basic auth) | `""` | +| `auth.basic.existingSecret` | Use existing secret for credentials | `""` | +| `auth.oauth.clientId` | OAuth client ID (OAuth mode, optional) | `""` | +| `auth.oauth.clientSecret` | OAuth client secret (OAuth mode, optional) | `""` | +| `auth.oauth.persistence.enabled` | Enable persistent storage for OAuth | `true` | +| `auth.oauth.persistence.size` | Size of OAuth storage PVC | `100Mi` | + +#### Image Configuration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `image.repository` | Container image repository | `ghcr.io/cbcoutinho/nextcloud-mcp-server` | +| `image.tag` | Container image tag | `""` (uses chart appVersion) | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | + +#### Resources + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `resources.limits.cpu` | CPU limit | `1000m` | +| `resources.limits.memory` | Memory limit | `512Mi` | +| `resources.requests.cpu` | CPU request | `100m` | +| `resources.requests.memory` | Memory request | `128Mi` | + +#### Service + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `service.type` | Service type | `ClusterIP` | +| `service.port` | Service port | `8000` | +| `service.oauthPort` | OAuth service port | `8001` | + +#### Ingress + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `ingress.enabled` | Enable ingress | `false` | +| `ingress.className` | Ingress class name | `""` | +| `ingress.hosts` | Ingress host configuration | See values.yaml | +| `ingress.tls` | Ingress TLS configuration | `[]` | + +#### Autoscaling + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `autoscaling.enabled` | Enable HPA | `false` | +| `autoscaling.minReplicas` | Minimum replicas | `1` | +| `autoscaling.maxReplicas` | Maximum replicas | `10` | +| `autoscaling.targetCPUUtilizationPercentage` | Target CPU % | `80` | + +#### Document Processing (Optional) + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `documentProcessing.enabled` | Enable document processing | `false` | +| `documentProcessing.defaultProcessor` | Default processor | `unstructured` | +| `documentProcessing.unstructured.enabled` | Enable Unstructured.io processor | `false` | +| `documentProcessing.unstructured.apiUrl` | Unstructured API URL | `http://unstructured:8000` | +| `documentProcessing.tesseract.enabled` | Enable Tesseract OCR | `false` | + +## Examples + +### Example 1: Basic Auth with Ingress + +```yaml +nextcloud: + host: https://cloud.example.com + +auth: + mode: basic + basic: + username: admin + password: secure-password + +ingress: + enabled: true + className: nginx + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + hosts: + - host: mcp.example.com + paths: + - path: / + pathType: Prefix + tls: + - secretName: mcp-tls + hosts: + - mcp.example.com + +resources: + limits: + cpu: 2000m + memory: 1Gi + requests: + cpu: 200m + memory: 256Mi +``` + +### Example 2: Using Existing Secrets + +Create a secret manually: + +```bash +kubectl create secret generic nextcloud-credentials \ + --from-literal=username=myuser \ + --from-literal=password=mypassword +``` + +Then reference it in your values: + +```yaml +auth: + mode: basic + basic: + existingSecret: nextcloud-credentials + usernameKey: username + passwordKey: password +``` + +### Example 3: OAuth with Document Processing + +```yaml +nextcloud: + host: https://cloud.example.com + mcpServerUrl: https://mcp.example.com + publicIssuerUrl: https://cloud.example.com + +auth: + mode: oauth + oauth: + persistence: + enabled: true + storageClass: fast-ssd + size: 200Mi + +documentProcessing: + enabled: true + defaultProcessor: unstructured + unstructured: + enabled: true + apiUrl: http://unstructured-api:8000 + strategy: hi_res + languages: eng,deu,fra + +ingress: + enabled: true + className: nginx + hosts: + - host: mcp.example.com + paths: + - path: / + pathType: Prefix +``` + +### Example 4: High Availability with Autoscaling + +```yaml +replicaCount: 2 + +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 + +resources: + limits: + cpu: 2000m + memory: 1Gi + requests: + cpu: 500m + memory: 512Mi + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - nextcloud-mcp-server + topologyKey: kubernetes.io/hostname +``` + +## Upgrading + +### To upgrade an existing deployment: + +```bash +helm upgrade nextcloud-mcp ./helm/nextcloud-mcp-server -f custom-values.yaml +``` + +### To upgrade with new values: + +```bash +helm upgrade nextcloud-mcp ./helm/nextcloud-mcp-server \ + --set image.tag=0.21.0 \ + --set resources.limits.memory=1Gi +``` + +## Uninstalling + +```bash +helm uninstall nextcloud-mcp +``` + +**Note:** This will delete all resources including PVCs. If you want to preserve OAuth client data, backup the PVC before uninstalling. + +## Troubleshooting + +### Check pod status + +```bash +kubectl get pods -l app.kubernetes.io/name=nextcloud-mcp-server +``` + +### View logs + +```bash +kubectl logs -l app.kubernetes.io/name=nextcloud-mcp-server --tail=100 -f +``` + +### Test connectivity to Nextcloud + +```bash +# Port forward to the service +kubectl port-forward svc/nextcloud-mcp 8000:8000 + +# In another terminal, test the connection +curl http://localhost:8000/ +``` + +### Common Issues + +1. **Connection refused to Nextcloud** + - Verify `nextcloud.host` is accessible from the Kubernetes cluster + - Check network policies and firewall rules + +2. **Authentication failures** + - For basic auth: verify username/password are correct + - For OAuth: check that OIDC app is properly configured + +3. **OAuth persistence issues** + - Verify PVC is bound: `kubectl get pvc` + - Check storage class exists: `kubectl get storageclass` + +4. **Resource constraints** + - Increase memory limits if seeing OOM errors + - Adjust CPU requests based on load + +## Security Considerations + +1. **Secrets Management**: Consider using external secret management (e.g., Sealed Secrets, External Secrets Operator) +2. **TLS**: Always use TLS/HTTPS for production deployments +3. **Network Policies**: Restrict network access to necessary services only +4. **RBAC**: Review and customize ServiceAccount permissions as needed +5. **App Passwords**: For basic auth, use Nextcloud app passwords instead of main account passwords + +## Support + +- GitHub Issues: https://github.com/cbcoutinho/nextcloud-mcp-server/issues +- Documentation: https://github.com/cbcoutinho/nextcloud-mcp-server#readme + +## License + +This chart is licensed under AGPL-3.0, consistent with the Nextcloud MCP Server project. diff --git a/helm/nextcloud-mcp-server/templates/NOTES.txt b/helm/nextcloud-mcp-server/templates/NOTES.txt new file mode 100644 index 0000000..64afb4d --- /dev/null +++ b/helm/nextcloud-mcp-server/templates/NOTES.txt @@ -0,0 +1,69 @@ +Thank you for installing {{ .Chart.Name }}! + +Your Nextcloud MCP Server has been deployed in {{ .Values.auth.mode }} authentication mode. + +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "nextcloud-mcp-server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "nextcloud-mcp-server.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "nextcloud-mcp-server.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "nextcloud-mcp-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your MCP server" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} + +2. Check the deployment status: + kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "nextcloud-mcp-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" + +{{- if eq .Values.auth.mode "basic" }} + +3. Basic Authentication Mode: + - Username: {{ .Values.auth.basic.username }} + - Password: (stored in secret {{ include "nextcloud-mcp-server.basicAuthSecretName" . }}) + - Connected to: {{ .Values.nextcloud.host }} +{{- else if eq .Values.auth.mode "oauth" }} + +3. OAuth Authentication Mode: + - Server URL: {{ .Values.nextcloud.mcpServerUrl }} + - Issuer URL: {{ .Values.nextcloud.publicIssuerUrl }} + - Connected to: {{ .Values.nextcloud.host }} + {{- if .Values.auth.oauth.persistence.enabled }} + - OAuth client credentials are persisted in PVC: {{ include "nextcloud-mcp-server.oauthPvcName" . }} + {{- end }} + + IMPORTANT: OAuth mode is experimental and requires patches to the user_oidc app. + See: https://github.com/cbcoutinho/nextcloud-mcp-server#authentication +{{- end }} + +{{- if .Values.documentProcessing.enabled }} + +4. Document Processing: + - Enabled: {{ .Values.documentProcessing.enabled }} + - Default processor: {{ .Values.documentProcessing.defaultProcessor }} + {{- if .Values.documentProcessing.unstructured.enabled }} + - Unstructured API: {{ .Values.documentProcessing.unstructured.apiUrl }} + {{- end }} +{{- end }} + +For more information and documentation: +- GitHub: https://github.com/cbcoutinho/nextcloud-mcp-server +- Documentation: https://github.com/cbcoutinho/nextcloud-mcp-server#readme + +To upgrade this deployment: + helm upgrade {{ .Release.Name }} nextcloud-mcp-server + +To uninstall: + helm uninstall {{ .Release.Name }}