Files
Adam CarhedenandHugo Shaka c8e23661ca Added proxy-only helm chart (#68037)
* Added proxy-only helm chart

* dleted unused text fixtures

* Deleted empty snapshots

* unused helmignore

* deleted debugging

* Switch empty join_params from values file to set to avoid lint-helm make target bug

* Put static join tokens in secert

* Remove PSP support

* Added token secret to validation hook

* fixed hook name in test

* Made example use more realistic kube+oidc token

* Set correct hook weight for secret

* Better validation of token secerts

* Fixed cluster ref in readme example

* Fixed typo in Account

* Preserve all join params

* Make tmp secret for install only

* Fixed wrong context for volumes calls

* Don't support creating token secret for upgrades

* Added optional audience to projected SA token

* Deleted unneeded snapshot

* Fixed merged proxy values for join token secret

* Ensures hook secret is created for proxy override

* Wrote docs

* Allowed empty value for proxyProtocol

* Fixed doc spelling errors

* Wrote index page for teleport-proxy chart

* Ensure bound keypair values are only in secrets

* Fixed extra whitespace

* fixed auth-token path and related tests

* Removed token and bound_keypair support

* Fixed lint version after rebase to helm4 link fix

* Corrected overrides for serviceAccountToken* settings

* corrected doc links

* Documented validation intent

* Fix doc links

* Fixed tls-routing doc link

* Fix arch doc ref

* arch link fix again

* forgot to checking vales

* Fix vale findings

* Update examples/chart/teleport-proxy/values.yaml

Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com>

* Fixed missing docs secions due to -- vs -

* Address code review comments

* Switched helm values to camelCase

* Removed legacy proxy key

* Remove legacy replica count munging

* Added Azure support to joinParams

* Fix unescaped doc chars

* Fixed doc heading and link

* fixed heading

* fixed vale checks

* code review fixes for values

* Added updated generated doc page

* Updated for helm unittest 1.0.3

* Fixed config version for scratch chart mode

* Remove unneeded license from proxy chart

* Clarified Anycast support in comment

* Clarified cluster name docs

* Noted limited purpose of chart

* Made various bits of docs admonitions

* Advised against using serviceAccountToken values

* Removed ACME support

* Fixed incorrect link

* fixed mdx/mxd doc extention conflation

* Fixed doc lint issues

* Removed serviceAccountToken custom fields

* Corrected docs on join token creation

* Corrected example token expiry in docs and unneded doc link in README

* Fixed spelling

* Fixed tctl create command

---------

Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com>
2026-08-13 21:36:57 +00:00
..

Library Helm Charts

This directory contains Helm Library charts used by multiple Application (i.e. "normal") charts. Library charts are kept here to distinguish them from those meant to be installed by end users.

What is a library chart?

A Library Chart is one that has type: library in Chart.yaml. Such charts behave differently in two ways:

  1. Helm will actively refuse to install them.

    $ helm install my-release .
    Error: INSTALLATION FAILED: library charts are not installable
    
  2. They render no templates

    Helm still registers the chart's named templates ({{ define ... }}) into the parent chart's global scope, but it does not render the library chart's own manifest templates. Files that don't start with _ are ignored.

Interface Contract

Library charts defined here should define Named Templates designed to take a copy of the calling chart's root context.

{{- include "my-lib-chart.my-template" . -}}

This follows patterns established by:

This means:

  • Parent charts should define top-level values the library chart's templates consume

    # parent/values.yaml
    
    # Correct!
    myLibChartValue: foo
    
    ## WRONG! Don't Copy ME
    my-lib-chart:
      myLibChartValue: bar
    
  • Library chart templates should consume them at:

    • .Values.myLibChartValue

    NOT:

    • .myLibChartValue # WRONG, DON'T COPY
    • .Values.my-lib-chart.myLibChartValue # WRONG, DON'T COPY

Value Defaults / Schema Validation

Library charts' default values and schema validation are processed just like subchart dependencies. This means that if a library chart has a values.yaml and/or values.schema.json, these will apply to the parent chart at .Values.<subkey>.*, not at the root level. This doesn't follow the pattern above, nor does it allow the parent chart to deviate from the dependent library chart when it needs different validation (i.e. if the parent chart manipulates the context passed to the library chart's named templates, thereby making the library chart's validation invalid). Library charts should therefore generally not define values or schema.

This does mean that multiple charts that depend on the same library chart will likely duplicate values and schema for the library chart. Helm has no great way to move that responsibility to library charts without limiting how the parent chart can define its required values.

Library charts can instead validate their inputs at render-time by having all public named templates call an internal validation template.

{{- define "my-lib-chart.my-template" -}}
{{- include "my-lib-chart.internal.validate" . -}}
...
{{- end -}}

{{- define "my-lib-chart.internal.validate" -}}
{{- if not (and (hasKey .Values "myRequiredValue") (kindIs "string" .Values.myRequiredValue)) -}}
{{- fail "'myRequiredValue' is required" -}}
{{- end -}}
...
{{- end -}}

Value Merging

It's possible to merge library chart values from the parent chart's root values and the library chart's subkey with an init helper called by library chart templates (example) to define values at multiple levels. However, including values and schema in the library chart still only applies defaults and validation to values defined under the library chart's subkey (.Values.my-lib-chart), so something like .Values.myLibChartValue still needs independent validation by the parent's schema.

Documentation

A library chart's public interface is its public (non-internal) named templates and the .Values keys they read. Document that interface in a README.md at the chart root (e.g. lib/teleport-proxy-lib/README.md). It should list each public template, how to call it, and the values it requires — plus any values the consuming chart must compute and inject.

Do not rely on values.yaml or values.schema.json for this. As described under "Value Defaults / Schema Validation" above, Helm applies a library chart's values.yaml/schema at .Values.<subkey>, not where the templates read, so they cannot serve as the interface contract.

Testing

Because they don't render templates, library charts can't be tested using helm unittest. To work around this, library charts should define an application chart as a test fixture/helper in the test-chart/ directory under their root. This chart should include the library chart with a symlink (my-lib-chart/test-chart/charts/my-lib-chart -> ../../). It should define templates and unit tests that call the library chart templates. Don't forget to add both the library chart AND test-chart to Helm Janitor (teleport/build.assets/tooling/cmd/helm-janitor/main.go).

Scoping & Naming

All named templates defined in a library chart are exported into the parent's global namespace. All named templates should therefore be prefixed with the library chart's name to avoid naming collisions:

{{- define "my-lib-chart.my-template" -}}

Kebab-case vs. camelCase

Use kebab-case for chart names and named-template names, and camelCase for values/field keys. The two never collide:

  • Named-template names are always quoted strings in define/include ({{ include "my-lib-chart.my-template" . }}), so a - is just a character in a string — it is never parsed as an identifier.
  • Value keys are read with dot notation (.Values.myValue). Go templates parse - as subtraction, so a dashed key like .Values.my-value won't work — you'd have to write index .Values "my-value". camelCase keeps dot access working.

Abstraction (if you must)

Helm does allow naming collisions, in which case the parent chart's version will be rendered. This can be used as a form of abstraction:

# my-lib-chart/templates/_helpers.tpl
{{- define "my-lib-chart.my-template" -}}
{{ fail "REDEFINE ME IN THE CALLING CHART PLEASE." }}
{{- end -}}
# parent/templates/_helpers.tpl
{{- define "my-lib-chart.my-template" -}}
A concrete implementation of my-template in parent chart.
{{- end -}}

This is acceptable, but should be well documented.

Internal / Private Named Templates

Helm has no way to protect / privatize some subset of a library chart's templates. To distinguish the library chart's public interface from templates not intended for consumption, "private" templates should have an .internal component to their name:

{{- define "my-lib-chart.internal.my-internal-template" -}}