nixos modules for convenient deployment of cloud resources
1{pkgs, lib, config, options, ...}: let
2 l = lib;
3 t = l.types;
4 taggedPorts = config.networking.firewall.public;
5 cfg = config.providers.hetzner.firewall;
6in {
7 options = {
8 providers.hetzner.firewall = {
9 id = l.mkOption {
10 type = t.ints.unsigned;
11 description = "The ID of the firewall to update.";
12 };
13 app = l.mkOption {
14 type = t.package;
15 readOnly = true;
16 description = ''
17 The generated app for this provider, run it to apply the configuration.
18
19 For this to work, you need to set the `HETZNER_API_TOKEN` environment variable to a valid API token from Hetzner.
20 '';
21 };
22 };
23 };
24
25 config = let
26 mkRule = proto: tag: port: {
27 description = tag;
28 direction = "in";
29 protocol = proto;
30 port =
31 if l.isAttrs port
32 then l.concatMapStringsSep "-" toString [port.from port.to]
33 else toString port;
34 };
35 mkTcpRule = mkRule "tcp";
36 mkUdpRule = mkRule "udp";
37 firewallRules = pkgs.writers.writeJSON "hetzner-firewall-${toString cfg.id}-rules.json" {
38 rules = l.flatten (
39 l.mapAttrsToList
40 (tag: ports: [
41 (l.map (mkTcpRule tag) ports.allowedTCPPorts)
42 (l.map (mkTcpRule tag) ports.allowedTCPPortRanges)
43 (l.map (mkUdpRule tag) ports.allowedUDPPorts)
44 (l.map (mkUdpRule tag) ports.allowedUDPPortRanges)
45 ])
46 taggedPorts
47 );
48 };
49 in {
50 providers.hetzner.firewall.app = pkgs.writers.writeNu "apply-hetzner" ''
51 let firewallId = ${toString cfg.id}
52 let rulesFile = ${firewallRules}
53 ${l.fileContents ./app.nu}
54 '';
55 };
56}