# How Outpost Works

Outpost (also called InHost) runs Relyance inventory and data inspection workers in your AWS account. You operate the EKS deployment and keep connection credentials in AWS Secrets Manager with **In Host BYOK**. Workers write inventory, indexed scan configuration and classification results to your S3 storage. Relyance copies completed inventory and results to hosted Google Cloud Storage (GCS) for processing and display. Metadata therefore leaves your AWS account.

This guide covers an existing EKS cluster, single-account AWS inventory, Amazon RDS including PostgreSQL, and ClickHouse Cloud. Relyance must set up your tenant and supply the complete deployment configuration before you install. Inventory stays off until that configuration is in place.

The setup uses these public, versioned references. Relyance supplies the complete tenant overlay or Helm values:

| What | Public reference | Version |
|---|---|---|
| Terraform module for the AWS resources | [`Relyance-Ext/sierra/aws`](https://registry.terraform.io/modules/Relyance-Ext/sierra/aws/0.9.0) ([source](https://github.com/Relyance-Ext/terraform-aws-sierra)) | 0.9.0 |
| Kustomize base | [Published services YAML](https://assets.relyance.ai/inhost/k8s/v1.4.1/services-aws-prod-v1.4.1.yaml) | 1.4.1 |
| Helm chart | [Published chart](https://assets.relyance.ai/inhost/helm/inhost-1.3.0.tgz) ([repository index](https://assets.relyance.ai/inhost/helm/index.yaml), [versioned checksums](https://assets.relyance.ai/inhost/helm/SHA256SUMS-chart-v1.3.0.txt)) | 1.3.0 |
| Terraform provider for connections | [`Relyance/relyance`](https://registry.terraform.io/providers/Relyance/relyance/1.1.1) | 1.1.1 |

The [Kustomize archive](https://assets.relyance.ai/inhost/k8s/v1.4.1/inhost-kustomize-v1.4.1.tar.gz) includes the tenant renderer at `inhost/bin/render-tenant`. The archive SHA-256 is `e6bd3cc4dc7e26d965adc1f47d1ebec715d9a86ce6c8bdb9466e190507c0f0aa`. Helm and Kustomize have separate version numbers; use the versions in your supplied package.

Step 3 includes both Kustomize and Helm procedures. Keep the management method, registered namespace and release name of an existing installation; agree any migration with Relyance.

## At a glance

1. **Agree the resource scope.** Complete the [onboarding worksheet](#onboarding-worksheet) with your Relyance team using resource references only.
2. **Prepare AWS access.** Review the Terraform plan for the existing EKS cluster, S3 storage, IAM roles and KMS permissions.
3. **Receive your deployment package.** Relyance registers your AWS resources, provisions hosted routing and transfer access, and supplies the complete tenant values, including the runtime images.
4. **Install and validate.** Apply the package, create BYOK connections, and verify discovery, sampling and hosted results separately.

Relyance has no Kubernetes or console access and no inbound access to your cluster or private data-source network. The authorized transfer role reads agreed S3 outputs through the S3 API. You run the installation steps with your own tools and credentials. For the full commands, refer to [Deployment plan](#deployment-plan).

## Design principles

| Principle | What it means |
|---|---|
| Local collection and classification | Workers collect metadata and classify samples in EKS. Completed metadata and classification results are copied to hosted GCS. |
| Credentials can stay with you | With the **In Host BYOK** runtime mode, the credentials for a data source stay in a secret in your account. Relyance stores only the location of the secret. |
| The cluster starts all connections | The Outpost cluster connects to Relyance. Relyance does not open connections to the cluster. |
| Scoped hosted reads | The Relyance transfer role reads only the agreed S3 output location and decrypts its objects. It does not read connection secrets or the work bucket. |
| No telemetry | The Outpost manifests include no monitoring, log or telemetry agent. |
| You operate it | You deploy and operate Outpost. Relyance has no access to the cluster. |

## Architecture

<figure style="margin:1.5rem 0">
<svg viewBox="0 0 880 600" width="100%" role="img" aria-labelledby="op-title op-desc" style="max-width:880px;height:auto;font-family:var(--body)">
<title id="op-title">Outpost architecture</title>
<desc id="op-desc">The Outpost cluster runs in the customer cloud account. It pulls images and scan commands from Relyance, reads credentials from the customer secret store, reads data sources, and writes inventory and results to S3. Relyance copies completed outputs to hosted GCS with a read-only identity for downstream processing.</desc>
<marker id="op-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" style="fill:var(--accent)"/></marker>
<rect x="20" y="20" width="840" height="130" rx="12" style="fill:var(--accent-tint);stroke:var(--accent);stroke-width:1.5"/>
<text x="40" y="46" style="fill:var(--ink);font-size:15px;font-weight:700">Relyance infrastructure</text>
<rect x="40" y="62" width="190" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="135" y="97" text-anchor="middle" style="fill:var(--ink);font-size:14px">Container registry</text>
<rect x="250" y="62" width="190" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="345" y="97" text-anchor="middle" style="fill:var(--ink);font-size:14px">Command queue</text>
<rect x="460" y="62" width="190" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="555" y="97" text-anchor="middle" style="fill:var(--ink);font-size:14px">Control plane API</text>
<rect x="670" y="62" width="170" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="755" y="90" text-anchor="middle" style="fill:var(--ink);font-size:14px">Transfer to GCS and</text>
<text x="755" y="108" text-anchor="middle" style="fill:var(--ink);font-size:14px">web application</text>
<rect x="20" y="190" width="840" height="270" rx="12" style="fill:none;stroke:var(--warn);stroke-width:1.5"/>
<text x="470" y="214" style="fill:var(--ink);font-size:15px;font-weight:700">Customer cloud account</text>
<rect x="40" y="228" width="400" height="212" rx="10" style="fill:var(--panel);stroke:var(--line)"/>
<text x="56" y="250" style="fill:var(--muted);font-size:13px">Kubernetes cluster</text>
<rect x="60" y="262" width="160" height="60" rx="8" style="fill:var(--bg);stroke:var(--line)"/>
<text x="140" y="297" text-anchor="middle" style="fill:var(--ink);font-size:14px">Autoscaler</text>
<rect x="250" y="262" width="170" height="160" rx="8" style="fill:var(--bg);stroke:var(--line)"/>
<text x="335" y="338" text-anchor="middle" style="fill:var(--ink);font-size:14px">Inventory and scan</text>
<text x="335" y="358" text-anchor="middle" style="fill:var(--muted);font-size:12px">workers in EKS</text>
<text x="60" y="350" style="fill:var(--muted);font-size:12px">Starts scanner workers</text>
<text x="60" y="366" style="fill:var(--muted);font-size:12px">for waiting commands</text>
<rect x="470" y="228" width="170" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="555" y="263" text-anchor="middle" style="fill:var(--ink);font-size:14px">Work bucket</text>
<rect x="670" y="228" width="170" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="755" y="263" text-anchor="middle" style="fill:var(--ink);font-size:14px">Output S3 bucket</text>
<rect x="470" y="352" width="170" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="555" y="387" text-anchor="middle" style="fill:var(--ink);font-size:14px">Secrets Manager</text>
<rect x="670" y="352" width="170" height="60" rx="8" style="fill:var(--panel);stroke:var(--line)"/>
<text x="755" y="378" text-anchor="middle" style="fill:var(--ink);font-size:14px">Customer-managed key</text>
<text x="755" y="396" text-anchor="middle" style="fill:var(--muted);font-size:12px">encrypts both buckets</text>
<rect x="20" y="500" width="840" height="80" rx="12" style="fill:var(--panel);stroke:var(--line)"/>
<text x="440" y="535" text-anchor="middle" style="fill:var(--ink);font-size:15px;font-weight:700">Data sources</text>
<text x="440" y="557" text-anchor="middle" style="fill:var(--muted);font-size:13px">Databases, storage and SaaS applications</text>
<g style="stroke:var(--accent);stroke-width:1.6;fill:none" marker-end="url(#op-arrow)">
<path d="M135 124V226"/>
<path d="M300 124V260"/>
<path d="M395 262L540 124" marker-start="url(#op-arrow)"/>
<path d="M422 280H468" marker-start="url(#op-arrow)"/>
<path d="M468 382H422"/>
<path d="M422 320H720V291"/>
<path d="M335 498V424"/>
<path d="M755 228V124"/>
<path d="M140 322Q180 330 248 330"/>
</g>
<g style="font-size:12px;font-weight:700;text-anchor:middle">
<circle cx="135" cy="170" r="11" style="fill:var(--accent)"/><text x="135" y="174" style="fill:#fff">1</text>
<circle cx="300" cy="170" r="11" style="fill:var(--accent)"/><text x="300" y="174" style="fill:#fff">2</text>
<circle cx="492" cy="170" r="11" style="fill:var(--accent)"/><text x="492" y="174" style="fill:#fff">3</text>
<circle cx="444" cy="366" r="11" style="fill:var(--accent)"/><text x="444" y="370" style="fill:#fff">4</text>
<circle cx="335" cy="470" r="11" style="fill:var(--accent)"/><text x="335" y="474" style="fill:#fff">5</text>
<circle cx="444" cy="264" r="11" style="fill:var(--accent)"/><text x="444" y="268" style="fill:#fff">6</text>
<circle cx="560" cy="320" r="11" style="fill:var(--accent)"/><text x="560" y="324" style="fill:#fff">7</text>
<circle cx="755" cy="170" r="11" style="fill:var(--accent)"/><text x="755" y="174" style="fill:#fff">8</text>
</g>
</svg>
<figcaption style="color:var(--muted);font-size:.9rem">Arrows show the direction in which data moves. The numbers match the steps in "How a scan works".</figcaption>
</figure>

Outpost has two parts: the components in your AWS account, and the Relyance platform.

| Component | Where it runs | What it does |
|---|---|---|
| Inventory workers | EKS, your AWS account | `data-pipelines` discovers the approved resources and writes inventory and indexed scan configuration to S3. `gai-inventory-notifications` starts supported data inspection when inventory finishes. |
| Scanner workers | EKS, your AWS account | Read the approved data sources, classify samples, and write results to S3. |
| Autoscaler | Kubernetes cluster, your AWS account | Starts scanner workers when scan commands wait. KEDA and a small scaler service do this. |
| Output storage | S3, your AWS account | Keeps inventory, indexed configuration and scan results under the agreed bucket/prefixes. Relyance copies the completed outputs. |
| Work bucket | Your AWS account | Keeps temporary data during a scan. Relyance cannot read it. |
| Secret store | Your AWS account | Keeps the credentials for the data sources, for In Host BYOK connections. |
| KMS key | Your AWS account | Encrypts the findings bucket and the work bucket. |
| Container registry | Relyance infrastructure | Supplies the scanner images. |
| Command queue | Relyance infrastructure | Holds scan commands until the cluster pulls them. |
| Control plane API | Relyance infrastructure | Supplies the connection settings and receives scan status. |
| GAI outputs transfer (GAIOT) | Relyance infrastructure | Copies completed inventory and results from S3 into hosted GCS. |
| Hosted processing and web application | Relyance infrastructure | Hosted data security and identity processing consume the hosted copy and make results available in the application. |

## Inventory workers

Inventory runs as two Deployments, separate from the four scanner ScaledJobs:

- `data-pipelines` discovers the approved resources and writes inventory and indexed scan configuration to S3.
- `gai-inventory-notifications` picks up finished inventory and starts any supported data inspection.

Each runs one replica. KEDA, `inhost-scaler` and Redis still run the scanner jobs.

You can install the package before you create any connections; the workers stay idle until there is work. Then create and authenticate an **In Host BYOK** connection and start its scan in the Relyance web application. You do not need to list connections in your values or update the deployment for each new connection. If your existing values contain `inventory.integration_ids`, remove it; the current package rejects it.

Setting `inventory.enabled: true` on its own is not enough. Relyance prepares these settings with you and supplies them in your package:

- The AWS accounts for the deployment, inventory and Secrets Manager.
- The S3 bucket, owner, storage region and inventory prefix.
- The findings-bucket deletion permission and `inventory.versioned_result_cleanup: true`, described below.
- The runtime images, the queue settings and the workload identity settings.

Keep these values as supplied. Do not edit them or copy them from examples.

Scanner and inventory workers share the `relyance` Kubernetes service account. `inhost-scaler` has its own service account to read queue length. Your AWS Pod Identity role needs read access to Secrets Manager, decryption with any KMS keys involved, and the S3 output permissions.

Scanner workers can save refreshed OAuth tokens to Secrets Manager for authentication methods that need it. Keep `byokSecretWriteBack` consistent with the write-back permission in Terraform. Inventory workers only read secrets.

Before Relyance can show results, it also registers your output location and reader role and turns on the copy to hosted storage. Check these separately after the first scan: inventory is written to S3, the copy to Relyance completes, and the results appear in the application.

## How a scan works

The numbers match the arrows in the diagram.

1. The cluster pulls the scanner images from the Relyance container registry.
2. Relyance puts a scan command in the command queue. The autoscaler sees the waiting command and starts scanner workers. A scanner worker pulls the command.
3. The scanner gets the connection settings from the control plane API. During the scan, it reports progress and completion to the same API. These reports contain status and counts, not your data.
4. The scanner reads the credentials for the data source from the secret store.
5. The scanner connects to the data source and reads samples for local classification. Review the agreed output policy under [What Relyance receives](#what-relyance-receives).
6. Workers keep temporary scan data in the work bucket. Inventory workers write their inventory datasets and indexed scan configuration to the agreed S3 output prefix; those configurations retain the original S3 source references.
7. The scanner classifies samples in EKS and writes results to S3. Inventory finalization and scan completion trigger the hosted transfer path.
8. GAIOT reads the completed S3 outputs with the scoped reader role and copies them to hosted GCS. Hosted data security and identity services use the hosted copy with their existing processing paths. Results appear after transfer and processing complete; local worker completion alone does not prove that they are visible.

## Deployment plan

### Onboarding worksheet

Share resource references through your agreed onboarding channel. Do not include passwords, API keys, secret JSON, database records or a Terraform state file.

| Resource | Record before installation |
|---|---|
| AWS account and regions | Deployment account ID; EKS region; S3 bucket region; inventory account ID; Resource Explorer aggregator region; intended discovery regions. The initial inventory scope is one account. |
| Existing EKS | Cluster name and ARN; namespace; Kubernetes service account names; Pod Identity role ARN and association IDs; Auto Mode and Pod Identity Agent availability. The published kustomize scanner uses `inhost:relyance`. |
| S3 ownership | Approved output and work bucket names/ARNs, owners and KMS key ARNs; inventory base prefix and scan output prefixes; retention/versioning policy; hosted reader role ARN. |
| Network | Existing VPC/subnet/security-group references, DNS path, outbound destinations and NAT egress addresses or private endpoints. Include RDS host/port and ClickHouse HTTPS endpoints. |
| Connection references | AWS discovery role ARN, RDS engine/endpoint and intended database/schema scope, ClickHouse organization/service IDs, and one Secrets Manager ARN per connection. Record secret KMS key ARNs, never values. |
| Relyance handoff | Tenant environment; module outputs; deployment package versions; approved service and region scope. |

Use existing approved infrastructure wherever possible. The public AWS module can reuse EKS, but still creates its S3 buckets, KMS key and IAM roles. It has no input for reusing arbitrary existing buckets or an existing bucket-encryption key. If those resources already exist, review their ownership and Terraform state with your infrastructure team before applying; use the Relyance-reviewed resource mapping rather than creating parallel storage or replacing resources.

### Who does what

| You | Relyance |
|---|---|
| Approve resource scope, routing, IAM, retention and capacity; apply AWS changes and Kubernetes manifests. | Register the deployment account, output bucket/region/prefix and reader identity against your tenant. |
| Create credentials in your AWS Secrets Manager and configure reference-only BYOK connections. | Provision tenant command/notification routing, workload federation and hosted transfer/processing access. |
| Verify pod identity, source reachability and known resources in each intended region; operate and update EKS. | Supply the complete tenant deployment package, inventory status, supported resource and region scope, and sizing guidance. |
| Run the first bounded scans and compare the visible results with your expected scope. | Confirm transfer and hosted processing and resolve hosted-side failures. |

Do not construct tenant identity values from examples. Confirm that Relyance has qualified the supplied inventory images and enabled inventory for your tenant before starting an AWS inventory scan. Installing a manifest or saving a connection is not acceptance of the deployment.

### Before you start

| You need | Details |
|---|---|
| An AWS account for Outpost | Use a dedicated account if you can. The scanner can read data sources in this account and in the accounts that you allow. |
| A cluster, or permission to create one | The default package uses EKS Auto Mode and EKS Pod Identity. For an existing standard EKS cluster, agree an existing-node and storage package with Relyance before applying; disabling the Terraform Auto Mode check alone does not adapt the Kubernetes manifests. |
| Terraform 1.9 or later | For the module. The Terraform provider for connections needs Terraform 1.11 or later. |
| AWS CLI | The module uses `aws eks get-token` to reach the cluster. |
| kubectl | Relyance tests the manifests with kubectl 1.33. |
| Helm 3.14 or later | For the Helm installation path. |
| Cluster capacity | Provide Linux amd64 nodes and metrics-server. The current Helm package requests 2 CPU and 16 GiB for `data-pipelines`, and 2 CPU, 4 GiB and a 5 GiB volume for Redis. Allow more for the scaler, the notification worker and scan jobs. |
| A Relyance tenant with Outpost turned on | Receive the tenant deployment package and confirmation of the enabled scan paths from your Relyance team. |

### Step 1: Create the AWS resources

Add the module to a Terraform configuration. Replace the example account, region and cluster name with the worksheet values. Set the AWS provider's `allowed_account_ids` to the deployment account so Terraform refuses credentials for a different account. This is separate from `assumable_account_ids`, which controls the source accounts the scanner may access. Use your own AWS credentials and review the plan before applying it.

The module supports AWS provider versions `>= 5.79, < 7.0`. The example below selects AWS provider 6.x.

**To use an existing EKS cluster:**

```hcl
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 6.0, < 7.0"
    }
  }
}

module "outpost" {
  source  = "Relyance-Ext/sierra/aws"
  version = "0.9.0"

  create_vpc_and_eks        = false
  existing_eks_cluster_name = "my-cluster"

  # The AWS accounts whose IAM roles the scanner can assume to read data sources.
  # Set this, or set assume_all_roles = true.
  assumable_account_ids = ["111122223333"]

  # The manifests deploy into the "inhost" namespace.
  additional_service_account_namespaces = ["inhost"]

  # Optional: secrets for In Host BYOK connections.
  byok_secret_arn_patterns = [
    "arn:aws:secretsmanager:us-west-2:111122223333:secret:relyance/inhost/*",
  ]
}

provider "aws" {
  region = "us-west-2"
  # Your Outpost deployment account from the worksheet, not a source account.
  allowed_account_ids = ["111122223333"]
  default_tags {
    tags = module.outpost.default_tags
  }
}

output "outpost" {
  description = "Send this output to Relyance"
  value       = module.outpost
}
```

**To create a new EKS cluster**, replace the cluster settings with the network ranges for the new VPC:

```hcl
  create_vpc_and_eks = true
  vpc_cidr           = "172.30.0.0/16"
  service_cidr       = "10.100.0.0/16"
  nat_subnet_cidr    = "172.30.255.0/24"
  subnet_cidrs = {
    usw2-az1 = "172.30.0.0/20"
    usw2-az2 = "172.30.16.0/20"
    usw2-az3 = "172.30.32.0/20"
    usw2-az4 = "172.30.48.0/20"
  }

  # Empty means the cluster API endpoint is private only.
  eks_public_access_cidrs = []
```

For a new cluster, set one subnet for each availability zone ID in the region. For either deployment path, confirm that the account returned below matches the deployment account in your worksheet before you plan:

```bash
aws sts get-caller-identity --query Account --output text
terraform init
terraform plan -out=outpost.tfplan
terraform apply outpost.tfplan
terraform output -json outpost
```

For all inputs, refer to the [module documentation](https://registry.terraform.io/modules/Relyance-Ext/sierra/aws/0.9.0).

#### What the module creates

| Resource | Name | Purpose |
|---|---|---|
| S3 bucket | `relyance-findings-<account-id>` | Scan results. Versioning on, public access blocked, encrypted with the KMS key. |
| S3 bucket | `relyance-work-<account-id>` | Temporary scan data. Same settings. |
| KMS key | `alias/Relyance_Sierra` | Encrypts both buckets. Key rotation is on. When the module creates the cluster, it also encrypts the Kubernetes secrets. |
| IAM role | `Relyance_Sierra` | The scanner role. The scanner pods get it through EKS Pod Identity. It can use both buckets, assume roles in the accounts that you allow, and read the secrets that match `byok_secret_arn_patterns`. |
| IAM role | `Relyance_Sierra_Reader` | The Relyance read-only role. Only a Relyance IAM principal with an external ID that the module generates can assume it. It can list and read the findings bucket and decrypt with the key. It has no other permissions. |
| EKS Pod Identity association | `relyance` service account | Connects the scanner pods to `Relyance_Sierra`. |
| VPC and EKS cluster | `Relyance_Sierra` | Only when `create_vpc_and_eks = true`. Private subnets, two NAT gateways, EKS Auto Mode, a private API endpoint by default, and all control plane logs on. |

The module creates its own KMS key. It does not accept an existing key. For existing approved storage, review the bucket and key policies with Relyance rather than substituting names in the module. The module's [S3 policy](https://github.com/Relyance-Ext/terraform-aws-sierra/blob/v0.9.0/modules/s3/policy.tf) gives a reader `s3:ListBucket`, `s3:GetObject` and `s3:GetObjectVersion`; the hosted transfer must retain those reads on the agreed outputs, plus decryption with the output key. The EKS workload needs the S3 read/write and multipart-upload permissions for its approved output/work prefixes. Secret read/decrypt permissions are separate and are detailed in the [BYOK access guide](/docs/introduction-to-relyance-ai/outpost-connection-credentials/#give-the-scanner-access).

#### Findings-bucket deletion permission

The supporting Terraform module grants the scanner role `s3:DeleteObject` and
`s3:DeleteObjectVersion` throughout the dedicated findings bucket. This includes
intermediate results, Delta files, journals and other findings objects. The permission is
for that findings bucket, not unrelated customer S3 buckets. Version deletion is permanent
and applies to every matching version accessible to the role, including existing sessions.
Review this access before applying the module.

The applied module emits `findings_object_deletion` with `enabled`, `account_id` and
`bucket`. Relyance validates these facts against your AWS account and findings bucket.
Enabled capability sets `GAI_INHOST_FINDINGS_DELETION_ENABLED` to `"true"` for the GAI
sampler/analyzer workers. An older module without this output leaves the new deletion gate
disabled. Inventory cleanup also requires the explicit deployment choice
`inventory.versioned_result_cleanup: true` before `DP_INHOST_VERSIONED_RESULT_CLEANUP`
is set to `"true"`. Module 0.9.0 emits this capability. Use the applied module output and a
reviewed runtime package before activation.

The application still chooses the objects it owns and must prove captured-version cleanup,
replacement preservation and Delta maintenance in the normal deployment rehearsal.
Keep credentials in AWS Secrets Manager. Findings-bucket deletion does not change
credential custody or the hosted GCS handoff.

#### Optional rehearsal subscriptions and query regions

For an approved rehearsal, Relyance can supply an explicit tenant-owned subscription
selector. It selects fresh DP and inventory-notification subscriptions in your trusted
project on the existing canonical topics. The package keeps the normal worker entrypoints
and requires a released notifier image that supports the selector. Review the exact
subscription/topic bindings and subscriber permissions before activation. Fresh
subscriptions leave old canonical queues intact and receive new topic traffic from all
producers. Verify producer quiescence and zero eligible pending transfers before the
rehearsal; a successful rehearsal does not qualify old queue contents.

Agree `inventory.query_regions` independently from the bucket's storage region. An
explicit nonempty list, such as `[us-west-2]`, bounds regional API discovery after the
runtime checks enabled/supported regions. Omission keeps the account-enabled regional
defaults. IAM and S3 discovery remain account-global. The package does not infer discovery
scope from the S3 bucket region.

### Step 2: Send the output to Relyance

Send only the `outpost` module output to your Relyance team through the agreed onboarding channel. It contains resource and access references, including the reader external ID. Do not send the Terraform state or credential secret values. Relyance uses these values:

| Output | What Relyance does with it |
|---|---|
| `aws_account_id` | Records the account of your deployment. Relyance accepts secret ARNs only from this account. |
| `reader_external_id` | Assumes `Relyance_Sierra_Reader` to copy the scan results. |
| `oidc_issuer` | Lets the cluster sign in to the Relyance command queue and API with short-lived credentials, with no keys. |

Relyance then sends you a complete Kustomize folder or full Helm `values.yaml`. It contains your routing, storage, identity and runtime image settings. When you upgrade, use the image settings from the new package; the chart version alone does not choose the images. Ask Relyance to confirm the [inventory settings](#inventory-workers) before you apply it. Do not build these values from examples or put connection credentials in them.

### Step 3: Install the cluster components

Use the version and complete configuration supplied for your tenant. Check the context and review cluster-scoped changes, including KEDA CRDs, the jobs NodePool and StorageClass, before applying. The default AWS package requires EKS Auto Mode, its `default` NodeClass and the Auto Mode EBS CSI provisioner. For standard EKS, obtain a reviewed node/storage configuration first.

Allow outbound traffic to the supplied ECR registry and its S3 image layers, the API hosts in the values file, `sts.googleapis.com`, `iamcredentials.googleapis.com`, `pubsub.googleapis.com`, `monitoring.googleapis.com`, the required AWS APIs, and your approved source endpoints. Verify DNS, routing and source security groups separately.

#### Prepare the cluster

1. Set `AWS_REGION`, `EKS_CLUSTER_NAME` and `INHOST_NAMESPACE` in your shell from the supplied package. The published Kustomize base uses `inhost`; an existing registered Helm deployment may use `sierra`. Preserve the supplied namespace because workload identity registration depends on it. Confirm your Kubernetes context and AWS account match the worksheet.

   ```bash
   aws eks update-kubeconfig --region "$AWS_REGION" --name "$EKS_CLUSTER_NAME"
   kubectl config current-context
   kubectl get nodes
   ```

2. Install KEDA if it is not already installed. The bundle below contains KEDA 2.20.2. If KEDA is already installed, check that it supports ScaledJobs and the `metrics-api` and Redis scalers instead of installing a second copy.

   ```bash
   kubectl apply --server-side \
     -f https://assets.relyance.ai/inhost/k8s/v1.4.1/keda-aws-prod-v1.4.1.yaml
   kubectl wait --for=condition=Established --timeout=120s \
     crd/scaledjobs.keda.sh crd/triggerauthentications.keda.sh
   kubectl -n keda rollout status deployment/keda-operator --timeout=5m
   kubectl -n keda rollout status deployment/keda-metrics-apiserver --timeout=5m
   kubectl -n keda rollout status deployment/keda-admission --timeout=5m
   ```

3. Create the namespace if it does not already exist.

   ```bash
   kubectl create namespace "$INHOST_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
   ```

#### Kustomize installations

Render and validate the complete folder from Relyance, then apply it:

```bash
kubectl kustomize ./relyance-outpost > outpost-rendered.yaml
kubectl apply --dry-run=server -k ./relyance-outpost
kubectl diff -k ./relyance-outpost
kubectl apply -k ./relyance-outpost
```

`kubectl diff` returns exit code 1 when changes are present and greater than 1 for an error. Review the changes before applying. Check that the rendered file has your agreed account, regions, S3 prefixes, service accounts and runtime image settings, with no unresolved `REPLACED-BY-TENANT-OVERLAY` values. Keep the supplied image references and pull policies. Do not apply the following abbreviated example as a complete tenant package.

The scanner part of `kustomization.yaml` starts like this:

```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://assets.relyance.ai/inhost/k8s/v1.4.1/services-aws-prod-v1.4.1.yaml
patches:
  - path: patch-tenant-values.yaml
    target:
      version: v1
      kind: ConfigMap
      name: common-env
  # ...
```

To read the manifests before you apply them, download them and check them against the published checksums:

```bash
curl -fsSLO https://assets.relyance.ai/inhost/k8s/v1.4.1/services-aws-prod-v1.4.1.yaml
curl -fsSL https://assets.relyance.ai/inhost/k8s/v1.4.1/SHA256SUMS-v1.4.1.txt \
  -o SHA256SUMS-v1.4.1.txt
shasum -a 256 -c SHA256SUMS-v1.4.1.txt --ignore-missing
```

#### Helm installations

Use the full `values.yaml` supplied by Relyance and Helm 3.14 or later. Set `INHOST_VALUES` to that file's path. Check `helm list --namespace "$INHOST_NAMESPACE"` and set `INHOST_RELEASE` to the existing release name. For a fresh installation, use `inhost`. Do not install a second release over existing resources or mix Helm and Kustomize ownership.

Download and verify the chart, then render, validate and review the proposed changes:

```bash
curl -fsSLO https://assets.relyance.ai/inhost/helm/inhost-1.3.0.tgz
curl -fsSLO https://assets.relyance.ai/inhost/helm/SHA256SUMS-chart-v1.3.0.txt
shasum -a 256 -c SHA256SUMS-chart-v1.3.0.txt --ignore-missing
printf '%s  %s\n' \
  78f1cc6c093bb58afc206a2dafefc16546aa78cfbb4315fe51c0b6419e32fda8 \
  inhost-1.3.0.tgz | shasum -a 256 -c -
helm lint ./inhost-1.3.0.tgz --values "$INHOST_VALUES"
helm template "$INHOST_RELEASE" ./inhost-1.3.0.tgz \
  --namespace "$INHOST_NAMESPACE" --values "$INHOST_VALUES" > outpost-rendered.yaml
kubectl --namespace "$INHOST_NAMESPACE" apply --dry-run=server -f outpost-rendered.yaml
kubectl --namespace "$INHOST_NAMESPACE" diff -f outpost-rendered.yaml
```

The server dry-run needs KEDA installed first. `kubectl diff` returns 1 when there are changes and more than 1 for an error; review the changes before you upgrade. The supplied values file is complete, so do not add another values file or use `--reuse-values`.

```bash
helm upgrade --install "$INHOST_RELEASE" ./inhost-1.3.0.tgz \
  --namespace "$INHOST_NAMESPACE" --create-namespace --values "$INHOST_VALUES" \
  --atomic --wait --timeout 40m
kubectl -n "$INHOST_NAMESPACE" rollout status deployment/data-pipelines --timeout=40m
kubectl -n "$INHOST_NAMESPACE" rollout status deployment/gai-inventory-notifications --timeout=10m
```

The two rollout checks apply when inventory is enabled. The 40-minute timeout gives a running inventory worker time to finish before it is replaced. Then continue with Step 5.

#### What the manifests install

| Kind | Name | Purpose |
|---|---|---|
| ScaledJob | `gai-sampler`, `gai-analyzer`, `gai-sampler-worker`, `gai-analyzer-worker` | The scanner workers. KEDA starts them only when scan commands wait. |
| Deployment | `inhost-scaler` | Tells KEDA how many scan commands wait. |
| Deployment | `data-pipelines`, `gai-inventory-notifications` | The [inventory workers](#inventory-workers). One replica each when inventory is enabled; zero otherwise. |
| StatefulSet | `gai-redis-master` | Coordinates the workers of one scan. It runs in the cluster. |
| ServiceAccount | `relyance`, `inhost-scaler` | The identities of the pods. |
| NodePool and StorageClass | Names from the supplied package | Auto Mode nodes and disks. Kustomize defaults are `inhost-jobs`/`inhost-gp3`; Helm defaults are `sierra-jobs`/`sierra-gp3`. These are cluster-scoped. |
| ConfigMap | `common-env`, `inventory-env` | Scanner and inventory settings supplied by the tenant overlay. |
| Service, PodDisruptionBudget | | Internal connections and availability settings. |

The services file contains no Role, ClusterRole or CRD, and no monitoring, log or telemetry agent. The KEDA file installs the standard KEDA components, with their own CRDs and cluster roles. The scanner ScaledJobs, `inhost-scaler` and Redis templates run as non-root with all Linux capabilities dropped, and meet the Kubernetes Restricted Pod Security Standard. Before inventory activation, Relyance must qualify the complete inventory overlay, including its images, identity and pod security settings.

### Step 4: Add connections

A connection tells the scanner how to reach one data source. Set its runtime mode to run the scan in Outpost:

| Runtime mode | Where the scan runs | Where the credentials are |
|---|---|---|
| In Host BYOK | Outpost | In a secret in your account. Relyance stores only the secret ARN. |
| In Host | Outpost | Relyance stores them in its secret store. |

New connections start as Relyance-hosted. Set the runtime mode on each Outpost connection. Use In Host BYOK to keep the credentials in your account.

**In the web application**, follow [Store Outpost Credentials in a Customer-Managed Secret](/docs/introduction-to-relyance-ai/outpost-connection-credentials/).

**With Terraform**, use the [Relyance provider](https://registry.terraform.io/providers/Relyance/relyance/1.1.1/docs/resources/integration_connection). Set `RELYANCE_CLIENT_ID` and `RELYANCE_CLIENT_SECRET` through your approved credential mechanism for an OAuth client with the Integration Configuration Management role. This example references an existing RDS credential secret. Create its value in AWS Secrets Manager using the [supported JSON shape](/docs/introduction-to-relyance-ai/outpost-connection-credentials/#aws-inventory-rds-and-clickhouse-secret-examples); do not put credential values in Terraform configuration or state.

If you keep this example in the same Terraform directory as Step 1, merge its `relyance` entry into the existing `required_providers` block.

```hcl
terraform {
  required_providers {
    relyance = {
      source  = "Relyance/relyance"
      version = "1.1.1"
    }
  }
}

provider "relyance" {}

variable "rds_secret_arn" {
  type        = string
  description = "Full ARN of the existing credential secret in your deployment account"
}

resource "relyance_integration_connection" "rds" {
  vendor       = "aws_rds"
  name         = "RDS (Outpost)"
  runtime_mode = "IN_HOST_BYOK"
  connect_on_apply = false
  secret_ref   = var.rds_secret_arn

  auth = {
    method = "username-password"
  }

  scans = {
    "data-inspection" = { enabled = false }
  }
}
```

This example leaves the connection unconnected and data inspection disabled while you verify the deployment and source access. Save the raw-sample storage policy and review the separate sanitized-context setting under [What Relyance receives](#what-relyance-receives) before connecting or enabling a scan. With `secret_ref`, all credential fields, including endpoint, engine, username and scope, belong in the AWS secret. Keep `auth.secrets_wo` unset and put only top-level settings in `auth.params`. Authentication methods and scan capabilities come from the provider's `relyance_integration_vendor` data source. Use the [BYOK guide](/docs/introduction-to-relyance-ai/outpost-connection-credentials/) for secret access and supported authentication methods.

#### AWS single-account inventory

Follow the [AWS inventory setup guide](/docs/cloud-accounts/amazon-web-services-inventory-integration/#outpost-single-account-setup) for Resource Explorer and discovery permissions. Choose **Direct Connection**, use **In Host BYOK**, and store `role_arn`, `external_id` and `region_name` in the AWS secret. The discovery role trusts the EKS workload role; the workload role must be allowed to assume it. Hosted trust examples in the integration guide require this adjustment for Outpost.

Use the agreed aggregator region and qualify every intended source region. A valid secret, an enabled AWS region, or a successful connection check does not establish complete inventory coverage. Begin with the approved resource types and a bounded scope; expand after the first successful scan. This path covers one AWS account, not an Organizations scan.

#### PostgreSQL on Amazon RDS

Use the [Amazon RDS guide](/docs/data-stores/amazon-rds-mysql-mariadb/#outpost-and-postgresql) for the engine and authentication setup. For direct PostgreSQL, set `engine` to `postgres` in the credential secret. Existing EKS-to-RDS routes, DNS and security groups must allow the database port. You do not need to make RDS public when EKS already has an approved private path.

For direct PostgreSQL, confirm approved `CONNECT` access to the `postgres` bootstrap database as well as the intended application databases; the [RDS guide](/docs/data-stores/amazon-rds-mysql-mariadb/#outpost-and-postgresql) explains how to validate this access and coordinate a supported alternative if it is forbidden. Verify database-side read grants independently of AWS IAM. IAM authentication additionally needs `rds-db:connect` for the intended database user and PostgreSQL `rds_iam` membership. Discovering the RDS instance is separate from opening SQL sessions and reading tables.

#### ClickHouse Cloud

Follow the [ClickHouse guide](/docs/data-stores/clickhouse/#outpost-on-aws). The Cloud API key discovers organizations and services; `db_user` and `db_password` authorize database inspection. Keep both sets in the AWS secret. Allow the ClickHouse Cloud API and each discovered service's HTTPS endpoint from EKS, using the service's TLS port. Native TCP connectivity alone does not validate the HTTP scanner path.

### Step 5: Check the deployment

First confirm the installed components using the namespace from your supplied package. With inventory enabled, `data-pipelines` and `gai-inventory-notifications` should each show one available replica.

```bash
kubectl get serviceaccounts,deployments,statefulsets,scaledjobs,pods -n "$INHOST_NAMESPACE"
kubectl rollout status deployment/inhost-scaler -n "$INHOST_NAMESPACE"
kubectl rollout status statefulset/gai-redis-master -n "$INHOST_NAMESPACE"
kubectl -n "$INHOST_NAMESPACE" get deployments data-pipelines gai-inventory-notifications
aws eks list-pod-identity-associations --cluster-name "$EKS_CLUSTER_NAME" --region "$AWS_REGION"
```

Compare the association's namespace, service account and role with the rendered pod specifications, and check that the running images match your package. An administrator's successful AWS CLI call does not prove the pod can access a secret or source. Scanner jobs are absent while idle; that is normal. The inventory Deployments should always be available.

Run one bounded scan per connection from the Relyance web application. Follow the scan status and warnings there, and observe workloads with `kubectl get pods -n "$INHOST_NAMESPACE" -w`. Check each layer:

| Check | Expected result |
|---|---|
| BYOK access | The workload reads its AWS secret without an authentication or KMS error. Saving the ARN alone does not test access. |
| AWS inventory | Known approved resources appear in each intended region; permission/coverage warnings are resolved or explicitly excluded from the agreed scope. |
| RDS | Intended databases, schemas and tables are enumerated; enabled data inspection produces classifications from an approved table. |
| ClickHouse | Organizations/services are discovered through the API, and the intended databases/tables are independently inspected through HTTPS SQL. |
| S3 output | New inventory/scan output is present under the agreed prefixes. Use object names and timestamps to verify progress; do not share object contents. |
| Hosted results | Relyance confirms copy and processing; expected assets, classifications and applicable identities become visible in the application. |

Compare against a customer-maintained list of known resources. Empty results, an incomplete region, or a warning require investigation; they are not proof that the source contains no resources. Agree capacity after measuring a representative scan. Throughput and region coverage depend on the qualified deployment and scan scope.

### Scan progress and retry

Record the connection, scan time, visible status and affected resource/region. Check pod events and the relevant workload's logs locally while the scan is active. Correct permanent errors such as secret shape, denied permissions or missing routes before starting another scan. After rotation, allow up to five minutes for the cached credential value to refresh.

A local scan can finish before the hosted copy and processing finish. If output exists in S3 but results remain absent, ask Relyance to check the transfer and hosted processing for that scan before starting a duplicate. For a failed scan, use the scan action available on your connection after correcting the cause. Do not delete output prefixes or Kubernetes state to force a retry; Relyance can coordinate recovery of an interrupted transfer.

## What Relyance receives

The hosted copy includes resource metadata (such as account, database, table, column and file names), applicable identities and permissions, classification results, and scan status/counts. Metadata can itself be sensitive. Review the enabled connectors and the agreed output policy before activation.

Raw matched values and stored source samples require explicit per-connection enablement where permitted; a missing setting or a tenant-wide default is not consent. Strict InHost mode blocks their egress even if `store_samples="true"`. To disable raw-sample storage, save an explicit per-connection `store_samples="false"` setting before enabling data inspection, run a fresh scan on the verified InHost image, and check that raw sample and quote-value fields are absent. Changing the setting does not remove outputs from earlier scans.

Sanitized v2 surrounding context is separate from raw matched values and samples. Typed redaction and a shipped dictionary transform this context before storage; the existing Relyance-managed explainability setting (`gai-explainability-context="quote"`) controls its use for hosted adjudication. When enabled on a qualified release, this context can be copied to hosted GCS and sent to the configured hosted model service, including with raw-sample storage disabled. Sanitization reduces exposure; it does not guarantee that every possible sensitive meaning is removed. Review this processing separately rather than assuming that disabling raw samples makes outputs context-free.

**Release qualification.** The current scanner baseline also suppresses surrounding context when `store_samples="false"`. The update that separates sanitized v2 context from raw-sample storage still requires release qualification. Before activation, Relyance must verify both settings and the exact scanner and transfer images, including an output check for the agreed policy. Do not rely on an unshipped update or a tenant default.

Hosted processing includes adjudication of copied findings. Structural names, paths, identifiers and classifications may be sent to the configured hosted model service. Disabling sample storage does not disable that metadata processing. Agree the allowed data categories and processing destinations before activation; BYOK is a credential-custody choice, not an all-data-stays-in-AWS guarantee.

In Host BYOK keeps connection credential values in your AWS Secrets Manager; Relyance stores the ARN reference and connection settings. BYOK controls credential custody. It does not keep all derived metadata in AWS. Hosted data security and identity services consume the copied inventory/results in GCS, rather than reading your customer S3 bucket directly.

## Security

**Identity.** The Outpost components use short-lived credentials for AWS and Relyance workload access. The scanner pods get the `Relyance_Sierra` role through EKS Pod Identity. They sign in to the Relyance command queue and API with short-lived credentials from workload identity federation.

**Credentials.** With In Host BYOK, the credentials stay in a secret in your account. Relyance stores only the secret ARN and rejects credential values for these connections. The scanner reads the secret during the scan with its own role. For the setup steps, refer to [Store Outpost Credentials in a Customer-Managed Secret](/docs/introduction-to-relyance-ai/outpost-connection-credentials/).

**Encryption.** All connections to Relyance use TLS. A KMS key in your account encrypts the findings bucket and the work bucket.

**Access.** The module creates the read-only role `Relyance_Sierra_Reader` for the findings bucket, with the external ID from your module. For inventory, confirm that the hosted reader also has the approved output-prefix and KMS read access in the supplied deployment mapping. It must not gain access to connection secrets or temporary work data. Relyance has no Kubernetes or console access and no inbound access to your cluster or private data-source network. The separately authorized transfer role reads the findings bucket through the S3 API. When the module creates the cluster, it gives cluster administrator access only to the identity that applies it and to the identities that you list in `eks_kubectl_admins`.

**Network.** The cluster makes only outbound connections. The VPC that the module creates has outbound internet access through NAT gateways and no inbound path. To limit outbound traffic, allow these destinations:

| Destination | Purpose |
|---|---|
| `209479300333.dkr.ecr.us-west-2.amazonaws.com`, and Amazon S3 in `us-west-2` for image layers | Relyance container registry |
| Relyance API endpoint supplied in your deployment package | Connection settings and scan status |
| `sts.googleapis.com`, `iamcredentials.googleapis.com` | Short-lived credentials for the command queue and API |
| `pubsub.googleapis.com`, `monitoring.googleapis.com` | Command queue, and the number of waiting commands |
| AWS APIs in the deployment, secret and approved source regions: S3, STS, Secrets Manager, KMS, Resource Explorer and enabled discovery services | Storage, role assumption, credentials and inventory discovery |
| `api.clickhouse.cloud` and discovered service HTTPS endpoints | ClickHouse discovery and SQL inspection |
| Your data sources | Scanning |

## Data retention in your account

| Data | Default retention | Module variable |
|---|---|---|
| Scan results in the findings bucket | 180 days | `s3_expiration_days` |
| Temporary scan data in the work bucket | 7 days | `s3_workspace_expiration_days` |

Versioning is on for both buckets. The lifecycle rules expire the current version of each object. Earlier versions of an object stay until you delete them, or until you add a lifecycle rule for noncurrent versions.

## Operations and support

### Troubleshooting

| Symptom | Next step |
|---|---|
| Pods pending or Redis unavailable | Inspect `kubectl describe pod` and namespace events. Check node capacity, Auto Mode scheduling, volume provisioning and the requested CPU/memory. Keep the worker/coordinator sizing from the approved package. |
| Image pull or workload federation failure | Check image pull permissions, the runtime image channel or explicit pins, projected service-account credentials and the package's outbound identity/API destinations. Ask Relyance to verify hosted grants. |
| Secret access or decryption failure | Check the pod's actual IAM role, secret ARN/account/region, `secretsmanager:GetSecretValue`, `kms:Decrypt` for a customer key, and resource/key policies. Follow [BYOK troubleshooting](/docs/introduction-to-relyance-ai/outpost-connection-credentials/#troubleshooting). |
| AWS inventory incomplete | Check discovery-role trust, the configured external ID, Resource Explorer indexes/views, per-service permissions and each intended region. Share the affected resource type/region and sanitized warning with Relyance. |
| Database timeout or TLS failure | Test DNS and the database endpoint from the same approved network path as EKS. Check routes, security groups, ClickHouse IP access lists and the correct TLS protocol/port. |
| Discovery succeeds but tables are absent | Check SQL credentials, database-side read permissions and scope filters. A Cloud API or AWS discovery check does not validate SQL sampling. |
| Local output exists but results do not appear | Preserve the output and ask Relyance to check hosted transfer and processing for the connection/scan time. |

**Updates.** You operate deployment updates:

| Part | How to update |
|---|---|
| Terraform module | Change `version` in the `module` block and apply. |
| Manifests | Change the version in the URLs in `kustomization.yaml` and the KEDA command, then apply them again. Earlier versions stay available. |
| Relyance application images | Relyance centrally promotes the mutable `:release` channel for your environment. New containers use `imagePullPolicy: Always` to pull the promoted image, without a tenant configuration PR for every code release. Explicit image pins remain available if you choose to manage them. |

Moving the `:release` tag does not restart running pods. Running containers keep their current image. Long-lived `data-pipelines` and `gai-inventory-notifications` Deployments adopt the promoted image during your normal approved maintenance rollout or restart. Repeat the validation checks after an update and confirm the images used by the new pods.

**Monitoring.** The deployment sends no logs, metrics or telemetry to Relyance. Logs stay in your cluster. Use your own tools to collect them.

**Support.** Relyance collects no diagnostic data automatically. Relyance support uses only the diagnostic data that you decide to share.

## Related

- [AWS inventory](/docs/cloud-accounts/amazon-web-services-inventory-integration/)
- [Amazon RDS](/docs/data-stores/amazon-rds-mysql-mariadb/)
- [ClickHouse Cloud](/docs/data-stores/clickhouse/)
- [How Relyance AI Works](/docs/introduction-to-relyance-ai/how-relyance-ai-works/)
- [Store Outpost Credentials in a Customer-Managed Secret](/docs/introduction-to-relyance-ai/outpost-connection-credentials/)
