1# GNU Virtual Private Ethernet
2
3{
4 config,
5 pkgs,
6 lib,
7 ...
8}:
9
10let
11 inherit (lib) mkOption mkIf types;
12
13 cfg = config.services.gvpe;
14
15 finalConfig =
16 if cfg.configFile != null then
17 cfg.configFile
18 else if cfg.configText != null then
19 pkgs.writeTextFile {
20 name = "gvpe.conf";
21 text = cfg.configText;
22 }
23 else
24 throw "You must either specify contents of the config file or the config file itself for GVPE";
25
26 ifupScript =
27 if cfg.ipAddress == null || cfg.subnet == null then
28 throw "Specify IP address and subnet (with mask) for GVPE"
29 else if cfg.nodename == null then
30 throw "You must set node name for GVPE"
31 else
32 (pkgs.writeTextFile {
33 name = "gvpe-if-up";
34 text = ''
35 #! /bin/sh
36
37 export PATH=$PATH:${pkgs.iproute2}/sbin
38
39 ip link set dev $IFNAME up
40 ip address add ${cfg.ipAddress} dev $IFNAME
41 ip route add ${cfg.subnet} dev $IFNAME
42
43 ${cfg.customIFSetup}
44 '';
45 executable = true;
46 });
47in
48
49{
50 options = {
51 services.gvpe = {
52 enable = lib.mkEnableOption "gvpe";
53
54 nodename = mkOption {
55 default = null;
56 type = types.nullOr types.str;
57 description = ''
58 GVPE node name
59 '';
60 };
61 configText = mkOption {
62 default = null;
63 type = types.nullOr types.lines;
64 example = ''
65 tcp-port = 655
66 udp-port = 655
67 mtu = 1480
68 ifname = vpn0
69
70 node = alpha
71 hostname = alpha.example.org
72 connect = always
73 enable-udp = true
74 enable-tcp = true
75 on alpha if-up = if-up-0
76 on alpha pid-file = /var/gvpe/gvpe.pid
77 '';
78 description = ''
79 GVPE config contents
80 '';
81 };
82 configFile = mkOption {
83 default = null;
84 type = types.nullOr types.path;
85 example = "/root/my-gvpe-conf";
86 description = ''
87 GVPE config file, if already present
88 '';
89 };
90 ipAddress = mkOption {
91 default = null;
92 type = types.nullOr types.str;
93 description = ''
94 IP address to assign to GVPE interface
95 '';
96 };
97 subnet = mkOption {
98 default = null;
99 type = types.nullOr types.str;
100 example = "10.0.0.0/8";
101 description = ''
102 IP subnet assigned to GVPE network
103 '';
104 };
105 customIFSetup = mkOption {
106 default = "";
107 type = types.lines;
108 description = ''
109 Additional commands to apply in ifup script
110 '';
111 };
112 };
113 };
114 config = mkIf cfg.enable {
115 systemd.services.gvpe = {
116 description = "GNU Virtual Private Ethernet node";
117 documentation = [
118 "info:gvpe"
119 "man:gvpe(8)"
120 ];
121 after = [ "network.target" ];
122 wantedBy = [ "multi-user.target" ];
123
124 preStart = ''
125 mkdir -p /var/gvpe
126 mkdir -p /var/gvpe/pubkey
127 chown root /var/gvpe
128 chmod 700 /var/gvpe
129 cp ${finalConfig} /var/gvpe/gvpe.conf
130 cp ${ifupScript} /var/gvpe/if-up
131 '';
132
133 script =
134 "${pkgs.gvpe}/sbin/gvpe -c /var/gvpe -D ${cfg.nodename} "
135 + " ${cfg.nodename}.pid-file=/var/gvpe/gvpe.pid"
136 + " ${cfg.nodename}.if-up=if-up"
137 + " &> /var/log/gvpe";
138
139 serviceConfig.Restart = "always";
140 };
141 };
142}