mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-25 00:12:56 +00:00
nixos/duckdns: init module (#294489)
This commit is contained in:
commit
1d95cb5fa7
@ -15915,6 +15915,12 @@
|
|||||||
githubId = 30374463;
|
githubId = 30374463;
|
||||||
name = "Michal S.";
|
name = "Michal S.";
|
||||||
};
|
};
|
||||||
|
notthebee = {
|
||||||
|
email = "moe@notthebe.ee";
|
||||||
|
github = "notthebee";
|
||||||
|
githubId = 30384331;
|
||||||
|
name = "Wolfgang";
|
||||||
|
};
|
||||||
notthemessiah = {
|
notthemessiah = {
|
||||||
email = "brian.cohen.88@gmail.com";
|
email = "brian.cohen.88@gmail.com";
|
||||||
github = "NOTtheMessiah";
|
github = "NOTtheMessiah";
|
||||||
|
125
nixos/modules/services/misc/duckdns.nix
Normal file
125
nixos/modules/services/misc/duckdns.nix
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.services.duckdns;
|
||||||
|
duckdns = pkgs.writeShellScriptBin "duckdns" ''
|
||||||
|
DRESPONSE=$(curl -sS --max-time 60 --no-progress-meter -k -K- <<< "url = \"https://www.duckdns.org/update?verbose=true&domains=$DUCKDNS_DOMAINS&token=$DUCKDNS_TOKEN&ip=\"")
|
||||||
|
IPV4=$(echo "$DRESPONSE" | awk 'NR==2')
|
||||||
|
IPV6=$(echo "$DRESPONSE" | awk 'NR==3')
|
||||||
|
RESPONSE=$(echo "$DRESPONSE" | awk 'NR==1')
|
||||||
|
IPCHANGE=$(echo "$DRESPONSE" | awk 'NR==4')
|
||||||
|
|
||||||
|
if [[ "$RESPONSE" = "OK" ]] && [[ "$IPCHANGE" = "UPDATED" ]]; then
|
||||||
|
if [[ "$IPV4" != "" ]] && [[ "$IPV6" == "" ]]; then
|
||||||
|
echo "Your IP was updated at $(date) to IPv4: $IPV4"
|
||||||
|
elif [[ "$IPV4" == "" ]] && [[ "$IPV6" != "" ]]; then
|
||||||
|
echo "Your IP was updated at $(date) to IPv6: $IPV6"
|
||||||
|
else
|
||||||
|
echo "Your IP was updated at $(date) to IPv4: $IPV4 & IPv6 to: $IPV6"
|
||||||
|
fi
|
||||||
|
elif [[ "$RESPONSE" = "OK" ]] && [[ "$IPCHANGE" = "NOCHANGE" ]]; then
|
||||||
|
echo "DuckDNS request at $(date) successful. IP(s) unchanged."
|
||||||
|
else
|
||||||
|
echo -e "Something went wrong, please check your settings\nThe response returned was:\n$DRESPONSE\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.duckdns = {
|
||||||
|
enable = lib.mkEnableOption "DuckDNS Dynamic DNS Client";
|
||||||
|
tokenFile = lib.mkOption {
|
||||||
|
default = null;
|
||||||
|
type = lib.types.path;
|
||||||
|
description = ''
|
||||||
|
The path to a file containing the token
|
||||||
|
used to authenticate with DuckDNS.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
domains = lib.mkOption {
|
||||||
|
default = null;
|
||||||
|
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||||
|
example = [ "examplehost" ];
|
||||||
|
description = ''
|
||||||
|
The domain(s) to update in DuckDNS
|
||||||
|
(without the .duckdns.org suffix)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
domainsFile = lib.mkOption {
|
||||||
|
default = null;
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
pkgs.writeText "duckdns-domains.txt" '''
|
||||||
|
examplehost
|
||||||
|
examplehost2
|
||||||
|
examplehost3
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
The path to a file containing a
|
||||||
|
newline-separated list of DuckDNS
|
||||||
|
domain(s) to be updated
|
||||||
|
(without the .duckdns.org suffix)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.domains != null || cfg.domainsFile != null;
|
||||||
|
message = "Either services.duckdns.domains or services.duckdns.domainsFile has to be defined";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = !(cfg.domains != null && cfg.domainsFile != null);
|
||||||
|
message = "services.duckdns.domains and services.duckdns.domainsFile can't both be defined at the same time";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = (cfg.tokenFile != null);
|
||||||
|
message = "services.duckdns.tokenFile has to be defined";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages = [ duckdns ];
|
||||||
|
|
||||||
|
systemd.services.duckdns = {
|
||||||
|
description = "DuckDNS Dynamic DNS Client";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
startAt = "*:0/5";
|
||||||
|
path = [
|
||||||
|
pkgs.gnused
|
||||||
|
pkgs.systemd
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.gawk
|
||||||
|
duckdns
|
||||||
|
];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
LoadCredential = [
|
||||||
|
"DUCKDNS_TOKEN_FILE:${cfg.tokenFile}"
|
||||||
|
] ++ lib.optionals (cfg.domainsFile != null) [ "DUCKDNS_DOMAINS_FILE:${cfg.domainsFile}" ];
|
||||||
|
DynamicUser = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
export DUCKDNS_TOKEN=$(systemd-creds cat DUCKDNS_TOKEN_FILE)
|
||||||
|
${lib.optionalString (cfg.domains != null) ''
|
||||||
|
export DUCKDNS_DOMAINS='${lib.strings.concatStringsSep "," cfg.domains}'
|
||||||
|
''}
|
||||||
|
${lib.optionalString (cfg.domainsFile != null) ''
|
||||||
|
export DUCKDNS_DOMAINS=$(systemd-creds cat DUCKDNS_DOMAINS_FILE | sed -z 's/\n/,/g')
|
||||||
|
''}
|
||||||
|
exec ${lib.getExe duckdns}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with lib.maintainers; [ notthebee ];
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user