From 5fbdf2ef1f06658c753cf6d69c640c2dac5d1102 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Tue, 20 Jul 2021 19:21:03 -0700 Subject: [PATCH] nixos/moonraker: init --- .../from_md/release-notes/rl-2111.section.xml | 7 + .../manual/release-notes/rl-2111.section.md | 3 + nixos/modules/misc/ids.nix | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/misc/moonraker.nix | 135 ++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 nixos/modules/services/misc/moonraker.nix diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index e3b94d00552..28ffda321d8 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -149,6 +149,13 @@ services.meshcentral.enable + + + moonraker, + an API web server for Klipper. Available as + moonraker. + +
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index e34c3f4e0b9..c7e6c3dc201 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -45,6 +45,9 @@ pt-services.clipcat.enable). - [MeshCentral](https://www.meshcommander.com/meshcentral2/overview), a remote administration service ("TeamViewer but self-hosted and with more features") is now available with a package and a module: [services.meshcentral.enable](#opt-services.meshcentral.enable) +- [moonraker](https://github.com/Arksine/moonraker), an API web server for Klipper. + Available as [moonraker](#opt-services.moonraker.enable). + ## Backward Incompatibilities {#sec-release-21.11-incompatibilities} - The `staticjinja` package has been upgraded from 1.0.4 to 3.0.1 diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index a6839e02c4f..c2e588bf00d 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -349,6 +349,7 @@ in zigbee2mqtt = 317; # shadow = 318; # unused hqplayer = 319; + moonraker = 320; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -652,6 +653,7 @@ in zigbee2mqtt = 317; shadow = 318; hqplayer = 319; + moonraker = 320; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 64b0c83bbae..d3217add69d 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -533,6 +533,7 @@ ./services/misc/mbpfan.nix ./services/misc/mediatomb.nix ./services/misc/metabase.nix + ./services/misc/moonraker.nix ./services/misc/mwlib.nix ./services/misc/mx-puppet-discord.nix ./services/misc/n8n.nix diff --git a/nixos/modules/services/misc/moonraker.nix b/nixos/modules/services/misc/moonraker.nix new file mode 100644 index 00000000000..de8668a0c06 --- /dev/null +++ b/nixos/modules/services/misc/moonraker.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: +with lib; +let + pkg = pkgs.moonraker; + cfg = config.services.moonraker; + format = pkgs.formats.ini { + # https://github.com/NixOS/nixpkgs/pull/121613#issuecomment-885241996 + listToValue = l: + if builtins.length l == 1 then generators.mkValueStringDefault {} (head l) + else lib.concatMapStrings (s: "\n ${generators.mkValueStringDefault {} s}") l; + mkKeyValue = generators.mkKeyValueDefault {} ":"; + }; +in { + options = { + services.moonraker = { + enable = mkEnableOption "Moonraker, an API web server for Klipper"; + + klipperSocket = mkOption { + type = types.path; + default = config.services.klipper.apiSocket; + description = "Path to Klipper's API socket."; + }; + + stateDir = mkOption { + type = types.path; + default = "/var/lib/moonraker"; + description = "The directory containing the Moonraker databases."; + }; + + configDir = mkOption { + type = types.path; + default = cfg.stateDir + "/config"; + description = '' + The directory containing client-writable configuration files. + + Clients will be able to edit files in this directory via the API. This directory must be writable. + ''; + }; + + user = mkOption { + type = types.str; + default = "moonraker"; + description = "User account under which Moonraker runs."; + }; + + group = mkOption { + type = types.str; + default = "moonraker"; + description = "Group account under which Moonraker runs."; + }; + + address = mkOption { + type = types.str; + default = "127.0.0.1"; + example = "0.0.0.0"; + description = "The IP or host to listen on."; + }; + + port = mkOption { + type = types.ints.unsigned; + default = 7125; + description = "The port to listen on."; + }; + + settings = mkOption { + type = format.type; + default = { }; + example = { + authorization = { + trusted_clients = [ "10.0.0.0/24" ]; + cors_domains = [ "https://app.fluidd.xyz" ]; + }; + }; + description = '' + Configuration for Moonraker. See the documentation + for supported values. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + warnings = optional (cfg.settings ? update_manager) + ''Enabling update_manager is not supported on NixOS and will lead to non-removable warnings in some clients.''; + + users.users = optionalAttrs (cfg.user == "moonraker") { + moonraker = { + group = cfg.group; + uid = config.ids.uids.moonraker; + }; + }; + + users.groups = optionalAttrs (cfg.group == "moonraker") { + moonraker.gid = config.ids.gids.moonraker; + }; + + environment.etc."moonraker.cfg".source = let + forcedConfig = { + server = { + host = cfg.address; + port = cfg.port; + klippy_uds_address = cfg.klipperSocket; + config_path = cfg.configDir; + database_path = "${cfg.stateDir}/database"; + }; + }; + fullConfig = recursiveUpdate cfg.settings forcedConfig; + in format.generate "moonraker.cfg" fullConfig; + + systemd.tmpfiles.rules = [ + "d '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -" + "d '${cfg.configDir}' - ${cfg.user} ${cfg.group} - -" + ]; + + systemd.services.moonraker = { + description = "Moonraker, an API web server for Klipper"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ] + ++ optional config.services.klipper.enable "klipper.service"; + + # Moonraker really wants its own config to be writable... + script = '' + cp /etc/moonraker.cfg ${cfg.configDir}/moonraker-temp.cfg + chmod u+w ${cfg.configDir}/moonraker-temp.cfg + exec ${pkg}/bin/moonraker -c ${cfg.configDir}/moonraker-temp.cfg + ''; + + serviceConfig = { + WorkingDirectory = cfg.stateDir; + Group = cfg.group; + User = cfg.user; + }; + }; + }; +}