grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / games / minetest-server.nix
blob98613e4391efe7d360d2aea69784434d38edce92
1 { config, lib, pkgs, ... }:
2 let
3   CONTAINS_NEWLINE_RE = ".*\n.*";
4   # The following values are reserved as complete option values:
5   # { - start of a group.
6   # """ - start of a multi-line string.
7   RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*";
8   NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}";
10   # There is no way to encode """ on its own line in a Minetest config.
11   UNESCAPABLE_RE = ".*\n\"\"\"\n.*";
13   toConfMultiline = name: value:
14     assert lib.assertMsg
15       ((builtins.match UNESCAPABLE_RE value) == null)
16       ''""" can't be on its own line in a minetest config.'';
17     "${name} = \"\"\"\n${value}\n\"\"\"\n";
19   toConf = values:
20     lib.concatStrings
21       (lib.mapAttrsToList
22         (name: value: {
23           bool = "${name} = ${toString value}\n";
24           int = "${name} = ${toString value}\n";
25           null = "";
26           set = "${name} = {\n${toConf value}}\n";
27           string =
28             if (builtins.match NEEDS_MULTILINE_RE value) != null
29             then toConfMultiline name value
30             else "${name} = ${value}\n";
31         }.${builtins.typeOf value})
32         values);
34   cfg   = config.services.minetest-server;
35   flag  = val: name: lib.optionals (val != null) ["--${name}" "${toString val}"];
37   flags = [
38     "--server"
39   ]
40     ++ (
41       if cfg.configPath != null
42       then ["--config" cfg.configPath]
43       else ["--config" (builtins.toFile "minetest.conf" (toConf cfg.config))])
44     ++ (flag cfg.gameId "gameid")
45     ++ (flag cfg.world "world")
46     ++ (flag cfg.logPath "logfile")
47     ++ (flag cfg.port "port")
48     ++ cfg.extraArgs;
51   options = {
52     services.minetest-server = {
53       enable = lib.mkOption {
54         type        = lib.types.bool;
55         default     = false;
56         description = "If enabled, starts a Minetest Server.";
57       };
59       gameId = lib.mkOption {
60         type        = lib.types.nullOr lib.types.str;
61         default     = null;
62         description = ''
63           Id of the game to use. To list available games run
64           `minetestserver --gameid list`.
66           If only one game exists, this option can be null.
67         '';
68       };
70       world = lib.mkOption {
71         type        = lib.types.nullOr lib.types.path;
72         default     = null;
73         description = ''
74           Name of the world to use. To list available worlds run
75           `minetestserver --world list`.
77           If only one world exists, this option can be null.
78         '';
79       };
81       configPath = lib.mkOption {
82         type        = lib.types.nullOr lib.types.path;
83         default     = null;
84         description = ''
85           Path to the config to use.
87           If set to null, the config of the running user will be used:
88           `~/.minetest/minetest.conf`.
89         '';
90       };
92       config = lib.mkOption {
93         type = lib.types.attrsOf lib.types.anything;
94         default = {};
95         description = ''
96           Settings to add to the minetest config file.
98           This option is ignored if `configPath` is set.
99         '';
100       };
102       logPath = lib.mkOption {
103         type        = lib.types.nullOr lib.types.path;
104         default     = null;
105         description = ''
106           Path to logfile for logging.
108           If set to null, logging will be output to stdout which means
109           all output will be caught by systemd.
110         '';
111       };
113       port = lib.mkOption {
114         type        = lib.types.nullOr lib.types.int;
115         default     = null;
116         description = ''
117           Port number to bind to.
119           If set to null, the default 30000 will be used.
120         '';
121       };
123       extraArgs = lib.mkOption {
124         type = lib.types.listOf lib.types.str;
125         default = [];
126         description = ''
127           Additional command line flags to pass to the minetest executable.
128         '';
129       };
130     };
131   };
133   config = lib.mkIf cfg.enable {
134     users.users.minetest = {
135       description     = "Minetest Server Service user";
136       home            = "/var/lib/minetest";
137       createHome      = true;
138       uid             = config.ids.uids.minetest;
139       group           = "minetest";
140     };
141     users.groups.minetest.gid = config.ids.gids.minetest;
143     systemd.services.minetest-server = {
144       description   = "Minetest Server Service";
145       wantedBy      = [ "multi-user.target" ];
146       after         = [ "network.target" ];
148       serviceConfig.Restart = "always";
149       serviceConfig.User    = "minetest";
150       serviceConfig.Group   = "minetest";
152       script = ''
153         cd /var/lib/minetest
155         exec ${pkgs.minetest}/bin/minetest ${lib.escapeShellArgs flags}
156       '';
157     };
158   };