# Run an automation with a key file

> Issue a private key, store its key file as a CI secret, and run a job that creates a computer, runs a command and deletes it

> Nevia is in beta and open to selected teams. Public launch in Dec 2026. The CLI installs with `curl -fsSL https://get.nevia.cloud | sh`, and the MCP server is at https://api.nevia.cloud/mcp. A person signs in once in the browser.
> Setup, sign-in and requesting access: [SKILL.md](https://nevia.cloud/SKILL.md). When Nevia fits and when it doesn't: [why.md](https://nevia.cloud/why.md).

> For the complete documentation index, see [llms.txt](https://nevia.cloud/llms.txt). This page's HTML version: https://nevia.cloud/docs/guides/automation-key-file

Run Nevia from a CI job with no person signing in. The job acts as a principal
with its own key file. It creates a computer, runs a command on it and deletes
the computer, even when a step fails.

## Prerequisites

* A workspace admin with the [CLI installed and signed in](https://nevia.cloud/docs/get-started/quickstart.md), to issue the key.
* A CI system that stores secrets. This guide uses GitHub Actions.
* A pinned CLI version, the same on your laptop and in CI. This guide pins `0.1.6`.

The principal has the `editor` role. It can create and delete computers and never
gets `admin`. See [Workspace permissions](https://nevia.cloud/docs/reference/workspace-permissions.md).

## 1. Issue the key

An admin runs this on a local machine:

```bash
nevia access add --private-key --description "ci"
```

The CLI saves the key file to `~/.config/nevia/keys/<key>.json`, readable only by
you. Nevia keeps no copy. Print the file and copy its full contents:

```bash
cat ~/.config/nevia/keys/<key>.json
```

Then delete the local copy. If you lose the key, issue a new one. For the other
`--out` options and `--role viewer`, see
[Give a script or agent access](https://nevia.cloud/docs/workspaces/private-key-auth.md).

## 2. Store the key file as a CI secret

Save the full JSON in your CI secret store. In GitHub, create a repository
secret named `NEVIA_KEY`. Don't commit the file or put it in a variable.

## 3. Run the job

The job installs the CLI, writes the key file to a temporary path with
`chmod 600`, and runs the steps. The delete step has `if: always()`, so a failed
command still removes the computer.

```yaml
name: nevia-automation

on:
  workflow_dispatch:

jobs:
  nevia:
    runs-on: ubuntu-latest
    steps:
      - name: Install nevia
        env:
          NEVIA_VERSION: "0.1.6"
        run: |
          curl -fsSL https://get.nevia.cloud | NEVIA_VERSION="$NEVIA_VERSION" NEVIA_INSTALL_DIR="$RUNNER_TEMP/bin" sh
          echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"

      - name: Write key file
        env:
          NEVIA_KEY: ${{ secrets.NEVIA_KEY }}
        run: |
          key_file="$RUNNER_TEMP/nevia-key.json"
          printf '%s' "$NEVIA_KEY" > "$key_file"
          chmod 600 "$key_file"
          echo "NEVIA_KEY_FILE=$key_file" >> "$GITHUB_ENV"

      - name: Check identity
        run: nevia whoami

      - name: Create computer
        id: create
        run: nevia new ci-${{ github.run_id }} --wait

      - name: Run command
        run: nevia exec ci-${{ github.run_id }} -- sh -c 'echo ok'

      - name: Delete computer
        if: ${{ always() && steps.create.outcome != 'skipped' }}
        run: nevia rm ci-${{ github.run_id }} --yes --wait
```

On another CI system, keep the same steps: a pinned install, the secret written
to a `chmod 600` file, `NEVIA_KEY_FILE` set, and the delete in an always-run
step.

## 4. Verify

`nevia whoami` shows `(private key)` and the one workspace. If it shows your
login, `NEVIA_KEY_FILE` didn't reach the step.

The CLI doesn't check for updates in CI, so the pinned version stays put.

## 5. Rotate the key

Keys expire 90 days after creation by default. Rotate before that date or the
job can't sign in.

An admin runs:

```bash
nevia access keys rotate <principal>
```

`keys rotate` revokes the old key in the same step, so update the `NEVIA_KEY`
secret before the next run or the job fails. Pass `--expires-in` for a shorter
lifetime. `nevia access ls` shows each principal's key state. To cut off access
with no replacement, run `nevia access keys rm <principal>`.

## Related

* [Give a script or agent access](https://nevia.cloud/docs/workspaces/private-key-auth.md): add, use, rotate and bring your own key.
* [`nevia auth use-key-file`](https://nevia.cloud/docs/reference/cli/auth/use-key-file.md): remember a key file path in a project.
* [Workspace permissions](https://nevia.cloud/docs/reference/workspace-permissions.md): what the `editor` role can do.
