A general-purpose Kubernetes workload Helm chart with batteries included. Deploy any container image as a Deployment or StatefulSet with optional addon sidecars for VPN, PostgreSQL, and Cloudflare Tunnel.
- Kubernetes 1.26+
- Helm 3.x
helm install my-release oci://ghcr.io/temikus/helm-charts/workload --version 1.8.0git clone https://github.com/Temikus/helm-workload.git
cd helm-workload
helm install my-release .releases:
- name: my-app
namespace: my-namespace
chart: oci://ghcr.io/temikus/helm-charts/workload
version: 1.8.0
values:
- image:
repository: nginx
tag: stable
ports:
- name: http
port: 80
service:
enabled: true
port: 80image:
repository: quay.io/curl/curl
tag: latest
command: ["sleep", "infinity"]image:
repository: homebridge/homebridge
tag: "2024-01-08"
ports:
- name: http
port: 8581
service:
enabled: true
port: 8581
persistence:
enabled: true
type: statefulset
storageClassName: longhorn-retained
mountPath: /homebridge
accessModes:
- ReadWriteOnce
size: 5Gi
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: letsencrypt-production
hosts:
- host: homebridge.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: homebridge-tls
hosts:
- homebridge.example.comAll configuration is done through values.yaml. See the file for full documentation of each field, or use helm show values oci://ghcr.io/temikus/helm-charts/workload.
| Parameter | Description | Default |
|---|---|---|
image.repository |
Container image repository | nginx |
image.tag |
Container image tag | latest |
replicaCount |
Number of replicas | 1 |
ports |
List of container/service port definitions | [] |
persistence.enabled |
Enable persistent storage | false |
ingress.enabled |
Enable Ingress resource | false |
autoscaling.enabled |
Enable HorizontalPodAutoscaler (autoscaling/v2) |
false |
hostNetwork.enabled |
Enable host networking | false |
strategy |
Rollout strategy (RollingUpdate/Recreate for Deployment; RollingUpdate/OnDelete for StatefulSet) |
{} |
networkPolicy.enabled |
Create a NetworkPolicy restricting ingress traffic | false |
extraServices |
Additional multi-port Service resources alongside port-derived services | [] |
env / secretEnv |
Environment variables rendered into a ConfigMap / a Secret | {} |
envFrom |
Extra secretRef/configMapRef entries for the main container |
[] |
annotations |
Annotations on the Deployment/StatefulSet object (pod template uses podAnnotations) |
{} |
addons.infisical.enabled |
Sync an Infisical secrets path into the container env via secrets-operator | false |
Addon sidecars are injected into the pod alongside your main container. All addons are disabled by default.
Run an init container before the main application starts.
addons:
init:
enabled: true
image:
repository: busybox
tag: latest
command: ["sh", "-c", "echo initializing"]Adds a Gluetun VPN sidecar. Supports OpenVPN and WireGuard with multiple providers.
addons:
vpn:
enabled: true
provider:
name: mullvad
type: wireguard
wireguard:
privateKey: "" # or use existingSecret
config:
timezone: UTC
serverSelection:
countries: SwedenAdds a PostgreSQL sidecar with persistent storage. Useful for applications that need a dedicated database.
addons:
postgres:
enabled: true
auth:
username: myapp
password: secret # or use existingSecret
database: myapp_db
persistence:
enabled: true
size: 8GiExposes your service through a Cloudflare Tunnel using the cloudflare-operator. Requires the operator to be installed in your cluster.
addons:
cloudflareTunnel:
enabled: true
fqdn: myapp.example.com
protocol: http
targetPort: 8080
tunnelRef:
kind: ClusterTunnel
name: my-cluster-tunnelSupports optional path filtering (nginx sidecar proxy) and NetworkPolicy for defense-in-depth.
Syncs a secrets folder from Infisical into a managed Kubernetes Secret via the Infisical secrets-operator and injects it into the main container's envFrom. Requires the operator in your cluster and a universal-auth credentials Secret (clientId/clientSecret) in the release namespace.
addons:
infisical:
enabled: true
hostAPI: https://infisical.example.com/api # omit for Infisical Cloud
projectSlug: myproject
envSlug: prod
secretsPath: /myapp
credentialsSecret: infisical-universal-auth # defaultUse keys to rename secrets on the way in (ENV_NAME: INFISICAL_KEY), combined with includeAllSecrets: false to expose only those. The workload gets the operator's secrets.infisical.com/auto-reload annotation so a rotated secret rolls the pods; set autoReload: false to opt out (for example when using Reloader via annotations).
env: # rendered into a ConfigMap
TZ: UTC
secretEnv: # rendered into a chart-owned Secret
API_KEY: "ref+vault://..."
envFrom: # appended after the generated refs; later entries win on key clash
- secretRef:
name: my-secretConfigure the rollout strategy for Deployments or StatefulSets. The same strategy value is used for both — it maps to spec.strategy on Deployments and spec.updateStrategy on StatefulSets.
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1Create a Kubernetes NetworkPolicy to restrict ingress traffic to the pod.
networkPolicy:
enabled: true
# Allow ingress on all ports from .Values.ports (default). Set false for deny-all.
allowPortsIngress: true
# Or specify explicit ingress rules:
ingress:
- ports:
- port: 80
protocol: TCP
from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoringCreate additional Service resources with custom port mappings (e.g. for UDP discovery protocols or mixed-type services).
extraServices:
- name: device-mgmt
type: LoadBalancer
ports:
- name: discovery
port: 29810
targetPort: discovery
protocol: UDP
- name: manager
port: 29811
targetPort: managerappVersionis not dynamically set from the image tag; it mirrors the chart version.
- Helm 3.x
- helm-unittest plugin
- just (optional, for task automation)
just lint # Lint the chart
just test # Run unit tests
just test -u # Update test snapshots
just build # Package the chartOr without just:
helm lint .
helm unittest .Apache License 2.0 - see LICENSE for details.