lol

nixosModules.MooseFS: Improve

+144 -72
+143 -70
nixos/modules/services/network-filesystems/moosefs.nix
··· 26 26 lib.mapAttrsToList (key: val: "${key} = ${valueToString val}") value )); 27 27 }; 28 28 29 - 29 + # Manual initialization tool 30 30 initTool = pkgs.writeShellScriptBin "mfsmaster-init" '' 31 31 if [ ! -e ${cfg.master.settings.DATA_PATH}/metadata.mfs ]; then 32 32 cp ${pkgs.moosefs}/var/mfs/metadata.mfs.empty ${cfg.master.settings.DATA_PATH} ··· 37 37 fi 38 38 ''; 39 39 40 - # master config file 41 - masterCfg = settingsFormat.generate 42 - "mfsmaster.cfg" cfg.master.settings; 43 - 44 - # metalogger config file 45 - metaloggerCfg = settingsFormat.generate 46 - "mfsmetalogger.cfg" cfg.metalogger.settings; 40 + masterCfg = settingsFormat.generate "mfsmaster.cfg" cfg.master.settings; 41 + metaloggerCfg = settingsFormat.generate "mfsmetalogger.cfg" cfg.metalogger.settings; 42 + chunkserverCfg = settingsFormat.generate "mfschunkserver.cfg" cfg.chunkserver.settings; 47 43 48 - # chunkserver config file 49 - chunkserverCfg = settingsFormat.generate 50 - "mfschunkserver.cfg" cfg.chunkserver.settings; 51 - 52 - # generic template for all daemons 53 44 systemdService = name: extraConfig: configFile: { 54 45 wantedBy = [ "multi-user.target" ]; 55 46 wants = [ "network-online.target" ]; ··· 66 57 67 58 in { 68 59 ###### interface 69 - 70 60 options = { 71 61 services.moosefs = { 72 62 masterHost = lib.mkOption { 73 63 type = lib.types.str; 74 64 default = null; 75 - description = "IP or DNS name of master host."; 65 + description = "IP or DNS name of the MooseFS master server."; 76 66 }; 77 67 78 68 runAsUser = lib.mkOption { 79 69 type = lib.types.bool; 80 70 default = true; 81 71 example = true; 82 - description = "Run daemons as user moosefs instead of root."; 72 + description = "Run daemons as moosefs user instead of root for better security."; 83 73 }; 84 74 85 - client.enable = lib.mkEnableOption "Moosefs client"; 75 + client.enable = lib.mkEnableOption "MooseFS client"; 86 76 87 77 master = { 88 78 enable = lib.mkOption { 89 79 type = lib.types.bool; 90 80 description = '' 91 - Enable Moosefs master daemon. 92 - 93 - You need to run `mfsmaster-init` on a freshly installed master server to 94 - initialize the `DATA_PATH` directory. 81 + Enable MooseFS master daemon. 82 + The master server coordinates all MooseFS operations and stores metadata. 95 83 ''; 96 84 default = false; 97 85 }; 98 86 87 + autoInit = lib.mkOption { 88 + type = lib.types.bool; 89 + default = false; 90 + description = "Whether to automatically initialize the master's metadata directory on first run. Use with caution."; 91 + }; 92 + 99 93 exports = lib.mkOption { 100 94 type = with lib.types; listOf str; 101 95 default = null; 102 - description = "Paths to export (see mfsexports.cfg)."; 96 + description = "Export definitions for MooseFS (see mfsexports.cfg)."; 103 97 example = [ 104 98 "* / rw,alldirs,admin,maproot=0:0" 105 99 "* . rw" ··· 108 102 109 103 openFirewall = lib.mkOption { 110 104 type = lib.types.bool; 111 - description = "Whether to automatically open the necessary ports in the firewall."; 105 + description = "Whether to automatically open required firewall ports for master service."; 112 106 default = false; 113 107 }; 114 108 ··· 119 113 options.DATA_PATH = lib.mkOption { 120 114 type = lib.types.str; 121 115 default = "/var/lib/mfs"; 122 - description = "Data storage directory."; 116 + description = "Directory for storing master metadata."; 123 117 }; 124 118 }; 125 - 126 - description = "Contents of config file (mfsmaster.cfg)."; 119 + description = "Master configuration options (mfsmaster.cfg)."; 127 120 }; 128 121 }; 129 122 130 123 metalogger = { 131 - enable = lib.mkEnableOption "Moosefs metalogger daemon"; 124 + enable = lib.mkEnableOption "MooseFS metalogger daemon that maintains a backup copy of the master's metadata"; 132 125 133 126 settings = lib.mkOption { 134 127 type = lib.types.submodule { ··· 137 130 options.DATA_PATH = lib.mkOption { 138 131 type = lib.types.str; 139 132 default = "/var/lib/mfs"; 140 - description = "Data storage directory"; 133 + description = "Directory for storing metalogger data."; 141 134 }; 142 135 }; 143 - 144 - description = "Contents of metalogger config file (mfsmetalogger.cfg)."; 136 + description = "Metalogger configuration options (mfsmetalogger.cfg)."; 145 137 }; 146 138 }; 147 139 148 140 chunkserver = { 149 - enable = lib.mkEnableOption "Moosefs chunkserver daemon"; 141 + enable = lib.mkEnableOption "MooseFS chunkserver daemon that stores file data"; 150 142 151 143 openFirewall = lib.mkOption { 152 144 type = lib.types.bool; 153 - description = "Whether to automatically open the necessary ports in the firewall."; 145 + description = "Whether to automatically open required firewall ports for chunkserver service."; 154 146 default = false; 155 147 }; 156 148 157 149 hdds = lib.mkOption { 158 150 type = with lib.types; listOf str; 159 - default = null; 160 - description = "Mount points to be used by chunkserver for storage (see mfshdd.cfg)."; 161 - example = [ "/mnt/hdd1" ]; 151 + default = null; 152 + description = "Mount points used by chunkserver for data storage (see mfshdd.cfg)."; 153 + example = [ "/mnt/hdd1" "/mnt/hdd2" ]; 162 154 }; 163 155 164 156 settings = lib.mkOption { ··· 168 160 options.DATA_PATH = lib.mkOption { 169 161 type = lib.types.str; 170 162 default = "/var/lib/mfs"; 171 - description = "Directory for lock file."; 163 + description = "Directory for lock files and other runtime data."; 172 164 }; 173 165 }; 166 + description = "Chunkserver configuration options (mfschunkserver.cfg)."; 167 + }; 168 + }; 174 169 175 - description = "Contents of chunkserver config file (mfschunkserver.cfg)."; 170 + cgiserver = { 171 + enable = lib.mkEnableOption '' 172 + MooseFS CGI server for web interface. 173 + Warning: The CGI server interface should be properly secured from unauthorized access, 174 + as it provides full control over your MooseFS installation. 175 + ''; 176 + 177 + openFirewall = lib.mkOption { 178 + type = lib.types.bool; 179 + description = "Whether to automatically open the web interface port."; 180 + default = false; 181 + }; 182 + 183 + settings = lib.mkOption { 184 + type = lib.types.submodule { 185 + freeformType = settingsFormat.type; 186 + options = { 187 + BIND_HOST = lib.mkOption { 188 + type = lib.types.str; 189 + default = "0.0.0.0"; 190 + description = "IP address to bind CGI server to."; 191 + }; 192 + 193 + PORT = lib.mkOption { 194 + type = lib.types.port; 195 + default = 9425; 196 + description = "Port for CGI server to listen on."; 197 + }; 198 + }; 199 + }; 200 + default = {}; 201 + description = "CGI server configuration options."; 176 202 }; 177 203 }; 178 204 }; 179 205 }; 180 206 181 207 ###### implementation 182 - 183 - config = lib.mkIf ( cfg.client.enable || cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) { 184 - 185 - warnings = [ ( lib.mkIf (!cfg.runAsUser) "Running moosefs services as root is not recommended.") ]; 208 + config = lib.mkIf (cfg.client.enable || cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable || cfg.cgiserver.enable) { 209 + warnings = [ ( lib.mkIf (!cfg.runAsUser) "Running MooseFS services as root is not recommended.") ]; 186 210 187 - # Service settings 188 211 services.moosefs = { 189 - master.settings = lib.mkIf cfg.master.enable { 190 - WORKING_USER = mfsUser; 191 - EXPORTS_FILENAME = toString ( pkgs.writeText "mfsexports.cfg" 192 - (lib.concatStringsSep "\n" cfg.master.exports)); 193 - }; 212 + master.settings = lib.mkIf cfg.master.enable (lib.mkMerge [ 213 + { 214 + WORKING_USER = mfsUser; 215 + EXPORTS_FILENAME = toString ( pkgs.writeText "mfsexports.cfg" 216 + (lib.concatStringsSep "\n" cfg.master.exports)); 217 + } 218 + (lib.mkIf cfg.cgiserver.enable { 219 + MFSCGISERV = toString cfg.cgiserver.settings.PORT; 220 + }) 221 + ]); 194 222 195 223 metalogger.settings = lib.mkIf cfg.metalogger.enable { 196 224 WORKING_USER = mfsUser; ··· 205 233 }; 206 234 }; 207 235 208 - # Create system user account for daemons 209 - users = lib.mkIf ( cfg.runAsUser && ( cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) ) { 236 + users = lib.mkIf ( cfg.runAsUser && ( cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable || cfg.cgiserver.enable ) ) { 210 237 users.moosefs = { 211 238 isSystemUser = true; 212 - description = "moosefs daemon user"; 239 + description = "MooseFS daemon user"; 213 240 group = "moosefs"; 214 241 }; 215 242 groups.moosefs = {}; ··· 219 246 (lib.optional cfg.client.enable pkgs.moosefs) ++ 220 247 (lib.optional cfg.master.enable initTool); 221 248 222 - networking.firewall.allowedTCPPorts = 223 - (lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) ++ 224 - (lib.optional cfg.chunkserver.openFirewall 9422); 249 + networking.firewall.allowedTCPPorts = lib.mkMerge [ 250 + (lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) 251 + (lib.optional cfg.chunkserver.openFirewall 9422) 252 + (lib.optional (cfg.cgiserver.enable && cfg.cgiserver.openFirewall) cfg.cgiserver.settings.PORT) 253 + ]; 225 254 226 - # Ensure storage directories exist 227 - systemd.tmpfiles.rules = 228 - lib.optional cfg.master.enable "d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}" 229 - ++ lib.optional cfg.metalogger.enable "d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}" 230 - ++ lib.optional cfg.chunkserver.enable "d ${cfg.chunkserver.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"; 255 + systemd.tmpfiles.rules = [ 256 + # Master directories 257 + (lib.optionalString cfg.master.enable 258 + "d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser} -") 231 259 232 - # Service definitions 233 - systemd.services.mfs-master = lib.mkIf cfg.master.enable 234 - ( systemdService "master" { 235 - TimeoutStartSec = 1800; 236 - TimeoutStopSec = 1800; 237 - Restart = "no"; 238 - } masterCfg ); 260 + # Metalogger directories 261 + (lib.optionalString cfg.metalogger.enable 262 + "d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser} -") 239 263 240 - systemd.services.mfs-metalogger = lib.mkIf cfg.metalogger.enable 241 - ( systemdService "metalogger" { Restart = "on-abnormal"; } metaloggerCfg ); 264 + # Chunkserver directories 265 + (lib.optionalString cfg.chunkserver.enable 266 + "d ${cfg.chunkserver.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser} -") 267 + ] ++ lib.optionals (cfg.chunkserver.enable && cfg.chunkserver.hdds != null) 268 + (map (dir: "d ${dir} 0755 ${mfsUser} ${mfsUser} -") cfg.chunkserver.hdds); 242 269 243 - systemd.services.mfs-chunkserver = lib.mkIf cfg.chunkserver.enable 244 - ( systemdService "chunkserver" { Restart = "on-abnormal"; } chunkserverCfg ); 245 - }; 270 + systemd.services = lib.mkMerge [ 271 + (lib.mkIf cfg.master.enable { 272 + mfs-master = (lib.mkMerge [ 273 + (systemdService "master" { 274 + TimeoutStartSec = 1800; 275 + TimeoutStopSec = 1800; 276 + Restart = "on-failure"; 277 + User = mfsUser; 278 + } masterCfg) 279 + { 280 + preStart = lib.mkIf cfg.master.autoInit "${initTool}/bin/mfsmaster-init"; 281 + } 282 + ]); 283 + }) 284 + 285 + (lib.mkIf cfg.metalogger.enable { 286 + mfs-metalogger = systemdService "metalogger" { 287 + Restart = "on-abnormal"; 288 + User = mfsUser; 289 + } metaloggerCfg; 290 + }) 291 + 292 + (lib.mkIf cfg.chunkserver.enable { 293 + mfs-chunkserver = systemdService "chunkserver" { 294 + Restart = "on-abnormal"; 295 + User = mfsUser; 296 + } chunkserverCfg; 297 + }) 298 + 299 + (lib.mkIf cfg.cgiserver.enable { 300 + mfs-cgiserv = { 301 + description = "MooseFS CGI Server"; 302 + wantedBy = [ "multi-user.target" ]; 303 + after = [ "mfs-master.service" ]; 304 + 305 + serviceConfig = { 306 + Type = "simple"; 307 + ExecStart = "${pkgs.moosefs}/bin/mfscgiserv -D /var/lib/mfs -f start"; 308 + ExecStop = "${pkgs.moosefs}/bin/mfscgiserv -D /var/lib/mfs stop"; 309 + Restart = "on-failure"; 310 + RestartSec = "30s"; 311 + User = mfsUser; 312 + Group = mfsUser; 313 + WorkingDirectory = "/var/lib/mfs"; 314 + }; 315 + }; 316 + }) 317 + ]; 318 + }; 246 319 }
+1 -2
nixos/tests/moosefs.nix
··· 12 12 services.moosefs.master = { 13 13 enable = true; 14 14 openFirewall = true; 15 + autoInit = true; 15 16 exports = [ 16 17 "* / rw,alldirs,admin,maproot=0:0" 17 18 "* . rw" ··· 76 77 # prepare master server 77 78 master.start() 78 79 master.wait_for_unit("multi-user.target") 79 - master.succeed("mfsmaster-init") 80 - master.succeed("systemctl restart mfs-master") 81 80 master.wait_for_unit("mfs-master.service") 82 81 83 82 metalogger.wait_for_unit("mfs-metalogger.service")