Installation¶
Prerequisites¶
- Kubernetes v1.16+
- Helm 3.0+
kubectlconfigured to access your cluster- A supported storage backend (S3 bucket, Azure Storage Account, GCS bucket, or local filesystem)
- (Optional) A GitHub App for authenticated API access
Optional OIDC Prerequisites (Recommended)¶
If you plan to use OIDC authentication and tofu login, also prepare:
- An OIDC issuer (Dex via Helm subchart or an external OIDC provider)
- A registered OIDC client for OpenDepot (client ID/secret)
- Externally reachable OIDC auth/token endpoints advertised in service discovery (
login.v1) - (Optional)
GroupBindingresources for fine-grained module/provider access control
See OIDC Configuration for full setup details and examples.
Install with Helm¶
Minimal install
For a quick start, the one-liner below is all you need. OpenDepot will use in-cluster defaults. Customise with --set flags or a values file once you're ready.
helm repo add opendepot https://tonedefdev.github.io/opendepot
helm repo update
helm install opendepot opendepot/opendepot \
-n opendepot-system \
--create-namespace
Upgrading an existing installation
Helm does not update CRDs during helm upgrade. If you are upgrading from a previous version, apply the latest CRDs manually first:
To customize values:
helm install opendepot opendepot/opendepot \
-n opendepot-system \
--create-namespace \
--set global.image.tag=v0.1.0 \
--set server.service.type=ClusterIP \
--set depot.enabled=false
Or use a values file:
helm install opendepot opendepot/opendepot \
-n opendepot-system \
--create-namespace \
-f my-values.yaml
Helm Chart Values¶
Full Helm values reference
The tables below list every configurable Helm value. Most defaults are sensible for a standard installation — focus on global.image.tag, your storage backend, and server.ingress or server.tls for production.
Global¶
| Value | Default | Description |
|---|---|---|
global.namespace | opendepot-system | Namespace for all resources |
global.imagePullPolicy | IfNotPresent | Image pull policy |
global.image.tag | "" | Image tag for all services (defaults to Chart.AppVersion when empty) |
Server¶
| Value | Default | Description |
|---|---|---|
server.enabled | true | Deploy the server |
server.replicaCount | 1 | Number of replicas |
server.anonymousAuth | false | Use the server's service account for unauthenticated module access (see note below) |
server.useBearerToken | true | Use bearer token auth instead of kubeconfig |
server.image.repository | ghcr.io/tonedefdev/opendepot/server | Server image |
server.service.type | LoadBalancer | Service type |
server.service.port | 80 | Service port |
server.service.targetPort | 8080 | Container port |
server.tls.enabled | false | Enable TLS on the server |
server.tls.certPath | /etc/tls/tls.crt | Path to TLS certificate |
server.tls.keyPath | /etc/tls/tls.key | Path to TLS key |
server.ingress.enabled | false | Enable Kubernetes Ingress |
server.ingress.istio.enabled | false | Enable Istio VirtualService |
server.ingress.istio.hosts | [opendepot.defdev.io] | Istio VirtualService hosts |
server.resources.requests.cpu | 100m | CPU request |
server.resources.requests.memory | 128Mi | Memory request |
server.resources.limits.cpu | not set | CPU limit |
server.resources.limits.memory | 512Mi | Memory limit |
server.nodeSelector | {} | Node selector |
server.tolerations | [] | Tolerations |
server.affinity | {} | Affinity rules |
server.podDisruptionBudget.enabled | false | Enable PDB |
server.podDisruptionBudget.minAvailable | 2 | Minimum available pods |
server.ingress.hosts | see values.yaml | Standard Ingress host/path rules |
server.ingress.tls | [] | Standard Ingress TLS configuration |
Server OIDC¶
| Value | Default | Description |
|---|---|---|
server.oidc.enabled | false | Enable OIDC token validation for registry requests |
server.oidc.issuerUrl | "" | OIDC issuer URL (auto-derived from Dex when blank and dex.enabled=true) |
server.oidc.clientId | opendepot | OIDC client ID used by tofu login |
server.oidc.clientSecretName | "" | Existing Secret name containing OIDC client secret |
server.oidc.clientSecret | "" | OIDC client secret used to create chart-managed Secret when clientSecretName is blank |
server.oidc.groupsClaim | "" | JWT claim name containing groups (defaults to groups in server flag behavior) |
server.oidc.allowServiceAccountFallback | false | Allow Kubernetes SA bearer tokens when OIDC is enabled |
server.oidc.allowClientCredentials | false | Allow Dex client-credentials tokens and map sub to client:<sub> for GroupBinding evaluation |
server.oidc.authzUrl | "" | Override login.v1.authz URL advertised in service discovery |
server.oidc.tokenUrl | "" | Override login.v1.token URL advertised in service discovery |
Valkey Stats Store¶
Download statistics are persisted in a bundled Valkey (Redis-compatible) instance that is always deployed as part of the chart. No extra configuration is required to enable stats — they are always on.
| Value | Default | Description |
|---|---|---|
valkey.resources | see values.yaml | Resource requests and limits for the Valkey pod |
valkey.dataStorage.enabled | true | Create a PVC for Valkey data. When false, stats are stored on an ephemeral in-pod volume and lost on restart |
valkey.dataStorage.className | "" | StorageClass for the PVC. Leave blank to use the cluster default |
valkey.dataStorage.requestedSize | 1Gi | PVC storage size |
valkey.auth.enabled | false | Enable Valkey ACL password authentication |
valkey.auth.usersExistingSecret | "" | Name of a pre-existing Secret whose keys are ACL usernames. Required when auth is enabled |
valkey.auth.aclUsers.default.permissions | ~stats:* &* -@all +HSET +HINCRBY +HGET +HGETALL +INCR +GET +ZINCRBY +ZREVRANGEBYSCORE +ZREVRANGE +EXPIREAT | ACL permissions string for the default user. Scoped to stats:* keys and only the commands used by the server — do not widen to +@all in production |
server.stats.valkeyPasswordSecretName | "" | Name of the Secret injected as OPENDEPOT_VALKEY_PASSWORD into the server. Must match valkey.auth.usersExistingSecret |
valkey.nodeSelector | {} | Node selector for the Valkey pod |
valkey.tolerations | [] | Tolerations for the Valkey pod |
valkey.affinity | {} | Affinity rules for the Valkey pod |
Set valkey.dataStorage.enabled: false for local Kind clusters or ephemeral environments where no StorageClass is available. For production, leave persistence enabled (the default) so stats survive pod restarts.
Production Security
Valkey ACL authentication is disabled by default. For production deployments, create a Kubernetes Secret containing the password, then set valkey.auth.enabled: true, valkey.auth.usersExistingSecret, and server.stats.valkeyPasswordSecretName to match. Use External Secrets Operator or HashiCorp Vault to provision the Secret in regulated environments.
Controllers¶
These values apply to version, module, depot, and provider independently:
| Value | Default | Description |
|---|---|---|
<service>.enabled | true (provider: false) | Deploy the controller |
<service>.replicaCount | 1 | Number of replicas |
<service>.image.repository | ghcr.io/tonedefdev/opendepot/<service>-controller | Image repository |
<service>.image.tag | "" | Overrides global.image.tag when set |
<service>.resources.requests.cpu | 100m | CPU request |
<service>.resources.requests.memory | version: 512Mi, others 128Mi | Memory request |
<service>.resources.limits.cpu | not set | CPU limit |
<service>.resources.limits.memory | version: 4Gi, others 512Mi | Memory limit |
<service>.nodeSelector | {} | Node selector |
<service>.tolerations | [] | Tolerations |
<service>.affinity | {} | Affinity rules |
Note
The provider controller is disabled by default (provider.enabled: false). Enable it explicitly when you are ready to sync provider binaries — provider archives can be several hundred megabytes each.
GPG Signing (Providers)¶
The server signs SHA256SUMS files for provider packages using a GPG key you supply. OpenTofu verifies this signature as part of the Provider Registry Protocol. You must create a Kubernetes Secret with the following keys and reference it via server.gpg.secretName:
| Secret Key | Description |
|---|---|
OPENDEPOT_PROVIDER_GPG_KEY_ID | Short or long hex key ID of the signing key |
OPENDEPOT_PROVIDER_GPG_ASCII_ARMOR | ASCII-armored public key block (included in the API response so OpenTofu can verify) |
OPENDEPOT_PROVIDER_GPG_PRIVATE_KEY_BASE64 | Base64-encoded ASCII-armored private key (used by the server to sign SHA256SUMS) |
| Value | Default | Description |
|---|---|---|
server.gpg.secretName | "" | Name of the Kubernetes Secret containing GPG signing credentials |
See GPG Signing for Providers in the Configuration section for full setup instructions.
Service Account & RBAC¶
| Value | Default | Description |
|---|---|---|
serviceAccount.create | true | Create service accounts |
serviceAccount.annotations | {} | Annotations (use for IRSA/Workload Identity) |
rbac.create | true | Create RBAC roles and bindings |
rbac.scopeToNamespace | false | Use namespace-scoped Role/RoleBinding instead of ClusterRole/ClusterRoleBinding |
Storage¶
| Value | Default | Description |
|---|---|---|
storage.filesystem.enabled | false | Enable shared volume for filesystem storage |
storage.filesystem.mountPath | /data/modules | Mount path inside containers |
storage.filesystem.hostPath | "" | Use a hostPath volume (for local dev with kind) |
storage.filesystem.storageClassName | "" | StorageClass for PVC (requires ReadWriteMany) |
storage.filesystem.size | 10Gi | PVC storage size |
Scanning¶
| Value | Default | Description |
|---|---|---|
scanning.enabled | false | Enable Trivy-based scanning (module IaC scanning and scanning image variant) |
scanning.providerScanning | false | Enable provider binary/source scanning (requires scanning.enabled=true) |
scanning.cacheMountPath | /var/cache/trivy | Mount path for Trivy DB cache |
scanning.offline | true | Run Trivy with offline scan mode |
scanning.blockOnCritical | false | Block reconciliation when CRITICAL findings exist |
scanning.blockOnHigh | false | Block reconciliation when HIGH findings exist |
scanning.cache.storageClassName | "" | StorageClass for Trivy DB PVC |
scanning.cache.accessMode | ReadWriteMany | Access mode for Trivy DB PVC |
scanning.cache.size | 1Gi | Trivy DB PVC size |
scanning.dbUpdater.schedule | 0 2 * * * | Cron schedule for DB refresh job |
scanning.dbUpdater.image.repository | aquasec/trivy | Trivy DB updater image repository |
scanning.dbUpdater.image.tag | 0.70.0 | Trivy DB updater image tag |
Build from Source (Alternative)¶
If you prefer to build container images yourself:
# Build all services for linux/arm64
make build
# Load into a kind cluster
make load
# Or build and load in one step
make deploy
Additional Makefile targets:
| Target | Description |
|---|---|
make build | Build all container images |
make load | Load all images into the kind cluster |
make deploy | Build and load all images |
make service NAME=server | Build and load a single service |
make restart | Restart all deployments in opendepot-system |
make redeploy | Build, load, and restart all services |
make kind-restart | Full cluster recreation with Istio, TLS, gateway, and Helm deploy (for production-like local setup) |
Configurable variables:
| Variable | Default | Description |
|---|---|---|
PLATFORM | linux/arm64 | Target platform for container builds |
KIND_CLUSTER | kind | Name of the kind cluster |
TAG | dev | Image tag for all services |
REGISTRY | ghcr.io/tonedefdev/opendepot | Container registry prefix |