2023-02-20 13:18:31 +01:00
|
|
|
# `villas` as a Nix Flake
|
|
|
|
|
2024-02-29 22:02:08 +01:00
|
|
|
<!--
|
2023-02-20 13:18:31 +01:00
|
|
|
SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
2023-08-31 11:25:01 +02:00
|
|
|
-->
|
|
|
|
|
2023-02-20 13:18:31 +01:00
|
|
|
`VILLASnode` is also packaged as a Nix Flake.
|
|
|
|
|
|
|
|
## Setup Nix
|
|
|
|
|
|
|
|
Note that flakes are an (as of May 2023) experimental feature of the Nix
|
|
|
|
project to provide the declarative and fully reproducible builds of Nix without
|
|
|
|
the hassle of manually updating hashes.
|
|
|
|
|
|
|
|
Using `villas` as a flake thus requires the nix package manager to be installed
|
|
|
|
and the `flakes` and `nix-command` features to be enabled.
|
|
|
|
|
|
|
|
Documentation:
|
|
|
|
- Installation: https://nixos.org/download.html
|
|
|
|
- Enable Flakes: https://nixos.wiki/wiki/Flakes#Enable_flakes
|
|
|
|
|
|
|
|
Check if your installation works by running e.g.
|
|
|
|
```shell
|
|
|
|
nix run nixpkgs#hello
|
|
|
|
```
|
|
|
|
|
|
|
|
## Getting Started
|
|
|
|
|
|
|
|
Try to run `villas node` by typing
|
|
|
|
|
|
|
|
```shell
|
|
|
|
# `nix run` runs an output package provided by a flake
|
|
|
|
# `github:VILLASframework/node` is the repository containing the flake
|
|
|
|
# `?dir=packaging/nix` indicates that the `flake.nix` resides in this subdirectory
|
2024-04-10 00:14:29 +02:00
|
|
|
# `#villas-node-minimal` chooses the output package you want to run
|
2023-02-20 13:18:31 +01:00
|
|
|
# after the `--` follow the arguments to the `villas` tool (e.g. `node -h`)
|
2024-04-10 00:14:29 +02:00
|
|
|
nix run 'github:VILLASframework/node?dir=packaging/nix#villas-node-minimal' -- node -h
|
2023-02-20 13:18:31 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
The [`flake.nix`] provides 2 versions of `villas`:
|
2024-04-10 00:14:29 +02:00
|
|
|
- `#villas-node-minimal`: `villas` CLI command without most optional dependencies
|
|
|
|
- `#villas-node`: `villas` CLI command with most optional dependencies available to Nix
|
2023-02-20 13:18:31 +01:00
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
The version chosen by default is `#villas-node`. Omitting the `#` suffix will
|
|
|
|
select the more complete version of the `villas` CLI command.
|
2023-02-20 13:18:31 +01:00
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:19:31 +02:00
|
|
|
# Omit `#` suffix in the flake reference from above
|
|
|
|
# Note the difference supported nodes/formats in help output compared to above
|
2023-02-20 13:18:31 +01:00
|
|
|
nix run 'github:VILLASframework/node?dir=packaging/nix' -- node -h
|
|
|
|
```
|
|
|
|
|
|
|
|
## Simple Install
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
You can also install the `villas` CLI command into your local profile and have it available in
|
2023-02-20 13:18:31 +01:00
|
|
|
`PATH`.
|
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:14:29 +02:00
|
|
|
nix profile install 'github:VILLASframework/node?dir=packaging/nix#villas-node'
|
2023-02-20 13:18:31 +01:00
|
|
|
```
|
|
|
|
|
2023-06-08 17:14:31 +02:00
|
|
|
If you don't want to add it directly into the global path you could add it into
|
|
|
|
the flake registry as well.
|
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:14:29 +02:00
|
|
|
nix registry add villas-node 'github:VILLASframework/node?dir=packaging/nix'
|
2023-06-08 17:14:31 +02:00
|
|
|
```
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
This allows you to substitute all references to
|
|
|
|
`github:VILLASframework/node?dir=packaging/nix#villas-node` with a simple `villas-node`.
|
2023-06-08 17:14:31 +02:00
|
|
|
I'll be using the `villas` registry entry in the following sections.
|
|
|
|
|
2023-02-20 13:18:31 +01:00
|
|
|
## Development
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
You can easily setup a development shell environment for the `villas` CLI command by using the
|
2023-02-20 13:18:31 +01:00
|
|
|
`devShells` provided in the [`flake.nix`] using `nix develop`.
|
2023-06-08 17:14:31 +02:00
|
|
|
Try for example these commands in the repository root to create a new shell with
|
2024-04-10 00:14:29 +02:00
|
|
|
all required dependencies to build various configurations of the `villas` CLI command.
|
2023-02-20 13:18:31 +01:00
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:15:28 +02:00
|
|
|
# The default creates the `#full` shell
|
2023-02-20 13:18:31 +01:00
|
|
|
nix develop ./packaging/nix
|
|
|
|
```
|
|
|
|
|
|
|
|
## Further Reading
|
|
|
|
|
|
|
|
- The [Nix Manual](https://nixos.org/manual/nix/stable/):
|
|
|
|
installing and using the Nix package manager and Nix language
|
|
|
|
- The [Nixpkgs Manual](https://nixos.org/manual/nixpkgs/stable/):
|
|
|
|
using the tools provided by Nixpkgs
|
|
|
|
|
|
|
|
## Docker/OCI Images
|
|
|
|
|
|
|
|
OCI images created using nix can be as small as the typical `FROM scratch`
|
2024-04-10 00:19:31 +02:00
|
|
|
images without worrying about missing dependencies or Copying things in between
|
2023-02-20 13:18:31 +01:00
|
|
|
`Dockerfile` stages. Copying exactly the application, it's dependencies an
|
|
|
|
nothing else can be done using only a few lines of Nix.
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
Here we build a docker image containing the `#villas-node` flake output:
|
2023-06-08 17:14:31 +02:00
|
|
|
|
2023-02-20 13:18:31 +01:00
|
|
|
```shell
|
|
|
|
# `docker load` reads OCI images from stdin
|
|
|
|
# `nix build --impure --expr` builds a derivation from an impure Nix expression
|
|
|
|
# `--no-link` omits creating the `result` symlink
|
|
|
|
# `--print-out-paths` prints the built image's path to stdout
|
|
|
|
docker load < $(nix build --no-link --print-out-paths --impure --expr '
|
|
|
|
let
|
2024-04-10 00:14:29 +02:00
|
|
|
villas-node = (builtins.getFlake "villas").packages.x86_64-linux.villas-node;
|
2023-02-20 13:18:31 +01:00
|
|
|
pkgs = (builtins.getFlake "nixpkgs").legacyPackages.x86_64-linux;
|
|
|
|
in
|
|
|
|
pkgs.dockerTools.buildImage {
|
|
|
|
name = "villas";
|
|
|
|
tag = "nix";
|
|
|
|
created = "now";
|
|
|
|
copyToRoot = [villas];
|
2024-04-10 00:14:29 +02:00
|
|
|
config.Cmd = ["${villas-node}/bin/villas" "node" "-h"];
|
2023-02-20 13:18:31 +01:00
|
|
|
}
|
|
|
|
')
|
|
|
|
```
|
|
|
|
|
|
|
|
See https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-dockerTools
|
|
|
|
|
|
|
|
## Customization
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
The [`villas.nix`] file contains the Nix "derivation" used to build the
|
|
|
|
`villas` CLI command. Check the `# customization` options at the top to find
|
|
|
|
out what optional things can be enabled.
|
2023-02-20 13:18:31 +01:00
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
### Building a customized `villas` CLI command
|
2023-02-20 13:18:31 +01:00
|
|
|
|
|
|
|
Using and customizing the villas package requires some knowledge of the Nix
|
|
|
|
expression language. And the standard `override` function used extensively in
|
|
|
|
`nixpkgs`. `override` is a Nix function provided by many packages to change
|
|
|
|
dependencies or build options. All of the inputs which can be overridden can be
|
|
|
|
found at the top of [`villas.nix`].
|
|
|
|
|
|
|
|
See https://nixos.org/manual/nixpkgs/stable/#chap-overrides
|
|
|
|
|
|
|
|
```shell
|
|
|
|
# `nix build` builds a derivation
|
2024-04-10 00:19:31 +02:00
|
|
|
# `--expr <EXPR>` specifies a Nix expression which evaluates to a "derivation"
|
2023-02-20 13:18:31 +01:00
|
|
|
# `--impure` allows us to use a flake without specifying the exact git revision in `ref`
|
|
|
|
# `ref` is the reference to the `villas` flake we want to use
|
|
|
|
# `pkgs` is the set of `x86_64-linux` packages provided by the flake
|
|
|
|
nix build --impure --expr '
|
|
|
|
let
|
2023-06-08 17:14:31 +02:00
|
|
|
pkgs = (builtins.getFlake "villas").packages.x86_64-linux;
|
2023-02-20 13:18:31 +01:00
|
|
|
in
|
2024-04-10 00:14:29 +02:00
|
|
|
pkgs.villas-node-minimal.override {
|
2023-06-08 17:14:31 +02:00
|
|
|
withExtraConfig = true;
|
2023-02-20 13:18:31 +01:00
|
|
|
withNodeIec60870 = true;
|
|
|
|
}
|
|
|
|
'
|
|
|
|
```
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
Here we override the `#villas-node-minimal` package to include `libconfig`
|
2023-02-20 13:18:31 +01:00
|
|
|
configuration support and enable the `IEC61870-5-104` node.
|
|
|
|
|
|
|
|
`nix build` now builds the customized `villas` and produces a `result` symlink
|
|
|
|
in the current directory. `result` now points to a directory in the Nix store
|
|
|
|
containing the installation. You can run the `villas` binary through the
|
|
|
|
symlink.
|
|
|
|
|
|
|
|
```shell
|
|
|
|
./result/bin/villas node -h
|
|
|
|
```
|
|
|
|
|
|
|
|
### Making it persistent
|
|
|
|
|
|
|
|
Making persistent build configuration changes in a canonical way involves
|
|
|
|
writing your own flake. A flake is basically a directory containing a
|
|
|
|
`flake.nix` file. Since Nix is aware of VCS, you should create your own
|
|
|
|
`flake.nix` in a new directory outside the `villas` source tree.
|
|
|
|
|
|
|
|
Here is a basic flake to build upon:
|
|
|
|
```nix
|
|
|
|
# flake.nix
|
|
|
|
{
|
|
|
|
description = "example of a customized villas";
|
|
|
|
|
|
|
|
inputs = {
|
|
|
|
villas.url = "github:VILLASframework/node?dir=packaging/nix";
|
|
|
|
};
|
|
|
|
|
|
|
|
outputs = { self, villas }:
|
|
|
|
let
|
|
|
|
villas-pkgs = villas.packages.x86_64-linux;
|
|
|
|
in {
|
|
|
|
packages.x86_64-linux = rec {
|
|
|
|
default = villas-custom;
|
2024-04-10 00:14:29 +02:00
|
|
|
villas-custom = villas-pkgs.villas-node-minimal.override {
|
2023-06-08 17:14:31 +02:00
|
|
|
version = "custom";
|
|
|
|
withExtraConfig = true;
|
2023-02-20 13:18:31 +01:00
|
|
|
withNodeIec60870 = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The attributes here are fairly simple:
|
|
|
|
- `description`: short description of the flake
|
|
|
|
- `inputs`: attribute set that specifies all dependencies of the flake
|
|
|
|
- `outputs`: a Nix function taking `self` and all fetched `inputs` producing
|
|
|
|
the flake outputs
|
|
|
|
|
|
|
|
The `packages.x86_64-linux` output of a flake is a set of all packages
|
|
|
|
buildable by nix on a `x86_64-linux` system.
|
|
|
|
|
|
|
|
You can now build/run/install your customized `villas`. `nix` commands default
|
|
|
|
to checking the current directory (and parent directories) for a `flake.nix`
|
|
|
|
and using the `default` attribute if no `#output` is specified.
|
|
|
|
|
|
|
|
The first time you use the flake a `flake.lock` will be created pinning villas
|
|
|
|
to an exact git revision so future invocations will be exactly reproducible.
|
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:19:31 +02:00
|
|
|
# Build custom `villas` and create the `result` symlink
|
2023-02-20 13:18:31 +01:00
|
|
|
nix build .
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Run custom `villas node -h`
|
2023-02-20 13:18:31 +01:00
|
|
|
nix run . -- node -h
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Install villas into default profile
|
2023-02-20 13:18:31 +01:00
|
|
|
nix profile install .
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Create a shell environment where `villas` is available in path
|
2023-02-20 13:18:31 +01:00
|
|
|
nix shell .
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Update the `flake.lock` if a newer `villas` is available on github
|
2023-02-20 13:18:31 +01:00
|
|
|
nix flake update
|
|
|
|
```
|
|
|
|
|
|
|
|
### Extending the flake
|
|
|
|
|
2024-04-10 00:14:29 +02:00
|
|
|
Installing the `villas` CLI command globally using `nix profile install` isn't really the
|
2023-02-20 13:18:31 +01:00
|
|
|
typical Nix usage. A more interesting use of Nix would be a custom Nix shell
|
|
|
|
environment containing your `villas-custom` and other tools of your choice.
|
|
|
|
|
|
|
|
Here is a more complete `flake.nix` containing `devShells` available to
|
2023-06-08 17:14:31 +02:00
|
|
|
`nix develop` and an OCI image.
|
|
|
|
|
2023-02-20 13:18:31 +01:00
|
|
|
```nix
|
|
|
|
# flake.nix
|
|
|
|
{
|
|
|
|
description = "example of a customized villas";
|
|
|
|
|
|
|
|
inputs = {
|
|
|
|
# nixpkgs from the `unstable` branch
|
|
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# VILLASnode from the official repository
|
2023-02-20 13:18:31 +01:00
|
|
|
villas.url = "github:VILLASframework/node?dir=packaging/nix";
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Overwrite the `nixpkgs` used by `villas` to our version above
|
2023-02-20 13:18:31 +01:00
|
|
|
#
|
2024-04-10 00:19:31 +02:00
|
|
|
# This will negate the reproducibility of the `villas` flake,
|
2023-02-20 13:18:31 +01:00
|
|
|
# but allows us to deduplicate the dependencies used in our shell
|
|
|
|
# and those in villas.
|
|
|
|
#
|
2024-04-10 00:19:31 +02:00
|
|
|
# Comment this line if an updated dependency causes a build failure
|
2023-02-20 13:18:31 +01:00
|
|
|
villas.inputs.nixpkgs.follows = "nixpkgs";
|
|
|
|
};
|
|
|
|
|
|
|
|
outputs = { self, villas }:
|
|
|
|
let
|
|
|
|
villas-pkgs = villas.packages.x86_64-linux;
|
|
|
|
pkgs = nixpkgs.packages.x86_64-linux;
|
|
|
|
in {
|
|
|
|
packages.x86_64-linux = rec {
|
|
|
|
# run/build/install the `villas-custom` package by default
|
|
|
|
default = villas-custom;
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# The customized villas package
|
2024-04-10 00:14:29 +02:00
|
|
|
villas-custom = villas-pkgs.villas-node-minimal.override {
|
2023-02-20 13:18:31 +01:00
|
|
|
withConfig = true;
|
|
|
|
withNodeIec60870 = true;
|
|
|
|
};
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# An OCI image containing `villas-custom`
|
2023-02-20 13:18:31 +01:00
|
|
|
image = pkgs.dockerTools.buildImage {
|
|
|
|
name = "villas";
|
|
|
|
tag = "nix";
|
|
|
|
created = "now";
|
|
|
|
copyToRoot = [villas-custom];
|
|
|
|
config.Cmd = ["${villas-custom}/bin/villas" "node" "-h"];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
devShells.x86_64-linux.default = pkgs.mkShell {
|
|
|
|
name = "my-villas-dev-shell";
|
|
|
|
shellHook = "exec $SHELL";
|
|
|
|
packages = with pkgs; [
|
|
|
|
self.packages.x86_64-linux.villas-custom
|
|
|
|
jq
|
|
|
|
bat
|
|
|
|
];
|
2023-05-25 18:47:27 +02:00
|
|
|
};
|
2023-02-20 13:18:31 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
You can use our new features like this:
|
|
|
|
|
|
|
|
```shell
|
2024-04-10 00:19:31 +02:00
|
|
|
# Run your shell for villas-node
|
2023-02-20 13:18:31 +01:00
|
|
|
nix develop
|
|
|
|
|
2024-04-10 00:19:31 +02:00
|
|
|
# Load your custom OCI image into docker
|
2023-02-20 13:18:31 +01:00
|
|
|
docker load < $(nix build --no-link --print-out-paths .#image)
|
|
|
|
```
|
|
|
|
|
|
|
|
[`villas.nix`]: ./villas.nix
|
|
|
|
[`flake.nix`]: ./flake.nix
|
2023-08-31 11:25:01 +02:00
|
|
|
|
|
|
|
## License
|
|
|
|
|
2023-06-08 17:14:31 +02:00
|
|
|
- SPDX-FileCopyrightText: 2023 OPAL-RT Germany GmbH
|
2023-02-20 13:18:31 +01:00
|
|
|
- SPDX-License-Identifier: Apache-2.0
|