{ config, lib, pkgs, ... }: with lib; let cfg = config.services.objectifier; pythonYolo = pkgs.python3.withPackages (pyPkgs: with pyPkgs; [ fastapi gunicorn opencv4 python-multipart uvicorn ]); in { options.services.objectifier = with types; { enable = mkEnableOption "Enable Objectifier object-detection web sevice."; port = mkOption { type = port; description = "Port on which to run the Objectifier web service."; default = 5121; }; workers = mkOption { type = int; description = "Number of worker threads to launch."; default = 3; }; listen-addresses = mkOption { type = listOf str; description = "List of IP addresses on which to listen for incoming requests."; default = [ "127.0.0.1" ]; }; cleanup = { max_file_age = mkOption { type = int; description = "Maximum age of a file (in seconds), after which it will be removed."; default = (60 * 60 * 8); # 8 hours }; delay = mkOption { type = int; description = "Time between cleanup sweeps."; default = (60 * 10); # 10 minutes }; }; }; config = mkIf cfg.enable { systemd.services.objectifier = { after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; reloadIfChanged = true; environment = { OBJECTIFIER_YOLOV3_CONFIG = "${pkgs.yolov3-data}/yolov3.cfg"; OBJECTIFIER_YOLOV3_WEIGHTS = "${pkgs.yolov3-data}/yolov3.weights"; OBJECTIFIER_YOLOV3_LABELS = "${pkgs.yolov3-data}/labels"; OBJECTIFIER_BUFFER_SIZE = "524288"; OBJECTIFIER_CLEANUP_MAX_AGE = toString cfg.cleanup.max_file_age; OBJECTIFIER_CLEANUP_DELAY = toString cfg.cleanup.delay; }; serviceConfig = { # PrivateUsers = true; # PrivateDevices = true; # PrivateTmp = true; # PrivateMounts = true; # ProtectControlGroups = true; # ProtectKernelTunables = true; # ProtectKernelModules = true; # ProtectSystem = true; # ProtectHostname = true; # ProtectHome = true; # ProtectClock = true; # ProtectKernelLogs = true; # DynamicUser = true; # MemoryDenyWriteExecute = true; # RestrictRealtime = true; # LockPersonality = true; # PermissionsStartOnly = true; WorkingDirectory = "${pkgs.objectifier}"; StateDirectory = "objectifier"; CacheDirectory = "objectifier"; LimitNOFILE = 4096; Restart = "on-failure"; RestartSec = "5s"; Type = "simple"; PIDFile = "/run/objectifier.pid"; ExecStart = let bindClause = concatStringsSep " " (map (addr: "--bind ${addr}:${toString cfg.port}") cfg.listen-addresses); in (concatStringsSep " " [ "${pkgs.objectifier}/bin/objectifier" bindClause "--workers ${toString cfg.workers}" "--pid /run/objectifier.pid" ]); }; }; }; }