nix functions
2025-07-23 UTCFunctions in nix can be very confusing, as nix is very different to your traditional programming languages, being entirely functional.
The basics
let
f = arg: arg + 1;
in
f 5 # evaluates to 6
Basic function syntax can be done as above, if we want multiple arguments, there are several ways to do it
let
add = num_1: num_2: num_1 + num_2;
in
add 1 3 # evaluates to 4
Add is a curried function and num_1
is actually a function too!, it just wraps around the other one providing the ability for two arguments. Think of it like this, first we apply num_1
leaving us with num_2: 1 + num_2
, since we applied num_1
we now have num_2
and then by just applying that we get 1 + 3
which is 4. Curried functions are applied over several steps until we get a final value.
There is another, more boring way to do “multiple” arguments; attr sets.
let
add = { num_1 , num_2 }: num_1 + num_2;
in
add { num_1 = 1; num_2 = 6; } # evaluates to 7
Here, we have a attr set with keys num_1
and num_2
. To call the function we must construct a set with the keys inside it, this ends up being more verbose but is good when you want to be a bit more clear
Example
services.caddy = {
enable = true;
virtualHosts = let
mkReverseProxy = {domain, ip}: {
${domain} = {
extraConfig = ''
tls internal
reverse_proxy ${ip} {
transport http {
tls
tls_insecure_skip_verify
}
}
'';
};
};
proxies = [
{ domain = "proxmox-1.home.com"; ip = "192.168.0.230:8006"; }
{ domain = "proxmox-2.home.com"; ip = "192.168.0.231:8006"; }
{ domain = "jellyfin.home.com"; ip = "localhost:8096"; }
];
in
builtins.foldl' (acc: val: acc // mkReverseProxy val) {} proxies;
};
Here, we have a few things, we define a function mkReverseProxy
which takes in an attr set with the domain and ip to proxy to and makes the required configuration for caddy. Then we make a list of those function inputs in the proxy list, after that we use builtins.foldl'
this function simply takes another function as it’s argument. builtins.foldl'
exists to recurse over a list applying a function to each input and accumulating the output. We call the function with the function acc: val: acc // mkReverseProxy val
, which adds the result of mkReverseProxy val
to acc
, our augments to this function are {}
and the list of proxies. {}
is just the starting state of our accumulator, we don’t need one so we use an empty set.