Introduction
Omnix aims to supplement the Nix CLI to improve developer experience.
warning
๐ง omnix is in active development. View the Github repo for ongoing progress.
Install
To install Omnix, you first need Nix installed,1 before running the following:
# Install omnix (using om.cachix.org Nix cache)
nix --accept-flake-config profile install github:juspay/omnix
# Make sure that the `om` command works
om --help
Next Steps
Checkout the CLI commands available.
Discussion
For discussing Omnix, use Github Discussions or Zulip.
We also plan to provide a static binary. See #207
The om
CLI
The Omnix CLI currently provides a fully-functioning health
and ci
commands. The show
command has basic functionality, whereas the init
command can be used to scaffold new projects using Nix. The develop
command enriches flakes support in direnv.
Show
The om show
command seeks to provide a better nix flake show
experience.
warning
Currently, om show
is a wrapper on nix flake show
, but with support for flake schemas. More is planned for om show
. See issue #162.
Usage
Run om show
on any flake - via URL or local path.
$ om show github:srid/nixos-config
๐ nix --extra-experimental-features 'nix-command flakes' show-config --json๏ธ
๐ /nix/store/n02w2ybg9fc78grzz9i2aj49q3rysp7m-nix-2.24.0pre20240801_af10904/bin/nix flake show --legacy --allow-import-from-derivation --json --default-flake-schemas /nix/store/xzalq6mcw0ahyaccab6k98dbx3ll53y6-source github:srid/nixos-config๏ธ
๐ฆ Packages (nix build github:srid/nixos-config#<name>)
โญโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ activate โ Activate NixOS/nix-darwin/home-manager configurations โ
โ default โ Activate NixOS/nix-darwin/home-manager configurations โ
โ update โ N/A โ
โฐโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ Devshells (nix develop github:srid/nixos-config#<name>)
โญโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ default โ Dev environment for nixos-config โ
โฐโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ Checks (nix flake check)
โญโโโโโโโโโโฌโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโผโโโโโโโโโโโโโโค
โ treefmt โ N/A โ
โฐโโโโโโโโโโดโโโโโโโโโโโโโโฏ
๐ง NixOS Configurations (nixos-rebuild switch --flake github:srid/nixos-config#<name>)
โญโโโโโโโโโโโโฌโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโโโผโโโโโโโโโโโโโโค
โ immediacy โ N/A โ
โฐโโโโโโโโโโโโดโโโโโโโโโโโโโโฏ
๐ Darwin Configurations (darwin-rebuild switch --flake github:srid/nixos-config#<name>)
โญโโโโโโโโโโโโโฌโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโโโโผโโโโโโโโโโโโโโค
โ appreciate โ N/A โ
โฐโโโโโโโโโโโโโดโโโโโโโโโโโโโโฏ
๐ง NixOS Modules
โญโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโฎ
โ name โ description โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโค
โ common โ N/A โ
โ default โ N/A โ
โ home-manager โ N/A โ
โ my-home โ N/A โ
โ nixosFlake โ N/A โ
โฐโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโฏ
om health
The om health
command checks the health of your Nix install. Furthermore, individual projects can configure their own health checks in their flake.nix
. For example, the nammayatri project checks that the cachix cache is in use.
note
History: om health
was formerly called nix-health
.
Checks performed
Check | Configurable in flake.nix ? |
---|---|
Flakes are enabled | - |
Nix version is not too old | Yes |
Nix runs natively (no rosetta)1 | Yes |
Builds use multiple cores (max-jobs ) | Yes |
Nix Caches in use | Yes |
$USER is in trusted-users | - |
Direnv: installed and activated | Yes |
Min RAM / Disk space | Yes |
This check is only performed on macOS with Apple Silicon.
Note that some checks are considered non-essential. For eg., the disk space check looks for 1TB+ disk space, but if the user is on a laptop with 256GB SSD, the check will report a warning instead of failing. This can also be configured in per-project basis from flake.nix
(see below).
Usage
om health
To run use the health check configuration specified in a project flake, pass that flake as an argument. For eg., to run halth checks defined from the nammayatri project, run:
# The argument can be any flake URL (including a local path)
om health github:nammayatri/nammayatri
Configuring in flake.nix
To add project specific health checks or configure health checks, add the following flake output:
{
outputs = inputs: {
om.health.default = {
# Add configuration here
caches.required = [ "https://ourproject.cachix.org" ];
};
};
}
To see all available configuration options, run om health --dump-schema
. This will dump the schema of the configuration in JSON format. Convert that to a Nix attrset to see what can be added under the om.health.default
attrset of your flake.
$ om health --dump-schema > schema.json
$ nix eval --impure --expr 'builtins.fromJSON (builtins.readFile ./schema.json)' \
| nix run nixpkgs#alejandra -- --quiet
This will output:
{
caches = {required = ["https://cache.nixos.org/"];};
direnv = {
enable = true;
required = false;
};
flake-enabled = {};
max-jobs = {};
nix-version = {min-required = "2.16.0";};
rosetta = {
enable = true;
required = true;
};
shell = {
enable = true;
required = false;
};
trusted-users = {};
}
Adding devShell check
warning
This section needs to be finalized for omnix. See here for the up-to-date proof of concept.
You can automatically run om health
whenever your Nix dev shell starts. To do this, import the flake module in your flake and use it in your devShell:
{
inputs = {
omnix-flake.url = "github:juspay/omnix?dir=nix/om";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
imports = [
inputs.omnix-flake.flakeModules.default
];
perSystem = { config, pkgs, ... }: {
devShells.default = pkgs.mkShell {
inputsFrom = [
config.om.health.outputs.devShell
]
};
};
};
}
Now suppose you have Nix 2.18 installed, but your project requires 2.19 or above due to the following config in its flake.nix
:
flake.om.health.default = {
nix-version.min-required = "2.19.0";
};
you can expect the devShell to print a giant message like this:
Note that you will still be dropped into the Nix dev shell (thereโs no way to abrupt the launching of a dev Shell).
Develop
The om develop
should be used indirectly in direnv, via the use omnix
directive in your .envrc
:
source_url https://raw.githubusercontent.com/juspay/omnix/75ed48923835963e2f18baba08f54a8adc307ba2/omnixrc "sha256-8C2Jb5bHx/0cvm1+9gOlBEdWzbikCWT5UsJWewUAFt4="
use omnix
use omnix
wraps use flake
(of nix-direnv) providing additional capabilities:
- Run
om health
to check the health of the Nix environment. - Run
cachix use
automatically if the project uses cachix. - Print a welcome text after spawning the Nix devshell.
The ideal goal here being that switching to a project should do everything necessary to get you started immediately.
om.yaml
You should also create a om.yaml
(empty file if thereโs no configuration) so your flake is not evaluated during direnv.
Welcome text
The welcome text can be configured in your om configuration:
{
om.develop.default = {
readme = ''
Welcome to our **project**
To get started, run the following:
```sh
just run
```
For more, read the README.md
'';
}
}
om ci
om ci
runs CI for your project. It builds all outputs in the flake, or optionally its sub-flakes. You can run om ci
locally or in an actual CI envirnoment, like GitHub Actions. Using devour-flake it will automatically build the following outputs:
Type | Output Key |
---|---|
Standard flake outputs | packages , apps , checks , devShells |
NixOS | nixosConfigurations.* |
nix-darwin | darwinConfigurations.* |
home-manager | legacyPackages.${system}.homeConfigurations.* |
The stdout of om ci run
will be a list of store paths built.
tip
If you are familiar with nixci, om ci
is basically the successor to nixci
.
Basic Usage
om ci run
accepts any valid flake URL or a Github PR URL.
# Run CI on current directory flake
$ om ci # Or `om ci run` or `om ci run .`
# Run CI on a local flake (default is $PWD)
$ om ci run ~/code/myproject
# Run CI on a github repo
$ om ci run github:hercules-ci/hercules-ci-agent
# Run CI on a github PR
$ om ci run https://github.com/srid/emanote/pull/451
# Run CI only the selected sub-flake
$ git clone https://github.com/srid/haskell-flake && cd haskell-flake
$ om ci run .#default.dev
# Run CI remotely over SSH
$ om ci run --on ssh://myname@myserver ~/code/myproject
Using in Github Actions
In addition to serving the purpose of being a โlocal CIโ, om ci
can be used in Github Actions to enable CI for your GitHub repositories.
Standard Runners
Add this to your workflow file (.github/workflows/ci.yml
) to build all flake outputs using GitHub provided runners:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- name: Install omnix
run: nix --accept-flake-config profile install "github:juspay/omnix"
- run: om ci
Self-hosted Runners with Job Matrix
Hereโs a more advanced example that configures a job matrix. This is useful when you want to run the CI on multiple systems (e.g. aarch64-linux
, aarch64-darwin
), each captured as a separate job by GitHub, as shown in the screenshot below. It also, incidentally, demonstrates how to use self-hosted runners.
The om ci gh-matrix
command outputs the matrix JSON for creating a matrix of job variations. An example configuration, using self-hosted runners, is shown below.
note
This currently requires an explicit CI configuration in your flake, viz.: om.ci.default.root.dir = ".";
.
# Run on aarch64-linux and aarch64-darwin
jobs:
configure:
runs-on: x86_64-linux
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- id: set-matrix
run: |
set -euxo pipefail
MATRIX="$(om ci gh-matrix --systems=x86_64-linux,aarch64-darwin | jq -c .)"
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
nix:
runs-on: ${{ matrix.system }}
needs: configure
strategy:
matrix: ${{ fromJson(needs.configure.outputs.matrix) }}
fail-fast: false
steps:
- uses: actions/checkout@v4
- run: om ci run --systems "${{ matrix.system }}" ".#default.${{ matrix.subflake }}"
tip
If your builds fail due to GitHubโs rate limiting, consider passing --extra-access-tokens
(see an example PR). If you get rate limits when accessing github:nix-systems
, use this workaround.
Configuring
By default, om ci
will build the top-level flake, but you can tell it to build sub-flakes (here, ./dir1
and ./dir2
) by adding the following output to your top-level flake:
# myproject/flake.nix
{
om.ci.default = {
dir1 = {
dir = "dir1";
};
dir2 = {
dir = "dir2";
overrideInputs.myproject = ./.;
};
}
}
You can have more than one CI configuration. For eg., om ci run .#foo
will run the configuration from om.ci.foo
flake output.
Custom CI actions
You can define custom CI actions in your flake, which will be run as part of om ci run
. For example, to run tests in the nix develop shell:
{
om.ci.default = {
root = {
dir = ".";
steps = {
# The build step is enabled by default. It builds all flake outputs.
build.enable = true;
# Other steps include: lockfile & flake-check
# Users can define custom steps to run any arbitrary flake app or devShell command.
custom = {
# Here, we run cargo tests in the nix shell
# This equivalent to `nix develop .#default -c cargo test`
cargo-test = {
type = "devshell";
# name = "default"
command = [ "cargo" "test" ];
};
# We can also flake apps
# This is equivalent to `nix run .#check-closure-size`
closure-size = {
type = "app";
name = "check-closure-size";
};
};
};
};
};
}
For a real-world example of custom steps, checkout Omnixโs configuration.
Examples
Some real-world examples of how om ci
is used with specific configurations:
warning
These examples use the predecessor, nixci
, so you want to replace nixci
with om ci
wherever applicable.
- omnix
- services-flake
- nixos-flake
- haskell-flake
- Hereโs a blog post that talks about how it is used in haskell-flake
- superposition
- haskell-rust-ffi-template
What it does
- Check that the Nix version is not tool old (using
om health
) - Determine the list of flakes in the repo to build
- By default, this is the root flake.
- The user can also explicitly specify multiple sub-flakes in
om.ci.default
output of their root flake.
- For each (sub)flake identified,
om ci run
will run the following steps:- Check that
flake.lock
is up to date, if applicable. - Build all flake outputs, using devour-flake1
- Then, print the built store paths to stdout
- Run
nix flake check
- Run user defined custom steps
- Check that
Support for flake-schemas is planned
See also
- github-nix-ci - A simple NixOS & nix-darwin module for self-hosting GitHub runners
- jenkins-nix-ci - Jenkins NixOS module that supports
nixci
(predecessor ofom ci
) as a Groovy function - cachix-push - A flake-parts module that provides an app to enable whitelisted pushing and pinning of store paths to cachix.
om init
The om init
command provides a better nix flake init
experience. Specifically, it provides:
- a registry of flake templates that you can choose from
- support for template paramters that can be filled in by the user
To get started, run:
om init -o ~/myproject
This will prompt you to choose a template from the builtin registry (see below section), and then initialize it in the myproject
directory.
Builtin registry
The builtin registry (stored in a flake) contains the following templates:
Initializing your own project templates
If your flake provides a om.templates
output (see below section), then om init
will recognize it. For example:
om init -o ~/myproject github:srid/haskell-flake
Because haskell-flake has a om.templates
output, om init
will prompt you to fill in the parameters defined in the template and initialize it.
You can also explicitly specify the template to choose from the flake:
om init -o ~/myproject github:srid/haskell-flake#haskell-flake
If there are multiple templates in the flake (as is the case with the builtin registry), omnix will the prompt the user to choose from them.
Configuration spec
Omnix templates can be defined by adding a om.template
flake output. This should be an attrset of templates. The value should contain the keys template
(referring to original flake template) as well as params
, defined as follows:
There are two kinds of params. String params are defined as follows:
{
name = "package-name";
description = "Name of the Rust package";
placeholder = "rust-nix-template";
}
Here, when prompting for this param, the user-provided value if any will replace the given placeholder
text across all files in the template.
Boolean params are defined as follows:
{
name = "vscode";
description = "Include the VSCode settings folder (./.vscode)";
paths = [ ".vscode" ];
value = true;
}
Here, if the user enables this param, the path globs specified in paths
will be retained in the template. Otherwise, the paths will be deleted. The value
key provides a default value; which key is supported for string params as well.
Both parameter types are distinguished by the presence of the relevant keys (placeholder
for string, paths
for boolean).
Testing templates
The configuration can also include a tests
key that defines a list of tests to run on the template. Each test is an attrset with params
and asserts
keys that indicates the parameter values to test along with the path existance assertions. For example:
{
tests = {
default = {
# systems = [ ]; # Optional whitelist of systems to limit this test to
params = {
username = "john";
git-email = "[email protected]";
git-name = "John Doe";
neovim = true;
};
asserts = {
# Path assertion tests under template output
source = {
# true means the path must exist; false means it must not exist
"modules/home/neovim/default.nix" = true;
".github/workflows" = false;
};
# Path assertion tests under the output of a Nix package
packages."homeConfigurations.john.activationPackage" = {
"home-path/bin/nvim" = true;
};
};
};
};
}
Release history
Unreleased
Enhancements
om develop
: New commandom init
- Initial working version of
om init
command
- Initial working version of
om health
- Display Nix installer used (supports DetSys installer)
- Display information in Markdown
- Remove RAM/disk space checks, moving them to โinformationโ section
- Add shell check, to ensure its dotfiles are managed by Nix.
om ci
- Support for remote builds over SSH (via
--on
option) - Support for CI steps
- Run
nix flake check
on all subflakes (#200) - Ability to add a custom CI step. For example, to run arbitrary commands.
- Run
- Add
--accept-flake-config
- Add
--results=FILE
to store CI results as JSON in a file - Misc
- Avoid running
nix-store
command multiple times (#224) - Locally cache
github:nix-systems
(to avoid Github API rate limit)
- Avoid running
- Support for remote builds over SSH (via
Fixes
om ci run
: The--override-input
option mandatedflake/
prefix (nixci legacy) which is no longer necessary in this release.om health
: Usewhoami
to determine username which is more reliable than relying onUSER
environment variable
Backward-incompatible changes
nix-health
andnixci
flake output configurations are no longer supported.om ci build
has been renamed toom ci run
.
0.1.0 (2024-08-08)
Initial release of omnix.