1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8# openafsBin, openafsSrv, mkCellServDB 9with import ./lib.nix { inherit config lib pkgs; }; 10 11let 12 inherit (lib) 13 concatStringsSep 14 literalExpression 15 mkIf 16 mkOption 17 mkEnableOption 18 mkPackageOption 19 optionalString 20 types 21 ; 22 23 bosConfig = pkgs.writeText "BosConfig" ( 24 '' 25 restrictmode 1 26 restarttime 16 0 0 0 0 27 checkbintime 3 0 5 0 0 28 '' 29 + (optionalString cfg.roles.database.enable '' 30 bnode simple vlserver 1 31 parm ${openafsSrv}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs} 32 end 33 bnode simple ptserver 1 34 parm ${openafsSrv}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs} 35 end 36 '') 37 + (optionalString cfg.roles.fileserver.enable '' 38 bnode dafs dafs 1 39 parm ${openafsSrv}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs} 40 parm ${openafsSrv}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs} 41 parm ${openafsSrv}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs} 42 parm ${openafsSrv}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs} 43 end 44 '') 45 + (optionalString 46 (cfg.roles.database.enable && cfg.roles.backup.enable && (!cfg.roles.backup.enableFabs)) 47 '' 48 bnode simple buserver 1 49 parm ${openafsSrv}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString useBuCellServDB "-cellservdb /etc/openafs/backup/"} 50 end 51 '' 52 ) 53 + (optionalString 54 (cfg.roles.database.enable && cfg.roles.backup.enable && cfg.roles.backup.enableFabs) 55 '' 56 bnode simple buserver 1 57 parm ${lib.getBin pkgs.fabs}/bin/fabsys server --config ${fabsConfFile} ${cfg.roles.backup.fabsArgs} 58 end 59 '' 60 ) 61 ); 62 63 netInfo = 64 if (cfg.advertisedAddresses != [ ]) then 65 pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n") 66 else 67 null; 68 69 buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" ( 70 mkCellServDB cfg.cellName cfg.roles.backup.cellServDB 71 ); 72 73 useBuCellServDB = (cfg.roles.backup.cellServDB != [ ]) && (!cfg.roles.backup.enableFabs); 74 75 cfg = config.services.openafsServer; 76 77 udpSizeStr = toString cfg.udpPacketSize; 78 79 fabsConfFile = pkgs.writeText "fabs.yaml" ( 80 builtins.toJSON ( 81 { 82 afs = { 83 aklog = cfg.package + "/bin/aklog"; 84 cell = cfg.cellName; 85 dumpscan = cfg.package + "/bin/afsdump_scan"; 86 fs = cfg.package + "/bin/fs"; 87 pts = cfg.package + "/bin/pts"; 88 vos = cfg.package + "/bin/vos"; 89 }; 90 k5start.command = (lib.getBin pkgs.kstart) + "/bin/k5start"; 91 } 92 // cfg.roles.backup.fabsExtraConfig 93 ) 94 ); 95 96in 97{ 98 99 options = { 100 101 services.openafsServer = { 102 103 enable = mkOption { 104 default = false; 105 type = types.bool; 106 description = '' 107 Whether to enable the OpenAFS server. An OpenAFS server needs a 108 complex setup. So, be aware that enabling this service and setting 109 some options does not give you a turn-key-ready solution. You need 110 at least a running Kerberos 5 setup, as OpenAFS relies on it for 111 authentication. See the Guide "QuickStartUnix" coming with 112 `pkgs.openafs.doc` for complete setup 113 instructions. 114 ''; 115 }; 116 117 advertisedAddresses = mkOption { 118 type = types.listOf types.str; 119 default = [ ]; 120 description = "List of IP addresses this server is advertised under. See {manpage}`NetInfo(5)`"; 121 }; 122 123 cellName = mkOption { 124 default = ""; 125 type = types.str; 126 description = "Cell name, this server will serve."; 127 example = "grand.central.org"; 128 }; 129 130 cellServDB = mkOption { 131 default = [ ]; 132 type = with types; listOf (submodule [ { options = cellServDBConfig; } ]); 133 description = "Definition of all cell-local database server machines."; 134 }; 135 136 package = mkPackageOption pkgs "openafs" { }; 137 138 roles = { 139 fileserver = { 140 enable = mkOption { 141 default = true; 142 type = types.bool; 143 description = "Fileserver role, serves files and volumes from its local storage."; 144 }; 145 146 fileserverArgs = mkOption { 147 default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000"; 148 type = types.str; 149 description = "Arguments to the dafileserver process. See its man page."; 150 }; 151 152 volserverArgs = mkOption { 153 default = ""; 154 type = types.str; 155 description = "Arguments to the davolserver process. See its man page."; 156 example = "-sync never"; 157 }; 158 159 salvageserverArgs = mkOption { 160 default = ""; 161 type = types.str; 162 description = "Arguments to the salvageserver process. See its man page."; 163 example = "-showlog"; 164 }; 165 166 salvagerArgs = mkOption { 167 default = ""; 168 type = types.str; 169 description = "Arguments to the dasalvager process. See its man page."; 170 example = "-showlog -showmounts"; 171 }; 172 }; 173 174 database = { 175 enable = mkOption { 176 default = true; 177 type = types.bool; 178 description = '' 179 Database server role, maintains the Volume Location Database, 180 Protection Database (and Backup Database, see 181 `backup` role). There can be multiple 182 servers in the database role for replication, which then need 183 reliable network connection to each other. 184 185 Servers in this role appear in AFSDB DNS records or the 186 CellServDB. 187 ''; 188 }; 189 190 vlserverArgs = mkOption { 191 default = ""; 192 type = types.str; 193 description = "Arguments to the vlserver process. See its man page."; 194 example = "-rxbind"; 195 }; 196 197 ptserverArgs = mkOption { 198 default = ""; 199 type = types.str; 200 description = "Arguments to the ptserver process. See its man page."; 201 example = "-restricted -default_access S---- S-M---"; 202 }; 203 }; 204 205 backup = { 206 enable = mkEnableOption '' 207 the backup server role. When using OpenAFS built-in buserver, use in conjunction with the 208 `database` role to maintain the Backup 209 Database. Normally only used in conjunction with tape storage 210 or IBM's Tivoli Storage Manager. 211 212 For a modern backup server, enable this role and see 213 {option}`enableFabs` 214 ''; 215 216 enableFabs = mkEnableOption '' 217 FABS, the flexible AFS backup system. It stores volumes as dump files, relying on other 218 pre-existing backup solutions for handling them 219 ''; 220 221 buserverArgs = mkOption { 222 default = ""; 223 type = types.str; 224 description = "Arguments to the buserver process. See its man page."; 225 example = "-p 8"; 226 }; 227 228 cellServDB = mkOption { 229 default = [ ]; 230 type = with types; listOf (submodule [ { options = cellServDBConfig; } ]); 231 description = '' 232 Definition of all cell-local backup database server machines. 233 Use this when your cell uses less backup database servers than 234 other database server machines. 235 ''; 236 }; 237 238 fabsArgs = mkOption { 239 default = ""; 240 type = types.str; 241 description = '' 242 Arguments to the fabsys process. See 243 {manpage}`fabsys_server(1)` and 244 {manpage}`fabsys_config(1)`. 245 ''; 246 }; 247 248 fabsExtraConfig = mkOption { 249 default = { }; 250 type = types.attrs; 251 description = '' 252 Additional configuration parameters for the FABS backup server. 253 ''; 254 example = literalExpression '' 255 { 256 afs.localauth = true; 257 afs.keytab = config.sops.secrets.fabsKeytab.path; 258 } 259 ''; 260 }; 261 }; 262 }; 263 264 dottedPrincipals = mkOption { 265 default = false; 266 type = types.bool; 267 description = '' 268 If enabled, allow principal names containing (.) dots. Enabling 269 this has security implications! 270 ''; 271 }; 272 273 udpPacketSize = mkOption { 274 default = 1310720; 275 type = types.int; 276 description = '' 277 UDP packet size to use in Bytes. Higher values can speed up 278 communications. The default of 1 MB is a sufficient in most 279 cases. Make sure to increase the kernel's UDP buffer size 280 accordingly via `net.core(w|r|opt)mem_max` 281 sysctl. 282 ''; 283 }; 284 285 }; 286 287 }; 288 289 config = mkIf cfg.enable { 290 291 assertions = [ 292 { 293 assertion = cfg.cellServDB != [ ]; 294 message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB."; 295 } 296 { 297 assertion = cfg.cellName != ""; 298 message = "You must specify the local cell name in config.services.openafsServer.cellName."; 299 } 300 ]; 301 302 environment.systemPackages = [ openafsBin ]; 303 304 environment.etc = { 305 bosConfig = { 306 source = bosConfig; 307 target = "openafs/BosConfig"; 308 mode = "0644"; 309 }; 310 cellServDB = { 311 text = mkCellServDB cfg.cellName cfg.cellServDB; 312 target = "openafs/server/CellServDB"; 313 mode = "0644"; 314 }; 315 thisCell = { 316 text = cfg.cellName; 317 target = "openafs/server/ThisCell"; 318 mode = "0644"; 319 }; 320 buCellServDB = { 321 enable = useBuCellServDB; 322 text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB; 323 target = "openafs/backup/CellServDB"; 324 }; 325 }; 326 327 systemd.services = { 328 openafs-server = { 329 description = "OpenAFS server"; 330 after = [ "network.target" ]; 331 wantedBy = [ "multi-user.target" ]; 332 restartIfChanged = false; 333 unitConfig.ConditionPathExists = [ 334 "|/etc/openafs/server/KeyFileExt" 335 ]; 336 preStart = '' 337 mkdir -m 0755 -p /var/openafs 338 ${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"} 339 ${optionalString useBuCellServDB "cp ${buCellServDB}"} 340 ''; 341 serviceConfig = { 342 ExecStart = "${openafsBin}/bin/bosserver -nofork"; 343 ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth"; 344 }; 345 }; 346 }; 347 }; 348}