# Connections

> Connect databases, S3 buckets, Weights & Biases and GitHub once, verified, and use them from Jobs, Sandboxes, imports and outputs.

Source: https://nodus-platform-site.pages.dev/docs/guides/connections/
Build revision: 211ad9f836655b1c3a2668c4693e442471f28614

A Connection is an external system that Nodus talks to for you: a Postgres database for query imports and outputs, an S3 bucket for inputs, a Weights & Biases project for live run tracking, or your GitHub repositories for private sources. Its credentials live in a [Secret](https://nodus-platform-site.pages.dev/docs/guides/secrets/); the Connection says what they are for, and Nodus checks that they work before anything uses them.

## Create a Connection

Put the credentials in a Secret, then point the Connection at it:

Terminal window

```console
nodus secret create analytics-db --from-literal DATABASE_URL=postgres://reader:...@db.example.com:5432/app
```

connection.yaml

```yaml
apiVersion: nodus.dev/v1
kind: Connection
metadata:
  name: ex-connections-postgres
spec:
  type: Postgres
  secret: ex-connections-postgres     # holds DATABASE_URL
  scope: Read                         # verified: the role can read, and is not asked to write
```

Terminal window

```console
nodus apply -f connection.yaml
nodus wait connection/ex-connections-postgres --for=condition=Verified
nodus describe connection/ex-connections-postgres
```

|`type`|Secret keys|Settings|Verified by|
|-|-|-|-|
|`Postgres`|`DATABASE_URL`|`scope`: `Read`, `Write` or `ReadWrite`|Connecting, a query, and for write scopes the right to create tables|
|`Neon`, `Supabase`|`DATABASE_URL`|`scope`; `neon.branch`|The same checks, on the provider’s own host|
|`S3`|`ROLE_ARN`, or `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`|`s3.bucket`, `s3.region`, `s3.prefix`, `s3.endpoint`|Reaching the bucket with short-lived credentials|
|`WandB`|`WANDB_API_KEY`|`wandb.entity`, `wandb.project`, `wandb.live`|The key’s access to the entity|

Prefer an IAM role (`ROLE_ARN`) for S3: Nodus assumes it for minutes at a time, so no long-lived key is stored. Every S3 Connection has its own external id in `status.externalId`, and Nodus sends exactly that id each time it assumes the role, so a role your trust policy grants to one Connection can’t be used through any other Connection or organization. Create the Connection, read the id, and require it in the role’s trust policy:

Terminal window

```console
nodus get connection/datasets -o jsonpath='{.status.externalId}'
```

```json
{
  "Effect": "Allow",
  "Principal": { "AWS": "<the Nodus principal shown in the console>" },
  "Action": "sts:AssumeRole",
  "Condition": { "StringEquals": { "sts:ExternalId": "<status.externalId>" } }
}
```

The Connection shows `Failed` until the trust policy names the id; the next check, within the hour, turns it `Ready`. You don’t need `EXTERNAL_ID` in the Secret. If you set it, it must equal `status.externalId`, and any other value is refused.

A Connection is `Ready` once verified, and `status.egressHosts` lists the hosts it may reach. Nodus checks it again every day, and every hour after a failure. When a check fails the Connection shows `Failed`, the `Verified` condition says why, and anything that needs it fails with `ConnectionNotReady` until you fix the Secret.

## Use it

```yaml
spec:
  connections: [tracking]               # injects WANDB_* and allows its hosts through the egress policy
  inputs:
    - name: shards
      bucket: {uri: s3://acme-data/shards/, connection: datasets}
```

A `WandB` Connection with `wandb.live: true` sets `WANDB_API_KEY`, `WANDB_ENTITY`, `WANDB_PROJECT`, `WANDB_RUN_GROUP`, `WANDB_NAME` and `WANDB_RUN_ID` for the Job, so `wandb.init()` needs no arguments. Each index of the Job logs to one run, and a run that Nodus restarts after lost capacity resumes it rather than starting a new one. A Job with one index shows the run’s page in `status.links`. A variable you set yourself keeps your value; setting `WANDB_RUN_ID`, `WANDB_ENTITY` or `WANDB_PROJECT` yourself means Nodus doesn’t link the run. A Job that names a Connection that is missing or not `Ready` runs without it and gets a `ConnectionNotReady` Event.

## Connect GitHub

A `GitHub` Connection installs the Nodus GitHub App on your account or organization. It needs no Secret:

Terminal window

```console
nodus create connection github --type GitHub
nodus get conn github -o jsonpath='{.status.installURL}'
```

Open the link, choose the repositories to share and install the App. GitHub returns you to Nodus, which checks that you can see the installation, and the Connection becomes `Ready` with `status.github` naming the account and repositories. `GET …/connections/github/repositories?limit=100` pages through all of them.

A Sandbox’s `init.git` can then clone a private repository: Nodus resolves the branch or tag to a commit when you create the Sandbox and clones that commit. The clone uses a short-lived token that can only read that one repository, and the token never appears in the Sandbox’s environment or files. If someone uninstalls the App, the Connection shows `Failed` with `InstallationRemoved` and a fresh `status.installURL` to install it again.

A Volume can import from a bucket (`source.s3`) or a query (`source.connectionQuery`); see [Volumes](https://nodus-platform-site.pages.dev/docs/guides/volumes/#import-from-elsewhere). A Job or Sandbox reaches only the hosts its Connections were verified against.
