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

# Update an executor's API key

> Apply a new or rotated exc_ key to an Agent or Operator executor — including one that was offline when its key was rotated

An executor authenticates with the `exc_` API key stored in its **own** config. When you [rotate or replace](/docs/executors/api-keys#rotate) that key in the UI, the old key is revoked immediately — but the executor keeps presenting whatever key is still in its config. This recipe shows where the key lives and how to swap it in, for both backends.

<Warning>
  If the executor was **offline** when you rotated its key, it can't recover on its own: it still holds the old key, which no longer exists, so it fails to authenticate the moment it comes back. Apply the new key with the steps below and it reconnects on the next sync.
</Warning>

## Before you start

* The **new `exc_` key** — shown only once, when you created or rotated it. If you don't have it, [rotate again](/docs/executors/api-keys#rotate) to mint a fresh one.
* **Owner** or **admin** to rotate the key; shell access to the **host** (Agent) or **cluster** (Operator) to apply it.

<Tabs>
  <Tab title="Agent (bare-metal)">
    The Agent reads its key from `[hub] token` in `/etc/nvcl/agent.toml`, once at startup. Update the file and restart the service.

    <Steps>
      <Step title="Write the new key">
        Edit `/etc/nvcl/agent.toml` as `root` and replace the `[hub] token` value:

        ```toml theme={null}
        [hub]
        url = "https://hub.novacula.io"
        token = "exc_…new-key…"
        name = "my-host"
        ```

        Or in place, without opening an editor:

        ```bash theme={null}
        sudo sed -i 's|^token = .*|token = "exc_…new-key…"|' /etc/nvcl/agent.toml
        ```

        Keep the file mode `0600` and owned by `root` — the token is the credential.
      </Step>

      <Step title="Restart the agent">
        ```bash theme={null}
        sudo systemctl restart nvcl-agent.service
        ```

        The config is read once at startup, so the restart is what picks up the new key. Running nodes are unaffected — their `nvcl-node-*` units keep running.
      </Step>

      <Step title="Confirm it reconnected">
        ```bash theme={null}
        journalctl -u nvcl-agent.service -n 100 -f
        ```

        The **Executors** row flips back to `online` within a few seconds. Auth errors here mean the key is wrong or has trailing whitespace.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Operator (Kubernetes)">
    The Operator reads its key from `[hub] token` in `operator.toml`, which Helm renders into the `nvcl-operator-config` Secret and mounts read-only into the pod. Re-run Helm with the new token — the pod rolls itself.

    <Steps>
      <Step title="Upgrade the release with the new token">
        ```bash theme={null}
        helm upgrade nvcl-operator oci://ghcr.io/rsquad/nvcl/charts/nvcl-operator \
          --namespace nvcl-system \
          --reuse-values \
          --set-string hub.token="exc_…new-key…" \
          --server-side=false \
          --atomic
        ```

        This is the command the UI renders on the executor's **Access** tab — copy it from there and the token is filled in for you.

        `--reuse-values` keeps the rest of your install (Hub URL, name, versions) and changes only the token. `--server-side=false` forces client-side apply, so the upgrade touches only the credential and doesn't reassert fields the Operator manages for itself — notably the image its self-update selected. `--atomic` rolls the release back if the new pod fails to come up, so a bad token can't leave you with a broken deployment.

        The chart stamps the pod template with a `checksum/config` annotation, so changing the token restarts the pod automatically — no separate restart needed.
      </Step>

      <Step title="Confirm it reconnected">
        ```bash theme={null}
        kubectl -n nvcl-system rollout status deploy/nvcl-operator
        kubectl -n nvcl-system logs deploy/nvcl-operator -f
        ```

        The **Executors** row flips back to `online` within seconds.
      </Step>
    </Steps>

    <Note>
      If you pinned `image.tag` at install and the Operator later self-updated, `helm upgrade --reuse-values` re-applies that pinned tag and can revert the image. To avoid it, pass the current `--set image.tag=…` (and `gateway.tag`) as well, or manage the image only through Helm — see the [Kubernetes recipe hardening note](/recipes/provision-on-kubernetes#hardening).
    </Note>
  </Tab>
</Tabs>

## Verify

In **Executors**, the row returns to `online`. On the **API keys** page, the new key's **Last used** updates from `never` to just now, confirming the executor presented it.

## Related

* [API keys](/docs/executors/api-keys) — rotate, revoke, and manage the keys themselves.
* [Provision on bare-metal](/recipes/provision-on-bare-metal) · [Provision on Kubernetes](/recipes/provision-on-kubernetes)
* [Connect an executor](/docs/executors/connect-an-executor)
