Configure media storage
Media storage allows agents to handle file uploads for multi-modal conversations. This guide covers configuring different storage backends.
Overview
Section titled “Overview”When enabled, the facade container provides HTTP endpoints for:
- Upload requests - Get presigned URLs for uploading files
- File uploads - Upload files directly (local storage) or to cloud (S3/GCS/Azure)
- File downloads - Retrieve uploaded files
- Media info - Get metadata about uploaded files
Configure a backend declaratively on spec.media.storage (see
AgentRuntime configuration below) — the operator
translates it into the OMNIA_MEDIA_STORAGE_* environment variables shown in
the per-backend sections that follow and injects them into both the facade and
runtime containers.
Storage backends
Section titled “Storage backends”Omnia supports four storage backends:
| Backend | Use Case | Authentication |
|---|---|---|
none |
Disable media storage (default) | N/A |
local |
Development, single-replica deployments | N/A |
s3 |
AWS deployments, S3-compatible services (MinIO) | IAM roles, workload identity, access keys |
gcs |
Google Cloud deployments | Workload identity, service account keys |
azure |
Azure deployments | Managed identity, workload identity, account keys |
Local storage
Section titled “Local storage”Local storage writes files to the pod’s filesystem. This is suitable for development and single-replica deployments.
# Environment variablesOMNIA_MEDIA_STORAGE_TYPE: localOMNIA_MEDIA_STORAGE_PATH: /var/lib/omnia/mediaOMNIA_MEDIA_MAX_FILE_SIZE: "104857600" # 100MBOMNIA_MEDIA_DEFAULT_TTL: "24h"Limitations:
- Files are lost when the pod restarts
- Not suitable for multi-replica deployments
- No CDN integration
S3 storage
Section titled “S3 storage”S3 storage supports Amazon S3 and S3-compatible services like MinIO and LocalStack.
AWS S3
Section titled “AWS S3”# Environment variablesOMNIA_MEDIA_STORAGE_TYPE: s3OMNIA_MEDIA_S3_BUCKET: my-media-bucketOMNIA_MEDIA_S3_REGION: us-west-2OMNIA_MEDIA_S3_PREFIX: omnia/media/ # OptionalOMNIA_MEDIA_MAX_FILE_SIZE: "104857600"OMNIA_MEDIA_DEFAULT_TTL: "24h"MinIO / S3-compatible
Section titled “MinIO / S3-compatible”OMNIA_MEDIA_STORAGE_TYPE: s3OMNIA_MEDIA_S3_BUCKET: my-bucketOMNIA_MEDIA_S3_REGION: us-east-1OMNIA_MEDIA_S3_ENDPOINT: http://minio.minio-system:9000OMNIA_MEDIA_S3_PREFIX: media/When OMNIA_MEDIA_S3_ENDPOINT is set, path-style addressing is automatically enabled for compatibility with MinIO.
Authentication
Section titled “Authentication”S3 storage uses the AWS SDK default credential chain:
- Environment variables -
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY - IAM Roles for Service Accounts (IRSA) - Recommended for EKS
- EC2 instance profiles - For self-managed Kubernetes on EC2
- Shared credentials file -
~/.aws/credentials
IRSA setup (EKS)
Section titled “IRSA setup (EKS)”# ServiceAccount annotationapiVersion: v1kind: ServiceAccountmetadata: name: omnia-agent annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/omnia-media-roleRequired IAM policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::my-media-bucket", "arn:aws:s3:::my-media-bucket/*" ] } ]}GCS storage
Section titled “GCS storage”Google Cloud Storage uses presigned URLs for direct uploads.
OMNIA_MEDIA_STORAGE_TYPE: gcsOMNIA_MEDIA_GCS_BUCKET: my-media-bucketOMNIA_MEDIA_GCS_PREFIX: omnia/media/ # OptionalOMNIA_MEDIA_MAX_FILE_SIZE: "104857600"OMNIA_MEDIA_DEFAULT_TTL: "24h"Authentication
Section titled “Authentication”GCS storage uses Google’s Application Default Credentials:
- Workload Identity - Recommended for GKE
- Service account key file -
GOOGLE_APPLICATION_CREDENTIALS - Compute Engine default service account
Workload identity setup (GKE)
Section titled “Workload identity setup (GKE)”# ServiceAccount annotationapiVersion: v1kind: ServiceAccountmetadata: name: omnia-agent annotations: iam.gke.io/gcp-service-account: omnia-media@my-project.iam.gserviceaccount.comRequired IAM role: roles/storage.objectAdmin on the bucket.
Azure blob storage
Section titled “Azure blob storage”Azure Blob Storage uses SAS tokens for presigned URLs.
OMNIA_MEDIA_STORAGE_TYPE: azureOMNIA_MEDIA_AZURE_ACCOUNT: mystorageaccountOMNIA_MEDIA_AZURE_CONTAINER: mediaOMNIA_MEDIA_AZURE_PREFIX: omnia/media/ # OptionalOMNIA_MEDIA_MAX_FILE_SIZE: "104857600"OMNIA_MEDIA_DEFAULT_TTL: "24h"Authentication
Section titled “Authentication”Azure storage supports multiple authentication methods:
- DefaultAzureCredential - Managed identity, workload identity, Azure CLI
- Account Key - Explicit key via
OMNIA_MEDIA_AZURE_KEY
Workload identity setup (AKS)
Section titled “Workload identity setup (AKS)”# ServiceAccount annotationapiVersion: v1kind: ServiceAccountmetadata: name: omnia-agent annotations: azure.workload.identity/client-id: <client-id> labels: azure.workload.identity/use: "true"Note: SAS URL generation currently requires an account key. For full workload identity support without keys, User Delegation SAS would need to be implemented (requires Storage Blob Delegator role).
Cross-cloud / explicit credentials
Section titled “Cross-cloud / explicit credentials”For cross-cloud scenarios or when workload identity isn’t available, store the
account key in a Kubernetes Secret and reference it via spec.media.storage.secretRef.
The Secret’s key must be named AZURE_ACCOUNT_KEY:
apiVersion: v1kind: Secretmetadata: name: azure-storage-keytype: OpaquestringData: AZURE_ACCOUNT_KEY: <your-storage-account-key>---# Reference in AgentRuntimeapiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata: name: my-agentspec: media: storage: type: azure azure: account: mystorageaccount container: media secretRef: name: azure-storage-keyUpload flow
Section titled “Upload flow”Local storage
Section titled “Local storage”sequenceDiagram participant C as Client participant F as Facade participant FS as Filesystem
C->>F: POST /media/request-upload F-->>C: {uploadId, url: "/media/upload/{id}"} C->>F: PUT /media/upload/{id} F->>FS: Write file F-->>C: 204 No ContentCloud storage (S3/GCS/Azure)
Section titled “Cloud storage (S3/GCS/Azure)”sequenceDiagram participant C as Client participant F as Facade participant CS as Cloud Storage
C->>F: POST /media/request-upload F-->>C: {uploadId, url: "presigned-url", storageRef} C->>CS: PUT presigned-url (direct upload) CS-->>C: 200 OK C->>F: POST /media/confirm-upload/{id} F->>CS: Verify object exists F-->>C: {mediaInfo}Prometheus metrics
Section titled “Prometheus metrics”Media storage exposes the following metrics:
| Metric | Type | Description |
|---|---|---|
omnia_facade_uploads_total |
Counter | Upload attempts by status (success/failed) |
omnia_facade_upload_bytes_total |
Counter | Total bytes uploaded |
omnia_facade_upload_duration_seconds |
Histogram | Upload duration |
omnia_facade_downloads_total |
Counter | Download attempts by status |
omnia_facade_download_bytes_total |
Counter | Total bytes downloaded |
omnia_facade_media_chunks_total |
Counter | Media chunks sent by type (json/binary) |
omnia_facade_media_chunk_bytes_total |
Counter | Total bytes sent as chunks |
All metrics include agent and namespace labels.
AgentRuntime configuration
Section titled “AgentRuntime configuration”Configure media storage declaratively on spec.media.storage. The operator
injects the equivalent OMNIA_MEDIA_STORAGE_* environment variables (shown
above, per-backend) into both the facade and runtime containers — you no
longer need to set them by hand.
Keyless S3 (recommended for AWS)
Section titled “Keyless S3 (recommended for AWS)”apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata: name: my-agentspec: media: storage: type: s3 s3: bucket: my-media-bucket region: us-west-2 # prefix: omnia/media/ # optional # No secretRef — credentials come from IRSA / workload identity. # maxFileSizeBytes: 104857600 # optional, 100MB # defaultTTL: 24h # optionalLocal storage (dev / single-replica)
Section titled “Local storage (dev / single-replica)”apiVersion: omnia.altairalabs.ai/v1alpha1kind: AgentRuntimemetadata: name: my-agentspec: media: storage: type: local local: basePath: /var/lib/omnia/mediaExplicit credentials (S3 / Azure)
Section titled “Explicit credentials (S3 / Azure)”Omit secretRef for keyless access (S3 IRSA, Azure workload identity — GCS is
always keyless via Application Default Credentials). To use explicit
credentials instead, reference a Secret. The Secret must contain the keys
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (S3) or AZURE_ACCOUNT_KEY
(Azure):
spec: media: storage: type: s3 s3: bucket: my-media-bucket region: us-west-2 secretRef: name: my-s3-credentials # must have AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY keysTroubleshooting
Section titled “Troubleshooting”Upload fails with “upload not found or expired”
Section titled “Upload fails with “upload not found or expired””The upload URL has expired. Default TTL is 15 minutes. Request a new upload URL.
S3 “access denied” errors
Section titled “S3 “access denied” errors”- Verify IAM role has required permissions
- Check IRSA annotation on ServiceAccount
- Verify bucket policy allows the IAM role
GCS “permission denied” errors
Section titled “GCS “permission denied” errors”- Verify Workload Identity is configured
- Check service account has
storage.objectAdminrole - Verify bucket IAM bindings
Azure “SAS generation requires shared key credential”
Section titled “Azure “SAS generation requires shared key credential””Azure SAS URL generation requires the account key. Set OMNIA_MEDIA_AZURE_KEY or implement User Delegation SAS for full workload identity support.