diff --git a/concepts/floxhub.mdx b/concepts/floxhub.mdx index b6543fb..ccb617c 100644 --- a/concepts/floxhub.mdx +++ b/concepts/floxhub.mdx @@ -26,6 +26,11 @@ You can return to FloxHub to view your environments any time at You can authenticate with FloxHub from the Flox CLI. Run [`flox auth login`](/man/flox-auth) and follow the on-screen instructions. +Where a browser isn't available, such as over SSH or inside a container, +use a [personal access token](/concepts/personal-access-tokens) instead. +For CI pipelines and other automation, +use a [service account](/concepts/service-accounts). + ## Working with Environments in FloxHub ### Environment page diff --git a/concepts/organizations.mdx b/concepts/organizations.mdx index 5b5fa07..aba59f0 100644 --- a/concepts/organizations.mdx +++ b/concepts/organizations.mdx @@ -30,6 +30,12 @@ Organizations in FloxHub use role-based access control (RBAC) to assign permissi The organization must have at least one owner, but may have multiple. Owners can manage the organization, including adding or removing members and changing roles. Owners may not modify their own role or remove themselves from the organization. +## Service Accounts + +A [service account](/concepts/service-accounts) is an identity your automation signs in with, such as a release pipeline or a nightly test run. It belongs to the organization rather than to the person who created it, has read-only or read and write access across the organization, and authenticates with its own tokens. + +Only owners can create service accounts and issue their tokens. See [Service accounts](/concepts/service-accounts) for how to set one up and how to rotate its tokens. + ## Machine Access Tokens In addition to _user-level_ access based on FloxHub accounts, FloxHub supports _programmatic_ access via `Auth0`-issued machine tokens, using the client credentials grant. These tokens are not tied to users—they authenticate as the organization itself and are intended for CI/CD or other non-interactive use cases. diff --git a/concepts/personal-access-tokens.mdx b/concepts/personal-access-tokens.mdx new file mode 100644 index 0000000..6187beb --- /dev/null +++ b/concepts/personal-access-tokens.mdx @@ -0,0 +1,78 @@ +--- +title: "Personal access tokens" +description: "Authenticate the Flox CLI as yourself without an interactive browser login." +--- + +A **personal access token** signs the Flox CLI in as you, carrying the same +access your FloxHub account has. Use one wherever the usual +[`flox auth login`](/man/flox-auth) browser flow cannot run: over SSH, inside a +container, or on any machine without a browser. Personal access tokens begin +with `flox_pat_` and are available on every plan. + + + Personal access tokens require **Flox CLI 1.14.0 or newer**. Earlier releases + do not recognize the token format. + + A personal access token acts as you. For automation that should belong to a + team rather than to a person, use a + [service account](/concepts/service-accounts) instead. + + +## Creating a token + +Personal access tokens are created in FloxHub, and only there. + +1. Sign in to [FloxHub](https://hub.flox.dev) +2. Open your **profile** page +3. Under **Personal access tokens**, select **Generate new token** +4. Give the token a name and choose how long it should last: **30 days** (the + default), **90 days**, **1 year**, or **No expiration** +5. Copy the token + +The name is a label to help you recognize the token later, usually the machine +or the task it is for. It has no effect on what the token can do, since every +token you create carries your full account access. + + + The token is shown once and cannot be retrieved afterwards. Copy it into a + password manager or secret store before closing the dialog. + + +## Using a token + +Write the token to a file and pass that file to +[`flox auth login`](/man/flox-auth): + +```bash +flox auth login --token-file ./token +``` + +Pass `-` in place of the path to read the token from stdin. Either way the +token is validated and stored, with no browser or prompt involved. + +You can also set the token in the `FLOX_FLOXHUB_TOKEN` environment variable, +which the Flox CLI reads without a login step: + +```bash +export FLOX_FLOXHUB_TOKEN="flox_pat_..." +flox activate -r my-org/my-env +``` + +Once authenticated, the CLI behaves exactly as it does after an interactive +login, and the token can reach anything you can. + +## Viewing and revoking tokens + +Your profile page lists every token you have created, showing when each one was +created, when it expires, and when it was last used. **Last used** is how you +tell whether a token is still in service before you retire it. + +When a token is no longer needed, revoke it from that same page: + +1. Find the token under **Personal access tokens** +2. Select the delete icon next to it +3. Confirm + +Revocation takes effect on the next request, so a job still running on that +token fails at its next call to FloxHub rather than finishing on access it no +longer has. Your other tokens and your interactive CLI sessions are unaffected. diff --git a/concepts/service-accounts.mdx b/concepts/service-accounts.mdx new file mode 100644 index 0000000..2444965 --- /dev/null +++ b/concepts/service-accounts.mdx @@ -0,0 +1,135 @@ +--- +title: "Service accounts" +description: "Give CI and other automation an identity that belongs to your organization rather than to a person." +--- + +A **service account** is an identity your automation signs in with, such as a +nightly test run or a release pipeline that publishes packages. It belongs to +your [organization](/concepts/organizations) rather than to the person who set +it up, and it authenticates with its own tokens, which begin with `flox_sat_`. + +Without one, a pipeline has to sign in as a person. Its access is that person's +access, it stops working when they leave the organization, and revoking its +credential also cuts off that person's own CLI sessions. + + + Service accounts require **Flox CLI 1.14.0 or newer**. Earlier releases do + not recognize the token format. + + They also require an organization. Personal FloxHub accounts cannot have + service accounts, so to authenticate the CLI as yourself, use a + [personal access token](/concepts/personal-access-tokens) instead. + + +## Access levels + +Every service account is created with one of two access levels, which apply +across the whole organization: + +| Access level | What it can do | +| --- | --- | +| **Read-only** | Pull the organization's environments and packages | +| **Read & write** | Also push environments and publish packages | + +The access level belongs to the service account rather than to any one of its +tokens, so every token issued to it has the same access, and that access cannot +be narrowed to a subset of environments or packages. + +A service account is never an organization owner, so it cannot manage members, +change organization settings, or create more service accounts. Creating a +service account and issuing its tokens both require a signed-in owner, which +means a leaked token cannot be used to create more credentials. + +## Creating a service account + +Service accounts are created in FloxHub, and only by organization owners. + +1. Sign in to [FloxHub](https://hub.flox.dev) +2. Open your organization's page +3. Go to the **Service accounts** tab +4. Select **Create service** +5. Give it a name and choose its access level + +Name the account after the job it does, such as `release-runner` or +`nightly-tests`. The name is how you recognize the account later and has no +effect on its access. + +## Issuing a token + +A service account has no credential until you issue one. From the +**Service accounts** tab: + +1. Select **Issue token** on the service account +2. Choose how long it should last: **30 days** (the default), **90 days**, + **1 year**, or **No expiration** +3. Copy the token + + + The token is shown once and cannot be retrieved afterwards. Copy it into your + CI platform's secret store before closing the dialog. + + +Service account tokens have no names of their own, since the service account is +what identifies them. FloxHub lists each one by when it was created, when it +expires, and when it was last used. + +## Using a token in CI + +Set the token in the `FLOX_FLOXHUB_TOKEN` environment variable, which the Flox +CLI reads without a separate login step. This example is a GitHub Actions +workflow that reads the token from a repository secret: + +```yaml title=".github/workflows/ci.yml" +jobs: + test: + runs-on: ubuntu-latest + env: + FLOX_FLOXHUB_TOKEN: ${{ secrets.FLOX_SERVICE_TOKEN }} + steps: + - uses: actions/checkout@v4 + - uses: flox/install-flox-action@v2 + - uses: flox/activate-action@v1 + with: + environment: my-org/my-env + command: make test +``` + +The same variable works on every platform. See +[Running Flox in CI/CD](/tutorials/ci-cd) for the equivalent setup on CircleCI +and GitLab. + +You can also write the token to a file and pass it to +[`flox auth login`](/man/flox-auth): + +```bash +flox auth login --token-file ./token +``` + +## Revoking a token + +When a token is no longer needed, revoke it from the **Service accounts** tab: + +1. Find the token under the service account it belongs to +2. Select the delete icon next to it +3. Confirm + +Revocation takes effect on the next request, so a job still running on that +token fails at its next call to FloxHub rather than finishing on access it no +longer has. Revoking one token leaves the service account and its other tokens +working. + +Deleting the service account goes further: it revokes the account's access to +the organization and every token issued to it. + +## Rotating without downtime + +A service account can have several live tokens at once, so you can replace one +without leaving a gap: + +1. Issue a second token for the service account +2. Deploy it to your CI platform in place of the old one +3. Watch the old token's **Last used** date until it stops moving +4. Revoke the old token + +This way the pipeline is never left with a token that has been revoked, so +rotation needs no maintenance window. diff --git a/docs.json b/docs.json index c974d12..9cef91c 100644 --- a/docs.json +++ b/docs.json @@ -125,6 +125,8 @@ "concepts/services", "concepts/composition", "concepts/organizations", + "concepts/service-accounts", + "concepts/personal-access-tokens", "concepts/builds", "concepts/manifest-builds", "concepts/nix-expression-builds", diff --git a/man/flox-auth.mdx b/man/flox-auth.mdx index e9497c4..6847365 100644 --- a/man/flox-auth.mdx +++ b/man/flox-auth.mdx @@ -32,9 +32,12 @@ interactively it can open the browser for you if you press ``. With `--token-file ` the login is non-interactive: the FloxHub token is read from `` instead (pass `-` to read the token from -stdin). The token is validated and stored, and no browser, prompt, or -network access is involved. Use this in CI, containers, and other -scripted setups. +stdin). The file can contain a JWT access token, a personal access +token, or a service account token. Token-file login does not open a +browser or prompt for input. A JWT access token is validated locally. +FloxHub must be reachable to validate personal access tokens and service +account tokens. The validated token is stored. Use this in CI, +containers, and other scripted setups. See also: [`flox-push`](/man/flox-push), [`flox-pull`](/man/flox-pull), diff --git a/tutorials/ci-cd.mdx b/tutorials/ci-cd.mdx index ae240db..c0046cc 100644 --- a/tutorials/ci-cd.mdx +++ b/tutorials/ci-cd.mdx @@ -11,6 +11,36 @@ This means that you can spend less time debugging your CI/CD pipeline and more t Let's look at how you can use Flox with a variety of CI/CD platforms. For the following examples assume that you have a repository that contains a Flox environment, and assume that you've installed some Node.js dependencies for your project. +## Authenticating with FloxHub + +A pipeline that only uses an environment committed to the repository needs no credentials at all. +You need to authenticate when the pipeline pulls a [FloxHub environment](/concepts/floxhub-environments), installs packages from a private catalog, or publishes. + +Give the pipeline its own identity rather than a person's. +Create a [service account](/concepts/service-accounts) in your organization, issue it a token, and store that token as a secret on your CI platform. +Set it in the `FLOX_FLOXHUB_TOKEN` environment variable, which the Flox CLI reads without a separate login step. +Here that variable is filled from a GitHub Actions repository secret: + +```yaml title=".github/workflows/ci.yml" +jobs: + build: + runs-on: "ubuntu-latest" + env: + FLOX_FLOXHUB_TOKEN: ${{ secrets.FLOX_SERVICE_TOKEN }} + steps: + - uses: "flox/install-flox-action@v2" + - uses: "flox/activate-action@v1" + with: + environment: my-org/my-env + command: npm run build +``` + +The same variable works on any platform. In CircleCI set it as a project environment variable, and in GitLab set it as a masked CI/CD variable. + +A read-only service account can pull environments and install packages but cannot push or publish, so a leaked CI token cannot be used to change what the rest of the team installs. + +If you are running CI under your own identity, on a personal project for example, a [personal access token](/concepts/personal-access-tokens) works the same way. Note that it carries your full access, and revoking it also ends your own CLI sessions. + ## GitHub Actions Flox provides two different actions that you can use in a GitHub Actions workflow: