1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.xinetd;
8
9 configFile = pkgs.writeText "xinetd.conf"
10 ''
11 defaults
12 {
13 log_type = SYSLOG daemon info
14 log_on_failure = HOST
15 log_on_success = PID HOST DURATION EXIT
16 ${cfg.extraDefaults}
17 }
18
19 ${concatMapStrings makeService cfg.services}
20 '';
21
22 makeService = srv:
23 ''
24 service ${srv.name}
25 {
26 protocol = ${srv.protocol}
27 ${optionalString srv.unlisted "type = UNLISTED"}
28 ${optionalString (srv.flags != "") "flags = ${srv.flags}"}
29 socket_type = ${if srv.protocol == "udp" then "dgram" else "stream"}
30 ${if srv.port != 0 then "port = ${toString srv.port}" else ""}
31 wait = ${if srv.protocol == "udp" then "yes" else "no"}
32 user = ${srv.user}
33 server = ${srv.server}
34 ${optionalString (srv.serverArgs != "") "server_args = ${srv.serverArgs}"}
35 ${srv.extraConfig}
36 }
37 '';
38
39in
40
41{
42
43 ###### interface
44
45 options = {
46
47 services.xinetd.enable = mkOption {
48 default = false;
49 description = ''
50 Whether to enable the xinetd super-server daemon.
51 '';
52 };
53
54 services.xinetd.extraDefaults = mkOption {
55 default = "";
56 type = types.string;
57 description = ''
58 Additional configuration lines added to the default section of xinetd's configuration.
59 '';
60 };
61
62 services.xinetd.services = mkOption {
63 default = [];
64 description = ''
65 A list of services provided by xinetd.
66 '';
67
68 type = types.listOf types.optionSet;
69
70 options = {
71
72 name = mkOption {
73 type = types.string;
74 example = "login";
75 description = "Name of the service.";
76 };
77
78 protocol = mkOption {
79 type = types.string;
80 default = "tcp";
81 description =
82 "Protocol of the service. Usually <literal>tcp</literal> or <literal>udp</literal>.";
83 };
84
85 port = mkOption {
86 type = types.int;
87 default = 0;
88 example = 123;
89 description = "Port number of the service.";
90 };
91
92 user = mkOption {
93 type = types.string;
94 default = "nobody";
95 description = "User account for the service";
96 };
97
98 server = mkOption {
99 type = types.string;
100 example = "/foo/bin/ftpd";
101 description = "Path of the program that implements the service.";
102 };
103
104 serverArgs = mkOption {
105 type = types.string;
106 default = "";
107 description = "Command-line arguments for the server program.";
108 };
109
110 flags = mkOption {
111 type = types.string;
112 default = "";
113 description = "";
114 };
115
116 unlisted = mkOption {
117 type = types.bool;
118 default = false;
119 description = ''
120 Whether this server is listed in
121 <filename>/etc/services</filename>. If so, the port
122 number can be omitted.
123 '';
124 };
125
126 extraConfig = mkOption {
127 type = types.string;
128 default = "";
129 description = "Extra configuration-lines added to the section of the service.";
130 };
131
132 };
133
134 };
135
136 };
137
138
139 ###### implementation
140
141 config = mkIf cfg.enable {
142 systemd.services.xinetd = {
143 description = "xinetd server";
144 after = [ "network-interfaces.target" ];
145 wantedBy = [ "multi-user.target" ];
146 path = [ pkgs.xinetd ];
147 script = "xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
148 };
149 };
150}