1{ config, pkgs, lib, ... }: 2 3with import ./lib.nix { inherit lib; }; 4 5let 6 inherit (lib) concatStringsSep intersperse mapAttrsToList mkForce mkIf mkMerge mkOption optionalString types; 7 8 bosConfig = pkgs.writeText "BosConfig" ('' 9 restrictmode 1 10 restarttime 16 0 0 0 0 11 checkbintime 3 0 5 0 0 12 '' + (optionalString cfg.roles.database.enable '' 13 bnode simple vlserver 1 14 parm ${openafsBin}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs} 15 end 16 bnode simple ptserver 1 17 parm ${openafsBin}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs} 18 end 19 '') + (optionalString cfg.roles.fileserver.enable '' 20 bnode dafs dafs 1 21 parm ${openafsBin}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs} 22 parm ${openafsBin}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs} 23 parm ${openafsBin}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs} 24 parm ${openafsBin}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs} 25 end 26 '') + (optionalString (cfg.roles.database.enable && cfg.roles.backup.enable) '' 27 bnode simple buserver 1 28 parm ${openafsBin}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString (cfg.roles.backup.cellServDB != []) "-cellservdb /etc/openafs/backup/"} 29 end 30 '')); 31 32 netInfo = if (cfg.advertisedAddresses != []) then 33 pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n") 34 else null; 35 36 buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.roles.backup.cellServDB); 37 38 cfg = config.services.openafsServer; 39 40 udpSizeStr = toString cfg.udpPacketSize; 41 42 openafsBin = lib.getBin pkgs.openafs; 43 44in { 45 46 options = { 47 48 services.openafsServer = { 49 50 enable = mkOption { 51 default = false; 52 type = types.bool; 53 description = '' 54 Whether to enable the OpenAFS server. An OpenAFS server needs a 55 complex setup. So, be aware that enabling this service and setting 56 some options does not give you a turn-key-ready solution. You need 57 at least a running Kerberos 5 setup, as OpenAFS relies on it for 58 authentication. See the Guide "QuickStartUnix" coming with 59 <literal>pkgs.openafs.doc</literal> for complete setup 60 instructions. 61 ''; 62 }; 63 64 advertisedAddresses = mkOption { 65 default = []; 66 description = "List of IP addresses this server is advertised under. See NetInfo(5)"; 67 }; 68 69 cellName = mkOption { 70 default = ""; 71 type = types.str; 72 description = "Cell name, this server will serve."; 73 example = "grand.central.org"; 74 }; 75 76 cellServDB = mkOption { 77 default = []; 78 type = with types; listOf (submodule [ { options = cellServDBConfig;} ]); 79 description = "Definition of all cell-local database server machines."; 80 }; 81 82 roles = { 83 fileserver = { 84 enable = mkOption { 85 default = true; 86 type = types.bool; 87 description = "Fileserver role, serves files and volumes from its local storage."; 88 }; 89 90 fileserverArgs = mkOption { 91 default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000"; 92 type = types.str; 93 description = "Arguments to the dafileserver process. See its man page."; 94 }; 95 96 volserverArgs = mkOption { 97 default = ""; 98 type = types.str; 99 description = "Arguments to the davolserver process. See its man page."; 100 example = "-sync never"; 101 }; 102 103 salvageserverArgs = mkOption { 104 default = ""; 105 type = types.str; 106 description = "Arguments to the salvageserver process. See its man page."; 107 example = "-showlog"; 108 }; 109 110 salvagerArgs = mkOption { 111 default = ""; 112 type = types.str; 113 description = "Arguments to the dasalvager process. See its man page."; 114 example = "-showlog -showmounts"; 115 }; 116 }; 117 118 database = { 119 enable = mkOption { 120 default = true; 121 type = types.bool; 122 description = '' 123 Database server role, maintains the Volume Location Database, 124 Protection Database (and Backup Database, see 125 <literal>backup</literal> role). There can be multiple 126 servers in the database role for replication, which then need 127 reliable network connection to each other. 128 129 Servers in this role appear in AFSDB DNS records or the 130 CellServDB. 131 ''; 132 }; 133 134 vlserverArgs = mkOption { 135 default = ""; 136 type = types.str; 137 description = "Arguments to the vlserver process. See its man page."; 138 example = "-rxbind"; 139 }; 140 141 ptserverArgs = mkOption { 142 default = ""; 143 type = types.str; 144 description = "Arguments to the ptserver process. See its man page."; 145 example = "-restricted -default_access S---- S-M---"; 146 }; 147 }; 148 149 backup = { 150 enable = mkOption { 151 default = false; 152 type = types.bool; 153 description = '' 154 Backup server role. Use in conjunction with the 155 <literal>database</literal> role to maintain the Backup 156 Database. Normally only used in conjunction with tape storage 157 or IBM's Tivoli Storage Manager. 158 ''; 159 }; 160 161 buserverArgs = mkOption { 162 default = ""; 163 type = types.str; 164 description = "Arguments to the buserver process. See its man page."; 165 example = "-p 8"; 166 }; 167 168 cellServDB = mkOption { 169 default = []; 170 type = with types; listOf (submodule [ { options = cellServDBConfig;} ]); 171 description = '' 172 Definition of all cell-local backup database server machines. 173 Use this when your cell uses less backup database servers than 174 other database server machines. 175 ''; 176 }; 177 }; 178 }; 179 180 dottedPrincipals= mkOption { 181 default = false; 182 type = types.bool; 183 description = '' 184 If enabled, allow principal names containing (.) dots. Enabling 185 this has security implications! 186 ''; 187 }; 188 189 udpPacketSize = mkOption { 190 default = 1310720; 191 type = types.int; 192 description = '' 193 UDP packet size to use in Bytes. Higher values can speed up 194 communications. The default of 1 MB is a sufficient in most 195 cases. Make sure to increase the kernel's UDP buffer size 196 accordingly via <literal>net.core(w|r|opt)mem_max</literal> 197 sysctl. 198 ''; 199 }; 200 201 }; 202 203 }; 204 205 config = mkIf cfg.enable { 206 207 assertions = [ 208 { assertion = cfg.cellServDB != []; 209 message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB."; 210 } 211 { assertion = cfg.cellName != ""; 212 message = "You must specify the local cell name in config.services.openafsServer.cellName."; 213 } 214 ]; 215 216 environment.systemPackages = [ pkgs.openafs ]; 217 218 environment.etc = { 219 bosConfig = { 220 source = bosConfig; 221 target = "openafs/BosConfig"; 222 mode = "0644"; 223 }; 224 cellServDB = { 225 text = mkCellServDB cfg.cellName cfg.cellServDB; 226 target = "openafs/server/CellServDB"; 227 mode = "0644"; 228 }; 229 thisCell = { 230 text = cfg.cellName; 231 target = "openafs/server/ThisCell"; 232 mode = "0644"; 233 }; 234 buCellServDB = { 235 enable = (cfg.roles.backup.cellServDB != []); 236 text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB; 237 target = "openafs/backup/CellServDB"; 238 }; 239 }; 240 241 systemd.services = { 242 openafs-server = { 243 description = "OpenAFS server"; 244 after = [ "syslog.target" "network.target" ]; 245 wantedBy = [ "multi-user.target" ]; 246 restartIfChanged = false; 247 unitConfig.ConditionPathExists = [ "/etc/openafs/server/rxkad.keytab" ]; 248 preStart = '' 249 mkdir -m 0755 -p /var/openafs 250 ${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"} 251 ${optionalString (cfg.roles.backup.cellServDB != []) "cp ${buCellServDB}"} 252 ''; 253 serviceConfig = { 254 ExecStart = "${openafsBin}/bin/bosserver -nofork"; 255 ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth"; 256 }; 257 }; 258 }; 259 }; 260}