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