mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-11-18 13:45:02 +01:00
the conversion procedure is simple: - find all things that look like options, ie calls to either `mkOption` or `lib.mkOption` that take an attrset. remember the attrset as the option - for all options, find a `description` attribute who's value is not a call to `mdDoc` or `lib.mdDoc` - textually convert the entire value of the attribute to MD with a few simple regexes (the set from mdize-module.sh) - if the change produced a change in the manual output, discard - if the change kept the manual unchanged, add some text to the description to make sure we've actually found an option. if the manual changes this time, keep the converted description this procedure converts 80% of nixos options to markdown. around 2000 options remain to be inspected, but most of those fail the "does not change the manual output check": currently the MD conversion process does not faithfully convert docbook tags like <code> and <package>, so any option using such tags will not be converted at all.
220 lines
6.4 KiB
Nix
220 lines
6.4 KiB
Nix
{ config, lib, pkgs, ... }:
|
||
|
||
with lib;
|
||
|
||
let
|
||
|
||
cfg = config.services.openvpn;
|
||
|
||
inherit (pkgs) openvpn;
|
||
|
||
makeOpenVPNJob = cfg: name:
|
||
let
|
||
|
||
path = makeBinPath (getAttr "openvpn-${name}" config.systemd.services).path;
|
||
|
||
upScript = ''
|
||
#! /bin/sh
|
||
export PATH=${path}
|
||
|
||
# For convenience in client scripts, extract the remote domain
|
||
# name and name server.
|
||
for var in ''${!foreign_option_*}; do
|
||
x=(''${!var})
|
||
if [ "''${x[0]}" = dhcp-option ]; then
|
||
if [ "''${x[1]}" = DOMAIN ]; then domain="''${x[2]}"
|
||
elif [ "''${x[1]}" = DNS ]; then nameserver="''${x[2]}"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
${cfg.up}
|
||
${optionalString cfg.updateResolvConf
|
||
"${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"}
|
||
'';
|
||
|
||
downScript = ''
|
||
#! /bin/sh
|
||
export PATH=${path}
|
||
${optionalString cfg.updateResolvConf
|
||
"${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"}
|
||
${cfg.down}
|
||
'';
|
||
|
||
configFile = pkgs.writeText "openvpn-config-${name}"
|
||
''
|
||
errors-to-stderr
|
||
${optionalString (cfg.up != "" || cfg.down != "" || cfg.updateResolvConf) "script-security 2"}
|
||
${cfg.config}
|
||
${optionalString (cfg.up != "" || cfg.updateResolvConf)
|
||
"up ${pkgs.writeScript "openvpn-${name}-up" upScript}"}
|
||
${optionalString (cfg.down != "" || cfg.updateResolvConf)
|
||
"down ${pkgs.writeScript "openvpn-${name}-down" downScript}"}
|
||
${optionalString (cfg.authUserPass != null)
|
||
"auth-user-pass ${pkgs.writeText "openvpn-credentials-${name}" ''
|
||
${cfg.authUserPass.username}
|
||
${cfg.authUserPass.password}
|
||
''}"}
|
||
'';
|
||
|
||
in {
|
||
description = "OpenVPN instance ‘${name}’";
|
||
|
||
wantedBy = optional cfg.autoStart "multi-user.target";
|
||
after = [ "network.target" ];
|
||
|
||
path = [ pkgs.iptables pkgs.iproute2 pkgs.nettools ];
|
||
|
||
serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --suppress-timestamps --config ${configFile}";
|
||
serviceConfig.Restart = "always";
|
||
serviceConfig.Type = "notify";
|
||
};
|
||
|
||
in
|
||
|
||
{
|
||
imports = [
|
||
(mkRemovedOptionModule [ "services" "openvpn" "enable" ] "")
|
||
];
|
||
|
||
###### interface
|
||
|
||
options = {
|
||
|
||
services.openvpn.servers = mkOption {
|
||
default = {};
|
||
|
||
example = literalExpression ''
|
||
{
|
||
server = {
|
||
config = '''
|
||
# Simplest server configuration: https://community.openvpn.net/openvpn/wiki/StaticKeyMiniHowto
|
||
# server :
|
||
dev tun
|
||
ifconfig 10.8.0.1 10.8.0.2
|
||
secret /root/static.key
|
||
''';
|
||
up = "ip route add ...";
|
||
down = "ip route del ...";
|
||
};
|
||
|
||
client = {
|
||
config = '''
|
||
client
|
||
remote vpn.example.org
|
||
dev tun
|
||
proto tcp-client
|
||
port 8080
|
||
ca /root/.vpn/ca.crt
|
||
cert /root/.vpn/alice.crt
|
||
key /root/.vpn/alice.key
|
||
''';
|
||
up = "echo nameserver $nameserver | ''${pkgs.openresolv}/sbin/resolvconf -m 0 -a $dev";
|
||
down = "''${pkgs.openresolv}/sbin/resolvconf -d $dev";
|
||
};
|
||
}
|
||
'';
|
||
|
||
description = ''
|
||
Each attribute of this option defines a systemd service that
|
||
runs an OpenVPN instance. These can be OpenVPN servers or
|
||
clients. The name of each systemd service is
|
||
<literal>openvpn-<replaceable>name</replaceable>.service</literal>,
|
||
where <replaceable>name</replaceable> is the corresponding
|
||
attribute name.
|
||
'';
|
||
|
||
type = with types; attrsOf (submodule {
|
||
|
||
options = {
|
||
|
||
config = mkOption {
|
||
type = types.lines;
|
||
description = lib.mdDoc ''
|
||
Configuration of this OpenVPN instance. See
|
||
{manpage}`openvpn(8)`
|
||
for details.
|
||
|
||
To import an external config file, use the following definition:
|
||
`config = "config /path/to/config.ovpn"`
|
||
'';
|
||
};
|
||
|
||
up = mkOption {
|
||
default = "";
|
||
type = types.lines;
|
||
description = lib.mdDoc ''
|
||
Shell commands executed when the instance is starting.
|
||
'';
|
||
};
|
||
|
||
down = mkOption {
|
||
default = "";
|
||
type = types.lines;
|
||
description = lib.mdDoc ''
|
||
Shell commands executed when the instance is shutting down.
|
||
'';
|
||
};
|
||
|
||
autoStart = mkOption {
|
||
default = true;
|
||
type = types.bool;
|
||
description = lib.mdDoc "Whether this OpenVPN instance should be started automatically.";
|
||
};
|
||
|
||
updateResolvConf = mkOption {
|
||
default = false;
|
||
type = types.bool;
|
||
description = lib.mdDoc ''
|
||
Use the script from the update-resolv-conf package to automatically
|
||
update resolv.conf with the DNS information provided by openvpn. The
|
||
script will be run after the "up" commands and before the "down" commands.
|
||
'';
|
||
};
|
||
|
||
authUserPass = mkOption {
|
||
default = null;
|
||
description = lib.mdDoc ''
|
||
This option can be used to store the username / password credentials
|
||
with the "auth-user-pass" authentication method.
|
||
|
||
WARNING: Using this option will put the credentials WORLD-READABLE in the Nix store!
|
||
'';
|
||
type = types.nullOr (types.submodule {
|
||
|
||
options = {
|
||
username = mkOption {
|
||
description = lib.mdDoc "The username to store inside the credentials file.";
|
||
type = types.str;
|
||
};
|
||
|
||
password = mkOption {
|
||
description = lib.mdDoc "The password to store inside the credentials file.";
|
||
type = types.str;
|
||
};
|
||
};
|
||
});
|
||
};
|
||
};
|
||
|
||
});
|
||
|
||
};
|
||
|
||
};
|
||
|
||
|
||
###### implementation
|
||
|
||
config = mkIf (cfg.servers != {}) {
|
||
|
||
systemd.services = listToAttrs (mapAttrsFlatten (name: value: nameValuePair "openvpn-${name}" (makeOpenVPNJob value name)) cfg.servers);
|
||
|
||
environment.systemPackages = [ openvpn ];
|
||
|
||
boot.kernelModules = [ "tun" ];
|
||
|
||
};
|
||
|
||
}
|