Skip to content

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 optionally AWS_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:

storageConfig:
  s3:
    bucket: opendepot-modules
    region: us-west-2

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, and AZURE_CLIENT_SECRET

Required Azure RBAC Roles:

  • Storage Blob Data Contributor on the Storage Account (for read, write, and delete)
  • Reader on the Storage Account resource (for container metadata operations)
  • Storage Blob Delegator on 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.create
  • storage.objects.get
  • storage.objects.delete
  • storage.objects.getMetadata (or the Storage Object Admin role)

Example Configuration:

storageConfig:
  gcs:
    bucket: opendepot-modules

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:

storageConfig:
  fileSystem:
    directoryPath: /data/modules

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