Fleet Profile Distribution

Fleet Profile Distribution

GloriousFlywheel enrollment needs one fleet-managed profile path that tells a developer machine or agent how it is attached to the shared substrate. This is the non-secret profile distribution layer: endpoints, mode, instance name, credential helper path, token-file path, and public Attic trust material.

It is not the auth authority. Short-lived Bazel/RBE tokens come from the token-exchange path and the enforcing cache/executor front doors. Fleet systems such as Home Manager, NixOS modules, sops-age, or Vault may distribute the profile file or install helper tooling, but they must not persist bearer tokens or become the token issuer.

States

GF_FLYWHEEL_PROFILE_STATE is the machine-readable state that flywheel-doctor and flywheel-verify inspect.

State Meaning Endpoint rule
unattached The machine has no Bazel cache or executor attachment. Must not set BAZEL_REMOTE_CACHE or executor.
shared-cache-backed Bazel may use the shared remote cache. Requires BAZEL_REMOTE_CACHE; no executor.
executor-backed Bazel may use the opt-in REAPI executor for eligible targets. Requires both cache and executor endpoints.
local-proof Bounded operator proof through a local port-forward. Requires GF_BAZEL_LOCAL_PROOF=port-forward.

GF_BAZEL_SUBSTRATE_MODE remains the wrapper-facing Bazel mode: shared-cache-backed or executor-backed. The explicit profile state lets an agent distinguish a real fleet profile from an ad hoc shell.

NixOS Module

Import the module from the GloriousFlywheel flake:

{
  inputs.gloriousflywheel.url = "github:tinyland-inc/GloriousFlywheel";

  outputs = { nixpkgs, gloriousflywheel, ... }: {
    nixosConfigurations.example = nixpkgs.lib.nixosSystem {
      modules = [
        gloriousflywheel.nixosModules.flywheel-profile
        {
          programs.gloriousflywheel.profile = {
            enable = true;
            state = "shared-cache-backed";
            substrateMode = "shared-cache-backed";
            remoteCache = "grpcs://bazel-cache.example.internal:9092";
            instanceName = "default";
            credentialHelper = "bazel-cache.example.internal=/run/current-system/sw/bin/gf-reapi-credhelper";
            credentialHelperTokenFile = "/run/user/1000/gloriousflywheel/gf-reapi-token.jwt";
            toolsPackage = gloriousflywheel.packages.x86_64-linux.gloriousflywheel-profile-tools;

            attic = {
              server = "https://nix-cache.example.internal";
              cache = "main";
              publicKey = "main:replace-with-live-public-key";
            };
          };
        }
      ];
    };
  };
}

The NixOS module exports session variables, writes /etc/profile.d/gloriousflywheel.sh, optionally installs the profile tools package, and configures Nix to trust the Attic substituter when Attic server, cache, and public key are supplied.

Home Manager Module

Home Manager can install the same non-secret profile for developer shells:

{
  imports = [ inputs.gloriousflywheel.homeManagerModules.flywheel-profile ];

  programs.gloriousflywheel.profile = {
    enable = true;
    state = "shared-cache-backed";
    substrateMode = "shared-cache-backed";
    remoteCache = "grpcs://bazel-cache.example.internal:9092";
    instanceName = "default";
    credentialHelper = "bazel-cache.example.internal=${config.home.homeDirectory}/.nix-profile/bin/gf-reapi-credhelper";
    credentialHelperTokenFile = "${config.xdg.runtimeDir}/gloriousflywheel/gf-reapi-token.jwt";
    toolsPackage = pkgs.gloriousflywheel-profile-tools;

    attic = {
      server = "https://nix-cache.example.internal";
      cache = "main";
      publicKey = "main:replace-with-live-public-key";
    };
  };
}

The Home Manager module exports shell variables and writes $HOME/.config/gloriousflywheel/profile.env. It does not configure global Nix daemon trust by itself; use the system module or the host’s normal Nix settings for substituters and trusted public keys.

Front-Door Commands

The profile tools package provides the canonical local commands:

flywheel-doctor
flywheel-verify
flywheel-enroll shared-cache-backed --cache-endpoint grpcs://cache.example:9092

In this repository the same commands are exposed through Just:

just flywheel-doctor
just flywheel-verify
just flywheel-enroll shared-cache-backed --cache-endpoint grpcs://cache.example:9092

flywheel-doctor is descriptive: it prints the current profile state, endpoint shape, instance name, local-proof marker, Attic public trust posture, and whether runtime auth wiring is present. flywheel-verify fails when the shell is unattached or internally contradictory. flywheel-enroll is only the fallback .env.flywheel.local materializer; normal enrolled machines should receive the same non-secret profile through the NixOS or Home Manager module.

Runtime Token Boundary

Do not put bearer tokens, header values, or long-lived cache credentials into the profile. Acceptable values are:

  • endpoint URLs selected by the operator
  • GF_FLYWHEEL_PROFILE_STATE and GF_BAZEL_SUBSTRATE_MODE
  • REAPI instance_name
  • public Attic trust material
  • credential helper executable mapping
  • path where the helper should read a short-lived token

The short-lived token file is populated by the token-exchange flow. The profile only tells tooling where to read it.

.env.flywheel.local Fallback

just flywheel-consumer-env remains useful for fixtures, bounded local proofs, and repos that have not yet adopted the fleet profile module:

just flywheel-consumer-env shared-cache-backed \
  --cache-endpoint "$BAZEL_REMOTE_CACHE" \
  --write .env.flywheel.local

That file is gitignored fallback material. Normal enrolled usage should prefer the NixOS or Home Manager module so endpoints and mode state are refreshed by fleet management instead of local operator memory.

Current Boundary

This profile distribution path does not make off-cluster executor use broadly available by itself. It installs the metadata and helper wiring that consumers need. The enforcing cache front door, routed executor data plane, token exchange deployment, and fresh-repo measured proof remain separate rollout gates.

GloriousFlywheel