
## Install via Docker Compose - Amazon SageMaker

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Amazon SageMaker (ai)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Anaplan

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Anaplan (business-intelligence)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Microsoft Fabric

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Microsoft Fabric (business-intelligence)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Iceberg

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Iceberg (data-lakehouses)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Google BigQuery

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Google BigQuery (data-warehouse)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP Datasphere

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP Datasphere (data-warehouse)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - AlloyDB PostgreSQL

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** AlloyDB PostgreSQL (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Amazon DocumentDB

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Amazon DocumentDB (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - ClickHouse

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** ClickHouse (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Cloud SQL PostgreSQL

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Cloud SQL PostgreSQL (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Hive

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Hive (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Microsoft SQL Server

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Microsoft SQL Server (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - MongoDB (self-managed)

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** MongoDB (self-managed) (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - MongoDB Atlas

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** MongoDB Atlas (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - MySQL

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** MySQL (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Oracle

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Oracle (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - PostgreSQL

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** PostgreSQL (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP ASE

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP ASE (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP HANA

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP HANA (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Starburst Enterprise

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Starburst Enterprise (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Teradata

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Teradata (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Trino

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Trino (database)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP BW/4HANA

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP BW/4HANA (erp)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP ECC

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP ECC (erp)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - SAP S/4HANA

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** SAP S/4HANA (erp)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - AWS Glue

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** AWS Glue (etl-tools)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Apache Kafka

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Apache Kafka (messaging)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - Confluent Kafka

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** Confluent Kafka (messaging)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---

## Install via Docker Compose - BigID

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-on-docker-compose
**Connector:** BigID (privacy)

> Install an App using Docker Compose configuration files and proper setup

:::warning Use the guided install wizard instead
**New Self-Deployed Runtime setups are encouraged to use the [guided install wizard](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/install-guided).** It assembles a complete guide tailored to your lifecycle mode, platform, and image procurement on a single page—and it's where new setup options (for example, HTTP proxy and custom CA trust) are documented going forward.

This page is kept for existing users who already reference it and may not include the latest steps.
:::

:::info **Did you know?** 
SDR requires additional enablement and licensing. Contact your Atlan representative for details.
:::

<h2 id="prerequisites">Prerequisites</h2>
Before you begin, make sure you have:

* Docker ecosystem (Docker Engine, Docker CLI, Docker Compose).
* A [Docker Hub Personal Access Token (PAT)](https://start.1password.com/open/i?a=WAVUZSKJO5GMNMVBYWAWECXIUE&v=ouvp3xf5334cxoamyiipzjlewy&i=p76avgzmkkcbftldcuvr5jcof4&h=atlanhq.1password.com) from Atlan
* Object storage: AWS S3, Google Cloud Storage, or Azure Blob Storage with read/write permissions
* Secret store access: AWS Secret Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp Vault with read permissions

:::warning For security reasons, the Docker Hub PAT Token is regenerated on a periodic basis. 
In case the token is embedded in automation scripts or CI/CD pipelines, those jobs may fail. 
Contact your Atlan representative for the latest token.
:::

<h2 id="download-deployment-config">Download deployment configuration</h2>

Atlan generates the per-app deployment configuration directly from the Marketplace UI, including the OAuth client credentials your runtime uses to authenticate to your tenant.

1. Sign in to your Atlan tenant as an administrator, open **Connector** > **Marketplace**, select the app you want to deploy, and click **Download config for Self-Deployed Runtime** in the right-hand sidebar.

2. In the dialog, keep **New deployment** selected (this mints the OAuth client and full config for a fresh runtime), choose **Docker Compose** as the deployment target, and enter a **Deployment name**: a short identifier (lowercase letters, digits, and dashes) that identifies this runtime; the agent in **Workflows > Agent** is named `<app_name>-<deployment_name>`.

3. Click **Generate**. Atlan mints a dedicated OAuth client and renders two files:
 - `config.yaml`: Atlan auth, with `client_id` and `client_secret` already filled in, plus placeholders for your object store and secret store.
 - `{{deploymentValues.packageName}}.yaml`: app metadata (name, id, image, version).

Save both files into a working directory; the rest of this guide runs from there.

<h2 id="prepare-deployment-environment">Prepare deployment environment</h2>

1. Use the Personal Access Token (PAT) provided by Atlan to authenticate with Docker Hub:

 ```bash
 docker login -u atlanhq
 # When prompted for password, enter the PAT provided by Atlan
 ```
 A "Login Succeeded" message confirms successful authentication.

2. Download the Docker Compose configurator binary for your platform into the same working directory. The archive extracts to a `docker-compose-generator/` directory.

 <Tabs groupId="platform">
 <TabItem value="linux-amd64" label="Linux AMD64" default>

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-amd64.tgz
 tar -xvf docker-compose-configurator-amd64.tgz
 ```

 </TabItem>
 <TabItem value="linux-arm64" label="Linux ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-arm64.tgz
 tar -xvf docker-compose-configurator-arm64.tgz
 ```

 </TabItem>
 <TabItem value="macos-arm64" label="macOS ARM64">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-aarch64.tgz
 tar -xvf docker-compose-configurator-macos-aarch64.tgz
 ```

 </TabItem>
 <TabItem value="macos-intel" label="macOS Intel">

 ```bash
 curl -O https://atlan-public.s3.amazonaws.com/apps/docker-compose-configurator-macos-intel.tgz
 tar -xvf docker-compose-configurator-macos-intel.tgz
 ```

 </TabItem>
 </Tabs>

<h2 id="configure-deployment-files">Configure deployment files</h2>

At this point your working directory contains at least:

 - `docker-compose-generator/generate`: the configurator binary
 - `config.yaml`: Atlan auth + `objectstore` and `secretstore` placeholders (downloaded from Marketplace)
 - `{{deploymentValues.packageName}}.yaml`: app metadata (downloaded from Marketplace)

Two files need attention before deploying. Edit `config.yaml` for your object and secret stores; edit `{{deploymentValues.packageName}}.yaml` only if you mirror images to a private registry. The Atlan auth fields in `config.yaml` are already populated; leave them as they are.

### Object storage (in `config.yaml`)

Self-Deployed Runtime needs a store for reading or writing files. Configure the object storage that matches your environment:

:::tip Don't see your preferred object store?
If your preferred object store isn't listed here, [reach out to Atlan support](https://docs.atlan.com/support/submit-request). Support for additional object stores may be available.
:::

<Tabs>
<TabItem value="local-path" label="Local file path" default>

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add local file path configuration for Docker volume mounts.

```yaml
objectstore:
 type: bindings.localstorage
 version: v1
 metadata:
 - name: rootPath
 value: "/data/storage"
```

> **Note**: Mount a Docker volume to the specified path in your `docker-compose.yml` file. This is the recommended option for Docker and local development environments where files can be stored on the host filesystem. **Example Docker Compose volume mount:**
 ```yaml
 volumes:
 - ./data:/data/storage
 ```

</TabItem>
<TabItem value="aws-s3" label="AWS S3">

**Required permissions:**

Apply object-level actions to `arn:aws:s3:::BUCKET/*` and the list action to `arn:aws:s3:::BUCKET` in separate IAM statement entries.

| IAM action | Operations covered |
|---|---|
| `s3:GetObject` | GetObject (full and byte-range), HeadObject |
| `s3:PutObject` | PutObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload |
| `s3:AbortMultipartUpload` | Abort in-flight multipart upload on error (required for streaming write error paths) |
| `s3:DeleteObject` | DeleteObject and DeleteObjects (bulk batch—same IAM action) |
| `s3:ListBucket` | ListObjectsV2—bucket-level permission, not object-level |

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:PutObject",
 "s3:AbortMultipartUpload",
 "s3:DeleteObject"
 ],
 "Resource": "arn:aws:s3:::YOUR-BUCKET/*"
 },
 {
 "Effect": "Allow",
 "Action": "s3:ListBucket",
 "Resource": "arn:aws:s3:::YOUR-BUCKET"
 }
 ]
}
```

**AssumeRole**: when using `assumeRoleArn`, the caller identity additionally needs `sts:AssumeRole` on the target role ARN. The role itself holds the bucket policy described earlier.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add AWS S3 configuration. For more information, see [AWS S3 Binding Spec](https://docs.dapr.io/reference/components-reference/supported-bindings/s3/).

```yaml
objectstore:
 type: bindings.aws.s3
 version: v1
 metadata:
 - name: accessKey #optional, leave this empty for iam authentication
 value: ""
 - name: secretKey #optional, leave this empty for iam authentication
 value: ""
 - name: bucket #required, name of the bucket where application can write
 value: "<bucket-name>"
 - name: region #required, region of the bucket where application can write
 value: "<bucket-region>"
 - name: forcePathStyle
 value: "true"
```

</TabItem>
<TabItem value="gcp-storage" label="Google Cloud Storage">

**Required permissions:**

| IAM permission | Operations covered |
|---|---|
| `storage.objects.get` | GetObject (full and byte-range), object metadata / HeadObject equivalent |
| `storage.objects.create` | PutObject, resumable / streaming write |
| `storage.objects.delete` | DeleteObject (GCS has no native bulk-delete API—`delete_prefix` issues parallel single-object deletes) |
| `storage.objects.list` | ListObjects |

No `storage.buckets.*` permissions are needed. The smallest predefined role that covers all four is **`roles/storage.objectAdmin`** scoped to the bucket. Alternatively, create a custom role with exactly these four permissions.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Google Cloud Storage configuration. For more information, see [GCP Storage Bucket binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/gcpbucket/).

```yaml
objectstore:
 type: bindings.gcp.bucket
 version: v1
 metadata:
 - name: bucket
 value: "your-gcs-bucket-name"
 - name: type
 value: "service_account"
 - name: project_id
 value: "your-gcp-project-id"
```

</TabItem>
<TabItem value="azure-blob" label="Azure Blob Storage">

**Required permissions:**

**RBAC**—assign at container or storage-account scope:

| RBAC action | Operations covered |
|---|---|
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read` | GetBlob, GetBlobProperties (HEAD), ListBlobs, byte-range GET |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write` | PutBlob, PutBlock + PutBlockList (streaming / block write) |
| `Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete` | DeleteBlob, BlobBatch delete (bulk—up to 256 keys per request) |

The smallest predefined role covering all three is **`Storage Blob Data Contributor`**. `Storage Blob Data Owner` is a superset and is only needed if you additionally require POSIX ACL management on ADLS Gen2.

**SAS token**— minimum permissions at container scope: `r` (read) + `w` (write) + `d` (delete) + `l` (list), that is a container-scoped SAS with **`rwdl`**.

**ADLS Gen2 with POSIX ACLs**: if the storage account has hierarchical namespace enabled and you use ACL-based access control instead of RBAC, the principal needs Execute (`X`) on every parent directory and Read / Write / Delete on the objects in scope. RBAC (`Storage Blob Data Contributor`) is simpler and is recommended unless you have a specific ACL requirement.

**Configure:**

1. Locate the `objectstore` attribute in `config.yaml`.
2. Add Azure Blob Storage configuration. For more information, see [Azure Blob Storage binding spec](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/).

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "your-storage-account-name"
 - name: accountKey
 value: "your-storage-account-key"
 - name: containerName
 value: "your-container-name"
```

</TabItem>
</Tabs>

### Secret storage (in `config.yaml`)

Self-Deployed Runtime fetches secrets from a secret store to connect to the source systems. The secret store references are used to configure the workflow. Configure the secret store that aligns with your security infrastructure:

:::info Did you know?
Dapr supports additional secret stores which aren't mentioned here. For more information, see [Dapr secret store documentation](https://docs.dapr.io/reference/components-reference/supported-secret-stores/) for other configurations.
:::

<Tabs>
<TabItem value="aws-secret-manager" label="AWS Secrets Manager" default>

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add AWS Secret Manager configuration. For more information, see [AWS Secrets Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/).

```yaml
secretstore:
 type: secretstores.aws.secretmanager
 version: v1
 metadata:
 - name: region # required, region in which secret is hosted
 value: <secret-region>
 # Needed if IAM authentication is not used
 - name: accessKey
 value: ""
 - name: secretKey
 value: ""
```

If you are using IAM role authentication, leave `accessKey` and `secretKey` empty.

If you are using an IAM user instead, set:
- `accessKey` to the IAM user's access key ID
- `secretKey` to the IAM user's secret access key

That IAM user must have permission to read the target secret from AWS Secrets Manager:

```json
{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "secretsmanager:GetSecretValue",
 "secretsmanager:DescribeSecret"
 ],
 "Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>*"
 }
 ]
}
```

:::note
Include the trailing `*` in the secret ARN. AWS appends a random suffix to secret names in the ARN, so omitting it can cause access failures.
:::

</TabItem>
<TabItem value="azure-key-vault" label="Azure Key Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Azure Key Vault configuration. For more information, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).

```yaml
secretstore:
 type: secretstores.azure.keyvault
 version: v1
 metadata:
 - name: vaultName
 value: "<your-keyvault-name>"
 - name: azureTenantId
 value: "<your-tenant-id>"
 - name: azureClientId
 value: "<your-client-id>"
 - name: azureClientSecret
 value: "<your-client-secret>"
 - name: azureEnvironment
 value: "AZUREPUBLICCLOUD" # Optional: AZUREPUBLICCLOUD, AZURECHINACLOUD, AZUREUSGOVERNMENTCLOUD, AZUREGERMANCLOUD
```

Azure Key Vault supports multiple authentication methods:
- **Client Secret**: Use `azureClientSecret` with tenant ID and client ID
- **Certificate**: Use `azureCertificateFile` instead of client secret
- **Managed Identity**: Omit authentication fields and use Azure managed identity

For detailed authentication setup, see the [Authenticating to Azure](https://docs.dapr.io/developing-applications/integrations/azure/azure-authentication/authenticating-azure/) documentation.

</TabItem>
<TabItem value="gcp-secret-manager" label="GCP Secret Manager">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Google Cloud Secret Manager configuration. For more information, see [GCP Secret Manager](https://docs.dapr.io/reference/components-reference/supported-secret-stores/gcp-secret-manager/).

```yaml
secretstore:
 type: secretstores.gcp.secretmanager
 version: v1
 metadata:
 - name: type
 value: "service_account"
 - name: project_id
 value: "<project-id>"
 - name: private_key_id
 value: "<private-key-id>"
 - name: private_key
 value: "<private-key>"
 - name: client_email
 value: "<client-email>"
 - name: client_id
 value: "<client-id>"
 - name: auth_uri
 value: "https://accounts.google.com/o/oauth2/auth"
 - name: token_uri
 value: "https://oauth2.googleapis.com/token"
 - name: auth_provider_x509_cert_url
 value: "https://www.googleapis.com/oauth2/v1/certs"
 - name: client_x509_cert_url
 value: "https://www.googleapis.com/robot/v1/metadata/x509/<client-email>"
```

</TabItem>
<TabItem value="hashicorp-vault" label="HashiCorp Vault">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add HashiCorp Vault configuration. For more information, see [HashiCorp Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/hashicorp-vault/).

```yaml
secretstore:
 type: secretstores.hashicorp.vault
 version: v1
 metadata:
 - name: vaultAddr
 value: "[vault_address]" # Optional. Default: "https://127.0.0.1:8200"
 - name: caCert # Optional. This or caPath or caPem
 value: "[ca_cert]"
 - name: caPath # Optional. This or CaCert or caPem
 value: "[path_to_ca_cert_file]"
 - name: caPem # Optional. This or CaCert or CaPath
 value: "[encoded_ca_cert_pem]"
 - name: skipVerify # Optional. Default: false
 value: "[skip_tls_verification]"
 - name: tlsServerName # Optional.
 value: "[tls_config_server_name]"
 - name: vaultTokenMountPath # Required if vaultToken not provided. Path to token file.
 value: "[path_to_file_containing_token]"
 - name: vaultToken # Required if vaultTokenMountPath not provided. Token value.
 value: "[vault_token]"
 - name: vaultKVPrefix # Optional. Default: "dapr"
 value: "[vault_prefix]"
 - name: vaultKVUsePrefix # Optional. default: "true"
 value: "[true/false]"
 - name: enginePath # Optional. default: "secret"
 value: "secret"
 - name: vaultValueType # Optional. default: "map"
 value: "map"
```

</TabItem>
<TabItem value="environment-variable-based" label="Environment Variables">

1. Locate the `secretstore` attribute in `config.yaml`.
2. Add Local environment variables as the spec. For more information, see [Local Environment Variables](https://docs.dapr.io/reference/components-reference/supported-secret-stores/envvar-secret-store/)

 ```yaml
 secretstore:
 enabled: true
 spec:
 type: secretstores.local.env
 version: v1
 ```

</TabItem>
</Tabs>

### Update private image reference (in `{{deploymentValues.packageName}}.yaml`)

**Optional.** Depending on organizational requirements, you may need to replicate images from Docker Hub to a private image repository. The specific steps vary by organization, here's one approach:

* Pull the required app image via Docker CLI. Use the image reference from the `app_image` field of your downloaded `{{deploymentValues.packageName}}.yaml`:

 ```bash
 docker pull <app_image>
 ```
 The command requires the same Docker Hub PAT from Atlan support that you used to authenticate with Docker Hub earlier.

* Push the image to your enterprise's registry. Note down the repository name and image tag generated.
* Update `app_image` in `{{deploymentValues.packageName}}.yaml` with the new repository and tag.

<h2 id="deploy-runtime">Deploy runtime</h2>

1. Generate the docker-compose setup files from your configuration:

 ```bash
 ./docker-compose-generator/generate --app {{deploymentValues.packageName}}.yaml --config config.yaml
 ```

 This command generates the docker-compose files in `{app_name}-deployment` by default. Override with `--output <dir>` if needed.

2. Start the deployment:

 ```bash
 cd {app_name}-deployment
 docker compose up -d
 ```

The deployment process typically takes a few minutes to complete depending on factors like network connectivity and image download time.

For more information on Docker Compose commands and configuration, see the [Docker Compose documentation](https://docs.docker.com/compose/).

<h2 id="verify-app">Verify app</h2>

Follow these steps to verify the deployment:

### Verify container status

1. Check container status:

 ```bash
 docker compose ps
 ```

 The output appears similar to:

 ```
 NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
 <package-name> atlanhq/<image-name>:<image-tag> "/app/entrypoint.sh" <package-name> 2 minutes ago Up 2 minutes
 ```
 
 Replace `<package-name>`, `<image-name>`, and `<image-tag>` with your app's values (shown in the system requirements section earlier in this guide).

 The container status shows `Up` indicating it's running successfully.

2. Verify logs for the running container:

 ```bash
 docker logs {{deploymentValues.packageName}} --tail=50 -f
 ```

 Look for these key log messages that confirm successful deployment:

 * `Uvicorn running on http://0.0.0.0:8000` - Web server started
 * `Workflow engine initialized` - Workflow processing ready
 * `dapr initialized. Status: Running` - Dapr runtime active
 * `Starting worker with task queue: atlan-<package-name>-DEPLOYMENT_NAME` - Worker process started (replace `<package-name>` with your app's package name)
 * `GET /server/ready 200` - Health check endpoint responding

### Verify registration via Atlan UI

Once the App is successfully deployed, it communicates to the Atlan tenant and registers itself. Verify App registration is successful in Atlan:

1. In the same Atlan tenant, navigate to **Workflows** > **Agent**.
2. Look for an entry named `<app_name>-<deployment_name>`, where `<app_name>` matches your selected app (for example, "Oracle" or "Microsoft SQL Server") and `<deployment_name>` is the deployment name you entered when generating the config.
3. Confirm the agent status displays as **Active**.

Agent registration and status takes a couple of minutes to reflect in the Atlan UI.

<h2 id="next-steps">Next steps</h2>

* [Configure workflow execution](https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/configure-workflow-execution): Set up workflow execution with secret retrieval for your Self-deployed Runtime

---
