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}