Flocken

Flocken (German for “flakes”) is a collection of utilities for nix flakes.

Usage

The project supports semantic versioning, so we advise to pin the major version (e.g., v2) to avoid breaking changes.

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    flocken = {
      url = "github:mirkolenz/flocken/v2";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };
  outputs = {nixpkgs, flocken, ...}:  {};
}

flocken.lib

A collection of utility functions for nix flakes. See the documentation for more details.

flocken.legacyPackages.${system}.mkDockerManifest

Create and push a Docker manifest to a registry. This is particularly useful for multi-arch images. Some arguments (e.g., version) differ between invocations and thus need to be provided in a dynamic fashion. We recommend to use environment variables for this purpose. For instance, when running in a GitHub action, you only have to provide a value for VERSION and GITHUB_TOKEN and then can use the following snippet:

docker-manifest = mkDockerManifest {
  github = {
    enable = true;
    token = "$GITHUB_TOKEN";
  };
  version = builtins.getEnv "VERSION";
  imageStreams = with self.packages; [x86_64-linux.docker aarch64-linux.docker];
}

[!warning] Reading environment variables requires the --impure flag (e.g., nix run --impure .#docker-manifest). Do not use builtins.getEnv to read secrets, as this would expose them in the Nix store and could lead to uploading them to binary caches. For tokens/password, pass the name of the environment variable instead.

Here is a complete example for a GitHub action that is able to build an image for multiple architectures:

on:
  push:
    branches: [main]
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
        with:
          platforms: arm64
      - uses: DeterminateSystems/nix-installer-action@v6
        with:
          extra-conf: |
            extra-platforms = aarch64-linux
      - uses: DeterminateSystems/magic-nix-cache-action@v2
      - run: nix run --impure .#docker-manifest
        env:
          VERSION: "1.0.0"
          GITHUB_TOKEN: ${{ github.token }}

getModules

Get all modules in a directory. Can for instance be used to automatically import all modules in a directory. Directories containing a default.nix file are considered modules. Paths starting with _ are ignored.

Inputs

dir : The directory to search for modules in.

Type

getModules :: Path -> [ Path ]

Examples

getModules ./.
=> [
  ./module1
  ./module2
]

optionalPath

Get a path as a list if it exists. Returns an empty list if the path does not exist. Useful for adding optional paths to import statements.

Inputs

path : The path to check for existence.

Type

optionalPath :: Path -> [ Path ]

Examples

optionalPath ./module.nix
=> [ ./module.nix ]
optionalPath ./non-existing-module.nix
=> [ ]

isEmpty

Check if a value of arbitrary type is empty.

Inputs

value : The value to check for emptiness.

Type

isEmpty :: Any -> Bool

Examples

isEmpty ""
=> true
isEmpty null
=> true
isEmpty [ ]
=> true
isEmpty { }
=> true
isEmpty "foo"
=> false
isEmpty [ "foo" ]
=> false
isEmpty { foo = "bar"; }
=> false

isNotEmpty

Check if a value of arbitrary type is non-empty. Opposite of isEmpty.

Inputs

value : The value to check for non-emptiness.

Type

isNotEmpty :: Any -> Bool

Examples

isNotEmpty ""
=> false

isEnabled

Checks if an attrset has a key with the name enable set to true.

Inputs

x : The attrset to check.

Type

isEnabled :: { enable ? Bool } -> Bool

Examples

isEnabled { enable = true; }
=> true
isEnabled { enable = false; }
=> false
isEnabled { }
=> false

githubSshKeys

Returns a list of GitHub SSH keys for a user.

Inputs

user : The GitHub username to get the SSH keys for.

sha256 : The sha256 hash of the file.

Type

githubSshKeys :: { user: String, sha256: String } -> [ String ]

Examples

githubSshKeys {
  user = "mirkolenz";
  sha256 = lib.fakeSha256;
}
=> [
  "ssh-rsa AAAA..."
  "ssh-rsa AAAA..."
]

getLeaves

Get all leaves of an attrset.

Inputs

attrs : The attrset to get the leaves of.

Type

getLeaves :: AttrSet -> AttrSet

Examples

getLeaves {
  foo = {
    bar = "baz";
  };
}
=> {
  "foo.bar" = "baz";
}

attrByDottedPath

Return an attribute from nested attribute sets.

Inputs

path : The path to the attribute.

default : The default value to return if the attribute does not exist.

set : The attribute set to get the attribute from.

Type

attrByPath :: String -> Any -> AttrSet -> Any

Examples

attrByPath "foo.bar" "default" { foo = { bar = "baz"; }; }
=> "baz"

getAttrFromDottedPath

Like attrByDottedPath, but without a default value. If it doesn’t find the path it will throw an error.

Inputs

path : The path to the attribute.

set : The attribute set to get the attribute from.

Type

getAttrFromDottedPath :: String -> AttrSet -> Any

Examples

getAttrFromDottedPath "foo.bar" { foo = { bar = "baz"; }; }
=> "baz"

setAttrByDottedPath

Create a new attribute set with value set at the nested attribute location specified in PATH.

Inputs

path : The path to the attribute.

value : The value to set.

Type

setAttrByDottedPath :: String -> Any -> AttrSet

Examples

setAttrByDottedPath "foo.bar" "baz"
=> { foo = { bar = "baz"; }; }

annotations

Annotations for the manifest. Most org.opencontainers.image annotations are set automatically if the GitHub option is enabled.

Type: attribute set of anything

Default: { }

autoTags

Configuration for tags that are generated automatically.

Type: submodule

Default: { }

autoTags.branch

Whether to enable add a tag based on the branch name.

Type: boolean

Default: true

Example: false

autoTags.latest

Whether to enable add a ‘latest’ tag if branch == defaultBranch.

Type: boolean

Default: true

Example: false

autoTags.major

Whether to enable add a tag based on the major version (e.g., 1).

Type: boolean

Default: true

Example: false

autoTags.majorMinor

Whether to enable add a tag based on the major and minor version (e.g., 1.2).

Type: boolean

Default: true

Example: false

autoTags.version

Whether to enable add a tag based on the version (e.g., 1.2.3).

Type: boolean

Default: true

Example: false

branch

Name of the git branch (e.g., main).

Type: null or string

Default: "github.branch || null"

defaultBranch

Name of the git branch that is used as default for the latest tag.

Type: string

Default: "if `github.enable` then `$GITHUB_DEFAULT_BRANCH` else `main`"

format

The format of the manifest

Type: one of “oci”, “v2s2”

Default: "oci"

github

GitHub integration configuration

Type: submodule

Default: { }

github.enable

Whether the GitHub integration is enabled. If set to true, you need to run nix with the --impure flag in order to access the GitHub API.

Type: boolean

Default: false

Example: true

github.enableRegistry

Whether to enable the GitHub container registry.

Type: boolean

Default: true

Example: false

github.actor

GitHub actor. Used as default value for registries."ghcr.io".username.

Type: null or string

Default: "$GITHUB_ACTOR || null"

github.apiEndpoint

GitHub API endpoint. Can be used for custom GitHub installations.

Type: string

Default: "https://api.github.com"

github.branch

Name of the git branch.

Type: null or string

Default: "$GITHUB_REF_NAME || null"

github.registry

Name of the GitHub registry

Type: string

Default: "ghcr.io"

github.repo

Full name of the GitHub repository (e.g., mirkolenz/flocken). Used as default value for registries."ghcr.io".repo.

Type: null or string

Default: "$GITHUB_REPOSITORY || null"

github.token

GitHub access token. Used as default value for registries."ghcr.io".password.

Type: string

Default: "$GITHUB_TOKEN"

imageFiles

List of Docker images to be added to the manifest. Can for instance be produced using dockerTools.buildLayeredImage. Note: This should be a list of identical images for different architectures.

Type: list of package

Default: [ ]

imageStreams

List of Docker image streams to be added to the manifest. Can for instance be produced using dockerTools.streamLayeredImage. Note: This should be a list of identical images for different architectures.

Type: list of package

Default: [ ]

images

Alias of imageFiles.

Type: list of package

manifestName

The name of the manifest

Type: string

Default: "flocken"

registries

Configuration for the Docker registries to be used. The key is the name of the registry (e.g., ghcr.io).

Type: attribute set of (submodule)

Default: { }

registries.<name>.enable

Whether to enable pushing to the registry.

Type: boolean

Default: true

Example: false

registries.<name>.name

The name/domain of the registry

Type: string

Default: "‹name›"

registries.<name>.password

Password for pushing to the registry.

Type: string

registries.<name>.repo

Fully qualified name of the Docker image in the registry (e.g., mirkolenz/flocken).

Type: string

registries.<name>.username

Username for pushing to the registry.

Type: string

tags

List of custom/additional tags to be added to the manifest.

Type: list of string

Default: [ ]

version

Semantic version of the image (e.g., v1.0.0 or 1.0.0).

Type: null or string

Default: "$VERSION || null"