1{ config, lib, pkgs, ... }: 2with lib; 3let 4 cfg = config.services.diod; 5 6 diodBool = b: if b then "1" else "0"; 7 8 diodConfig = pkgs.writeText "diod.conf" '' 9 allsquash = ${diodBool cfg.allsquash} 10 auth_required = ${diodBool cfg.authRequired} 11 exportall = ${diodBool cfg.exportall} 12 exportopts = "${concatStringsSep "," cfg.exportopts}" 13 exports = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.exports)} } 14 listen = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.listen)} } 15 logdest = "${cfg.logdest}" 16 nwthreads = ${toString cfg.nwthreads} 17 squashuser = "${cfg.squashuser}" 18 statfs_passthru = ${diodBool cfg.statfsPassthru} 19 userdb = ${diodBool cfg.userdb} 20 ${cfg.extraConfig} 21 ''; 22in 23{ 24 options = { 25 services.diod = { 26 enable = mkOption { 27 type = types.bool; 28 default = false; 29 description = "Whether to enable the diod 9P file server."; 30 }; 31 32 listen = mkOption { 33 type = types.listOf types.str; 34 default = [ "0.0.0.0:564" ]; 35 description = '' 36 [ "IP:PORT" [,"IP:PORT",...] ] 37 List the interfaces and ports that diod should listen on. 38 ''; 39 }; 40 41 exports = mkOption { 42 type = types.listOf types.str; 43 default = []; 44 description = '' 45 List the file systems that clients will be allowed to mount. All paths should 46 be fully qualified. The exports table can include two types of element: 47 a string element (as above), 48 or an alternate table element form { path="/path", opts="ro" }. 49 In the alternate form, the (optional) opts attribute is a comma-separated list 50 of export options. The two table element forms can be mixed in the exports 51 table. Note that although diod will not traverse file system boundaries for a 52 given mount due to inode uniqueness constraints, subdirectories of a file 53 system can be separately exported. 54 ''; 55 }; 56 57 exportall = mkOption { 58 type = types.bool; 59 default = true; 60 description = '' 61 Export all file systems listed in /proc/mounts. If new file systems are mounted 62 after diod has started, they will become immediately mountable. If there is a 63 duplicate entry for a file system in the exports list, any options listed in 64 the exports entry will apply. 65 ''; 66 }; 67 68 exportopts = mkOption { 69 type = types.listOf types.str; 70 default = []; 71 description = '' 72 Establish a default set of export options. These are overridden, not appended 73 to, by opts attributes in an "exports" entry. 74 ''; 75 }; 76 77 nwthreads = mkOption { 78 type = types.int; 79 default = 16; 80 description = '' 81 Sets the (fixed) number of worker threads created to handle 9P 82 requests for a unique aname. 83 ''; 84 }; 85 86 authRequired = mkOption { 87 type = types.bool; 88 default = false; 89 description = '' 90 Allow clients to connect without authentication, i.e. without a valid MUNGE credential. 91 ''; 92 }; 93 94 userdb = mkOption { 95 type = types.bool; 96 default = false; 97 description = '' 98 This option disables password/group lookups. It allows any uid to attach and 99 assumes gid=uid, and supplementary groups contain only the primary gid. 100 ''; 101 }; 102 103 allsquash = mkOption { 104 type = types.bool; 105 default = true; 106 description = '' 107 Remap all users to "nobody". The attaching user need not be present in the 108 password file. 109 ''; 110 }; 111 112 squashuser = mkOption { 113 type = types.str; 114 default = "nobody"; 115 description = '' 116 Change the squash user. The squash user must be present in the password file. 117 ''; 118 }; 119 120 logdest = mkOption { 121 type = types.str; 122 default = "syslog:daemon:err"; 123 description = '' 124 Set the destination for logging. 125 The value has the form of "syslog:facility:level" or "filename". 126 ''; 127 }; 128 129 130 statfsPassthru = mkOption { 131 type = types.bool; 132 default = false; 133 description = '' 134 This option configures statfs to return the host file system's type 135 rather than V9FS_MAGIC. 136 ''; 137 }; 138 139 extraConfig = mkOption { 140 type = types.lines; 141 default = ""; 142 description = "Extra configuration options for diod.conf."; 143 }; 144 }; 145 }; 146 147 config = mkIf config.services.diod.enable { 148 environment.systemPackages = [ pkgs.diod ]; 149 150 systemd.services.diod = { 151 description = "diod 9P file server"; 152 wantedBy = [ "multi-user.target" ]; 153 after = [ "network.target" ]; 154 serviceConfig = { 155 ExecStart = "${pkgs.diod}/sbin/diod -f -c ${diodConfig}"; 156 Capabilities = "cap_net_bind_service+=ep"; 157 }; 158 }; 159 }; 160}