Trustix - Builder setup with Colmena (flake based)
Up until now we have talked about components in isolation, let's take a stab at a real deployment using Colmena. Once we're done we will have:
- A Trustix instance that others can subscribe to
- A local post build hook that publishes builds
Most of the contents in this article will be applicable to other deployment systems too with only minimal changes, the biggest difference should be how they deal with key material (secrets).
Requisites / assumptions
- You need a recent Nix with Flakes enabled
- We start off in an empty git repository
- Our domain name is
demo.trustix.dev
Create keys
All Trustix build logs are first and foremost identified by their key pair, which will be the first thing we have to generate.
Let's start by generating a key pair for our log:
$ mkdir secrets
$ nix run github:nix-community/trustix#trustix -- generate-key --privkey secrets/log-priv --pubkey secrets/log-pub
Additionally logs are identified not just by their key, but how that key is used. If a key is used for multiple protocols (not just Nix) those logs will have a different ID. This ID is what subscribers use to indicate what they want to subscribe to.
To find out the log ID for the key pair you just generated:
$ nix run github:nix-community/trustix#trustix -- print-log-id --protocol nix --pubkey $(cat secrets/log-pub)
Create a deployment
In your flake.nix
put:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
trustix = {
url = "github:nix-community/trustix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, flake-utils, trustix, ... }:
let
hostName = "demo.trustix.dev";
in
# Provide colmena
(flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
packages = [ pkgs.colmena ];
};
})
) // {
# Our actual deployment
colmena = {
meta = {
nixpkgs = import nixpkgs {
system = "x86_64-linux";
# Note that the overlay has to be applied manually when using Colmena
overlays = [ trustix.overlays.default ];
};
};
# Import the Trustix NixOS modules on all machines
defaults = { pkgs, ... }: {
imports = [
trustix.nixosModules.trustix
];
};
"${hostName}" = {
# Main Trustix daemon configuration
services.trustix = {
enable = true;
# Signers & publishers are separate concepts as the same key
# could potentially be used to publish multiple logs under different Trustix subprotocols.
#
# If you don't know what this means: While Trustix is build for Nix first, the core can be used for other ecosystems too, not just Nix.
signers.my-signer = {
type = "ed25519";
ed25519.private-key-path = "/var/lib/my-trustix-key";
};
publishers = [
{
signer = "my-signer"; # Use the key configured above
protocol = "nix"; # This publisher is using the Nix subprotocol
# An arbitrary (string -> string) attrset with metadata about this log
meta = {
upstream = "https://cache.nixos.org";
};
publicKey = {
type = "ed25519";
key = builtins.readFile ./secrets/log-pub;
};
}
];
};
# Enable the post build hook to push builds to the main Trustix daemon
services.trustix-nix-build-hook = {
enable = true;
# The logID we got earlier
publisher = "453016597475f45532e0a22a448ea7e0fb915e950d3c8930bfd23d962d73f9c1";
};
deployment = {
targetHost = hostName;
targetUser = "root";
# We are using the Colmena secrets facility to upload the keys to the remote
# without ending up world readable in the Nix store.
keys = {
my-trustix-key = {
keyFile = ./secrets/log-priv;
# This mode is too open for a real world deployment but we don't want to deal
# with the complexities of secrets management here.
permissions = "0644";
destDir = "/var/lib";
};
};
};
};
};
};
}
Enter the development shell and deploy:
$ nix develop # Pulls in Colmena via Flakes devShells
$ colmena apply # Deploy
Spread your log
In the next chapter we will go over how to use this log from clients. The most important thing right now is to make a note of your public key and your domain name.