mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-19 07:59:24 +03:00

When obtaining the IP address from an interface iproute2 is missing: "Unable to obtain information for 'bond-wan' -- missing ip or ifconfig command" The prefix check to include iproute2 is incorrect for "usev4" and "usev6". Currently the NixOS module checks for the "if" prefix. This prefix is not valid with "usev4" and "usev6": "Invalid Value for keyword 'usev4' = 'if'" "ifv4" must be used with "usev4", and "ifv6" with "usev6". I updated the nixos module to check for the correct prefix with "usev4" and "usev6", and include iproute2 as necessary.
247 lines
7.7 KiB
Nix
247 lines
7.7 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
let
|
|
cfg = config.services.ddclient;
|
|
boolToStr = bool: if bool then "yes" else "no";
|
|
dataDir = "/var/lib/ddclient";
|
|
StateDirectory = builtins.baseNameOf dataDir;
|
|
RuntimeDirectory = StateDirectory;
|
|
|
|
configFile' = pkgs.writeText "ddclient.conf" ''
|
|
# This file can be used as a template for configFile or is automatically generated by Nix options.
|
|
cache=${dataDir}/ddclient.cache
|
|
foreground=YES
|
|
${lib.optionalString (cfg.use != "") "use=${cfg.use}"}
|
|
${lib.optionalString (cfg.use == "" && cfg.usev4 != "") "usev4=${cfg.usev4}"}
|
|
${lib.optionalString (cfg.use == "" && cfg.usev6 != "") "usev6=${cfg.usev6}"}
|
|
login=${cfg.username}
|
|
password=${if cfg.protocol == "nsupdate" then "/run/${RuntimeDirectory}/ddclient.key" else "@password_placeholder@"}
|
|
protocol=${cfg.protocol}
|
|
${lib.optionalString (cfg.script != "") "script=${cfg.script}"}
|
|
${lib.optionalString (cfg.server != "") "server=${cfg.server}"}
|
|
${lib.optionalString (cfg.zone != "") "zone=${cfg.zone}"}
|
|
ssl=${boolToStr cfg.ssl}
|
|
wildcard=YES
|
|
quiet=${boolToStr cfg.quiet}
|
|
verbose=${boolToStr cfg.verbose}
|
|
${cfg.extraConfig}
|
|
${lib.concatStringsSep "," cfg.domains}
|
|
'';
|
|
configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
|
|
|
|
preStart = ''
|
|
install --mode=600 --owner=$USER ${configFile} /run/${RuntimeDirectory}/ddclient.conf
|
|
${lib.optionalString (cfg.configFile == null) (if (cfg.protocol == "nsupdate") then ''
|
|
install --mode=600 --owner=$USER ${cfg.passwordFile} /run/${RuntimeDirectory}/ddclient.key
|
|
'' else if (cfg.passwordFile != null) then ''
|
|
"${pkgs.replace-secret}/bin/replace-secret" "@password_placeholder@" "${cfg.passwordFile}" "/run/${RuntimeDirectory}/ddclient.conf"
|
|
'' else ''
|
|
sed -i '/^password=@password_placeholder@$/d' /run/${RuntimeDirectory}/ddclient.conf
|
|
'')}
|
|
'';
|
|
in
|
|
{
|
|
|
|
imports = [
|
|
(lib.mkChangedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ]
|
|
(config:
|
|
let value = lib.getAttrFromPath [ "services" "ddclient" "domain" ] config;
|
|
in lib.optional (value != "") value))
|
|
(lib.mkRemovedOptionModule [ "services" "ddclient" "homeDir" ] "")
|
|
(lib.mkRemovedOptionModule [ "services" "ddclient" "password" ] "Use services.ddclient.passwordFile instead.")
|
|
(lib.mkRemovedOptionModule [ "services" "ddclient" "ipv6" ] "")
|
|
];
|
|
|
|
###### interface
|
|
|
|
options = {
|
|
|
|
services.ddclient = with lib.types; {
|
|
|
|
enable = lib.mkOption {
|
|
default = false;
|
|
type = bool;
|
|
description = ''
|
|
Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org).
|
|
'';
|
|
};
|
|
|
|
package = lib.mkOption {
|
|
type = package;
|
|
default = pkgs.ddclient;
|
|
defaultText = lib.literalExpression "pkgs.ddclient";
|
|
description = ''
|
|
The ddclient executable package run by the service.
|
|
'';
|
|
};
|
|
|
|
domains = lib.mkOption {
|
|
default = [ "" ];
|
|
type = listOf str;
|
|
description = ''
|
|
Domain name(s) to synchronize.
|
|
'';
|
|
};
|
|
|
|
username = lib.mkOption {
|
|
# For `nsupdate` username contains the path to the nsupdate executable
|
|
default = lib.optionalString (config.services.ddclient.protocol == "nsupdate") "${pkgs.bind.dnsutils}/bin/nsupdate";
|
|
defaultText = "";
|
|
type = str;
|
|
description = ''
|
|
User name.
|
|
'';
|
|
};
|
|
|
|
passwordFile = lib.mkOption {
|
|
default = null;
|
|
type = nullOr str;
|
|
description = ''
|
|
A file containing the password or a TSIG key in named format when using the nsupdate protocol.
|
|
'';
|
|
};
|
|
|
|
interval = lib.mkOption {
|
|
default = "10min";
|
|
type = str;
|
|
description = ''
|
|
The interval at which to run the check and update.
|
|
See {command}`man 7 systemd.time` for the format.
|
|
'';
|
|
};
|
|
|
|
configFile = lib.mkOption {
|
|
default = null;
|
|
type = nullOr path;
|
|
description = ''
|
|
Path to configuration file.
|
|
When set this overrides the generated configuration from module options.
|
|
'';
|
|
example = "/root/nixos/secrets/ddclient.conf";
|
|
};
|
|
|
|
protocol = lib.mkOption {
|
|
default = "dyndns2";
|
|
type = str;
|
|
description = ''
|
|
Protocol to use with dynamic DNS provider (see https://ddclient.net/protocols.html ).
|
|
'';
|
|
};
|
|
|
|
server = lib.mkOption {
|
|
default = "";
|
|
type = str;
|
|
description = ''
|
|
Server address.
|
|
'';
|
|
};
|
|
|
|
ssl = lib.mkOption {
|
|
default = true;
|
|
type = bool;
|
|
description = ''
|
|
Whether to use SSL/TLS to connect to dynamic DNS provider.
|
|
'';
|
|
};
|
|
|
|
quiet = lib.mkOption {
|
|
default = false;
|
|
type = bool;
|
|
description = ''
|
|
Print no messages for unnecessary updates.
|
|
'';
|
|
};
|
|
|
|
script = lib.mkOption {
|
|
default = "";
|
|
type = str;
|
|
description = ''
|
|
script as required by some providers.
|
|
'';
|
|
};
|
|
|
|
use = lib.mkOption {
|
|
default = "";
|
|
type = str;
|
|
description = ''
|
|
Method to determine the IP address to send to the dynamic DNS provider.
|
|
'';
|
|
};
|
|
usev4 = lib.mkOption {
|
|
default = "webv4, webv4=ipify-ipv4";
|
|
type = str;
|
|
description = ''
|
|
Method to determine the IPv4 address to send to the dynamic DNS provider. Only used if `use` is not set.
|
|
'';
|
|
};
|
|
usev6 = lib.mkOption {
|
|
default = "webv6, webv6=ipify-ipv6";
|
|
type = str;
|
|
description = ''
|
|
Method to determine the IPv6 address to send to the dynamic DNS provider. Only used if `use` is not set.
|
|
'';
|
|
};
|
|
|
|
verbose = lib.mkOption {
|
|
default = false;
|
|
type = bool;
|
|
description = ''
|
|
Print verbose information.
|
|
'';
|
|
};
|
|
|
|
zone = lib.mkOption {
|
|
default = "";
|
|
type = str;
|
|
description = ''
|
|
zone as required by some providers.
|
|
'';
|
|
};
|
|
|
|
extraConfig = lib.mkOption {
|
|
default = "";
|
|
type = lines;
|
|
description = ''
|
|
Extra configuration. Contents will be added verbatim to the configuration file.
|
|
|
|
::: {.note}
|
|
`daemon` should not be added here because it does not work great with the systemd-timer approach the service uses.
|
|
:::
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
###### implementation
|
|
|
|
config = lib.mkIf config.services.ddclient.enable {
|
|
warnings = lib.optional (cfg.use != "") "Setting `use` is deprecated, ddclient now supports `usev4` and `usev6` for separate IPv4/IPv6 configuration.";
|
|
|
|
systemd.services.ddclient = {
|
|
description = "Dynamic DNS Client";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" ];
|
|
restartTriggers = lib.optional (cfg.configFile != null) cfg.configFile;
|
|
path = lib.optional (lib.hasPrefix "if," cfg.use || lib.hasPrefix "ifv4," cfg.usev4 || lib.hasPrefix "ifv6," cfg.usev6) pkgs.iproute2;
|
|
|
|
serviceConfig = {
|
|
DynamicUser = true;
|
|
RuntimeDirectoryMode = "0700";
|
|
inherit RuntimeDirectory;
|
|
inherit StateDirectory;
|
|
Type = "oneshot";
|
|
ExecStartPre = [ "!${pkgs.writeShellScript "ddclient-prestart" preStart}" ];
|
|
ExecStart = "${lib.getExe cfg.package} -file /run/${RuntimeDirectory}/ddclient.conf";
|
|
};
|
|
};
|
|
|
|
systemd.timers.ddclient = {
|
|
description = "Run ddclient";
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnBootSec = cfg.interval;
|
|
OnUnitInactiveSec = cfg.interval;
|
|
};
|
|
};
|
|
};
|
|
}
|