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