nixos/bluemap: init module

Changed files
+314
nixos
doc
manual
release-notes
modules
services
web-servers
+2
nixos/doc/manual/release-notes/rl-2405.section.md
···
- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
+
- [Bluemap](https://bluemap.bluecolored.de/), a 3D minecraft map renderer. Available as [services.bluemap](#opt-services.bluemap.enable).
+
- [fritz-exporter](https://github.com/pdreker/fritz_exporter), a Prometheus exporter for extracting metrics from [FRITZ!](https://avm.de/produkte/) devices. Available as [services.prometheus.exporters.fritz](#opt-services.prometheus.exporters.fritz.enable).
- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
+1
nixos/modules/module-list.nix
···
./services/web-apps/zitadel.nix
./services/web-servers/agate.nix
./services/web-servers/apache-httpd/default.nix
+
./services/web-servers/bluemap.nix
./services/web-servers/caddy/default.nix
./services/web-servers/darkhttpd.nix
./services/web-servers/fcgiwrap.nix
+311
nixos/modules/services/web-servers/bluemap.nix
···
+
{ config, lib, pkgs, ... }:
+
let
+
cfg = config.services.bluemap;
+
format = pkgs.formats.hocon { };
+
+
coreConfig = format.generate "core.conf" cfg.coreSettings;
+
webappConfig = format.generate "webapp.conf" cfg.webappSettings;
+
webserverConfig = format.generate "webserver.conf" cfg.webserverSettings;
+
+
mapsFolder = pkgs.linkFarm "maps"
+
(lib.attrsets.mapAttrs' (name: value:
+
lib.nameValuePair "${name}.conf"
+
(format.generate "${name}.conf" value))
+
cfg.maps);
+
+
storageFolder = pkgs.linkFarm "storage"
+
(lib.attrsets.mapAttrs' (name: value:
+
lib.nameValuePair "${name}.conf"
+
(format.generate "${name}.conf" value))
+
cfg.storage);
+
+
configFolder = pkgs.linkFarm "bluemap-config" {
+
"maps" = mapsFolder;
+
"storages" = storageFolder;
+
"core.conf" = coreConfig;
+
"webapp.conf" = webappConfig;
+
"webserver.conf" = webserverConfig;
+
"resourcepacks" = pkgs.linkFarm "resourcepacks" cfg.resourcepacks;
+
};
+
+
inherit (lib) mkOption;
+
in {
+
options.services.bluemap = {
+
enable = lib.mkEnableOption "bluemap";
+
+
eula = mkOption {
+
type = lib.types.bool;
+
description = ''
+
By changing this option to true you confirm that you own a copy of minecraft Java Edition,
+
and that you agree to minecrafts EULA.
+
'';
+
default = false;
+
};
+
+
defaultWorld = mkOption {
+
type = lib.types.path;
+
description = ''
+
The world used by the default map ruleset.
+
If you configure your own maps you do not need to set this.
+
'';
+
example = lib.literalExpression "\${config.services.minecraft.dataDir}/world";
+
};
+
+
enableRender = mkOption {
+
type = lib.types.bool;
+
description = "Enable rendering";
+
default = true;
+
};
+
+
webRoot = mkOption {
+
type = lib.types.path;
+
default = "/var/lib/bluemap/web";
+
description = "The directory for saving and serving the webapp and the maps";
+
};
+
+
enableNginx = mkOption {
+
type = lib.types.bool;
+
default = true;
+
description = "Enable configuring a virtualHost for serving the bluemap webapp";
+
};
+
+
host = mkOption {
+
type = lib.types.str;
+
default = "bluemap.${config.networking.domain}";
+
defaultText = lib.literalExpression "bluemap.\${config.networking.domain}";
+
description = "Domain to configure nginx for";
+
};
+
+
onCalendar = mkOption {
+
type = lib.types.str;
+
description = ''
+
How often to trigger rendering the map,
+
in the format of a systemd timer onCalendar configuration.
+
See {manpage}`systemd.timer(5)`.
+
'';
+
default = "*-*-* 03:10:00";
+
};
+
+
coreSettings = mkOption {
+
type = lib.types.submodule {
+
freeformType = format.type;
+
options = {
+
data = mkOption {
+
type = lib.types.path;
+
description = "Folder for where bluemap stores its data";
+
default = "/var/lib/bluemap";
+
};
+
metrics = lib.mkEnableOption "Sending usage metrics containing the version of bluemap in use";
+
};
+
};
+
description = "Settings for the core.conf file, [see upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/core.conf).";
+
};
+
+
webappSettings = mkOption {
+
type = lib.types.submodule {
+
freeformType = format.type;
+
};
+
default = {
+
enabled = true;
+
webroot = cfg.webRoot;
+
};
+
defaultText = lib.literalExpression ''
+
{
+
enabled = true;
+
webroot = config.services.bluemap.webRoot;
+
}
+
'';
+
description = "Settings for the webapp.conf file, see [upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webapp.conf).";
+
};
+
+
webserverSettings = mkOption {
+
type = lib.types.submodule {
+
freeformType = format.type;
+
options = {
+
enabled = mkOption {
+
type = lib.types.bool;
+
description = ''
+
Enable bluemap's built-in webserver.
+
Disabled by default in nixos for use of nginx directly.
+
'';
+
default = false;
+
};
+
};
+
};
+
default = { };
+
description = ''
+
Settings for the webserver.conf file, usually not required.
+
[See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webserver.conf).
+
'';
+
};
+
+
maps = mkOption {
+
type = lib.types.attrsOf (lib.types.submodule {
+
freeformType = format.type;
+
options = {
+
world = lib.mkOption {
+
type = lib.types.path;
+
description = "Path to world folder containing the dimension to render";
+
};
+
};
+
});
+
default = {
+
"overworld" = {
+
world = "${cfg.defaultWorld}";
+
ambient-light = 0.1;
+
cave-detection-ocean-floor = -5;
+
};
+
+
"nether" = {
+
world = "${cfg.defaultWorld}/DIM-1";
+
sorting = 100;
+
sky-color = "#290000";
+
void-color = "#150000";
+
ambient-light = 0.6;
+
world-sky-light = 0;
+
remove-caves-below-y = -10000;
+
cave-detection-ocean-floor = -5;
+
cave-detection-uses-block-light = true;
+
max-y = 90;
+
};
+
+
"end" = {
+
world = "${cfg.defaultWorld}/DIM1";
+
sorting = 200;
+
sky-color = "#080010";
+
void-color = "#080010";
+
ambient-light = 0.6;
+
world-sky-light = 0;
+
remove-caves-below-y = -10000;
+
cave-detection-ocean-floor = -5;
+
};
+
};
+
defaultText = lib.literalExpression ''
+
{
+
"overworld" = {
+
world = "''${cfg.defaultWorld}";
+
ambient-light = 0.1;
+
cave-detection-ocean-floor = -5;
+
};
+
+
"nether" = {
+
world = "''${cfg.defaultWorld}/DIM-1";
+
sorting = 100;
+
sky-color = "#290000";
+
void-color = "#150000";
+
ambient-light = 0.6;
+
world-sky-light = 0;
+
remove-caves-below-y = -10000;
+
cave-detection-ocean-floor = -5;
+
cave-detection-uses-block-light = true;
+
max-y = 90;
+
};
+
+
"end" = {
+
world = "''${cfg.defaultWorld}/DIM1";
+
sorting = 200;
+
sky-color = "#080010";
+
void-color = "#080010";
+
ambient-light = 0.6;
+
world-sky-light = 0;
+
remove-caves-below-y = -10000;
+
cave-detection-ocean-floor = -5;
+
};
+
};
+
'';
+
description = ''
+
Settings for files in `maps/`.
+
If you define anything here you must define everything yourself.
+
See the default for an example with good options for the different world types.
+
For valid values [consult upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/maps/map.conf).
+
'';
+
};
+
+
storage = mkOption {
+
type = lib.types.attrsOf (lib.types.submodule {
+
freeformType = format.type;
+
options = {
+
storage-type = mkOption {
+
type = lib.types.enum [ "FILE" "SQL" ];
+
description = "Type of storage config";
+
default = "FILE";
+
};
+
};
+
});
+
description = ''
+
Where the rendered map will be stored.
+
Unless you are doing something advanced you should probably leave this alone and configure webRoot instead.
+
[See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/tree/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/storages)
+
'';
+
default = {
+
"file" = {
+
root = "${cfg.webRoot}/maps";
+
};
+
};
+
defaultText = lib.literalExpression ''
+
{
+
"file" = {
+
root = "''${config.services.bluemap.webRoot}/maps";
+
};
+
}
+
'';
+
};
+
+
resourcepacks = mkOption {
+
type = lib.types.attrsOf lib.types.pathInStore;
+
default = { };
+
description = "A set of resourcepacks to use, loaded in alphabetical order";
+
};
+
};
+
+
+
config = lib.mkIf cfg.enable {
+
assertions =
+
[ { assertion = config.services.bluemap.eula;
+
message = ''
+
You have enabled bluemap but have not accepted minecraft's EULA.
+
You can achieve this through setting `services.bluemap.eula = true`
+
'';
+
}
+
];
+
+
services.bluemap.coreSettings.accept-download = cfg.eula;
+
+
systemd.services."render-bluemap-maps" = lib.mkIf cfg.enableRender {
+
serviceConfig = {
+
Type = "oneshot";
+
Group = "nginx";
+
UMask = "026";
+
};
+
script = ''
+
${lib.getExe pkgs.bluemap} -c ${configFolder} -gs -r
+
'';
+
};
+
+
systemd.timers."render-bluemap-maps" = lib.mkIf cfg.enableRender {
+
wantedBy = [ "timers.target" ];
+
timerConfig = {
+
OnCalendar = cfg.onCalendar;
+
Persistent = true;
+
Unit = "render-bluemap-maps.service";
+
};
+
};
+
+
services.nginx.virtualHosts = lib.mkIf cfg.enableNginx {
+
"${cfg.host}" = {
+
root = config.services.bluemap.webRoot;
+
locations = {
+
"~* ^/maps/[^/]*/tiles/[^/]*.json$".extraConfig = ''
+
error_page 404 =200 /assets/emptyTile.json;
+
gzip_static always;
+
'';
+
"~* ^/maps/[^/]*/tiles/[^/]*.png$".tryFiles = "$uri =204";
+
};
+
};
+
};
+
};
+
+
meta = {
+
maintainers = with lib.maintainers; [ dandellion h7x4 ];
+
};
+
}