This section gives an example of how to use Typhon with a GitHub project. Let's assume your username is $user and you have two repositories,$user/$project and$user/$config. $project is the repository you want to put under CI, $config is going to contain the Typhon declaration. These two repositories can actually be the same, but separating the two can mitigate security concerns. Finally, let's assume your Typhon instance URL is $typhon_url (you must have https enabled).

Creating a new Typhon project

Log in to your Typhon instance and create a new project, with an identifier $id (typically $id == $project). Set the declaration to use the flake URL github:$user/$config. Once the project is created, a public key is associated to it, let's call it $pk.

GitHub settings

We need to generate a token on GitHub and make sure it has permission to update statuses on $project, let's call it $token. Then let's generate a random string $secret and add a webhook to $project with the following settings:

  • payload URL: $typhon_url/api/projects/$id/webhook
  • content type: application/json
  • secret: $secret
  • events: Just the push event

The configuration flake

Let's create a flake in the $config repository, then add an output typhonProject. We are going to import typhon as a flake input and use the github.mkProject helper function from the library:

  inputs = {typhon.url = "github:typhon-ci/typhon";};

  outputs = {
  }: {
    typhonProject = typhon.lib.github.mkProject {
      owner = "$user";
      repo = "$project";
      secrets = ./secrets.age;
      typhonUrl = "$typhon_url";

We need to generate the secrets.age file. First let's write a secrets.json file containing the secrets you generated (don't commit it!):

  "github_token": "$token",
  "github_webhook_secret": "$secret"

Then, we encrypt the JSON file with age, using the public key of the project:

nix run nixpkgs#age -- --encrypt -r "$pk" -o secrets.age secrets.json

We also need to generate the lock file:

nix flake lock

Finally, we commit secrets.age, flake.nix and flake.lock.

The project flake

In the $project repository, we create a flake with a typhonJobs attribute. For instance, let's declare GNU hello as your only job:

  inputs = {nixpkgs.url = "nixpkgs";};

  outputs = {
  }: let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
  in {
    typhonJobs.${system} = {
      inherit (pkgs) hello;

We need to generate a lock file and commit flake.nix and flake.lock.

Refreshing the project declaration

Let's go to your project's page on Typhon and refresh the declaration. This is not done automatically on purpose. Always be careful before refreshing: if a malicious commit was made on $config, your secrets could be compromised. Once this is done, your Typhon project is using the settings declared in $config.

Verifying everything is working

We can now update the jobsets of your project from the project interface. A list of jobsets should appear, one for each branch of your repository. Now, any push to the repository should generate an evaluation in the corresponding jobset and statuses should appear on your repository.


Now, let's add a deployment action to push your store paths to Cachix. We will assume you have a cache named $cache already set up and an authentication token that comes with it. First add the token to your secrets as an attribute called cachix_token. Then edit $config as follows:

typhonProject = typhon.lib.github.mkProject {
  deploy = [
      name = "Push to Cachix";
      value = typhon.lib.cachix.mkPush {name = "$cache";};

Refresh your project on Typhon, then your binaries should be pushed to your cache at the end of every job.

Finally, you can use typhon.lib.compose.match to run your deployments only on certain jobsets or jobs.