Skip to content

Commit

Permalink
Feat/openvpn (#18)
Browse files Browse the repository at this point in the history
* feat: added implementation of vpn-client in a dedicated service

* fix: removed vpn client autostart

* fix: missing toString operation on integer

* feat: added implementation of vpn-server in a dedicated service

* fix: typo in type of ipPool.filePath

* fix: typo in route attribute

* fix: used wrong concatenation operand for two strings
  • Loading branch information
LilianSchall authored Feb 12, 2025
1 parent 9049ffa commit b186a98
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 0 deletions.
2 changes: 2 additions & 0 deletions modules/services/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
./netauth.nix
./nginx.nix
./openssh.nix
./vpn-client.nix
./vpn-server.nix
];
}
63 changes: 63 additions & 0 deletions modules/services/vpn-client.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{config, lib, pkgs, ...}:
let
cfg = config.fndx.services.vpn-client;
in
with lib;
{
options = {
fndx.services.vpn-client = {
enable = mkEnableOption "VPN Client Service";
serverAddress = mkOption {
type = types.str;
example = "vpn.example.com";
description = "The address of the VPN server";
};
port = mkOption {
type = types.int;
default = 1194;
description = "The port of the VPN server";
};
caPath = mkOption {
type = types.path;
example = "/etc/openvpn/ca.crt";
description = "The path to the CA certificate";
};
certPath = mkOption {
type = types.path;
example = "/etc/openvpn/client.crt";
description = "The path to the client certificate";
};
keyPath = mkOption {
type = types.path;
example = "/etc/openvpn/client.key";
description = "The path to the client key";
};
};
};

config = mkIf cfg.enable {
services.openvpn.servers = {
client = {
config = ''
client
dev tun
proto udp
remote ${cfg.serverAddress} ${toString cfg.port}
resolv-retry infinite
nobind
persist-tun
ca ${toString cfg.caPath}
cert ${toString cfg.certPath}
key ${toString cfg.keyPath}
verb 3
'';
updateResolvConf = true;
};
};

# this is a hack to make sure the openvpn-client service is not started by default
# You can start it manually with `systemctl start openvpn-client.service`
systemd.services."openvpn-client".wantedBy = lib.mkForce [];
};
}
120 changes: 120 additions & 0 deletions modules/services/vpn-server.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{config, lib, pkgs, ...}:
with lib;
let
cfg = config.fndx.services.vpn-server;
route = types.submodule {
options = {
subnet = mkOption {
type = types.str;
example = "192.168.0.0";
description = "The subnet to route";
};
netmask = mkOption {
type = types.str;
example = "255.255.255.0";
description = "The netmask of the subnet";
};
};
};
in
{
options = {
fndx.services.vpn-server = {
enable = mkEnableOption "VPN Server Service";
port = mkOption {
type = types.int;
default = 1194;
description = "The port of the VPN server";
};
caPath = mkOption {
type = types.path;
example = "/etc/openvpn/ca.crt";
description = "The path to the CA certificate";
};
certPath = mkOption {
type = types.path;
example = "/etc/openvpn/client.crt";
description = "The path to the client certificate";
};
keyPath = mkOption {
type = types.path;
example = "/etc/openvpn/client.key";
description = "The path to the client key";
};
dhPath = mkOption {
type = types.path;
example = "/etc/openvpn/dh.pem";
description = "The path to the Diffie-Hellman parameters";
};
networkSubnet = mkOption {
type = types.str;
default = "10.8.0.0";
description = "The network subnet for the VPN";
};
networkNetmask = mkOption {
type = types.str;
default = "255.255.255.0";
description = "The network netmask for the VPN";
};

persistentIpPool = {
enable = mkEnableOption "Enable persistent IP pool";
filePath = mkOption {
type = types.path;
example = "/etc/openvpn/ipp.txt";
description = "The path to the file that stores the persistent IP pool";
};
};

routes = mkOption {
type = types.listOf route;
default = [];
description = "The routes to add to the VPN server";
};

dhcp-server = {
enable = mkEnableOption "Enable Routing to dhcp server";
address = mkOption {
type = types.str;
example = "10.8.0.1";
};
};
};
};

config = mkIf cfg.enable {
services.openvpn.servers = {
server = {
config = ''
port ${toString cfg.port}
proto udp
dev tun
ca ${toString cfg.caPath}
cert ${toString cfg.certPath}
key ${toString cfg.keyPath}
dh ${toString cfg.dhPath}
topology subnet
server ${cfg.networkSubnet} ${cfg.networkNetmask}
${optionalString (cfg.persistentIpPool.enable) ''
ifconfig-pool-persist ${cfg.persistentIpPool.filePath}
''}
keepalive 20 120
verb 1
explicit-exit-notify 1
push "tcp-nodelay 1"
${optionalString (cfg.dhcp-server.enable) ''
push "dhcp-option DNS ${cfg.dhcp-server.address}"
''}
'' + concatStringsSep "\n" (map (route: ''
push "route ${route.subnet} ${route.netmask}"
'') cfg.routes);
};
};
};
}

0 comments on commit b186a98

Please sign in to comment.