Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.opal.dev/llms.txt

Use this file to discover all available pages before exploring further.

Self-hosted Opal stores async data exports (large CSV/ZIP downloads) in an S3 or S3-compatible bucket. Cloud customers get this bucket automatically. If you self-host, you provision the bucket and provide credentials. This setup is optional. If you skip these steps, exports still work, but they’re tied to the browser session — they cancel if you navigate away or close the tab.

1. Create the bucket

Create a private bucket in the same region as your cluster, with:
  • All public access blocked
  • Server-side encryption (AES256 or KMS)
  • A bucket policy that denies any request where aws:SecureTransport=false
Use a dedicated bucket per Opal deployment (e.g. <your-org>-opal-exports). Don’t share it with other applications or other environments.
Do not add an S3 lifecycle expiration rule. Opal runs its own file cleanup job, and should be the only thing deleting objects in this bucket. A lifecycle policy might cause previously-saved exports to be orphaned.
Versioning and CORS are not required. Downloads are served through the Opal backend, not directly from the browser.

2. Create an IAM user and access key

Opal authenticates to the bucket with a static access key pair. This is a two-step process: create a dedicated IAM user with a scoped policy, then issue an access key for that user.

2a. Create the IAM user

Create a dedicated IAM user (e.g. opal-exports-service) and attach a policy with only these permissions:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::my-org-opal-exports/*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-org-opal-exports"
    }
  ]
}

2b. Issue an access key

Generate one access key pair for the user (aws iam create-access-key --user-name opal-exports-service, or via the IAM console). Store both the access key ID and secret access key in your secret manager — you’ll paste them in step 3. If you provision the user via infrastructure-as-code, create the access key separately so the secret stays out of state. The secret access key is shown only once at creation time.
IAM Roles for Service Accounts (IRSA) and Workload Identity are not supported today. Static access keys are the only authentication method.

3. Update Opal Configuration

Pick the section that matches your install method.

KOTS

Open the admin console and find the Async Exports Storage section:
  1. Click Enable Async Exports.
  2. Bucket name: my-org-opal-exports
  3. Region: e.g. us-east-2
  4. Access key ID and secret access key from step 2.
Save and deploy. KOTS encrypts the secret at rest.

Helm

Add the following to your helm values:
exportStorage:
  bucketName: my-org-opal-exports
  region: us-east-2
  accessKey: <access key id>
  secretKey: <secret access key>
Then run a helm upgrade to apply the configuration.

4. Verify

Run a query in Opal Query and trigger an export. You should get a download link and be able to download the exported data. Async exports are currently only supported via Opal Query.
Last modified on May 29, 2026