1{ pkgs, lib, config, options, ... }:
2
3with lib;
4
5let
6 cfg = config.services.openntpd;
7
8 package = pkgs.openntpd_nixos;
9
10 configFile = ''
11 ${concatStringsSep "\n" (map (s: "server ${s}") cfg.servers)}
12 ${cfg.extraConfig}
13 '';
14
15 pidFile = "/run/openntpd.pid";
16
17in
18{
19 ###### interface
20
21 options.services.openntpd = {
22 enable = mkEnableOption (lib.mdDoc "OpenNTP time synchronization server");
23
24 servers = mkOption {
25 default = config.services.ntp.servers;
26 defaultText = literalExpression "config.services.ntp.servers";
27 type = types.listOf types.str;
28 inherit (options.services.ntp.servers) description;
29 };
30
31 extraConfig = mkOption {
32 type = with types; lines;
33 default = "";
34 example = ''
35 listen on 127.0.0.1
36 listen on ::1
37 '';
38 description = lib.mdDoc ''
39 Additional text appended to {file}`openntpd.conf`.
40 '';
41 };
42
43 extraOptions = mkOption {
44 type = with types; separatedString " ";
45 default = "";
46 example = "-s";
47 description = lib.mdDoc ''
48 Extra options used when launching openntpd.
49 '';
50 };
51 };
52
53 ###### implementation
54
55 config = mkIf cfg.enable {
56 meta.maintainers = with lib.maintainers; [ thoughtpolice ];
57 services.timesyncd.enable = mkForce false;
58
59 # Add ntpctl to the environment for status checking
60 environment.systemPackages = [ package ];
61
62 environment.etc."ntpd.conf".text = configFile;
63
64 users.users.ntp = {
65 isSystemUser = true;
66 group = "ntp";
67 description = "OpenNTP daemon user";
68 home = "/var/empty";
69 };
70 users.groups.ntp = {};
71
72 systemd.services.openntpd = {
73 description = "OpenNTP Server";
74 wantedBy = [ "multi-user.target" ];
75 wants = [ "network-online.target" "time-sync.target" ];
76 before = [ "time-sync.target" ];
77 after = [ "dnsmasq.service" "bind.service" "network-online.target" ];
78 serviceConfig = {
79 ExecStart = "${package}/sbin/ntpd -p ${pidFile} ${cfg.extraOptions}";
80 Type = "forking";
81 PIDFile = pidFile;
82 };
83 };
84 };
85}