background grid image
Image for post flakehub-cache-beta
Mar 13, 2024 by Luc Perkins

Introducing FlakeHub Cache

Binary caching is truly one of the most wonderful core features of Nix. It enables you to fetch the build results of derivations rather than building them locally, which makes just about everything you do with Nix—development environments, package builds, continuous integrations runs—so much faster that Nix without caching is essentially a different, lesser tool. But despite our love for Nix caching, we’ve believed that existing caching solutions are not suitable for secure, production use cases. And so we’ve opted to build something better.

Today, we’re excited to announce FlakeHub Cache, a powerful new caching concept from us at Determinate Systems that offers robust per-flake access control. FlakeHub Cache is currently in private beta and we’re actively iterating on the implementation and seeking design partners to try it out. You can sign up for the beta right here and we’ll let you know next steps soon:

Register for the FlakeHub Cache private beta

The core feature: granular access control

Nix’s official binary cache server, nix-serve, has some major gaps that make it unsuitable for secure, production use cases. Most importantly, nix-serve serves up a Nix store as a single monolithic cache, and everything in the cache is available to anyone with a public key. This is an unacceptably fast-and-loose access model for most organizations.

With FlakeHub Cache’s access control model, however, you can grant or deny read and write access at the flake level, which affords you substantially more control. So what does this look like?

Reading from FlakeHub Cache

Let’s start with read access to pull from a flake’s cache. If your org has a flake called security-mega-important, for example, you can provide read access only to a small set of trusted users—or automated agents—in your org. If, on the other hand, you have a flake called shared that’s meant to be used by everyone, you can provide read access to everyone in your org.

Writing to FlakeHub Cache

In terms of write access to push to a flake’s cache, we’ve opted for a model centered around controlled, authenticated build environments. FlakeHub Cache currently allows pushing to the cache solely as part of GitHub Actions runs (with GitLab support on the way). This means that there is no ad-hoc push access whatsoever, so you can’t accidentally push to a cache in a shell script or CLI command.

The granular and controlled nature of this model is far more suited for organizations with demanding security and other requirements, and a significant leap beyond existing solutions.

Authentication model

In order to grant or deny access, of course, FlakeHub Cache needs to figure out who—or what—is making a request. Authentication for FlakeHub Cache is based on JSON Web Tokens (JWTs). We currently use GitHub as our JWT authentication provider but will be adding GitLab support soon. In the future, this flexible model will enable us to support a wide variety of authentication solutions, including SAML and various Single Sign-on (SSO) providers.

Static tokens are great for some use cases—and FlakeHub enables you to create such tokens in the UI—but we’re opting to go beyond this model.

How the cache itself works

FlakeHub Cache is able to provide granular access control because of instead of serving an entire Nix store as “the cache,” FlakeHub Cache applies a slice abstraction, where a slice is some subset of all store paths. With FlakeHub Cache enabled, each flake you publish on FlakeHub gets its own slice and read and write access is applied at this level.

When a user has authenticated with FlakeHub Cache, it determines which slices you’re allowed to access and combines those slices into a single view of the cache. With this view abstraction, FlakeHub Cache can make decisions like these:

  • User devops_aficionado_123 from the WidgetsDotCom org may pull from the cache for the WidgetsDotCom/devops flake.
  • User AnaBooper from the WidgetsDotCom org may not pull from WidgetsDotCom/super-secure flake.

Although these users are in the same organization, WidgetsDotCom can make access decisions on a per-flake basis and thus choose whichever access patterns and collaboration models they wish. This model is certainly more robust from a security standpoint but it also:

  1. Is much simpler. When using Nix, you only need to configure FlakeHub Cache; there’s no need to distribute public keys for a multitude of them.
  2. Offers better performance. Using only one platform for caching means fewer network round trips and fewer authentication handshakes. In addition, we run FlakeHub Cache in a variety of regions with CDN-backed storage. This results in a clear speed-up in your Nix builds.

In addition to access control, things like garbage collection are also configurable at the flake level.

A new caching model

Two core aspects of using FlakeHub Cache make it a significant departure from other available cache systems:

  1. No public caches. That’s right: FlakeHub Cache doesn’t allow you to expose public caches like cache.nixos.org. You can pull from the cache for a specific flake only if you’re (a) authenticated and (b) have permission. That means that you can’t even accidentally make caches for specific flakes truly public. We’re open to exploring public caches in the future but would only do so with due care.

  2. Push only from CI. At the moment, when you create FlakeHub Cache authentication tokens, those only apply to pulling from the cache. You can’t push to the cache in an ad-hoc way using a CLI or other tool; you can only push from GitHub Actions, particularly the Magic Nix Cache Action (with GitLab support coming soon). If you enroll in the beta, you can enable pushing with this one-liner in your Actions configuration:

    permissions:
    contents: read
    id-token: write
    steps:
    - uses: actions/checkout@v3
    - uses: DeterminateSystems/nix-installer-action@main
    - uses: DeterminateSystems/magic-nix-cache-action@main
    - run: nix flake check

With that in place, anything that you nix build is automatically pushed to the cache—if authorized to!—without any need for separate push commands.

A bold step forward

We firmly believe that FlakeHub Cache is the first enterprise-ready cache in the Nix ecosystem. Public caches and caches without granular access control are not suited for a broad range of use cases and even whole industries, particularly those subject to exacting compliance standards, regulatory regimes, and security requirements. If you’re compelled by the power of Nix but have concerns about existing solutions, this might be precisely the sea change you’ve been waiting for.

On top of that, Determinate Systems is the only SOC2-compliant vendor in the Nix ecosystem, which should make otherwise-difficult discussions with the higher-ups go much more smoothly.

You can try out FlakeHub Cache for yourself soon. Sign up below, configure one of your GitHub Actions runs to use the Magic Nix Cache Action, make a small update to your Nix configuration, and you’ll experience this sea change first hand.

Register for the FlakeHub Cache private beta


Share
Avatar for Luc Perkins
Written by Luc Perkins

Luc is a technical writer, software engineer, and Nix advocate who's always on the lookout for qualitatively better ways of building software. He originally hails from the Pacific Northwest but has recently taken to living abroad.