1 { config, lib, options, pkgs, ... }:
4 cfg = config.services.slurm;
5 opt = options.services.slurm;
6 # configuration file can be generated by https://slurm.schedmd.com/configurator.html
10 configFile = pkgs.writeTextDir "slurm.conf"
12 ClusterName=${cfg.clusterName}
13 StateSaveLocation=${cfg.stateSaveLocation}
15 ${lib.optionalString (cfg.controlMachine != null) "controlMachine=${cfg.controlMachine}"}
16 ${lib.optionalString (cfg.controlAddr != null) "controlAddr=${cfg.controlAddr}"}
17 ${toString (map (x: "NodeName=${x}\n") cfg.nodeName)}
18 ${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)}
19 PlugStackConfig=${plugStackConfig}/plugstack.conf
20 ProctrackType=${cfg.procTrackType}
24 plugStackConfig = pkgs.writeTextDir "plugstack.conf"
26 ${lib.optionalString cfg.enableSrunX11 "optional ${pkgs.slurm-spank-x11}/lib/x11.so"}
27 ${cfg.extraPlugstackConfig}
30 cgroupConfig = pkgs.writeTextDir "cgroup.conf"
32 ${cfg.extraCgroupConfig}
35 slurmdbdConf = pkgs.writeText "slurmdbd.conf"
37 DbdHost=${cfg.dbdserver.dbdHost}
39 StorageType=accounting_storage/mysql
40 StorageUser=${cfg.dbdserver.storageUser}
41 ${cfg.dbdserver.extraConfig}
44 # slurm expects some additional config files to be
45 # in the same directory as slurm.conf
46 etcSlurm = pkgs.symlinkJoin {
48 paths = [ configFile cgroupConfig plugStackConfig ] ++ cfg.extraConfigPaths;
56 meta.maintainers = [ lib.maintainers.markuskowa ];
63 enable = lib.mkOption {
64 type = lib.types.bool;
67 Whether to enable the slurm control daemon.
68 Note that the standard authentication method is "munge".
69 The "munge" service needs to be provided with a password file in order for
70 slurm to work properly (see `services.munge.password`).
76 enable = lib.mkEnableOption "SlurmDBD service";
78 dbdHost = lib.mkOption {
80 default = config.networking.hostName;
81 defaultText = lib.literalExpression "config.networking.hostName";
83 Hostname of the machine where `slurmdbd`
84 is running (i.e. name returned by `hostname -s`).
88 storageUser = lib.mkOption {
91 defaultText = lib.literalExpression "config.${opt.user}";
97 storagePassFile = lib.mkOption {
98 type = with lib.types; nullOr str;
101 Path to file with database password. The content of this will be used to
102 create the password for the `StoragePass` option.
106 extraConfig = lib.mkOption {
107 type = lib.types.lines;
110 Extra configuration for `slurmdbd.conf` See also:
111 {manpage}`slurmdbd.conf(8)`.
117 enable = lib.mkEnableOption "slurm client daemon";
120 enableStools = lib.mkOption {
121 type = lib.types.bool;
124 Whether to provide a slurm.conf file.
125 Enable this option if you do not run a slurm daemon on this host
126 (i.e. `server.enable` and `client.enable` are `false`)
127 but you still want to run slurm commands from this host.
131 package = lib.mkPackageOption pkgs "slurm" {
132 example = "slurm-full";
134 default = pkgs.slurm.override { enableX11 = ! cfg.enableSrunX11; };
137 controlMachine = lib.mkOption {
138 type = lib.types.nullOr lib.types.str;
142 The short hostname of the machine where SLURM control functions are
143 executed (i.e. the name returned by the command "hostname -s", use "tux001"
144 rather than "tux001.my.com").
148 controlAddr = lib.mkOption {
149 type = lib.types.nullOr lib.types.str;
150 default = cfg.controlMachine;
151 defaultText = lib.literalExpression "config.${opt.controlMachine}";
154 Name that ControlMachine should be referred to in establishing a
159 clusterName = lib.mkOption {
160 type = lib.types.str;
162 example = "myCluster";
164 Necessary to distinguish accounting records in a multi-cluster environment.
168 nodeName = lib.mkOption {
169 type = lib.types.listOf lib.types.str;
171 example = lib.literalExpression ''[ "linux[1-32] CPUs=1 State=UNKNOWN" ];'';
173 Name that SLURM uses to refer to a node (or base partition for BlueGene
174 systems). Typically this would be the string that "/bin/hostname -s"
175 returns. Note that now you have to write node's parameters after the name.
179 partitionName = lib.mkOption {
180 type = lib.types.listOf lib.types.str;
182 example = lib.literalExpression ''[ "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP" ];'';
184 Name by which the partition may be referenced. Note that now you have
185 to write the partition's parameters after the name.
189 enableSrunX11 = lib.mkOption {
191 type = lib.types.bool;
193 If enabled srun will accept the option "--x11" to allow for X11 forwarding
194 from within an interactive session or a batch job. This activates the
195 slurm-spank-x11 module. Note that this option also enables
196 {option}`services.openssh.forwardX11` on the client.
198 This option requires slurm to be compiled without native X11 support.
199 The default behavior is to re-compile the slurm package with native X11
200 support disabled if this option is set to true.
202 To use the native X11 support add `PrologFlags=X11` in {option}`extraConfig`.
203 Note that this method will only work RSA SSH host keys.
207 procTrackType = lib.mkOption {
208 type = lib.types.str;
209 default = "proctrack/linuxproc";
211 Plugin to be used for process tracking on a job step basis.
212 The slurmd daemon uses this mechanism to identify all processes
213 which are children of processes it spawns for a user job step.
217 stateSaveLocation = lib.mkOption {
218 type = lib.types.str;
219 default = "/var/spool/slurmctld";
221 Directory into which the Slurm controller, slurmctld, saves its state.
225 user = lib.mkOption {
226 type = lib.types.str;
227 default = defaultUser;
229 Set this option when you want to run the slurmctld daemon
230 as something else than the default slurm user "slurm".
231 Note that the UID of this user needs to be the same
236 extraConfig = lib.mkOption {
238 type = lib.types.lines;
240 Extra configuration options that will be added verbatim at
241 the end of the slurm configuration file.
245 extraPlugstackConfig = lib.mkOption {
247 type = lib.types.lines;
249 Extra configuration that will be added to the end of `plugstack.conf`.
253 extraCgroupConfig = lib.mkOption {
255 type = lib.types.lines;
257 Extra configuration for `cgroup.conf`. This file is
258 used when `procTrackType=proctrack/cgroup`.
262 extraConfigPaths = lib.mkOption {
263 type = with lib.types; listOf path;
266 Slurm expects config files for plugins in the same path
267 as `slurm.conf`. Add extra nix store
268 paths that should be merged into same directory as
273 etcSlurm = lib.mkOption {
274 type = lib.types.path;
277 defaultText = lib.literalMD ''
278 Directory created from generated config files and
279 `config.${opt.extraConfigPaths}`.
282 Path to directory with slurm config files. This option is set by default from the
283 Slurm module and is meant to make the Slurm config file available to other modules.
292 (lib.mkRemovedOptionModule [ "services" "slurm" "dbdserver" "storagePass" ] ''
293 This option has been removed so that the database password is not exposed via the nix store.
294 Use services.slurm.dbdserver.storagePassFile to provide the database password.
296 (lib.mkRemovedOptionModule [ "services" "slurm" "dbdserver" "configFile" ] ''
297 This option has been removed. Use services.slurm.dbdserver.storagePassFile
298 and services.slurm.dbdserver.extraConfig instead.
302 ###### implementation
306 wrappedSlurm = pkgs.stdenv.mkDerivation {
307 name = "wrappedSlurm";
309 builder = pkgs.writeText "builder.sh" ''
312 find ${lib.getBin cfg.package}/bin -type f -executable | while read EXE
314 exename="$(basename $EXE)"
315 wrappername="$out/bin/$exename"
316 cat > "$wrappername" <<EOT
318 if [ -z "$SLURM_CONF" ]
320 SLURM_CONF="${cfg.etcSlurm}/slurm.conf" "$EXE" "\$@"
325 chmod +x "$wrappername"
329 ln -s ${lib.getBin cfg.package}/share/man $out/share/man
333 in lib.mkIf ( cfg.enableStools ||
336 cfg.dbdserver.enable ) {
338 environment.systemPackages = [ wrappedSlurm ];
340 services.munge.enable = lib.mkDefault true;
342 # use a static uid as default to ensure it is the same on all nodes
343 users.users.slurm = lib.mkIf (cfg.user == defaultUser) {
346 uid = config.ids.uids.slurm;
349 users.groups.slurm.gid = config.ids.uids.slurm;
351 systemd.services.slurmd = lib.mkIf (cfg.client.enable) {
352 path = with pkgs; [ wrappedSlurm coreutils ]
353 ++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
355 wantedBy = [ "multi-user.target" ];
357 "systemd-tmpfiles-clean.service"
359 "network-online.target"
362 wants = [ "network-online.target" ];
366 KillMode = "process";
367 ExecStart = "${wrappedSlurm}/bin/slurmd";
368 PIDFile = "/run/slurmd.pid";
369 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
370 LimitMEMLOCK = "infinity";
375 systemd.tmpfiles.rules = lib.mkIf cfg.client.enable [
376 "d /var/spool/slurmd 755 root root -"
379 services.openssh.settings.X11Forwarding = lib.mkIf cfg.client.enable (lib.mkDefault true);
381 systemd.services.slurmctld = lib.mkIf (cfg.server.enable) {
382 path = with pkgs; [ wrappedSlurm munge coreutils ]
383 ++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
385 wantedBy = [ "multi-user.target" ];
386 after = [ "network.target" "munged.service" ];
387 requires = [ "munged.service" ];
391 ExecStart = "${wrappedSlurm}/bin/slurmctld";
392 PIDFile = "/run/slurmctld.pid";
393 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
397 mkdir -p ${cfg.stateSaveLocation}
398 chown -R ${cfg.user}:slurm ${cfg.stateSaveLocation}
402 systemd.services.slurmdbd = let
403 # slurm strips the last component off the path
404 configPath = "$RUNTIME_DIRECTORY/slurmdbd.conf";
405 in lib.mkIf (cfg.dbdserver.enable) {
406 path = with pkgs; [ wrappedSlurm munge coreutils ];
408 wantedBy = [ "multi-user.target" ];
409 after = [ "network.target" "munged.service" "mysql.service" ];
410 requires = [ "munged.service" "mysql.service" ];
413 install -m 600 -o ${cfg.user} -T ${slurmdbdConf} ${configPath}
414 ${lib.optionalString (cfg.dbdserver.storagePassFile != null) ''
415 echo "StoragePass=$(cat ${cfg.dbdserver.storagePassFile})" \
421 export SLURM_CONF=${configPath}
422 exec ${cfg.package}/bin/slurmdbd -D
426 RuntimeDirectory = "slurmdbd";
428 PIDFile = "/run/slurmdbd.pid";
429 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";