about summary refs log tree commit diff
path: root/nixos/modules/services/web-servers
diff options
context:
space:
mode:
authorDaniel Olsen <daniel.olsen99@gmail.com>2024-04-09 22:43:30 +0200
committerDaniel Olsen <daniel.olsen99@gmail.com>2024-05-21 19:16:21 +0200
commit718819092b39edbf8eb87d3874a038780a301e3e (patch)
tree59be4aae5f76aaab7e9d4a613ac1836c0b69d184 /nixos/modules/services/web-servers
parentd16a5f357ab837ceb940d8c6f71497df5f1a39e0 (diff)
nixos/bluemap: init module
Diffstat (limited to 'nixos/modules/services/web-servers')
-rw-r--r--nixos/modules/services/web-servers/bluemap.nix311
1 files changed, 311 insertions, 0 deletions
diff --git a/nixos/modules/services/web-servers/bluemap.nix b/nixos/modules/services/web-servers/bluemap.nix
new file mode 100644
index 0000000000000..28eaad3db313e
--- /dev/null
+++ b/nixos/modules/services/web-servers/bluemap.nix
@@ -0,0 +1,311 @@
+{ 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 ];
+  };
+}