1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.softether;
7
8 package = cfg.package.override { inherit (cfg) dataDir; };
9
10in
11{
12
13 ###### interface
14
15 options = {
16
17 services.softether = {
18
19 enable = mkEnableOption (lib.mdDoc "SoftEther VPN services");
20
21 package = mkOption {
22 type = types.package;
23 default = pkgs.softether;
24 defaultText = literalExpression "pkgs.softether";
25 description = lib.mdDoc ''
26 softether derivation to use.
27 '';
28 };
29
30 vpnserver.enable = mkEnableOption (lib.mdDoc "SoftEther VPN Server");
31
32 vpnbridge.enable = mkEnableOption (lib.mdDoc "SoftEther VPN Bridge");
33
34 vpnclient = {
35 enable = mkEnableOption (lib.mdDoc "SoftEther VPN Client");
36 up = mkOption {
37 type = types.lines;
38 default = "";
39 description = lib.mdDoc ''
40 Shell commands executed when the Virtual Network Adapter(s) is/are starting.
41 '';
42 };
43 down = mkOption {
44 type = types.lines;
45 default = "";
46 description = lib.mdDoc ''
47 Shell commands executed when the Virtual Network Adapter(s) is/are shutting down.
48 '';
49 };
50 };
51
52 dataDir = mkOption {
53 type = types.path;
54 default = "/var/lib/softether";
55 description = lib.mdDoc ''
56 Data directory for SoftEther VPN.
57 '';
58 };
59
60 };
61
62 };
63
64 ###### implementation
65
66 config = mkIf cfg.enable (
67
68 mkMerge [{
69 environment.systemPackages = [ package ];
70
71 systemd.services.softether-init = {
72 description = "SoftEther VPN services initial task";
73 wantedBy = [ "network.target" ];
74 serviceConfig = {
75 Type = "oneshot";
76 RemainAfterExit = false;
77 };
78 script = ''
79 for d in vpnserver vpnbridge vpnclient vpncmd; do
80 if ! test -e ${cfg.dataDir}/$d; then
81 ${pkgs.coreutils}/bin/mkdir -m0700 -p ${cfg.dataDir}/$d
82 install -m0600 ${package}${cfg.dataDir}/$d/hamcore.se2 ${cfg.dataDir}/$d/hamcore.se2
83 fi
84 done
85 rm -rf ${cfg.dataDir}/vpncmd/vpncmd
86 ln -s ${package}${cfg.dataDir}/vpncmd/vpncmd ${cfg.dataDir}/vpncmd/vpncmd
87 '';
88 };
89 }
90
91 (mkIf cfg.vpnserver.enable {
92 systemd.services.vpnserver = {
93 description = "SoftEther VPN Server";
94 after = [ "softether-init.service" ];
95 requires = [ "softether-init.service" ];
96 wantedBy = [ "network.target" ];
97 serviceConfig = {
98 Type = "forking";
99 ExecStart = "${package}/bin/vpnserver start";
100 ExecStop = "${package}/bin/vpnserver stop";
101 };
102 preStart = ''
103 rm -rf ${cfg.dataDir}/vpnserver/vpnserver
104 ln -s ${package}${cfg.dataDir}/vpnserver/vpnserver ${cfg.dataDir}/vpnserver/vpnserver
105 '';
106 postStop = ''
107 rm -rf ${cfg.dataDir}/vpnserver/vpnserver
108 '';
109 };
110 })
111
112 (mkIf cfg.vpnbridge.enable {
113 systemd.services.vpnbridge = {
114 description = "SoftEther VPN Bridge";
115 after = [ "softether-init.service" ];
116 requires = [ "softether-init.service" ];
117 wantedBy = [ "network.target" ];
118 serviceConfig = {
119 Type = "forking";
120 ExecStart = "${package}/bin/vpnbridge start";
121 ExecStop = "${package}/bin/vpnbridge stop";
122 };
123 preStart = ''
124 rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge
125 ln -s ${package}${cfg.dataDir}/vpnbridge/vpnbridge ${cfg.dataDir}/vpnbridge/vpnbridge
126 '';
127 postStop = ''
128 rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge
129 '';
130 };
131 })
132
133 (mkIf cfg.vpnclient.enable {
134 systemd.services.vpnclient = {
135 description = "SoftEther VPN Client";
136 after = [ "softether-init.service" ];
137 requires = [ "softether-init.service" ];
138 wantedBy = [ "network.target" ];
139 serviceConfig = {
140 Type = "forking";
141 ExecStart = "${package}/bin/vpnclient start";
142 ExecStop = "${package}/bin/vpnclient stop";
143 };
144 preStart = ''
145 rm -rf ${cfg.dataDir}/vpnclient/vpnclient
146 ln -s ${package}${cfg.dataDir}/vpnclient/vpnclient ${cfg.dataDir}/vpnclient/vpnclient
147 '';
148 postStart = ''
149 sleep 1
150 ${cfg.vpnclient.up}
151 '';
152 postStop = ''
153 rm -rf ${cfg.dataDir}/vpnclient/vpnclient
154 sleep 1
155 ${cfg.vpnclient.down}
156 '';
157 };
158 boot.kernelModules = [ "tun" ];
159 })
160
161 ]);
162
163}