---
title: "Service accounts for Flutter CI/CD with Shorebird"
description: "Stop running Shorebird releases on personal API keys. Service accounts give CI its own role and keys, and GitHub Actions can sign in with OIDC and no stored secret."
url: https://shorebird.dev/blog/service-accounts-for-ci/
---

# Your CI shouldn't run on someone's personal key

![Abhishek Doshi](/_astro/abhishek-doshi.DveI0bx__17rggU.webp)

Abhishek DoshiDeveloper Relations Engineer

October 29, 2026

5 min read

A developer sets up your release pipeline. They create an API key, paste it into CI as `SHOREBIRD_TOKEN`, and everything works for months. Then they leave the company. Their account is removed, and the next release fails. Nobody knows which key it was, who can create a new one, or what else depended on it.

The pipeline wasn’t broken. It was borrowing a person’s identity, and that person left.

Your release pipeline is infrastructure. It shouldn’t depend on any one person’s account. That’s why Shorebird now has **service accounts**: credentials that belong to your organization, not to a person.

## Why personal keys are the wrong fit for CI

Until now, every Shorebird API key belonged to a person. That works for your own scripts. It’s the wrong fit for anything your team depends on.

A personal key breaks when people move on: delete the account and the key stops working. It can do at most what its owner can do, so your pipeline’s access changes whenever that person’s role does, not with what the pipeline needs. It lives on its owner’s account, not in your organization’s settings, so your team can’t easily tell which credentials are acting on your apps. And when CI ships a patch with your key, it looks like you shipped it.

This credential matters. The `SHOREBIRD_TOKEN` in your CI can ship a patch to every device running your app. It deserves its own identity.

## Service accounts: an identity for your automation

A service account is an account that belongs to your organization. In the [Shorebird Console](https://console.shorebird.dev), open your organization’s **Settings**, select **Service accounts**, click New service account, and name it something like “GitHub Actions”. Then pick a role and give it a way to sign in.

The account and its keys belong to the organization, not to whoever set them up, so they keep working as your team changes. Each service account has one role, so you can give your pipeline what it needs and nothing more:

| Role                | What it can do                                                                                                                                       |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Viewer              | Read-only, for dashboards and reporting.                                                                                                             |
| Developer (default) | Creates releases and patches, and promotes and rolls back patches. The right role for most pipelines.                                                |
| App Manager         | Everything Developer can do, plus creating, updating and deleting apps, for automation that runs `shorebird init`.                                   |
| Auditor             | Reads the audit log and nothing else, so you can export it to your SIEM without handing out an Admin’s key. The audit log is on the Enterprise plan. |

A service account can never be an Admin or Owner, so a leaked key can’t add members, change billing, or touch the organization itself. Admins and Owners can see, create and revoke every service account and key, and a revoked key stops working on its next request. In the audit log, a service account’s actions appear under its name followed by “\[bot]”, such as “GitHub Actions\[bot]”, along with the key it used.

Service accounts and their keys are available on every plan, including the free plan.

## Use one in any CI

A service account key works the same way as the API key you use today. Set it as `SHOREBIRD_TOKEN`, and nothing else in your pipeline changes:

```
export SHOREBIRD_TOKEN="<service account key>"
shorebird patch android
```

Keys expire after 1 year by default. You can also choose 30 days, 90 days or never. To rotate a key without downtime, create a second key, update your CI secret, then revoke the old key. Every key acts as the same account, so your history stays in one place.

This works with any CI provider, including [GitHub Actions](https://docs.shorebird.dev/code-push/ci/github/), [Codemagic](https://docs.shorebird.dev/code-push/ci/codemagic/), [Fastlane](https://docs.shorebird.dev/code-push/ci/fastlane/) and [other CI systems](https://docs.shorebird.dev/code-push/ci/generic/).

## On GitHub Actions, drop the stored key

The safest secret is one you never store. If you release from GitHub Actions, a service account can sign in with no `SHOREBIRD_TOKEN` at all.

Add a **trust rule** to the service account. It names your repository and workflow file, and optionally a GitHub environment and a branch or tag pattern. When a matching job runs, the Shorebird CLI exchanges the short-lived OIDC token GitHub issues to that job for a Shorebird token that lasts 15 minutes, and renews it during long builds. Jobs from any other repository or workflow are refused.

Your workflow needs two additions: permission to request the OIDC token, and your project’s ID. If your trust rule names a GitHub environment, the job also runs in that environment.

```
jobs:
  release:
    runs-on: ubuntu-latest
    environment: production # Only if your trust rule names an environment
    permissions:
      contents: read
      id-token: write
    env:
      SHOREBIRD_PROJECT_ID: '123' # From the console. Not a secret.
    steps:
      - uses: actions/checkout@v7
      - uses: shorebirdtech/setup-shorebird@v1
        with:
          cache: true
      - run: shorebird release android
```

There’s nothing to leak and nothing to rotate. For an extra safeguard, name a GitHub environment with required reviewers in the trust rule, so a release can’t run until someone approves it. On the Enterprise plan, every sign-in is recorded in the audit log with the workflow run it came from.

Trust rules need Shorebird v1.6.129 or newer and are available on the Business and Enterprise plans. The full setup is in the [GitHub Actions guide](https://docs.shorebird.dev/code-push/ci/github/#sign-in-with-oidc-instead-of-a-stored-key).

## What changes for personal API keys

Personal keys stay. They’re still the right choice for your own scripts and local tools. New personal keys expire within a year, and your existing keys keep working. For anything long-lived, use a service account: if your team depends on it, it shouldn’t depend on one person’s account.

## We moved our own CI first

Before launching this, we moved our own pipelines over. Shorebird’s end-to-end tests and the tests for our GitHub Actions sign in from GitHub Actions as a service account, with a trust rule and no stored key. Every team should run their release pipeline this way.

## Get started

Create a service account for your pipeline with the narrowest role that does the job, which for most pipelines is Developer. Set its key as `SHOREBIRD_TOKEN`, or on GitHub Actions add a trust rule and skip the key. Once your pipeline runs on the service account, revoke the personal key it used before. The [service accounts](https://docs.shorebird.dev/account/service-accounts/) and [trust rules](https://docs.shorebird.dev/account/trust-rules/) docs have the full setup.

Have questions, or want help moving your pipeline over? Find us on [Discord](https://discord.gg/shorebird).

## Start shipping fast, today!

Integrate with your current codebase in less than 5 minutes.

[Try for Free](https://console.shorebird.dev/login)[Learn more](https://docs.shorebird.dev/getting-started/)
