grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / games / crossfire-server.nix
blob91a684873c2aaa5b9a94b0e74587df83898eed82
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.crossfire-server;
4   serverPort = 13327;
5 in {
6   options.services.crossfire-server = {
7     enable = lib.mkOption {
8       type = lib.types.bool;
9       default = false;
10       description = ''
11         If enabled, the Crossfire game server will be started at boot.
12       '';
13     };
15     package = lib.mkPackageOption pkgs "crossfire-server" {
16       extraDescription = ''
17         ::: {.note}
18         This will also be used for map/arch data, if you don't change {option}`dataDir`
19         :::
20       '';
21     };
23     dataDir = lib.mkOption {
24       type = lib.types.str;
25       default = "${cfg.package}/share/crossfire";
26       defaultText = lib.literalExpression ''"''${config.services.crossfire.package}/share/crossfire"'';
27       description = ''
28         Where to load readonly data from -- maps, archetypes, treasure tables,
29         and the like. If you plan to edit the data on the live server (rather
30         than overlaying the crossfire-maps and crossfire-arch packages and
31         nixos-rebuilding), point this somewhere read-write and copy the data
32         there before starting the server.
33       '';
34     };
36     stateDir = lib.mkOption {
37       type = lib.types.str;
38       default = "/var/lib/crossfire";
39       description = ''
40         Where to store runtime data (save files, persistent items, etc).
42         If left at the default, this will be automatically created on server
43         startup if it does not already exist. If changed, it is the admin's
44         responsibility to make sure that the directory exists and is writeable
45         by the `crossfire` user.
46       '';
47     };
49     openFirewall = lib.mkOption {
50       type = lib.types.bool;
51       default = false;
52       description = ''
53         Whether to open ports in the firewall for the server.
54       '';
55     };
57     configFiles = lib.mkOption {
58       type = lib.types.attrsOf lib.types.str;
59       description = ''
60         Text to append to the corresponding configuration files. Note that the
61         files given in the example are *not* the complete set of files available
62         to customize; look in /etc/crossfire after enabling the server to see
63         the available files, and read the comments in each file for detailed
64         documentation on the format and what settings are available.
66         Note that the motd, rules, and news files, if configured here, will
67         overwrite the example files that come with the server, rather than being
68         appended to them as the other configuration files are.
69       '';
70       example = lib.literalExpression ''
71         {
72           dm_file = '''
73             admin:secret_password:localhost
74             alice:xyzzy:*
75           ''';
76           ban_file = '''
77             # Bob is a jerk
78             bob@*
79             # So is everyone on 192.168.86.255/24
80             *@192.168.86.
81           ''';
82           metaserver2 = '''
83             metaserver2_notification on
84             localhostname crossfire.example.net
85           ''';
86           motd = "Welcome to CrossFire!";
87           news = "No news yet.";
88           rules = "Don't be a jerk.";
89           settings = '''
90             # be nicer to newbies and harsher to experienced players
91             balanced_stat_loss true
92             # don't let players pick up and use admin-created items
93             real_wiz false
94           ''';
95         }
96       '';
97       default = {};
98     };
99   };
101   config = lib.mkIf cfg.enable {
102     users.users.crossfire = {
103       description     = "Crossfire server daemon user";
104       home            = cfg.stateDir;
105       createHome      = false;
106       isSystemUser    = true;
107       group           = "crossfire";
108     };
109     users.groups.crossfire = {};
111     # Merge the cfg.configFiles setting with the default files shipped with
112     # Crossfire.
113     # For most files this consists of reading ${crossfire}/etc/crossfire/${name}
114     # and appending the user setting to it; the motd, news, and rules are handled
115     # specially, with user-provided values completely replacing the original.
116     environment.etc = lib.attrsets.mapAttrs'
117       (name: value: lib.attrsets.nameValuePair "crossfire/${name}" {
118         mode = "0644";
119         text =
120           (lib.optionalString (!lib.elem name ["motd" "news" "rules"])
121             (lib.fileContents "${cfg.package}/etc/crossfire/${name}"))
122           + "\n${value}";
123       }) ({
124         ban_file = "";
125         dm_file = "";
126         exp_table = "";
127         forbid = "";
128         metaserver2 = "";
129         motd = lib.fileContents "${cfg.package}/etc/crossfire/motd";
130         news = lib.fileContents "${cfg.package}/etc/crossfire/news";
131         rules = lib.fileContents "${cfg.package}/etc/crossfire/rules";
132         settings = "";
133         stat_bonus = "";
134       } // cfg.configFiles);
136     systemd.services.crossfire-server = {
137       description   = "Crossfire Server Daemon";
138       wantedBy      = [ "multi-user.target" ];
139       after         = [ "network.target" ];
141       serviceConfig = lib.mkMerge [
142         {
143           ExecStart = "${cfg.package}/bin/crossfire-server -conf /etc/crossfire -local '${cfg.stateDir}' -data '${cfg.dataDir}'";
144           Restart = "always";
145           User = "crossfire";
146           Group = "crossfire";
147           WorkingDirectory = cfg.stateDir;
148         }
149         (lib.mkIf (cfg.stateDir == "/var/lib/crossfire") {
150           StateDirectory = "crossfire";
151         })
152       ];
154       # The crossfire server needs access to a bunch of files at runtime that
155       # are not created automatically at server startup; they're meant to be
156       # installed in $PREFIX/var/crossfire by `make install`. And those files
157       # need to be writeable, so we can't just point at the ones in the nix
158       # store. Instead we take the approach of copying them out of the store
159       # on first run. If `bookarch` already exists, we assume the rest of the
160       # files do as well, and copy nothing -- otherwise we risk ovewriting
161       # server state information every time the server is upgraded.
162       preStart = ''
163         if [ ! -e "${cfg.stateDir}"/bookarch ]; then
164           ${pkgs.rsync}/bin/rsync -a --chmod=u=rwX,go=rX \
165             "${cfg.package}/var/crossfire/" "${cfg.stateDir}/"
166         fi
167       '';
168     };
170     networking.firewall = lib.mkIf cfg.openFirewall {
171       allowedTCPPorts = [ serverPort ];
172     };
173   };