base16-schemes: unstable-2024-06-21 -> unstable-2024-11-12
[NixPkgs.git] / nixos / modules / services / misc / octoprint.nix
blobd8e4c9c302b38e8cd7841d39119afb58cf58cba7
1 { config, lib, pkgs, ... }:
2 let
4   cfg = config.services.octoprint;
6   baseConfig = {
7     plugins.curalegacy.cura_engine = "${pkgs.curaengine_stable}/bin/CuraEngine";
8     server.port = cfg.port;
9     webcam.ffmpeg = "${pkgs.ffmpeg.bin}/bin/ffmpeg";
10   } // lib.optionalAttrs (cfg.host != null) {server.host = cfg.host;};
12   fullConfig = lib.recursiveUpdate cfg.extraConfig baseConfig;
14   cfgUpdate = pkgs.writeText "octoprint-config.yaml" (builtins.toJSON fullConfig);
16   pluginsEnv = package.python.withPackages (ps: [ ps.octoprint ] ++ (cfg.plugins ps));
18   package = pkgs.octoprint;
22   ##### interface
24   options = {
26     services.octoprint = {
28       enable = lib.mkEnableOption "OctoPrint, web interface for 3D printers";
30       host = lib.mkOption {
31         type = lib.types.nullOr lib.types.str;
32         default = null;
33         description = ''
34           Host to bind OctoPrint to.
35         '';
36       };
38       port = lib.mkOption {
39         type = lib.types.port;
40         default = 5000;
41         description = ''
42           Port to bind OctoPrint to.
43         '';
44       };
46       openFirewall = lib.mkOption {
47         type = lib.types.bool;
48         default = false;
49         description = "Open ports in the firewall for OctoPrint.";
50       };
52       user = lib.mkOption {
53         type = lib.types.str;
54         default = "octoprint";
55         description = "User for the daemon.";
56       };
58       group = lib.mkOption {
59         type = lib.types.str;
60         default = "octoprint";
61         description = "Group for the daemon.";
62       };
64       stateDir = lib.mkOption {
65         type = lib.types.path;
66         default = "/var/lib/octoprint";
67         description = "State directory of the daemon.";
68       };
70       plugins = lib.mkOption {
71         type = lib.types.functionTo (lib.types.listOf lib.types.package);
72         default = plugins: [ ];
73         defaultText = lib.literalExpression "plugins: []";
74         example = lib.literalExpression "plugins: with plugins; [ themeify stlviewer ]";
75         description = "Additional plugins to be used. Available plugins are passed through the plugins input.";
76       };
78       extraConfig = lib.mkOption {
79         type = lib.types.attrs;
80         default = { };
81         description = "Extra options which are added to OctoPrint's YAML configuration file.";
82       };
84     };
86   };
88   ##### implementation
90   config = lib.mkIf cfg.enable {
92     users.users = lib.optionalAttrs (cfg.user == "octoprint") {
93       octoprint = {
94         group = cfg.group;
95         uid = config.ids.uids.octoprint;
96       };
97     };
99     users.groups = lib.optionalAttrs (cfg.group == "octoprint") {
100       octoprint.gid = config.ids.gids.octoprint;
101     };
103     systemd.tmpfiles.rules = [
104       "d '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -"
105       # this will allow octoprint access to raspberry specific hardware to check for throttling
106       # read-only will not work: "VCHI initialization failed" error
107       "a /dev/vchiq - - - - u:octoprint:rw"
108     ];
110     systemd.services.octoprint = {
111       description = "OctoPrint, web interface for 3D printers";
112       wantedBy = [ "multi-user.target" ];
113       after = [ "network.target" ];
114       path = [ pluginsEnv ];
116       preStart = ''
117         if [ -e "${cfg.stateDir}/config.yaml" ]; then
118           ${pkgs.yaml-merge}/bin/yaml-merge "${cfg.stateDir}/config.yaml" "${cfgUpdate}" > "${cfg.stateDir}/config.yaml.tmp"
119           mv "${cfg.stateDir}/config.yaml.tmp" "${cfg.stateDir}/config.yaml"
120         else
121           cp "${cfgUpdate}" "${cfg.stateDir}/config.yaml"
122           chmod 600 "${cfg.stateDir}/config.yaml"
123         fi
124       '';
126       serviceConfig = {
127         ExecStart = "${pluginsEnv}/bin/octoprint serve -b ${cfg.stateDir}";
128         User = cfg.user;
129         Group = cfg.group;
130         SupplementaryGroups = [
131           "dialout"
132         ];
133       };
134     };
136     networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
137   };