Storage Backends¶
OpenDepot supports four storage backends. Each is configured via the storageConfig field on Depot.spec.global.storageConfig, ModuleConfig.storageConfig, or directly on a Module.spec.moduleConfig.storageConfig.
Amazon S3¶
Recommended for production. Stores module archives in S3 buckets 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 | Bucket key prefix (auto-generated by the Module controller) |
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 module archives in Azure Blob Storage containers 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 module archives 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 | No | Directory path where modules are stored (must match the container mount path) |
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 module archives 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 | Mount path inside containers |
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).
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).
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, 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 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. 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 |