1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9
10let
11
12 cfg = config.services.atd;
13
14 inherit (pkgs) at;
15
16in
17
18{
19
20 ###### interface
21
22 options = {
23
24 services.atd.enable = mkOption {
25 type = types.bool;
26 default = false;
27 description = ''
28 Whether to enable the {command}`at` daemon, a command scheduler.
29 '';
30 };
31
32 services.atd.allowEveryone = mkOption {
33 type = types.bool;
34 default = false;
35 description = ''
36 Whether to make {file}`/var/spool/at{jobs,spool}`
37 writeable by everyone (and sticky). This is normally not
38 needed since the {command}`at` commands are
39 setuid/setgid `atd`.
40 '';
41 };
42
43 };
44
45 ###### implementation
46
47 config = mkIf cfg.enable {
48
49 # Not wrapping "batch" because it's a shell script (kernel drops perms
50 # anyway) and it's patched to invoke the "at" setuid wrapper.
51 security.wrappers = builtins.listToAttrs (
52 map
53 (program: {
54 name = "${program}";
55 value = {
56 source = "${at}/bin/${program}";
57 owner = "atd";
58 group = "atd";
59 setuid = true;
60 setgid = true;
61 };
62 })
63 [
64 "at"
65 "atq"
66 "atrm"
67 ]
68 );
69
70 environment.systemPackages = [ at ];
71
72 security.pam.services.atd = { };
73
74 users.users.atd = {
75 uid = config.ids.uids.atd;
76 group = "atd";
77 description = "atd user";
78 home = "/var/empty";
79 };
80
81 users.groups.atd.gid = config.ids.gids.atd;
82
83 systemd.services.atd = {
84 description = "Job Execution Daemon (atd)";
85 documentation = [ "man:atd(8)" ];
86 wantedBy = [ "multi-user.target" ];
87
88 path = [ at ];
89
90 preStart = ''
91 # Snippets taken and adapted from the original `install' rule of
92 # the makefile.
93
94 # We assume these values are those actually used in Nixpkgs for
95 # `at'.
96 spooldir=/var/spool/atspool
97 jobdir=/var/spool/atjobs
98 etcdir=/etc/at
99
100 install -dm755 -o atd -g atd "$etcdir"
101 spool_and_job_dir_perms=${if cfg.allowEveryone then "1777" else "1770"}
102 install -dm"$spool_and_job_dir_perms" -o atd -g atd "$spooldir" "$jobdir"
103 if [ ! -f "$etcdir"/at.deny ]; then
104 touch "$etcdir"/at.deny
105 chown root:atd "$etcdir"/at.deny
106 chmod 640 "$etcdir"/at.deny
107 fi
108 if [ ! -f "$jobdir"/.SEQ ]; then
109 touch "$jobdir"/.SEQ
110 chown atd:atd "$jobdir"/.SEQ
111 chmod 600 "$jobdir"/.SEQ
112 fi
113 '';
114
115 script = "atd";
116
117 serviceConfig.Type = "forking";
118 };
119 };
120}