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