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

# Aspect Enterprise local setup

> Connect your machine to an Aspect Enterprise deployment: record it with aspect auth configure, log in, then build with aspect --remote or point vanilla bazel at its cache, build events and remote execution.

export const gatedAccess = (user, group) => {
  const loggedIn = !!(user && user.loggedIn);
  const groups = user && user.tenantMetadata && user.tenantMetadata.docsGroups || [];
  if (loggedIn && (!group || groups.indexOf(group) >= 0)) {
    return "entitled";
  }
  return loggedIn ? "signed-in" : "anonymous";
};

export const GatedLink = ({access, href, group, children}) => {
  const note = group ? "Aspect Enterprise customers" : "free Aspect account";
  const muted = {
    fontSize: "0.85em",
    opacity: 0.7,
    whiteSpace: "nowrap"
  };
  if (access === "entitled") {
    return <a href={href}>{children}</a>;
  }
  if (access !== "signed-in") {
    return <span>
        <a href={"/login?redirect=" + encodeURIComponent(href)}>{children}</a>
        <span style={muted}> (sign in: {note})</span>
      </span>;
  }
  return <span>
      {children}
      <span style={muted}> ({note})</span>
    </span>;
};

<Info>
  For Aspect Enterprise deployments with [external endpoints](#the-external-endpoint) enabled.
</Info>

An Aspect Enterprise deployment has its own hostnames and its own sign-in, so your machine has to be told about it once. After that, builds reach its remote cache, build event service and, if the deployment runs one, its remote executor.

## The external endpoint

A deployment's CI runners reach its cache and remote execution privately, inside the deployment's network. Developer machines, and CI you run outside that network, reach them through a second, **external** endpoint over the internet, authenticated by the deployment's sign-in. It's `remote.<your-domain>` by default, and it's turned on in the deployment's configuration, hosted by Aspect or self-hosted.

It runs in one of two modes:

* **Separate**: its own cache and remote executor fleet, sized and scaled separately from CI's, which keeps developer traffic away from CI's.
* **Shared with CI**: CI's cache and remote executor fleet.

{user.loggedIn && user.tenantMetadata?.docsGroups?.includes('workflows-subscriber') ? (
<Info>
See also:
<ul>
<li><a href="/docs/aspect-workflows/enterprise/self-hosted/configuration/remote-cache">Remote cache configuration</a></li>
<li><a href="/docs/aspect-workflows/enterprise/self-hosted/configuration/remote-execution">Remote execution configuration</a></li>
<li><a href="/docs/aspect-workflows/enterprise/self-hosted/configuration/external-cache-exec">External remote cache and execution configuration</a></li>
</ul>
</Info>
) : !user.loggedIn ? (
<Info>
The Terraform and infrastructure reference for self-hosted deployments is available to customers. <a href="/login?redirect=%2Fdocs%2Faspect-workflows%2Fenterprise%2Fconnect%2Flocal-setup">Log in</a> to read it, or ask an admin in your organization to invite you in <a href="https://app.aspect.build/settings/org/users">Aspect settings</a>.
<br /><br />
<a href="/contact">Talk to us</a> about a <a href="/trial">30-day trial of Aspect Enterprise</a>.
</Info>
) : (
<Info>
The Terraform and infrastructure reference for self-hosted deployments is available to customers. If your organization is one, contact Aspect support for access.
<br /><br />
Not a customer yet? <a href="/contact">Talk to us</a> about a <a href="/trial">30-day trial of Aspect Enterprise</a>.
</Info>
)}

## Before you start

* **The Aspect CLI, v2026.39.10 or newer.** [Install it](/docs/cli/install), then pin the version for everyone in `.aspect/version.axl`:

  ```python title=".aspect/version.axl" theme={null}
  version("2026.39.10")
  ```

* **Your deployment's host**, something like `remote.acme.aspect.build`. Your Aspect contact gives you this, or it's an output of your Terraform.

* **Workflows 6.0 or later.** 5.17 and 5.18 authenticate through a standalone credential helper instead; see <GatedLink access={gatedAccess(user, "workflows-subscriber")} href="/docs/aspect-workflows/enterprise/legacy/credential-helper-5-17-18" group="workflows-subscriber">Credential helper (5.17 and 5.18)</GatedLink>, and the <GatedLink access={gatedAccess(user, "workflows-subscriber")} href="/docs/aspect-workflows/enterprise/release-notes/6_0_upgrade" group="workflows-subscriber">6.0 upgrade guide</GatedLink> when you're ready to move.

## 1. Record the deployment

```shell theme={null}
aspect auth configure remote.acme.aspect.build
```

The CLI fetches the host's `/.well-known/oauth-protected-resource` document ([RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) discovery). That document names the deployment's sign-in and the endpoints it serves: cache, build events, remote execution and the Build Results UI. The CLI records them in `~/.aspect/config.json`, then runs the login.

The argument can be a bare host or any URL the deployment serves; scheme, port and path are stripped. `remote` is only the default DNS label, so if your deployment uses a different one, use that.

| Flag               | What it does                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------- |
| `--name <name>`    | Name the deployment. Defaults to the name it advertises, or one derived from the host       |
| `--default`        | Make it what `--remote` targets                                                             |
| `--issuer <url>`   | Pick the sign-in, for a deployment advertising more than one. Required when non-interactive |
| `--login=false`    | Record the deployment without logging in                                                    |
| `--no-browser`     | Print the sign-in URL instead of opening a browser                                          |
| `--profile <name>` | File the login under this profile instead of `default`; see [profiles](#your-credential)    |

**If configure can't connect**, fetch the document yourself:

```shell theme={null}
curl https://remote.acme.aspect.build/.well-known/oauth-protected-resource
```

If that fails too, the problem is reachability (DNS, VPN or a firewall), not the CLI. Your machine needs a route to the deployment's external endpoint, or to its private one from inside its network.

**The deployment's name** is what `--deployment`, `aspect auth use` and the `--config` sections use. Without `--name`, it's the name the deployment advertises or, failing that, the host minus its first label, with Aspect's own domain dropped:

| Host                       | Name               |
| -------------------------- | ------------------ |
| `remote.acme.aspect.build` | `acme`             |
| `remote.acme.example.com`  | `acme.example.com` |

This page uses `acme`. Substitute the name `aspect auth status` shows, or pass `--name acme` to choose it.

## 2. Log in

`configure` runs the login for you. To log in again later:

```shell theme={null}
aspect auth login --deployment acme
```

**Over SSH**, the CLI detects the remote session and prints the sign-in URL instead of opening a browser. Open it anywhere, sign in, and paste back either the callback URL from the address bar or the authorization code. `--no-browser` forces this flow.

If your account belongs to more than one organization, you're prompted to pick one. Pass `--org <name|id>` to choose without a prompt.

## 3. Make it the default

Configuring a deployment doesn't make it the one `--remote` targets. Until you say otherwise, that's Aspect Cloud:

```shell theme={null}
aspect auth use acme
```

`aspect auth use aspect-cloud` hands the default back.

## 4. Build with `--remote`

```shell theme={null}
aspect build //... --remote
aspect test //... --remote=exec
```

`--remote` connects the task to the deployment's remote cache and build event service. Off CI, a task builds locally unless you ask.

### What the flag accepts

`--remote` takes a comma-separated list. The cache and build events are on unless you subtract them with a `no-` token; remote execution is off unless you name `exec`.

| Form                   | Uses                                                                         |
| ---------------------- | ---------------------------------------------------------------------------- |
| `--remote`             | Cache and build events                                                       |
| `--remote=cache`       | Cache and build events, the same as bare `--remote`                          |
| `--remote=no-bes`      | Cache only, without streaming the build to the Build Results UI              |
| `--remote=no-cache`    | Build events only                                                            |
| `--remote=exec`        | Cache, build events and remote execution                                     |
| `--remote=exec,no-bes` | Cache and remote execution                                                   |
| `--remote=no-exec`     | Cache and build events; cancels an `exec` set in `config.axl`                |
| `--remote=none`        | Nothing                                                                      |
| `--remote=auto`        | The default when the flag is left off: bare `--remote` on CI, nothing off it |

Remote execution is never implied. It changes where your actions run, which means every action needs a toolchain available on a remote worker and an exec platform matching a worker pool; see [Targeting remote execution worker pools](/docs/aspect-workflows/platform/guides/remote-execution-worker-pools). Naming a capability the deployment doesn't serve is an error, and `aspect auth status` lists what each deployment serves.

**More than one deployment**, such as staging and production? `--deployment` picks which one for a single build, without changing the default:

```shell theme={null}
aspect build //... --remote --deployment staging
```

`--deployment` without `--remote` is an error on a build or test: it names a deployment without saying what to use it for.

To stop typing the flag, set it once for the repository:

```python title=".aspect/config.axl" theme={null}
load("@aspect//feature/deployment.axl", "Deployment")

def config(ctx: ConfigContext):
    ctx.features[Deployment].args.remote = "exec"
```

`--remote=none` opts a single build out, and `--remote=no-exec` keeps the cache and build events while running that one build's actions locally.

## 5. Or use vanilla `bazel`

`--remote` is an Aspect CLI flag, so a `bazel build` from the same shell doesn't know about it. [`aspect setup bazelrc`](/docs/cli/tasks/setup_bazelrc) writes the equivalent flags where Bazel finds them.

```shell theme={null}
aspect setup bazelrc
```

On your machine this writes the **repository rc**: `.aspect/bazelrc` in the checkout, plus a `try-import` at the top of the repository's `.bazelrc`. Commit both. The file gives every configured deployment a section of its own and turns nothing on, so it's safe for everyone who builds the repository. Opt a build in by name:

```shell theme={null}
bazel build //... --config=aspect-acme        # cache and build events
bazel build //... --config=aspect-acme-exec   # ... and remote execution
```

To turn the cache on for every `bazel` call on your machine instead, write the **machine rc**, which is never committed:

```shell theme={null}
aspect setup bazelrc --home --remote
```

Either way, Bazel authenticates through `aspect` as a [credential helper](https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md), serving your login. `aspect` has to be on `PATH` wherever `bazel` runs.

## Check it worked

```shell theme={null}
# Is the deployment recorded, is it the default, and are you logged in?
aspect auth status

# Is Bazel picking the flags up? --announce_rc names the --config group each flag came from.
bazel build //... --config=aspect-acme --announce_rc
```

To see the cache work, clear your local outputs and build again, so nothing can come from your own machine:

```shell theme={null}
aspect build //... --remote
bazel clean
aspect build //... --remote    # almost entirely "remote cache hit"
```

Or let CI build a commit first, then build the same commit locally. Open either invocation in the [Build Results UI](/docs/aspect-workflows/platform/features/webui); its cache chart gives you the hit rate. Hits show only when CI and your machine share cache storage: CI on runners you manage does when it points at the same external endpoint, and Workflows runners do only where the external cache [shares CI's storage](#the-external-endpoint).

If the rebuild still misses, the cache is reachable but something in the build isn't deterministic. [`aspect cache diff`](/docs/cli/tasks/cache_diff) names the actions that missed.

## If the deployment uses your own identity provider

Every deployment signs in through Aspect sign-in or through your own identity provider. For a developer at a terminal it makes no difference: the browser flow works the same, and `--no-browser` covers SSH and containers.

It matters for two things:

* **CI**: there's no Aspect API token, so CI brings its own credential helper. See [CI setup](/docs/aspect-workflows/enterprise/connect/ci-setup).
* **Registering redirect URIs**, which your identity provider admin does once. On Aspect sign-in, Aspect registers them for you. Getting one wrong produces `redirect_uri_mismatch` at login.

| Login                | AWS                                       | GCP                                       |
| -------------------- | ----------------------------------------- | ----------------------------------------- |
| **Build Results UI** | `https://app.<domain>/oauth2/idpresponse` | `https://app.<domain>/oauth2/callback`    |
| **Aspect CLI**       | `https://remote.<domain>/oauth2/callback` | `https://remote.<domain>/oauth2/callback` |

`app` and `remote` are the default DNS labels. If yours differ, use the hostnames your deployment serves; `aspect auth status` prints them.

**If logins stop renewing** on your own identity provider, look at the scopes the deployment advertises. The CLI sends that set verbatim and adds nothing; it never adds `offline_access`, because some providers reject scopes they don't expect.

## Your credential

**It renews itself.** A browser login also obtains a refresh token, so you log in again only when that expires.

**It's separate per deployment.** Each deployment has its own sign-in, so a credential for one isn't accepted by any other, or by Aspect Cloud. With Aspect sign-in you're still the same Aspect account everywhere.

**It lives in your OS keyring**: the macOS Keychain, or the Linux kernel keyring. Where no keyring is reachable, the CLI falls back to a `0600` file at `~/.aspect/credentials.json`. Set `ASPECT_CREDENTIALS_FILE` to store it in a file at that path instead.

**Profiles keep identities apart.** One profile holds one credential per deployment, so switching profiles switches them all:

```shell theme={null}
aspect auth login --profile work
export ASPECT_AUTH_PROFILE=work    # for this shell; vanilla bazel follows it too
```

**Log out and forget:**

```shell theme={null}
aspect auth logout --deployment acme   # clear the credential, keep the deployment
aspect auth logout --all               # every credential, every profile
aspect auth remove acme                # forget the deployment entirely
```

Logging out of the default deployment also clears the default.

## Next

* [CI setup](/docs/aspect-workflows/enterprise/connect/ci-setup): point CI at the deployment, on Workflows runners or runners you manage.
* [Targeting remote execution worker pools](/docs/aspect-workflows/platform/guides/remote-execution-worker-pools): route actions to the right remote execution worker pool.
* [Build metadata](/docs/cli/tasks/setup_workspace_data): label vanilla `bazel` builds with their commit and branch in the Build Results UI.
