···
TemporaryFileSystem = [ "/" ];
19
-
"/run/current-system/kernel-modules"
19
+
"/run/booted-system/kernel-modules"
# Give capabilities to load the module and configure it
···
configFormat = pkgs.formats.json {};
34
-
mkDefaultAttrs = lib.mapAttrs (n: v: lib.mkDefault v);
34
+
# Generate the config file of instance `name`
36
+
configFormat.generate "jool-nat64-${name}.conf"
37
+
(cfg.nat64.${name} // { instance = name; });
39
+
configFormat.generate "jool-siit-${name}.conf"
40
+
(cfg.siit.${name} // { instance = name; });
43
+
nat64Options = lib.types.submodule {
44
+
# The format is plain JSON
45
+
freeformType = configFormat.type;
46
+
# Some options with a default value
47
+
options.framework = lib.mkOption {
48
+
type = lib.types.enum [ "netfilter" "iptables" ];
49
+
default = "netfilter";
50
+
description = lib.mdDoc ''
51
+
The framework to use for attaching Jool's translation to the exist
52
+
kernel packet processing rules. See the
53
+
[documentation](https://nicmx.github.io/Jool/en/intro-jool.html#design)
54
+
for the differences between the two options.
57
+
options.global.pool6 = lib.mkOption {
58
+
type = lib.types.strMatching "[[:xdigit:]:]+/[[:digit:]]+"
59
+
// { description = "Network prefix in CIDR notation"; };
60
+
default = "64:ff9b::/96";
61
+
description = lib.mdDoc ''
62
+
The prefix used for embedding IPv4 into IPv6 addresses.
63
+
Defaults to the well-known NAT64 prefix, defined by
64
+
[RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
70
+
siitOptions = lib.types.submodule {
71
+
# The format is, again, plain JSON
72
+
freeformType = configFormat.type;
73
+
# Some options with a default value
74
+
options = { inherit (nat64Options.getSubOptions []) framework; };
37
-
instance = "default";
38
-
framework = "netfilter";
39
-
global.pool6 = "64:ff9b::/96";
77
+
makeNat64Unit = name: opts: {
78
+
"jool-nat64-${name}" = {
79
+
description = "Jool, NAT64 setup of instance ${name}";
80
+
documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
81
+
after = [ "network.target" ];
82
+
wantedBy = [ "multi-user.target" ];
85
+
RemainAfterExit = true;
86
+
ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
87
+
ExecStart = "${jool-cli}/bin/jool file handle ${nat64Conf name}";
88
+
ExecStop = "${jool-cli}/bin/jool -f ${nat64Conf name} instance remove";
42
-
instance = "default";
43
-
framework = "netfilter";
93
+
makeSiitUnit = name: opts: {
94
+
"jool-siit-${name}" = {
95
+
description = "Jool, SIIT setup of instance ${name}";
96
+
documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
97
+
after = [ "network.target" ];
98
+
wantedBy = [ "multi-user.target" ];
101
+
RemainAfterExit = true;
102
+
ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
103
+
ExecStart = "${jool-cli}/bin/jool_siit file handle ${siitConf name}";
104
+
ExecStop = "${jool-cli}/bin/jool_siit -f ${siitConf name} instance remove";
46
-
nat64Conf = configFormat.generate "jool-nat64.conf" cfg.nat64.config;
47
-
siitConf = configFormat.generate "jool-siit.conf" cfg.siit.config;
109
+
checkNat64 = name: _: ''
110
+
printf 'Validating Jool configuration for NAT64 instance "${name}"... '
111
+
jool file check ${nat64Conf name}
112
+
printf 'Ok.\n'; touch "$out"
115
+
checkSiit = name: _: ''
116
+
printf 'Validating Jool configuration for SIIT instance "${name}"... '
117
+
jool_siit file check ${siitConf name}
118
+
printf 'Ok.\n'; touch "$out"
networking.jool.enable = lib.mkOption {
···
NAT64, analogous to the IPv4 NAPT. Refer to the upstream
[documentation](https://nicmx.github.io/Jool/en/intro-xlat.html) for
the supported modes of translation and how to configure them.
138
+
Enabling this option will install the Jool kernel module and the
139
+
command line tools for controlling it.
70
-
networking.jool.nat64.enable = lib.mkEnableOption (lib.mdDoc "a NAT64 instance of Jool.");
71
-
networking.jool.nat64.config = lib.mkOption {
72
-
type = configFormat.type;
73
-
default = defaultNat64;
143
+
networking.jool.nat64 = lib.mkOption {
144
+
type = lib.types.attrsOf nat64Options;
example = lib.literalExpression ''
76
-
# custom NAT64 prefix
77
-
global.pool6 = "2001:db8:64::/96";
149
+
# custom NAT64 prefix
150
+
global.pool6 = "2001:db8:64::/96";
81
-
{ # SSH 192.0.2.16 → 2001:db8:a::1
83
-
"ipv4 address" = "192.0.2.16#22";
84
-
"ipv6 address" = "2001:db8:a::1#22";
86
-
{ # DNS (TCP) 192.0.2.16 → 2001:db8:a::2
88
-
"ipv4 address" = "192.0.2.16#53";
89
-
"ipv6 address" = "2001:db8:a::2#53";
91
-
{ # DNS (UDP) 192.0.2.16 → 2001:db8:a::2
93
-
"ipv4 address" = "192.0.2.16#53";
94
-
"ipv6 address" = "2001:db8:a::2#53";
154
+
{ # SSH 192.0.2.16 → 2001:db8:a::1
155
+
"protocol" = "TCP";
156
+
"ipv4 address" = "192.0.2.16#22";
157
+
"ipv6 address" = "2001:db8:a::1#22";
159
+
{ # DNS (TCP) 192.0.2.16 → 2001:db8:a::2
160
+
"protocol" = "TCP";
161
+
"ipv4 address" = "192.0.2.16#53";
162
+
"ipv6 address" = "2001:db8:a::2#53";
164
+
{ # DNS (UDP) 192.0.2.16 → 2001:db8:a::2
165
+
"protocol" = "UDP";
166
+
"ipv4 address" = "192.0.2.16#53";
167
+
"ipv6 address" = "2001:db8:a::2#53";
99
-
# Ports for dynamic translation
100
-
{ protocol = "TCP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
101
-
{ protocol = "UDP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
102
-
{ protocol = "ICMP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
172
+
# Port ranges for dynamic translation
173
+
{ protocol = "TCP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
174
+
{ protocol = "UDP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
175
+
{ protocol = "ICMP"; prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
104
-
# Ports for static BIB entries
105
-
{ protocol = "TCP"; prefix = "192.0.2.16/32"; "port range" = "22"; }
106
-
{ protocol = "UDP"; prefix = "192.0.2.16/32"; "port range" = "53"; }
177
+
# Ports for static BIB entries
178
+
{ protocol = "TCP"; prefix = "192.0.2.16/32"; "port range" = "22"; }
179
+
{ protocol = "UDP"; prefix = "192.0.2.16/32"; "port range" = "53"; }
description = lib.mdDoc ''
111
-
The configuration of a stateful NAT64 instance of Jool managed through
112
-
NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
185
+
Definitions of NAT64 instances of Jool.
187
+
[documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
188
+
the available options. Also check out the
189
+
[tutorial](https://nicmx.github.io/Jool/en/run-nat64.html) for an
190
+
introduction to NAT64 and how to troubleshoot the setup.
192
+
The attribute name defines the name of the instance, with the main one
193
+
being `default`: this can be accessed from the command line without
194
+
specifying the name with `-i`.
116
-
Existing or more instances created manually will not interfere with the
117
-
NixOS instance, provided the respective `pool4` addresses and port
118
-
ranges are not overlapping.
197
+
Instances created imperatively from the command line will not interfere
198
+
with the NixOS instances, provided the respective `pool4` addresses and
199
+
port ranges are not overlapping.
122
-
Changes to the NixOS instance performed via `jool instance nixos-nat64`
123
-
are applied correctly but will be lost after restarting
124
-
`jool-nat64.service`.
203
+
Changes to an instance performed via `jool -i <name>` are applied
204
+
correctly but will be lost after restarting the respective
205
+
`jool-nat64-<name>.service`.
129
-
networking.jool.siit.enable = lib.mkEnableOption (lib.mdDoc "a SIIT instance of Jool.");
130
-
networking.jool.siit.config = lib.mkOption {
131
-
type = configFormat.type;
132
-
default = defaultSiit;
210
+
networking.jool.siit = lib.mkOption {
211
+
type = lib.types.attrsOf siitOptions;
example = lib.literalExpression ''
135
-
# Maps any IPv4 address x.y.z.t to 2001:db8::x.y.z.t and v.v.
136
-
pool6 = "2001:db8::/96";
216
+
# Maps any IPv4 address x.y.z.t to 2001:db8::x.y.z.t and v.v.
217
+
global.pool6 = "2001:db8::/96";
138
-
# Explicit address mappings
140
-
# 2001:db8:1:: ←→ 192.0.2.0
141
-
{ "ipv6 prefix": "2001:db8:1::/128", "ipv4 prefix": "192.0.2.0" }
142
-
# 2001:db8:1::x ←→ 198.51.100.x
143
-
{ "ipv6 prefix": "2001:db8:2::/120", "ipv4 prefix": "198.51.100.0/24" }
219
+
# Explicit address mappings
221
+
# 2001:db8:1:: ←→ 192.0.2.0
222
+
{ "ipv6 prefix" = "2001:db8:1::/128"; "ipv4 prefix" = "192.0.2.0"; }
223
+
# 2001:db8:1::x ←→ 198.51.100.x
224
+
{ "ipv6 prefix" = "2001:db8:2::/120"; "ipv4 prefix" = "198.51.100.0/24"; }
description = lib.mdDoc ''
148
-
The configuration of a SIIT instance of Jool managed through
149
-
NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
230
+
Definitions of SIIT instances of Jool.
232
+
[documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
233
+
the available options. Also check out the
234
+
[tutorial](https://nicmx.github.io/Jool/en/run-vanilla.html) for an
235
+
introduction to SIIT and how to troubleshoot the setup.
237
+
The attribute name defines the name of the instance, with the main one
238
+
being `default`: this can be accessed from the command line without
239
+
specifying the name with `-i`.
153
-
Existing or more instances created manually will not interfere with the
154
-
NixOS instance, provided the respective `EAMT` address mappings are not
242
+
Instances created imperatively from the command line will not interfere
243
+
with the NixOS instances, provided the respective EAMT addresses and
244
+
port ranges are not overlapping.
159
-
Changes to the NixOS instance performed via `jool instance nixos-siit`
160
-
are applied correctly but will be lost after restarting
161
-
`jool-siit.service`.
248
+
Changes to an instance performed via `jool -i <name>` are applied
249
+
correctly but will be lost after restarting the respective
250
+
`jool-siit-<name>.service`.
168
-
###### implementation
config = lib.mkIf cfg.enable {
171
-
environment.systemPackages = [ jool-cli ];
258
+
# Install kernel module and cli tools
boot.extraModulePackages = [ jool ];
174
-
systemd.services.jool-nat64 = lib.mkIf cfg.nat64.enable {
175
-
description = "Jool, NAT64 setup";
176
-
documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
177
-
after = [ "network.target" ];
178
-
wantedBy = [ "multi-user.target" ];
179
-
reloadIfChanged = true;
182
-
RemainAfterExit = true;
183
-
ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
184
-
ExecStart = "${jool-cli}/bin/jool file handle ${nat64Conf}";
185
-
ExecStop = "${jool-cli}/bin/jool -f ${nat64Conf} instance remove";
189
-
systemd.services.jool-siit = lib.mkIf cfg.siit.enable {
190
-
description = "Jool, SIIT setup";
191
-
documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
192
-
after = [ "network.target" ];
193
-
wantedBy = [ "multi-user.target" ];
194
-
reloadIfChanged = true;
197
-
RemainAfterExit = true;
198
-
ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
199
-
ExecStart = "${jool-cli}/bin/jool_siit file handle ${siitConf}";
200
-
ExecStop = "${jool-cli}/bin/jool_siit -f ${siitConf} instance remove";
204
-
system.checks = lib.singleton (pkgs.runCommand "jool-validated" {
205
-
nativeBuildInputs = [ pkgs.buildPackages.jool-cli ];
206
-
preferLocalBuild = true;
208
-
printf 'Validating Jool configuration... '
209
-
${lib.optionalString cfg.siit.enable "jool_siit file check ${siitConf}"}
210
-
${lib.optionalString cfg.nat64.enable "jool file check ${nat64Conf}"}
260
+
environment.systemPackages = [ jool-cli ];
215
-
networking.jool.nat64.config = mkDefaultAttrs defaultNat64;
216
-
networking.jool.siit.config = mkDefaultAttrs defaultSiit;
262
+
# Install services for each instance
263
+
systemd.services = lib.mkMerge
264
+
(lib.mapAttrsToList makeNat64Unit cfg.nat64 ++
265
+
lib.mapAttrsToList makeSiitUnit cfg.siit);
267
+
# Check the configuration of each instance
268
+
system.checks = lib.optional (cfg.nat64 != {} || cfg.siit != {})
269
+
(pkgs.runCommand "jool-validated"
271
+
nativeBuildInputs = with pkgs.buildPackages; [ jool-cli ];
272
+
preferLocalBuild = true;
275
+
(lib.mapAttrsToList checkNat64 cfg.nat64 ++
276
+
lib.mapAttrsToList checkSiit cfg.siit)));
meta.maintainers = with lib.maintainers; [ rnhmjoj ];