mirror of
https://github.com/Mintplex-Labs/helm-charts.git
synced 2026-07-01 16:42:09 -04:00
feat: adding anythingllm chart + required files
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
name: Lint, test and release Helm charts
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io/mintplex-labs/helm-charts
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 0 }
|
||||
|
||||
- uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Lint
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
for d in charts/*; do
|
||||
[[ -f "$d/Chart.yaml" ]] || continue
|
||||
echo "==> helm lint $d"
|
||||
helm lint "$d"
|
||||
done
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request' || github.base_ref == github.head_ref
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 0 }
|
||||
|
||||
- uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
check-latest: false
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: helm/chart-testing-action@v2
|
||||
|
||||
- name: Run chart-testing (list-changed)
|
||||
id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }})
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Run chart-testing (lint)
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
run: ct lint --target-branch ${{ github.event.repository.default_branch }}
|
||||
|
||||
- name: Create kind cluster
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
uses: helm/kind-action@v1
|
||||
|
||||
- name: Run chart-testing (install)
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref_name == github.event.repository.default_branch
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Login to GHCR
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Publish charts to Helm repo
|
||||
uses: helm/chart-releaser-action@v1
|
||||
env:
|
||||
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
CR_SKIP_EXISTING: "true"
|
||||
|
||||
- name: Publish charts to Helm registry
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
|
||||
mkdir -p dist
|
||||
for d in charts/*; do
|
||||
[[ -f "$d/Chart.yaml" ]] || continue
|
||||
echo "==> helm package $d"
|
||||
helm package "$d" -d dist
|
||||
done
|
||||
|
||||
for tgz in dist/*.tgz; do
|
||||
name="$(basename "$tgz" | sed -E 's/(.*)-([0-9].*)\.tgz/\1/')"
|
||||
ver="$(basename "$tgz" | sed -E 's/(.*)-([0-9].*)\.tgz/\2/')"
|
||||
repo="oci://${REGISTRY,,}/$name"
|
||||
echo "==> $name:$ver"
|
||||
if helm show chart "$repo" --version "$ver" >/dev/null 2>&1; then
|
||||
echo " already exists, skipping"
|
||||
else
|
||||
helm push "$tgz" "oci://${REGISTRY,,}"
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,359 @@
|
||||
# Mintplex Labs Helm Charts
|
||||
|
||||
This is the central repository for Mintplex Labs Helm Charts, providing production-ready Kubernetes deployments for various applications.
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Available Charts](#available-charts)
|
||||
- [Repository Architecture](#repository-architecture)
|
||||
- [Development Workflow](#development-workflow)
|
||||
- [GitHub Pages Integration](#github-pages-integration)
|
||||
- [Contributing](#contributing)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### Prerequisites
|
||||
|
||||
[Helm](https://helm.sh) must be installed to use the charts.
|
||||
Please refer to Helm's [documentation](https://helm.sh/docs/) to get started.
|
||||
|
||||
### Adding the Repository
|
||||
|
||||
Once Helm is set up properly, add the repo as follows:
|
||||
|
||||
```bash
|
||||
helm repo add mintplex-labs https://mintplex-labs.github.io/helm-charts
|
||||
```
|
||||
|
||||
If you had already added this repo earlier, run `helm repo update` to retrieve the latest versions of the packages:
|
||||
|
||||
```bash
|
||||
helm repo update
|
||||
```
|
||||
|
||||
### Searching and Installing Charts
|
||||
|
||||
You can then run `helm search repo mintplex-labs` to see the charts:
|
||||
|
||||
```bash
|
||||
helm search repo mintplex-labs
|
||||
```
|
||||
|
||||
Install a chart with:
|
||||
|
||||
```bash
|
||||
helm install my-release mintplex-labs/<chart-name>
|
||||
```
|
||||
|
||||
### Alternative Installation Methods
|
||||
|
||||
#### OCI Registry (GitHub Container Registry)
|
||||
|
||||
Charts are also available via OCI registry:
|
||||
|
||||
```bash
|
||||
# Install directly from OCI registry
|
||||
helm install my-release oci://ghcr.io/mintplex-labs/helm-charts/<chart-name> --version <version>
|
||||
```
|
||||
|
||||
#### Direct from GitHub Releases
|
||||
|
||||
Download chart packages directly from [GitHub Releases](https://github.com/mintplex-labs/helm-charts/releases):
|
||||
|
||||
```bash
|
||||
# Download and install from release assets
|
||||
wget https://github.com/mintplex-labs/helm-charts/releases/download/<chart-name>-<version>/<chart-name>-<version>.tgz
|
||||
helm install my-release ./<chart-name>-<version>.tgz
|
||||
```
|
||||
|
||||
## 🏗️ Repository Architecture
|
||||
|
||||
This repository follows a structured approach to manage and distribute Helm charts:
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── helm.yml # CI/CD pipeline for chart releases
|
||||
├── charts/
|
||||
│ └── <chart-name>/
|
||||
│ ├── Chart.yaml # Chart metadata
|
||||
│ ├── values.yaml # Default configuration values
|
||||
│ ├── README.md # Chart-specific documentation
|
||||
│ └── templates/ # Kubernetes manifest templates
|
||||
├── index.html # GitHub Pages landing page
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
### Branching Strategy
|
||||
|
||||
- **`main`**: Primary development branch containing chart sources
|
||||
- **`gh-pages`**: Auto-generated branch serving the Helm repository via GitHub Pages
|
||||
|
||||
## 🔄 Development Workflow
|
||||
|
||||
### How the Repository Works
|
||||
|
||||
This repository uses a sophisticated CI/CD pipeline that automatically:
|
||||
|
||||
1. **Builds and validates** charts when changes are pushed to `main`
|
||||
2. **Publishes charts** to multiple distribution channels
|
||||
3. **Updates the repository index** for seamless chart discovery
|
||||
|
||||
### Automated Release Process
|
||||
|
||||
When you push changes to the `charts/` directory on the `main` branch, the following happens automatically:
|
||||
|
||||
#### 1. Chart Validation
|
||||
|
||||
```yaml
|
||||
# The CI pipeline performs:
|
||||
- helm dependency build # Downloads chart dependencies
|
||||
- helm lint # Validates chart syntax and best practices
|
||||
- helm package # Creates distributable .tgz files
|
||||
```
|
||||
|
||||
#### 2. Multi-Channel Publishing
|
||||
|
||||
**a) OCI Registry (GitHub Container Registry)**
|
||||
|
||||
- Charts are pushed to `ghcr.io/mintplex-labs/helm-charts/<chart-name>`
|
||||
- Enables modern `helm install oci://` installation method
|
||||
- Provides container-native distribution
|
||||
|
||||
**b) GitHub Releases**
|
||||
|
||||
- Creates individual releases tagged as `<chart-name>-<version>`
|
||||
- Attaches chart `.tgz` files as release assets
|
||||
- Generates rich release notes with installation instructions
|
||||
|
||||
**c) Traditional Helm Repository (GitHub Pages)**
|
||||
|
||||
- Updates the `gh-pages` branch with chart packages
|
||||
- Generates/updates `index.yaml` for Helm repository discovery
|
||||
- Serves charts via `https://mintplex-labs.github.io/helm-charts`
|
||||
|
||||
#### 3. Repository Index Updates
|
||||
|
||||
The pipeline automatically:
|
||||
|
||||
- Downloads all chart packages from GitHub Releases
|
||||
- Generates a new `index.yaml` with all available charts and versions
|
||||
- Updates the GitHub Pages site with the latest repository index
|
||||
- Copies the main `index.html` landing page to the gh-pages branch
|
||||
|
||||
## 🌐 GitHub Pages Integration
|
||||
|
||||
### How GitHub Pages Serves the Helm Repository
|
||||
|
||||
The repository leverages GitHub Pages to provide a traditional Helm repository endpoint:
|
||||
|
||||
#### Repository Structure (gh-pages branch)
|
||||
|
||||
```
|
||||
gh-pages/
|
||||
├── README.md # README (copied from main branch)
|
||||
├── index.html # Landing page (copied from main branch)
|
||||
├── index.yaml # Helm repository index (auto-generated)
|
||||
```
|
||||
|
||||
#### Access Points
|
||||
|
||||
1. **Helm Repository**: `https://mintplex-labs.github.io/helm-charts`
|
||||
|
||||
- Accessed via `helm repo add` commands
|
||||
- Serves `index.yaml` for chart discovery
|
||||
|
||||
2. **Landing Page**: `https://mintplex-labs.github.io/helm-charts`
|
||||
|
||||
- User-friendly web interface
|
||||
- Installation instructions and chart documentation
|
||||
|
||||
3. **Direct Package Access**: `https://mintplex-labs.github.io/helm-charts/packages/<chart-name>-<version>.tgz`
|
||||
- Direct download links for chart packages
|
||||
|
||||
### Repository Index (`index.yaml`)
|
||||
|
||||
The `index.yaml` file is the heart of a Helm repository, containing:
|
||||
|
||||
- Chart metadata (name, version, description)
|
||||
- Download URLs for chart packages
|
||||
- Checksums for package integrity
|
||||
- Dependencies and requirements
|
||||
|
||||
Example structure:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
entries:
|
||||
chart-name:
|
||||
- name: chart-name
|
||||
version: 1.0.0
|
||||
appVersion: "1.0"
|
||||
description: Chart description
|
||||
urls:
|
||||
- https://mintplex-labs.github.io/helm-charts/packages/chart-name-1.0.0.tgz
|
||||
digest: sha256:...
|
||||
created: "2025-10-12T10:00:00Z"
|
||||
```
|
||||
|
||||
## 🛠️ Contributing
|
||||
|
||||
### For Chart Developers
|
||||
|
||||
#### Adding a New Chart
|
||||
|
||||
1. **Create Chart Structure**:
|
||||
|
||||
```bash
|
||||
mkdir -p charts/my-new-chart
|
||||
cd charts/my-new-chart
|
||||
helm create . # Or create manually
|
||||
```
|
||||
|
||||
2. **Update Chart.yaml**:
|
||||
|
||||
```yaml
|
||||
apiVersion: v2
|
||||
name: my-new-chart
|
||||
description: A Helm chart for my application
|
||||
version: 0.1.0
|
||||
appVersion: "1.0"
|
||||
```
|
||||
|
||||
3. **Configure values.yaml**:
|
||||
|
||||
- Set sensible defaults
|
||||
- Document all configuration options
|
||||
- Follow consistent naming conventions
|
||||
|
||||
4. **Create README.md**:
|
||||
- Installation instructions
|
||||
- Configuration options table
|
||||
- Usage examples
|
||||
|
||||
#### Updating Existing Charts
|
||||
|
||||
1. **Bump Version**: Update `version` in `Chart.yaml`
|
||||
2. **Update App Version**: Update `appVersion` if the underlying application version changed
|
||||
3. **Document Changes**: Update the chart's README.md with changes
|
||||
4. **Test Locally**:
|
||||
```bash
|
||||
helm lint charts/my-chart
|
||||
helm template test charts/my-chart
|
||||
```
|
||||
|
||||
#### Version Conventions
|
||||
|
||||
Follow [Semantic Versioning](https://semver.org/):
|
||||
|
||||
- **MAJOR**: Incompatible API changes
|
||||
- **MINOR**: Backwards-compatible functionality additions
|
||||
- **PATCH**: Backwards-compatible bug fixes
|
||||
|
||||
### Workflow Integration Points
|
||||
|
||||
#### CI/CD Pipeline (`.github/workflows/helm.yml`)
|
||||
|
||||
The workflow is triggered by:
|
||||
|
||||
- **Path Filter**: Only runs when files in `charts/**` are modified
|
||||
- **Branch Filter**: Only runs on pushes to `main` branch
|
||||
|
||||
Key workflow steps:
|
||||
|
||||
1. **Setup**: Configures Helm, Git, and required tools
|
||||
2. **Validation**: Lints and validates all charts
|
||||
3. **Packaging**: Creates distributable chart packages
|
||||
4. **Publishing**: Pushes to OCI registry and creates GitHub releases
|
||||
5. **Repository Update**: Updates GitHub Pages with new chart index
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
The workflow uses these environment variables:
|
||||
|
||||
- `REGISTRY`: OCI registry URL (`ghcr.io/mintplex-labs/helm-charts`)
|
||||
- `GITHUB_TOKEN`: Automatically provided for authentication
|
||||
- `GITHUB_ACTOR`: GitHub username for Git configuration
|
||||
|
||||
#### Permissions Required
|
||||
|
||||
The workflow requires these permissions:
|
||||
|
||||
```yaml
|
||||
permissions:
|
||||
contents: write # For creating releases and updating gh-pages
|
||||
packages: write # For pushing to GitHub Container Registry
|
||||
pull-requests: write # For PR automation (future use)
|
||||
```
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Chart Not Appearing in Repository
|
||||
|
||||
1. **Check Workflow Status**: Verify the GitHub Actions workflow completed successfully
|
||||
2. **Verify Chart Structure**: Ensure `Chart.yaml` is valid and properly formatted
|
||||
3. **Check Version**: Ensure you bumped the chart version in `Chart.yaml`
|
||||
4. **Repository Cache**: Run `helm repo update` to refresh your local cache
|
||||
|
||||
#### OCI Registry Issues
|
||||
|
||||
1. **Authentication**: Verify GitHub Container Registry permissions
|
||||
2. **Package Visibility**: Check if packages are public in GitHub settings
|
||||
3. **Version Conflicts**: Ensure you're not trying to overwrite an existing version
|
||||
|
||||
#### GitHub Pages Not Updating
|
||||
|
||||
1. **Workflow Permissions**: Verify the workflow has `contents: write` permission
|
||||
2. **Branch Protection**: Check if `gh-pages` branch has protection rules
|
||||
3. **Pages Settings**: Ensure GitHub Pages is enabled and pointing to `gh-pages` branch
|
||||
|
||||
### Development Tips
|
||||
|
||||
#### Local Testing
|
||||
|
||||
```bash
|
||||
# Lint charts
|
||||
helm lint charts/*
|
||||
|
||||
# Test template rendering
|
||||
helm template test-release charts/my-chart
|
||||
|
||||
# Test installation (with dry-run)
|
||||
helm install test-release charts/my-chart --dry-run --debug
|
||||
|
||||
# Package locally
|
||||
helm package charts/my-chart
|
||||
```
|
||||
|
||||
#### Debugging Workflow
|
||||
|
||||
1. **Check Workflow Logs**: Navigate to Actions tab in GitHub
|
||||
2. **Validate YAML**: Use `yamllint` to check chart YAML files
|
||||
3. **Test Locally**: Reproduce the workflow steps locally before pushing
|
||||
|
||||
### Getting Help
|
||||
|
||||
- **Issues**: Create an issue in this repository for bugs or feature requests
|
||||
- **Discussions**: Use GitHub Discussions for questions and community support
|
||||
- **Documentation**: Refer to [Helm's official documentation](https://helm.sh/docs/)
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- [Helm Documentation](https://helm.sh/docs/)
|
||||
- [Helm Best Practices](https://helm.sh/docs/chart_best_practices/)
|
||||
- [GitHub Pages Documentation](https://docs.github.com/en/pages)
|
||||
- [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)
|
||||
|
||||
---
|
||||
|
||||
**Maintainer**: Mintplex Labs Team
|
||||
**Repository**: https://github.com/mintplex-labs/helm-charts
|
||||
**Website**: https://mintplex-labs.com
|
||||
@@ -0,0 +1,23 @@
|
||||
# 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/
|
||||
@@ -0,0 +1,31 @@
|
||||
apiVersion: v2
|
||||
name: anythingllm
|
||||
description: The all-in-one Desktop & Docker AI application with built-in RAG, AI agents, No-code agent builder, MCP compatibility, and more.
|
||||
appVersion: "1.9.0"
|
||||
version: 1.0.0
|
||||
kubeVersion: ">=1.19.0-0"
|
||||
home: https://anythingllm.com/
|
||||
icon: https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/refs/heads/master/frontend/public/favicon.png
|
||||
sources:
|
||||
- https://github.com/Mintplex-Labs/anything-llm
|
||||
- https://github.com/Mintplex-Labs/helm-charts
|
||||
maintainers:
|
||||
- name: Mintplex-Labs
|
||||
email: team@mintplexlabs.com
|
||||
type: application
|
||||
keywords:
|
||||
- AI
|
||||
- LLM
|
||||
- RAG
|
||||
- Agents
|
||||
- No-code
|
||||
- MCP
|
||||
- Vector DB
|
||||
- AnythingLLM
|
||||
annotations:
|
||||
"artifacthub.io/operator": "false"
|
||||
"artifacthub.io/licenses": "MIT"
|
||||
"artifacthub.io/links.logo": "https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/refs/heads/master/frontend/public/favicon.png"
|
||||
"artifacthub.io/links.home": https://anythingllm.com/
|
||||
"artifacthub.io/links.maintainers": "https://mintplexlabs.com"
|
||||
"artifacthub.io/links.source": "https://github.com/Mintplex-Labs/helm-chart"
|
||||
@@ -0,0 +1,149 @@
|
||||
# anythingllm
|
||||
|
||||
  
|
||||
|
||||

|
||||
|
||||
[AnythingLLM](https://github.com/Mintplex-Labs/anything-llm)
|
||||
|
||||
The all-in-one Desktop & Docker AI application with built-in RAG, AI agents, No-code agent builder, MCP compatibility, and more.
|
||||
|
||||
**Configuration & Usage**
|
||||
|
||||
- **Config vs Secrets:** This chart exposes application configuration via two mechanisms:
|
||||
- `config` (in `values.yaml`) — rendered into a `ConfigMap` and injected using `envFrom` in the pod. Do NOT place sensitive values (API keys, secrets) in `config` because `ConfigMap`s are not encrypted.
|
||||
- `env` / `envFrom` — the preferred way to inject secrets. Use Kubernetes `Secret` objects and reference them from `env` (with `valueFrom.secretKeyRef`) or `envFrom.secretRef`.
|
||||
|
||||
- **Storage & STORAGE_DIR mapping:** The chart creates (or mounts) a `PersistentVolumeClaim` using the `persistentVolume.*` settings. The container mount path is set from `persistentVolume.mountPath`. Ensure the container `STORAGE_DIR` config key matches that path (defaults are set in `values.yaml`).
|
||||
|
||||
**Providing API keys & secrets (recommended)**
|
||||
|
||||
Use Kubernetes Secrets. Below are example workflows and `values.yaml` snippets.
|
||||
|
||||
1) Create a Kubernetes Secret with API keys:
|
||||
|
||||
```
|
||||
kubectl create secret generic openai-secret --from-literal=OPENAI_KEY="sk-..."
|
||||
# or from a file
|
||||
# kubectl create secret generic openai-secret --from-file=OPENAI_KEY=/path/to/keyfile
|
||||
```
|
||||
|
||||
2) Reference the Secret from `values.yaml` using `envFrom` (recommended when your secret contains multiple env keys):
|
||||
|
||||
```yaml
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: openai-secret
|
||||
```
|
||||
|
||||
This will inject all key/value pairs from the `openai-secret` Secret as environment variables in the container.
|
||||
|
||||
3) Or reference a single secret key via `env` (explicit mapping):
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OPENAI_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openai-secret
|
||||
key: OPENAI_KEY
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Avoid placing secret values into `config:` (the chart's `ConfigMap`) — `ConfigMap`s are visible to anyone who can read the namespace. Use `Secret` objects for any credentials/tokens.
|
||||
- If you use a GitOps workflow, consider integrating an external secret operator (ExternalSecrets, SealedSecrets, etc.) so you don't store raw secrets in Git.
|
||||
|
||||
**Example `values-secret.yaml` to pass during `helm install`**
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: mintplexlabs/anythingllm
|
||||
tag: "1.9.0"
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3001
|
||||
|
||||
# Reference secret containing API keys
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: openai-secret
|
||||
|
||||
# Optionally override other values
|
||||
persistentVolume:
|
||||
size: 16Gi
|
||||
mountPath: /storage
|
||||
```
|
||||
|
||||
Install with:
|
||||
|
||||
```
|
||||
helm install my-anythingllm ./anythingllm -f values-secret.yaml
|
||||
```
|
||||
|
||||
**Best practices & tips**
|
||||
|
||||
- Use `envFrom` for convenience when many environment variables are stored in a single `Secret` and use `env`/`valueFrom` for explicit single-key mappings.
|
||||
- Use `kubectl create secret generic` or your secrets management solution. If you need to reference multiple different provider keys (OpenAI, Anthropic, etc.), create a single `Secret` with multiple keys or multiple Secrets and add multiple `envFrom` entries.
|
||||
- Keep probe paths and `service.port` aligned. If your probes fail after deployment, check that the probe `port` matches the container port (or named port `http`) and that the `path` is valid.
|
||||
- For storage, if you have a pre-existing PVC set `persistentVolume.existingClaim` to the PVC name; the chart will mount that claim (and will not attempt to create a new PVC).
|
||||
- For production, provide resource `requests` and `limits` in `values.yaml` to prevent scheduler starvation and to control cost.
|
||||
|
||||
## Values
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | |
|
||||
| config.DISABLE_TELEMETRY | string | `"true"` | |
|
||||
| config.GID | string | `"1000"` | |
|
||||
| config.NODE_ENV | string | `"production"` | |
|
||||
| config.STORAGE_DIR | string | `"/storage"` | |
|
||||
| config.UID | string | `"1000"` | |
|
||||
| env | object | `{}` | |
|
||||
| envFrom | object | `{}` | |
|
||||
| fullnameOverride | string | `""` | |
|
||||
| image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| image.repository | string | `"mintplexlabs/anythingllm"` | |
|
||||
| image.tag | string | `"1.9.0"` | |
|
||||
| imagePullSecrets | list | `[]` | |
|
||||
| ingress.annotations | object | `{}` | |
|
||||
| ingress.className | string | `""` | |
|
||||
| ingress.enabled | bool | `false` | |
|
||||
| ingress.hosts[0].host | string | `"chart-example.local"` | |
|
||||
| ingress.hosts[0].paths[0].path | string | `"/"` | |
|
||||
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
|
||||
| ingress.tls | list | `[]` | |
|
||||
| initContainers | list | `[]` | |
|
||||
| livenessProbe.failureThreshold | int | `3` | |
|
||||
| livenessProbe.httpGet.path | string | `"/v1/api/health"` | |
|
||||
| livenessProbe.httpGet.port | int | `8888` | |
|
||||
| livenessProbe.initialDelaySeconds | int | `15` | |
|
||||
| livenessProbe.periodSeconds | int | `5` | |
|
||||
| nameOverride | string | `""` | |
|
||||
| nodeSelector | object | `{}` | |
|
||||
| persistentVolume.accessModes[0] | string | `"ReadWriteOnce"` | |
|
||||
| persistentVolume.annotations | object | `{}` | |
|
||||
| persistentVolume.existingClaim | string | `""` | |
|
||||
| persistentVolume.labels | object | `{}` | |
|
||||
| persistentVolume.mountPath | string | `"/storage"` | |
|
||||
| persistentVolume.size | string | `"8Gi"` | |
|
||||
| podAnnotations | object | `{}` | |
|
||||
| podLabels | object | `{}` | |
|
||||
| podSecurityContext.fsGroup | int | `1000` | |
|
||||
| readinessProbe.httpGet.path | string | `"/v1/api/health"` | |
|
||||
| readinessProbe.httpGet.port | int | `8888` | |
|
||||
| readinessProbe.initialDelaySeconds | int | `15` | |
|
||||
| readinessProbe.periodSeconds | int | `5` | |
|
||||
| readinessProbe.successThreshold | int | `2` | |
|
||||
| replicaCount | int | `1` | |
|
||||
| resources | object | `{}` | |
|
||||
| securityContext | object | `{}` | |
|
||||
| service.port | int | `3001` | |
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
| serviceAccount.annotations | object | `{}` | |
|
||||
| serviceAccount.automount | bool | `true` | |
|
||||
| serviceAccount.create | bool | `true` | |
|
||||
| serviceAccount.name | string | `""` | |
|
||||
| tolerations | list | `[]` | |
|
||||
| volumeMounts | list | `[]` | |
|
||||
| volumes | list | `[]` | |
|
||||
@@ -0,0 +1,103 @@
|
||||
{{ template "chart.header" . }}
|
||||
{{ template "chart.deprecationWarning" . }}
|
||||
|
||||
{{ template "chart.badgesSection" . }}
|
||||
|
||||

|
||||
|
||||
[AnythingLLM](https://github.com/Mintplex-Labs/anything-llm)
|
||||
|
||||
{{ template "chart.description" . }}
|
||||
|
||||
{{ template "chart.homepageLine" . }}
|
||||
|
||||
{{ template "chart.maintainersSection" . }}
|
||||
|
||||
{{ template "chart.sourcesSection" . }}
|
||||
|
||||
{{ template "chart.requirementsSection" . }}
|
||||
|
||||
**Configuration & Usage**
|
||||
|
||||
- **Config vs Secrets:** This chart exposes application configuration via two mechanisms:
|
||||
- `config` (in `values.yaml`) — rendered into a `ConfigMap` and injected using `envFrom` in the pod. Do NOT place sensitive values (API keys, secrets) in `config` because `ConfigMap`s are not encrypted.
|
||||
- `env` / `envFrom` — the preferred way to inject secrets. Use Kubernetes `Secret` objects and reference them from `env` (with `valueFrom.secretKeyRef`) or `envFrom.secretRef`.
|
||||
|
||||
- **Storage & STORAGE_DIR mapping:** The chart creates (or mounts) a `PersistentVolumeClaim` using the `persistentVolume.*` settings. The container mount path is set from `persistentVolume.mountPath`. Ensure the container `STORAGE_DIR` config key matches that path (defaults are set in `values.yaml`).
|
||||
|
||||
|
||||
**Providing API keys & secrets (recommended)**
|
||||
|
||||
Use Kubernetes Secrets. Below are example workflows and `values.yaml` snippets.
|
||||
|
||||
1) Create a Kubernetes Secret with API keys:
|
||||
|
||||
```
|
||||
kubectl create secret generic openai-secret --from-literal=OPENAI_KEY="sk-..."
|
||||
# or from a file
|
||||
# kubectl create secret generic openai-secret --from-file=OPENAI_KEY=/path/to/keyfile
|
||||
```
|
||||
|
||||
2) Reference the Secret from `values.yaml` using `envFrom` (recommended when your secret contains multiple env keys):
|
||||
|
||||
```yaml
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: openai-secret
|
||||
```
|
||||
|
||||
This will inject all key/value pairs from the `openai-secret` Secret as environment variables in the container.
|
||||
|
||||
3) Or reference a single secret key via `env` (explicit mapping):
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OPENAI_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openai-secret
|
||||
key: OPENAI_KEY
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Avoid placing secret values into `config:` (the chart's `ConfigMap`) — `ConfigMap`s are visible to anyone who can read the namespace. Use `Secret` objects for any credentials/tokens.
|
||||
- If you use a GitOps workflow, consider integrating an external secret operator (ExternalSecrets, SealedSecrets, etc.) so you don't store raw secrets in Git.
|
||||
|
||||
|
||||
**Example `values-secret.yaml` to pass during `helm install`**
|
||||
|
||||
```yaml
|
||||
image:
|
||||
repository: mintplexlabs/anythingllm
|
||||
tag: "1.9.0"
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3001
|
||||
|
||||
# Reference secret containing API keys
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: openai-secret
|
||||
|
||||
# Optionally override other values
|
||||
persistentVolume:
|
||||
size: 16Gi
|
||||
mountPath: /storage
|
||||
```
|
||||
|
||||
Install with:
|
||||
|
||||
```
|
||||
helm install my-anythingllm ./anythingllm -f values-secret.yaml
|
||||
```
|
||||
|
||||
**Best practices & tips**
|
||||
|
||||
- Use `envFrom` for convenience when many environment variables are stored in a single `Secret` and use `env`/`valueFrom` for explicit single-key mappings.
|
||||
- Use `kubectl create secret generic` or your secrets management solution. If you need to reference multiple different provider keys (OpenAI, Anthropic, etc.), create a single `Secret` with multiple keys or multiple Secrets and add multiple `envFrom` entries.
|
||||
- Keep probe paths and `service.port` aligned. If your probes fail after deployment, check that the probe `port` matches the container port (or named port `http`) and that the `path` is valid.
|
||||
- For storage, if you have a pre-existing PVC set `persistentVolume.existingClaim` to the PVC name; the chart will mount that claim (and will not attempt to create a new PVC).
|
||||
- For production, provide resource `requests` and `limits` in `values.yaml` to prevent scheduler starvation and to control cost.
|
||||
|
||||
{{ template "chart.valuesSection" . }}
|
||||
@@ -0,0 +1,28 @@
|
||||
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 "anythingllm.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 its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "anythingllm.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "anythingllm.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 "anythingllm.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 "To access locally, run:"
|
||||
echo " kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT"
|
||||
echo "Then visit http://127.0.0.1:8080"
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "anythingllm.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "anythingllm.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "anythingllm.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "anythingllm.labels" -}}
|
||||
helm.sh/chart: {{ include "anythingllm.chart" . }}
|
||||
{{ include "anythingllm.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "anythingllm.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "anythingllm.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "anythingllm.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "anythingllm.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
name: {{ include "anythingllm.fullname" . }}-config
|
||||
data:
|
||||
{{- range $key, $value := .Values.config }}
|
||||
{{ $key }}: "{{ $value }}"
|
||||
{{- end }}
|
||||
@@ -0,0 +1,83 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "anythingllm.fullname" . }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "anythingllm.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 8 }}
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "anythingllm.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
{{- with .Values.initContainers }}
|
||||
initContainers:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.strategy }}
|
||||
strategy:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- with .Values.env }}
|
||||
env:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "anythingllm.fullname" . }}-config
|
||||
{{- with .Values.envFrom }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: storage
|
||||
mountPath: {{ .Values.persistentVolume.mountPath }}
|
||||
volumes:
|
||||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "anythingllm.fullname" . }}-storage-claim
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,4 @@
|
||||
{{ range .Values.extraObjects }}
|
||||
---
|
||||
{{ tpl (toYaml .) $ }}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,61 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "anythingllm.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
{{- if .Values.persistentVolume.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.persistentVolume.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
{{- with .Values.persistentVolume.labels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "anythingllm.fullname" . }}-storage-claim
|
||||
spec:
|
||||
accessModes:
|
||||
{{- toYaml .Values.persistentVolume.accessModes | nindent 4 }}
|
||||
{{- if .Values.persistentVolume.storageClass }}
|
||||
{{- if (eq "-" .Values.persistentVolume.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: "{{ .Values.persistentVolume.storageClass }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistentVolume.size }}
|
||||
{{- if .Values.persistentVolume.volumeName }}
|
||||
volumeName: "{{ .Values.persistentVolume.volumeName }}"
|
||||
{{- end -}}
|
||||
{{- with .Values.persistentVolume.selector }}
|
||||
selector:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "anythingllm.fullname" . }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "anythingllm.selectorLabels" . | nindent 4 }}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "anythingllm.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "anythingllm.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "anythingllm.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: healthcheck
|
||||
image: curlimages/curl:8.1.2
|
||||
command: ["sh", "-c"]
|
||||
args:
|
||||
- "curl -fsS -o /dev/null http://{{ include "anythingllm.fullname" . }}:{{ .Values.service.port }}|| exit 1"
|
||||
restartPolicy: Never
|
||||
@@ -0,0 +1,235 @@
|
||||
replicaCount: 1
|
||||
|
||||
initContainers:
|
||||
[]
|
||||
# - name: init-myservice
|
||||
# image: busybox
|
||||
# command: ['sh', '-c', 'chown -R 1000:1000 /storage']
|
||||
|
||||
image:
|
||||
repository: mintplexlabs/anythingllm
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "1.9.0"
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
persistentVolume:
|
||||
# AnythingLLM storage data Persistent Volume access modes
|
||||
# Must match those of existing PV or dynamic provisioner
|
||||
# Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
|
||||
#
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
|
||||
# AnythingLLM storage data Persistent Volume labels
|
||||
#
|
||||
labels: {}
|
||||
|
||||
# AnythingLLM storage data Persistent Volume annotations
|
||||
#
|
||||
annotations: {}
|
||||
|
||||
# AnythingLLM storage data Persistent Volume existing claim name
|
||||
# If defined, PVC must be created manually before volume will be bound
|
||||
#
|
||||
existingClaim: ""
|
||||
|
||||
# AnythingLLM storage data Persistent Volume size
|
||||
#
|
||||
size: 8Gi
|
||||
|
||||
# AnythingLLM storage data Persistent Volume mount path
|
||||
# Must match the STORAGE_DIR config value
|
||||
#
|
||||
mountPath: /app/server/storage
|
||||
|
||||
# AnythingLLM storage data Persistent Volume Storage Class
|
||||
# If defined, storageClassName: <storageClass>
|
||||
# If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||
# If undefined (the default) or set to null, no storageClassName spec is
|
||||
# set, choosing the default provisioner. (gp2 on AWS, standard on
|
||||
# GKE, AWS & OpenStack)
|
||||
#
|
||||
storageClass: ""
|
||||
|
||||
# AnythingLLM storage data Persistent Volume Claim Selector
|
||||
# Useful if Persistent Volumes have been provisioned in advance
|
||||
# Ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector
|
||||
#
|
||||
selector: {}
|
||||
# selector:
|
||||
# matchLabels:
|
||||
# release: "stable"
|
||||
# matchExpressions:
|
||||
# - { key: environment, operator: In, values: [ dev ] }
|
||||
|
||||
# AnythingLLM storage data Persistent Volume Name
|
||||
# Useful if Persistent Volumes have been provisioned in advance and you want to use a specific one
|
||||
#
|
||||
volumeName: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Automatically mount a ServiceAccount's API credentials?
|
||||
automount: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
# The Anything LLM application deployment strategy
|
||||
# This is set to "Recreate" by default as AnythingLLM support is not yet
|
||||
# production ready. Once it is, this can be changed to "RollingUpdate"
|
||||
# Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
|
||||
#
|
||||
strategy:
|
||||
# Type of deployment. Can be "Recreate" or "RollingUpdate". Default is "Recreate"
|
||||
type: Recreate
|
||||
# If type is "RollingUpdate", the following values can be set:
|
||||
# rollingUpdate:
|
||||
# maxUnavailable: 1
|
||||
# maxSurge: 1
|
||||
|
||||
podAnnotations: {}
|
||||
podLabels: {}
|
||||
|
||||
podSecurityContext:
|
||||
# fsGroup needs to be set as the same as the uid/gid used to run the application
|
||||
# in order to have the right permissions on mounted volumes
|
||||
fsGroup: 1000
|
||||
|
||||
securityContext:
|
||||
{}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
# AnythingLLM configuration options, these are stored in a ConfigMap and passed
|
||||
# to the container as environment variables.
|
||||
# See https://github.com/Mintplex-Labs/anything-llm/blob/render/docker/.env.example
|
||||
# for all available environment variables to use as configuration options
|
||||
#
|
||||
config:
|
||||
DISABLE_TELEMETRY: "true"
|
||||
NODE_ENV: production
|
||||
STORAGE_DIR: /app/server/storage
|
||||
UID: "1000"
|
||||
GID: "1000"
|
||||
|
||||
# The preferred method for setting secret environment variables
|
||||
# Ref: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#define-a-container-environment-variable-with-data-from-a-single-secret
|
||||
#
|
||||
env: {}
|
||||
# - name: OPEN_AI_KEY
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: openai-secret
|
||||
# key: openai_key
|
||||
|
||||
# Typically used to reference a pre existing Secret containing multiple environment variables
|
||||
# Ref: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#define-a-container-environment-variable-with-data-from-a-single-secret
|
||||
#
|
||||
envFrom:
|
||||
{}
|
||||
# - secretRef:
|
||||
# name: mysecret
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3001
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations:
|
||||
{}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources:
|
||||
{}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /v1/api/health
|
||||
port: 8888
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 5
|
||||
successThreshold: 2
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /v1/api/health
|
||||
port: 8888
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
|
||||
# Additional volumes on the output Deployment definition.
|
||||
#
|
||||
volumes: []
|
||||
# - name: foo
|
||||
# secret:
|
||||
# secretName: mysecret
|
||||
# optional: false
|
||||
|
||||
# Additional volumeMounts on the output Deployment definition.
|
||||
#
|
||||
volumeMounts: []
|
||||
# - name: foo
|
||||
# mountPath: "/etc/foo"
|
||||
# readOnly: true
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
## Array of extra manifests/obhects to create
|
||||
#
|
||||
extraObjects: []
|
||||
# - apiVersion: external-secrets.io/v1beta1
|
||||
# kind: ExternalSecret
|
||||
# metadata:
|
||||
# name: open-ai-api-key-external-secret
|
||||
# namespace: default
|
||||
# spec:
|
||||
# refreshInterval: 1h
|
||||
# secretStoreRef:
|
||||
# name: vault
|
||||
# kind: ClusterSecretStore
|
||||
# target:
|
||||
# name: open-ai-api-key-secret
|
||||
# template:
|
||||
# type: Opaque
|
||||
# data:
|
||||
# - secretKey: open_ai_key
|
||||
# remoteRef:
|
||||
# key: secret/data/anything-llm
|
||||
# property: open_ai_key
|
||||
+634
@@ -0,0 +1,634 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Mintplex Labs Helm Charts</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Official Helm Charts repository for Mintplex Labs - Deploy applications on Kubernetes with ease"
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="helm, charts, kubernetes, k8s, mintplex-labs, anything-llm, deployment"
|
||||
/>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link
|
||||
rel="icon"
|
||||
href="https://helm.sh/img/favicon-196x196.png"
|
||||
type="image/png"
|
||||
/>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Font Awesome for icons -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
|
||||
/>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #0f1419;
|
||||
--secondary-color: #326ce5;
|
||||
--accent-color: #4fc3f7;
|
||||
--text-primary: #333;
|
||||
--text-secondary: #666;
|
||||
--background: #ffffff;
|
||||
--card-background: #f8f9fa;
|
||||
--border-color: #e1e5e9;
|
||||
--success-color: #28a745;
|
||||
--warning-color: #ffc107;
|
||||
--border-radius: 8px;
|
||||
--shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--primary-color) 0%,
|
||||
var(--secondary-color) 100%
|
||||
);
|
||||
color: white;
|
||||
padding: 2rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 20"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="1"/></pattern></defs><rect width="100" height="20" fill="url(%23grid)"/></svg>');
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.3rem;
|
||||
margin-bottom: 2rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.helm-logo {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Main content */
|
||||
main {
|
||||
padding: 4rem 0;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--primary-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
/* Quick Start */
|
||||
.quick-start {
|
||||
background: var(--card-background);
|
||||
padding: 2rem;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow);
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.quick-start h3 {
|
||||
color: var(--secondary-color);
|
||||
margin-bottom: 1.5rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background: var(--primary-color);
|
||||
color: #f8f8f2;
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--border-radius);
|
||||
margin: 1rem 0;
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.code-block pre {
|
||||
margin: 0;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background: var(--accent-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Charts Grid */
|
||||
.charts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
background: var(--card-background);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 2rem;
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.chart-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: var(--shadow);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chart-icon {
|
||||
font-size: 3rem;
|
||||
color: var(--secondary-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.chart-description {
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.chart-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-stable {
|
||||
background: rgba(40, 167, 69, 0.1);
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
.status-beta {
|
||||
background: rgba(255, 193, 7, 0.1);
|
||||
color: var(--warning-color);
|
||||
}
|
||||
|
||||
/* Features */
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
text-align: center;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 3rem;
|
||||
color: var(--secondary-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
padding: 3rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.footer-section h4 {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.footer-section ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.footer-section ul li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-section a {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.footer-section a:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding-top: 2rem;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.hero h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.charts-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.fade-in-up {
|
||||
animation: fadeInUp 0.6s ease-out;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="hero fade-in-up">
|
||||
<div class="helm-logo">⎈</div>
|
||||
<h1>Mintplex Labs Helm Charts</h1>
|
||||
<p>
|
||||
Official Helm Charts Repository - Deploy applications on Kubernetes
|
||||
with ease
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="container">
|
||||
<!-- Quick Start Section -->
|
||||
<section class="section">
|
||||
<h2 class="section-title">Quick Start</h2>
|
||||
<p class="section-subtitle">
|
||||
Get started with Mintplex Labs Helm Charts in minutes
|
||||
</p>
|
||||
|
||||
<div class="quick-start fade-in-up">
|
||||
<h3><i class="fas fa-rocket"></i> Add the Repository</h3>
|
||||
<div class="code-block">
|
||||
<button class="copy-button" onclick="copyToClipboard('add-repo')">
|
||||
<i class="fas fa-copy"></i> Copy
|
||||
</button>
|
||||
<pre id="add-repo">
|
||||
helm repo add mintplex-labs https://mintplex-labs.github.io/helm-charts</pre
|
||||
>
|
||||
</div>
|
||||
|
||||
<h3><i class="fas fa-sync-alt"></i> Update Repository</h3>
|
||||
<div class="code-block">
|
||||
<button
|
||||
class="copy-button"
|
||||
onclick="copyToClipboard('update-repo')"
|
||||
>
|
||||
<i class="fas fa-copy"></i> Copy
|
||||
</button>
|
||||
<pre id="update-repo">helm repo update</pre>
|
||||
</div>
|
||||
|
||||
<h3><i class="fas fa-search"></i> Search Charts</h3>
|
||||
<div class="code-block">
|
||||
<button
|
||||
class="copy-button"
|
||||
onclick="copyToClipboard('search-charts')"
|
||||
>
|
||||
<i class="fas fa-copy"></i> Copy
|
||||
</button>
|
||||
<pre id="search-charts">helm search repo mintplex-labs</pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features Section -->
|
||||
<section class="section">
|
||||
<h2 class="section-title">Why Choose Our Charts?</h2>
|
||||
<p class="section-subtitle">
|
||||
Built with best practices and production experience
|
||||
</p>
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card fade-in-up">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Production Ready</h3>
|
||||
<p>
|
||||
Battle-tested charts with security best practices and
|
||||
comprehensive configuration options
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card fade-in-up" style="animation-delay: 0.2s">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-cogs"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Highly Configurable</h3>
|
||||
<p>
|
||||
Extensive customization options to fit your specific deployment
|
||||
requirements
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card fade-in-up" style="animation-delay: 0.4s">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-book"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Well Documented</h3>
|
||||
<p>
|
||||
Comprehensive documentation with examples and troubleshooting
|
||||
guides
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card fade-in-up" style="animation-delay: 0.6s">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Community Driven</h3>
|
||||
<p>
|
||||
Open source with active community support and regular updates
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h4>Resources</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/mintplex-labs/helm-charts"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fab fa-github"></i> Source Code
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/mintplex-labs/helm-charts/issues"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fas fa-bug"></i> Report Issues
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/mintplex-labs/helm-charts/discussions"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fas fa-comments"></i> Discussions
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<h4>Documentation</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://helm.sh/docs/" target="_blank">
|
||||
<i class="fas fa-book"></i> Helm Documentation
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://kubernetes.io/docs/" target="_blank">
|
||||
<i class="fas fa-dharmachakra"></i> Kubernetes Docs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/mintplex-labs/helm-charts/blob/main/README.md"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fas fa-readme"></i> Getting Started
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<h4>Community</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://mintplexlabs.com/" target="_blank">
|
||||
<i class="fas fa-globe"></i> Mintplex Labs Website
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="mailto:team@mintplexlabs.com">
|
||||
<i class="fas fa-envelope"></i> Contact Us
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-bottom">
|
||||
<p>© 2025 Mintplex Labs. Licensed under the MIT License.</p>
|
||||
<p>
|
||||
Made with
|
||||
<i class="fas fa-heart" style="color: var(--accent-color)"></i> for
|
||||
the Kubernetes community
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// Copy to clipboard functionality
|
||||
function copyToClipboard(elementId) {
|
||||
const element = document.getElementById(elementId);
|
||||
const text = element.textContent;
|
||||
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
// Show feedback
|
||||
const button = element.parentElement.querySelector(".copy-button");
|
||||
const originalText = button.innerHTML;
|
||||
button.innerHTML = '<i class="fas fa-check"></i> Copied!';
|
||||
button.style.background = "var(--success-color)";
|
||||
|
||||
setTimeout(() => {
|
||||
button.innerHTML = originalText;
|
||||
button.style.background = "var(--accent-color)";
|
||||
}, 2000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Failed to copy text: ", err);
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(textArea);
|
||||
});
|
||||
}
|
||||
|
||||
// Add smooth scrolling for anchor links
|
||||
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
||||
anchor.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute("href"));
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "start",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add animation on scroll
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: "0px 0px -50px 0px",
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.style.opacity = "1";
|
||||
entry.target.style.transform = "translateY(0)";
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Observe all fade-in-up elements
|
||||
document.querySelectorAll(".fade-in-up").forEach((el) => {
|
||||
el.style.opacity = "0";
|
||||
el.style.transform = "translateY(30px)";
|
||||
el.style.transition = "opacity 0.6s ease-out, transform 0.6s ease-out";
|
||||
observer.observe(el);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user