Skip to content

Commit b3429b3

Browse files
committed
nixosModules.MooseFS: Improve
1 parent c76e6f0 commit b3429b3

File tree

2 files changed

+148
-76
lines changed

2 files changed

+148
-76
lines changed

nixos/modules/services/network-filesystems/moosefs.nix

Lines changed: 147 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let
2626
lib.mapAttrsToList (key: val: "${key} = ${valueToString val}") value ));
2727
};
2828

29-
29+
# Manual initialization tool
3030
initTool = pkgs.writeShellScriptBin "mfsmaster-init" ''
3131
if [ ! -e ${cfg.master.settings.DATA_PATH}/metadata.mfs ]; then
3232
cp ${pkgs.moosefs}/var/mfs/metadata.mfs.empty ${cfg.master.settings.DATA_PATH}
@@ -37,19 +37,10 @@ let
3737
fi
3838
'';
3939

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;
47-
48-
# chunkserver config file
49-
chunkserverCfg = settingsFormat.generate
50-
"mfschunkserver.cfg" cfg.chunkserver.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;
5143

52-
# generic template for all daemons
5344
systemdService = name: extraConfig: configFile: {
5445
wantedBy = [ "multi-user.target" ];
5546
wants = [ "network-online.target" ];
@@ -66,40 +57,43 @@ let
6657

6758
in {
6859
###### interface
69-
7060
options = {
7161
services.moosefs = {
7262
masterHost = lib.mkOption {
7363
type = lib.types.str;
7464
default = null;
75-
description = "IP or DNS name of master host.";
65+
description = "IP or DNS name of the MooseFS master server.";
7666
};
7767

7868
runAsUser = lib.mkOption {
7969
type = lib.types.bool;
8070
default = true;
8171
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.";
8373
};
8474

85-
client.enable = lib.mkEnableOption "Moosefs client";
75+
client.enable = lib.mkEnableOption "MooseFS client";
8676

8777
master = {
8878
enable = lib.mkOption {
8979
type = lib.types.bool;
9080
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.
9583
'';
9684
default = false;
9785
};
9886

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+
9993
exports = lib.mkOption {
10094
type = with lib.types; listOf str;
10195
default = null;
102-
description = "Paths to export (see mfsexports.cfg).";
96+
description = "Export definitions for MooseFS (see mfsexports.cfg).";
10397
example = [
10498
"* / rw,alldirs,admin,maproot=0:0"
10599
"* . rw"
@@ -108,7 +102,7 @@ in {
108102

109103
openFirewall = lib.mkOption {
110104
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.";
112106
default = false;
113107
};
114108

@@ -119,16 +113,15 @@ in {
119113
options.DATA_PATH = lib.mkOption {
120114
type = lib.types.str;
121115
default = "/var/lib/mfs";
122-
description = "Data storage directory.";
116+
description = "Directory for storing master metadata.";
123117
};
124118
};
125-
126-
description = "Contents of config file (mfsmaster.cfg).";
119+
description = "Master configuration options (mfsmaster.cfg).";
127120
};
128121
};
129122

130123
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";
132125

133126
settings = lib.mkOption {
134127
type = lib.types.submodule {
@@ -137,28 +130,27 @@ in {
137130
options.DATA_PATH = lib.mkOption {
138131
type = lib.types.str;
139132
default = "/var/lib/mfs";
140-
description = "Data storage directory";
133+
description = "Directory for storing metalogger data.";
141134
};
142135
};
143-
144-
description = "Contents of metalogger config file (mfsmetalogger.cfg).";
136+
description = "Metalogger configuration options (mfsmetalogger.cfg).";
145137
};
146138
};
147139

148140
chunkserver = {
149-
enable = lib.mkEnableOption "Moosefs chunkserver daemon";
141+
enable = lib.mkEnableOption "MooseFS chunkserver daemon that stores file data";
150142

151143
openFirewall = lib.mkOption {
152144
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.";
154146
default = false;
155147
};
156148

157149
hdds = lib.mkOption {
158150
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" ];
162154
};
163155

164156
settings = lib.mkOption {
@@ -168,29 +160,65 @@ in {
168160
options.DATA_PATH = lib.mkOption {
169161
type = lib.types.str;
170162
default = "/var/lib/mfs";
171-
description = "Directory for lock file.";
163+
description = "Directory for lock files and other runtime data.";
172164
};
173165
};
166+
description = "Chunkserver configuration options (mfschunkserver.cfg).";
167+
};
168+
};
169+
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+
'';
174176

175-
description = "Contents of chunkserver config file (mfschunkserver.cfg).";
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.";
176202
};
177203
};
178204
};
179205
};
180206

181207
###### implementation
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.") ];
182210

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.") ];
186-
187-
# Service settings
188211
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+
]);
194222

195223
metalogger.settings = lib.mkIf cfg.metalogger.enable {
196224
WORKING_USER = mfsUser;
@@ -205,11 +233,10 @@ in {
205233
};
206234
};
207235

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 ) ) {
210237
users.moosefs = {
211238
isSystemUser = true;
212-
description = "moosefs daemon user";
239+
description = "MooseFS daemon user";
213240
group = "moosefs";
214241
};
215242
groups.moosefs = {};
@@ -219,28 +246,74 @@ in {
219246
(lib.optional cfg.client.enable pkgs.moosefs) ++
220247
(lib.optional cfg.master.enable initTool);
221248

222-
networking.firewall.allowedTCPPorts =
223-
(lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) ++
224-
(lib.optional cfg.chunkserver.openFirewall 9422);
225-
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}";
231-
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 );
239-
240-
systemd.services.mfs-metalogger = lib.mkIf cfg.metalogger.enable
241-
( systemdService "metalogger" { Restart = "on-abnormal"; } metaloggerCfg );
242-
243-
systemd.services.mfs-chunkserver = lib.mkIf cfg.chunkserver.enable
244-
( systemdService "chunkserver" { Restart = "on-abnormal"; } chunkserverCfg );
245-
};
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+
];
254+
255+
systemd.tmpfiles.rules = [
256+
# Master directories
257+
(lib.optionalString cfg.master.enable
258+
"d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser} -")
259+
260+
# Metalogger directories
261+
(lib.optionalString cfg.metalogger.enable
262+
"d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser} -")
263+
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);
269+
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+
};
246319
}

nixos/tests/moosefs.nix

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import ./make-test-python.nix (
1212
services.moosefs.master = {
1313
enable = true;
1414
openFirewall = true;
15+
autoInit = true;
1516
exports = [
1617
"* / rw,alldirs,admin,maproot=0:0"
1718
"* . rw"
@@ -76,8 +77,6 @@ import ./make-test-python.nix (
7677
# prepare master server
7778
master.start()
7879
master.wait_for_unit("multi-user.target")
79-
master.succeed("mfsmaster-init")
80-
master.succeed("systemctl restart mfs-master")
8180
master.wait_for_unit("mfs-master.service")
8281
8382
metalogger.wait_for_unit("mfs-metalogger.service")

0 commit comments

Comments
 (0)