2021-06-03 20:26:57 -07:00
|
|
|
|
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-module-abstractions">
|
|
|
|
|
<title>Abstractions</title>
|
|
|
|
|
<para>
|
|
|
|
|
If you find yourself repeating yourself over and over, it’s time to
|
|
|
|
|
abstract. Take, for instance, this Apache HTTP Server configuration:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-06-03 20:26:57 -07:00
|
|
|
|
{
|
|
|
|
|
services.httpd.virtualHosts =
|
|
|
|
|
{ "blog.example.org" = {
|
|
|
|
|
documentRoot = "/webroot/blog.example.org";
|
|
|
|
|
adminAddr = "alice@example.org";
|
|
|
|
|
forceSSL = true;
|
|
|
|
|
enableACME = true;
|
|
|
|
|
enablePHP = true;
|
|
|
|
|
};
|
|
|
|
|
"wiki.example.org" = {
|
|
|
|
|
documentRoot = "/webroot/wiki.example.org";
|
|
|
|
|
adminAddr = "alice@example.org";
|
|
|
|
|
forceSSL = true;
|
|
|
|
|
enableACME = true;
|
|
|
|
|
enablePHP = true;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
It defines two virtual hosts with nearly identical configuration;
|
|
|
|
|
the only difference is the document root directories. To prevent
|
|
|
|
|
this duplication, we can use a <literal>let</literal>:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-06-03 20:26:57 -07:00
|
|
|
|
let
|
|
|
|
|
commonConfig =
|
|
|
|
|
{ adminAddr = "alice@example.org";
|
|
|
|
|
forceSSL = true;
|
|
|
|
|
enableACME = true;
|
|
|
|
|
};
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
services.httpd.virtualHosts =
|
|
|
|
|
{ "blog.example.org" = (commonConfig // { documentRoot = "/webroot/blog.example.org"; });
|
|
|
|
|
"wiki.example.org" = (commonConfig // { documentRoot = "/webroot/wiki.example.com"; });
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
The <literal>let commonConfig = ...</literal> defines a variable
|
|
|
|
|
named <literal>commonConfig</literal>. The <literal>//</literal>
|
|
|
|
|
operator merges two attribute sets, so the configuration of the
|
|
|
|
|
second virtual host is the set <literal>commonConfig</literal>
|
|
|
|
|
extended with the document root option.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
You can write a <literal>let</literal> wherever an expression is
|
|
|
|
|
allowed. Thus, you also could have written:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-06-03 20:26:57 -07:00
|
|
|
|
{
|
|
|
|
|
services.httpd.virtualHosts =
|
|
|
|
|
let commonConfig = ...; in
|
|
|
|
|
{ "blog.example.org" = (commonConfig // { ... })
|
|
|
|
|
"wiki.example.org" = (commonConfig // { ... })
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
but not <literal>{ let commonConfig = ...; in ...; }</literal> since
|
|
|
|
|
attributes (as opposed to attribute values) are not expressions.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
<emphasis role="strong">Functions</emphasis> provide another method
|
|
|
|
|
of abstraction. For instance, suppose that we want to generate lots
|
|
|
|
|
of different virtual hosts, all with identical configuration except
|
|
|
|
|
for the document root. This can be done as follows:
|
|
|
|
|
</para>
|
2022-12-21 22:00:27 +01:00
|
|
|
|
<programlisting language="nix">
|
2021-06-03 20:26:57 -07:00
|
|
|
|
{
|
|
|
|
|
services.httpd.virtualHosts =
|
|
|
|
|
let
|
|
|
|
|
makeVirtualHost = webroot:
|
|
|
|
|
{ documentRoot = webroot;
|
|
|
|
|
adminAddr = "alice@example.org";
|
|
|
|
|
forceSSL = true;
|
|
|
|
|
enableACME = true;
|
|
|
|
|
};
|
|
|
|
|
in
|
|
|
|
|
{ "example.org" = (makeVirtualHost "/webroot/example.org");
|
|
|
|
|
"example.com" = (makeVirtualHost "/webroot/example.com");
|
|
|
|
|
"example.gov" = (makeVirtualHost "/webroot/example.gov");
|
|
|
|
|
"example.nl" = (makeVirtualHost "/webroot/example.nl");
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
Here, <literal>makeVirtualHost</literal> is a function that takes a
|
|
|
|
|
single argument <literal>webroot</literal> and returns the
|
|
|
|
|
configuration for a virtual host. That function is then called for
|
|
|
|
|
several names to produce the list of virtual host configurations.
|
|
|
|
|
</para>
|
|
|
|
|
</section>
|