Storage Backends¶
OpenDepot supports four storage backends. storageConfig can be set at multiple levels:
Depot.spec.globalConfig.storageConfig(applies to resources managed by a Depot unless overridden)Module.spec.moduleConfig.storageConfigProvider.spec.providerConfig.storageConfig- Inline
Version.spec.moduleConfigRef.storageConfigorVersion.spec.providerConfigRef.storageConfig
Amazon S3¶
Recommended for production. Stores OpenDepot artifacts (module archives and provider binaries) in S3 with SHA256 checksum validation.
CRD Fields:
| Field | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | S3 bucket name |
region | string | Yes | AWS region (e.g., us-west-2) |
key | string | No | Optional S3 object key prefix prepended to stored artifacts |
Authentication: Uses the AWS SDK v2 default credentials chain. In Kubernetes, this typically means:
- EKS with IRSA (recommended): Annotate the Version controller's ServiceAccount with an IAM role ARN
- Environment variables: Set
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionallyAWS_SESSION_TOKEN - EC2 instance profile: Automatically used when running on EC2/EKS nodes
Required IAM Permissions:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectAttributes"
],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
Example Configuration:
Azure Blob Storage¶
Recommended for production. Stores OpenDepot artifacts (module archives and provider binaries) in Azure Blob Storage with checksum metadata.
CRD Fields:
| Field | Type | Required | Description |
|---|---|---|---|
accountName | string | Yes | Azure Storage Account name |
accountUrl | string | Yes | Storage Account URL (e.g., https://myaccount.blob.core.windows.net) |
subscriptionID | string | Yes | Azure subscription ID |
resourceGroup | string | Yes | Resource Group containing the Storage Account |
Authentication: Uses Azure DefaultAzureCredential. In Kubernetes, this typically means:
- AKS with Workload Identity (recommended): Configure federated identity credentials on the Version controller's ServiceAccount
- Managed Identity: Assign a managed identity to the AKS node pool or pod
- Environment variables: Set
AZURE_CLIENT_ID,AZURE_TENANT_ID, andAZURE_CLIENT_SECRET
Required Azure RBAC Roles:
Storage Blob Data Contributoron the Storage Account (for read, write, and delete)Readeron the Storage Account resource (for container metadata operations)Storage Blob Delegatoron the Storage Account (required when pre-signed URLs are enabled — used to obtain a User Delegation Key for SAS generation)
Example Configuration:
storageConfig:
azureStorage:
accountName: opendepotmodules
accountUrl: https://opendepotmodules.blob.core.windows.net
subscriptionID: 00000000-0000-0000-0000-000000000000
resourceGroup: opendepot-rg
Google Cloud Storage¶
CRD Fields:
| Field | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | GCS bucket name |
Authentication: Uses Application Default Credentials (ADC). In Kubernetes, this typically means:
- GKE with Workload Identity (recommended): Bind a Google service account to the Version controller's Kubernetes ServiceAccount
- Service account key: Mount a JSON key file and set
GOOGLE_APPLICATION_CREDENTIALS
Required GCS Permissions:
storage.objects.createstorage.objects.getstorage.objects.deletestorage.objects.getMetadata(or theStorage Object Adminrole)
Example Configuration:
Local Filesystem¶
Stores OpenDepot artifacts on a shared volume mounted to both the Version controller and the Server pods. Suitable for development, testing, and air-gapped environments when paired with a PersistentVolumeClaim.
CRD Fields:
| Field | Type | Required | Description |
|---|---|---|---|
directoryPath | string | Yes (when using fileSystem) | Directory path where artifacts are stored; must match storage.filesystem.mountPath |
How it works: The Helm chart creates a shared volume (either a PersistentVolumeClaim or a hostPath) and mounts it to both the Version controller and the Server. The Version controller writes artifacts to the volume, and the Server reads and serves them.
Helm Storage Configuration:
| Value | Default | Description |
|---|---|---|
storage.filesystem.enabled | false | Enable shared volume for filesystem storage |
storage.filesystem.mountPath | /data/modules | Required when filesystem storage is enabled; mount path inside containers and root path enforced by the server download guard |
storage.filesystem.hostPath | "" | Use a hostPath volume (for local dev with kind) |
storage.filesystem.storageClassName | "" | StorageClass for the PVC (must support ReadWriteMany) |
storage.filesystem.size | 10Gi | PVC size |
Note
Set directoryPath in your CRD to match the storage.filesystem.mountPath Helm value (default /data/modules). This pairing is required for filesystem downloads to work with the server's path-guard enforcement.
Local Development with kind (hostPath):
helm install opendepot opendepot/opendepot \
-n opendepot-system \
--create-namespace \
--set storage.filesystem.enabled=true \
--set storage.filesystem.hostPath=/tmp/opendepot-modules
When using hostPath, the chart adds an initContainer that runs as root to set ownership of the volume to uid 65532 (the non-root user the containers run as). The pod-level runAsNonRoot: true setting is preserved — only the initContainer carries a container-level override (runAsNonRoot: false, runAsUser: 0). This setup is intended for local development only and is not recommended for production.
Download path enforcement:
The server enforces that every filesystem download request resolves to a path within the configured mount directory. Any request for a path outside this root is rejected with HTTP 403. The mount path is controlled by storage.filesystem.mountPath (default /data/modules) and passed to the server via the --filesystem-mount-path flag. When storage.filesystem.enabled is true and mountPath is set, the chart passes this flag automatically — no manual server configuration is required.
Production with PVC (ReadWriteMany):
helm install opendepot opendepot/opendepot \
-n opendepot-system \
--create-namespace \
--set storage.filesystem.enabled=true \
--set storage.filesystem.storageClassName=efs-sc \
--set storage.filesystem.size=50Gi
The PVC requires a StorageClass that supports ReadWriteMany (e.g., AWS EFS, Azure Files, NFS).
Example CRD Configuration:
Pre-signed URL Redirects¶
When enabled (provider downloads), the server issues an HTTP 307 Temporary Redirect to a time-limited URL signed by the storage backend instead of proxying the binary itself. The OpenTofu client fetches the provider artifact directly from the storage backend, reducing network egress through the server.
Pre-signed URLs are supported on Amazon S3, Google Cloud Storage, and Azure Blob Storage for provider artifact downloads. The filesystem backend does not support them.
Configure pre-signing via the presign field on any StorageConfig:
storageConfig:
s3:
bucket: opendepot-providers
region: us-east-1
presign:
enabled: true
ttl: "15m"
fallbackToProxy: true
PresignConfig fields:
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | When true, download requests are redirected to the storage backend via a pre-signed URL. |
ttl | duration | 15m | How long the pre-signed URL remains valid (e.g. "15m", "1h"). |
fallbackToProxy | bool | true | When true, if pre-sign generation fails the server falls back to proxying the download through itself. Set to false to make pre-signing strictly required. |
Additional IAM permissions required for S3 pre-signing:
No additional IAM permissions are needed. s3:GetObject (already required for the proxy path) is sufficient to generate pre-signed GET URLs.
Additional permissions required for Azure pre-signing:
Azure pre-signed URLs use user delegation SAS tokens. Assign the Storage Blob Delegator role to the controller's identity in addition to the existing Storage Blob Data Contributor role.
GCS signed URLs:
GCS pre-signed URLs use the HMAC/V4 signing method. The workload identity must have the iam.serviceAccounts.signBlob permission (included in the Service Account Token Creator role) in addition to the existing storage permissions.
Storage Backend Comparison¶
| Feature | Amazon S3 | Azure Blob | Google Cloud Storage | Filesystem |
|---|---|---|---|---|
| Production Ready | Yes | Yes | Yes | With PVC |
| Checksum Validation | SHA256 (native) | SHA256 (metadata) | SHA256 (metadata) | SHA256 (computed) |
| Authentication | AWS SDK v2 defaults | DefaultAzureCredential | ADC | None |
| Server Download Route | Yes | Yes | Yes | Yes |
| Shared Volume Required | No | No | No | Yes (PVC or hostPath) |
| Pre-signed URL Redirects | Yes | Yes | Yes | No |