1{ config, pkgs, lib, ... }:
2
3let
4
5 inherit (lib) mkOption mkIf singleton;
6 inherit (pkgs) ddclient;
7
8 stateDir = "/var/spool/ddclient";
9 ddclientUser = "ddclient";
10 ddclientFlags = "-foreground -verbose -noquiet -file /etc/ddclient.conf";
11 ddclientPIDFile = "${stateDir}/ddclient.pid";
12
13in
14
15{
16
17 ###### interface
18
19 options = {
20
21 services.ddclient = with lib.types; {
22
23 enable = mkOption {
24 default = false;
25 type = bool;
26 description = ''
27 Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org).
28 '';
29 };
30
31 domain = mkOption {
32 default = "";
33 type = str;
34 description = ''
35 Domain name to synchronize.
36 '';
37 };
38
39 username = mkOption {
40 default = "";
41 type = str;
42 description = ''
43 Username.
44 '';
45 };
46
47 password = mkOption {
48 default = "";
49 type = str;
50 description = ''
51 Password. WARNING: The password becomes world readable in the Nix store.
52 '';
53 };
54
55 protocol = mkOption {
56 default = "dyndns2";
57 type = str;
58 description = ''
59 Protocol to use with dynamic DNS provider (see http://sourceforge.net/apps/trac/ddclient/wiki/Protocols).
60 '';
61 };
62
63 server = mkOption {
64 default = "";
65 type = str;
66 description = ''
67 Server address.
68 '';
69 };
70
71 ssl = mkOption {
72 default = true;
73 type = bool;
74 description = ''
75 Whether to use to use SSL/TLS to connect to dynamic DNS provider.
76 '';
77 };
78
79 extraConfig = mkOption {
80 default = "";
81 type = str;
82 description = ''
83 Extra configuration. Contents will be added verbatim to the configuration file.
84 '';
85 };
86
87 use = mkOption {
88 default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '";
89 type = str;
90 description = ''
91 Method to determine the IP address to send to the dymanic DNS provider.
92 '';
93 };
94 };
95 };
96
97
98 ###### implementation
99
100 config = mkIf config.services.ddclient.enable {
101
102 environment.systemPackages = [ ddclient ];
103
104 users.extraUsers = singleton {
105 name = ddclientUser;
106 uid = config.ids.uids.ddclient;
107 description = "ddclient daemon user";
108 home = stateDir;
109 };
110
111 environment.etc."ddclient.conf" = {
112 uid = config.ids.uids.ddclient;
113 mode = "0600";
114 text = ''
115 daemon=600
116 cache=${stateDir}/ddclient.cache
117 pid=${ddclientPIDFile}
118 use=${config.services.ddclient.use}
119 login=${config.services.ddclient.username}
120 password=${config.services.ddclient.password}
121 protocol=${config.services.ddclient.protocol}
122 server=${config.services.ddclient.server}
123 ssl=${if config.services.ddclient.ssl then "yes" else "no"}
124 wildcard=YES
125 ${config.services.ddclient.domain}
126 ${config.services.ddclient.extraConfig}
127 '';
128 };
129
130 systemd.services.ddclient = {
131 description = "Dynamic DNS Client";
132 wantedBy = [ "multi-user.target" ];
133 after = [ "network.target" ];
134 restartTriggers = [ config.environment.etc."ddclient.conf".source ];
135
136 serviceConfig = {
137 # Uncomment this if too many problems occur:
138 # Type = "forking";
139 User = ddclientUser;
140 Group = "nogroup"; #TODO get this to work
141 PermissionsStartOnly = "true";
142 PIDFile = ddclientPIDFile;
143 ExecStartPre = ''
144 ${pkgs.stdenv.shell} -c "${pkgs.coreutils}/bin/mkdir -m 0755 -p ${stateDir} && ${pkgs.coreutils}/bin/chown ${ddclientUser} ${stateDir}"
145 '';
146 ExecStart = "${ddclient}/bin/ddclient ${ddclientFlags}";
147 #ExecStartPost = "${pkgs.coreutils}/bin/rm -r ${stateDir}"; # Should we have this?
148 };
149 };
150 };
151}