Create your first Composition
So, you want to create your first composition? That’s cool!
Let’s get started on creating something simple & improving it step-by-step!
Starting fresh
First, we want to initialize the basic template wherever you feel like it
belongs:
cd somewhere
nxc init -t basic
You will then find the following files within:
composition.nix- This is the file where you will describe your nodes
flake.nix- This is the nix flakes that provides the information of your composition to NixOS-Compose, we will edit this later.
nxc.json- This is the saved user preferences.
Editing your composition
Our composition is described in composition.nix, we can’t go ahead & add a
package to our node by doing this:
composition.nix:
{ pkgs, ... }: {
roles = {
foo = { pkgs, lib, ... }:
- { };
+ {
+ environment.systemPackages = with pkgs; [ socat ];
+ };
};
testScript = ''
foo.succeed("true")
'';
}
Testing it locally
That’s great, we now have a node with the socat package installed, let’s go
ahead and test this.
We can run the following commands to do so:
nxc build
nxc start -I
This will build, then start your composition in a VM (running QEMU).
The -I parameter in nxc start starts a Python repl in your terminal, so we
can interact with your composition directly.
Testing manually
Now that our composition is running & that we are in repl, we can run tests manually!
Start
Let’s first start our composition by running the following:
start_all()
This will start the VM and execute nothing else.
Tip
Running
start_all()is not necessary in compositions, but it ensures that ALL your nodes are started & ready to be used, even if you don’t reference it in your test_script!
Run a command that succeeds
Now let’s test that socat properly works by running the following command in
repl:
foo.succeed("socat /dev/null TCP4:google.com:443")
Of note in the example above:
foois our node (hostname)succeed(...)is a function provided by the NixOS-test environment to check if a command succeeds."socat ..."is the command we are running on the node.
If everything goes well, the VM will print out the following:
(finished: must succeed: socat /dev/null TCP4:google.com:443, in 0.19 seconds)
Run a command that fails
If we try running a command that fails:
foo.succeed("socat /dev/null TCP4:bad:443")
repl will output a stacktrace of our command failing:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/nix/store/097dh3q9rr4i4mzhpr26cww2hnxlas6q-python3-3.13.15-env/lib/python3.13/site-packages/nixos_compose/driver/machine.py", line 482, in succeed
raise RuntimeError(
f"command `{command}` failed (exit code {status})"
)
RuntimeError: command `socat /dev/null TCP4:bad:443` failed (exit code 1)
Exit
You can exit repl by running:
exit()
Automated testing
Cool, our manual socat tests work!
That’s great & all, but we want to make sure that we run this exact set of commands everytime we start the composition!
So let’s get to it, let’s write our first test-script!
Add your own test-script
NixOS-Compose can execute your test-script located in your composition file. Let’s use the example above as our test:
composition.nix:
{ pkgs, ... }: {
roles = {
foo = { pkgs, lib, ... }:
{
environment.systemPackages = with pkgs; [ socat ];
};
};
testScript = ''
- foo.succeed("true")
+ foo.succeed("socat /dev/null TCP4:google.com:443")
+ foo.fail("socat /dev/null TCP4:bad:443")
'';
}
You can then run your composition with:
nxc build
nxc start -t
The -t parameter in nxc start starts the test-scripts automatically.
It should output the following line if all tests succeed:
test script finished in 20.34s
Running on another flavour
Now that our composition is ready to be used, we can start it with other flavours.
Let’s try locally, with docker first, with the following:
nxc build -f docker
nxc start -f docker -t
Running on an experiment platform
Cool, it runs well locally. Let’s try on Grid5000.
First of all, you will need to follow the install process for Grid5000 as described here.
Once that’s done, we can build & start our composition.
Building on Grid5000
Start a fresh SSH session, oarsub -I if required by your preffered method.
On this shell, you want to have nix & nxc available.
- One way to enable
nixis to run thesetup-remote-nix.sh(mostly limited access), ornix-user-chroot.sh. - One way to enable
nxcis by having it installed by usingpip install.
Once this is done, you can run:
nxc build -f g5k-nfs-store
Starting on Grid5000
Start another fresh SSH session, stay on the frontend.
On this shell you want to have nxc available. DON’T user-chroot nix, as that
will break you OAR accesses.
Once this is done, you can order your node by running:
export $(oarsub -l nodes=1,walltime=1:0:0 "$(nxc helper g5k_script) 1h" | grep OAR_JOB_ID)
echo $OAR_JOB_ID
The above command will order 1 node (node=1) for 1 hour (walltime=1:0:0),
with the correct setup script (nxc helper g5k_script). It will re-export
$OAR_JOB_ID for future commands & oardel.
You can then start with the following:
nxc start -m OAR.$OAR_JOB_ID.stdout -W -f g5k-nfs-store
By default, the test-script won’t run here. You can use the following command to connect to your node:
nxc connect
Once you are done, you can stop your node by deleting your job reservation by running:
oardel $OAR_JOB_ID