> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensorlake.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox Proxy on AWS

> Install and verify the Tensorlake Sandbox Proxy in an Amazon EKS cluster.

This procedure installs the Tensorlake Sandbox Proxy in an Amazon EKS cluster.

The preparation script creates Kubernetes manifests for an AWS Network Load
Balancer Service. The AWS Load Balancer Controller creates the Network Load
Balancer, or NLB.

The NLB accepts HTTPS traffic on port `443`. It also accepts native SSH traffic
on port `22`.

## 1. Prepare the required values

Prepare these values:

| Value                 | Example                                               |
| --------------------- | ----------------------------------------------------- |
| Project API key       | `<project-api-key>`                                   |
| Public host           | `sandboxes.customer.example`                          |
| Kubernetes namespace  | `tensorlake-sandbox-proxy`                            |
| Output directory      | `./tensorlake-sandbox-proxy`                          |
| ACM certificate ARN   | `arn:aws:acm:us-east-1:123456789012:certificate/<id>` |
| NLB security group ID | `sg-0123456789abcdef0`                                |

The public endpoint must be an HTTPS origin. Do not add a port or a path.

The EKS cluster must have the AWS Load Balancer Controller. The controller must
support `service.k8s.aws/nlb` Services.

Install these local commands:

```text theme={null}
curl
jq
openssl
base64
ssh-keygen
kubectl
tl
```

Install the Tensorlake CLI if the `tl` command is not available:

```bash theme={null}
curl -fsSL https://tensorlake.ai/install | sh
```

## 2. Create the AWS certificate and security group

Create an AWS Certificate Manager, or ACM, certificate in the same AWS Region
as the NLB.

Add these names to the certificate:

```text theme={null}
sandboxes.customer.example
*.sandboxes.customer.example
```

Create the DNS validation records. Wait until ACM shows the certificate status
as `ISSUED`.

Create one security group for the NLB. Add these rules:

| Direction | Port     | Source or target                     |
| --------- | -------- | ------------------------------------ |
| Inbound   | TCP 443  | Internet or approved client networks |
| Inbound   | TCP 22   | Approved SSH client networks         |
| Outbound  | TCP 9080 | Kubernetes target security group     |
| Outbound  | TCP 2222 | Kubernetes target security group     |

The generated NLB has listeners on ports `443` and `22`. Restrict port `22` if
public SSH access is not required.

## 3. Run the preparation script

Download the preparation script. Run it with the required values:

```bash theme={null}
curl -fsSL \
  https://cloud.tensorlake.ai/byoc/sandbox-proxy/prepare.sh \
  --output prepare.sh

chmod +x prepare.sh

./prepare.sh \
  --api-key <api-key> \
  --endpoint https://sandboxes.customer.example \
  --namespace tensorlake-sandbox-proxy \
  --output-dir ./tensorlake-sandbox-proxy \
  --enable-aws-lb \
  --aws-lb-certificate-arn '<acm-certificate-arn>' \
  --aws-lb-security-group-id '<nlb-security-group-id>'
```

The script creates the Kubernetes manifests. It does not change the Kubernetes
cluster.

Keep the output directory secure. It contains private keys.

## 4. Review and apply the resources

Confirm the Kubernetes context:

```bash theme={null}
kubectl config current-context
```

Review the generated resources. Run the server dry run:

```bash theme={null}
kubectl kustomize ./tensorlake-sandbox-proxy

kubectl apply \
  --server-side \
  --dry-run=server \
  -k ./tensorlake-sandbox-proxy
```

Add a Deployment patch if the cluster requires a node selector or a toleration.

Apply the resources:

```bash theme={null}
kubectl apply -k ./tensorlake-sandbox-proxy

kubectl \
  --namespace tensorlake-sandbox-proxy \
  rollout status deployment/sandbox-proxy
```

Wait for the NLB hostname:

```bash theme={null}
kubectl \
  --namespace tensorlake-sandbox-proxy \
  get service sandbox-proxy-public
```

Confirm that both NLB target groups are healthy. Port `443` uses target port
`9080`. Port `22` uses target port `2222`.

## 5. Create the public DNS records

Create two DNS alias records. Configure both records to use the NLB hostname:

```text theme={null}
sandboxes.customer.example
*.sandboxes.customer.example
```

## 6. Activate the endpoint

Open the project settings in [Tensorlake Cloud](https://cloud.tensorlake.ai).

Set **SSH proxy public key** to the content of this file:

```text theme={null}
./tensorlake-sandbox-proxy/ssh/outbound.key.pub
```

Set **Sandbox ingress endpoint** to this value:

```text theme={null}
https://sandboxes.customer.example
```

Save both settings.

## 7. Verify the endpoint

Verify the health route:

```bash theme={null}
curl -fsS https://sandboxes.customer.example/health
```

Verify the wildcard certificate:

```bash theme={null}
openssl s_client \
  -connect sandboxes.customer.example:443 \
  -servername test.sandboxes.customer.example \
  </dev/null
```

Create a test sandbox. Confirm that its URL has this form:

```text theme={null}
https://<sandbox-id>.sandboxes.customer.example
```

Test command execution and WebSocket SSH:

```bash theme={null}
tl sbx exec <sandbox-id> sh -lc 'printf TL_EXEC_OK'
tl sbx ssh <sandbox-id>
```

Test native SSH if port `22` is enabled.

First, sign in to the Tensorlake CLI with your Tensorlake user account. A
project API key cannot register a user SSH key:

```bash theme={null}
tl login
```

Register a user SSH key. Connect to the sandbox:

```bash theme={null}
tl sbx ssh keys add ~/.ssh/id_ed25519.pub
ssh <sandbox-id>@<sandbox-id>.sandboxes.customer.example
```

The Sandbox Proxy connects to the sandbox SSH server on private port `8096`.

## 8. Rotate the certificate and keys

Use this step when the certificate or keys must change.

Run `prepare.sh` again with a new output directory.

Review and apply the new resources. The certificate fingerprint starts a
rolling pod update.

Update **SSH proxy public key** with the new `outbound.key.pub` value.

Keep the previous output directory in secure storage until the update passes.
