{ config, lib, pkgs, ... }: let inherit (lib) literalExpression mkEnableOption mkIf mkOption mkPackageOption mkRemovedOptionModule types ; cfg = config.services.plantuml-server; in { imports = [ (mkRemovedOptionModule [ "services" "plantuml-server" "allowPlantumlInclude" ] "This option has been removed from PlantUML.") ]; options = { services.plantuml-server = { enable = mkEnableOption "PlantUML server"; package = mkPackageOption pkgs "plantuml-server" { }; packages = { jdk = mkPackageOption pkgs "jdk" { }; jetty = mkPackageOption pkgs "jetty" { default = [ "jetty_11" ]; extraDescription = '' At the time of writing (v1.2023.12), PlantUML Server does not support Jetty versions higher than 12.x. Jetty 12.x has introduced major breaking changes, see and ''; }; }; user = mkOption { type = types.str; default = "plantuml"; description = "User which runs PlantUML server."; }; group = mkOption { type = types.str; default = "plantuml"; description = "Group which runs PlantUML server."; }; home = mkOption { type = types.path; default = "/var/lib/plantuml"; description = "Home directory of the PlantUML server instance."; }; listenHost = mkOption { type = types.str; default = "127.0.0.1"; description = "Host to listen on."; }; listenPort = mkOption { type = types.int; default = 8080; description = "Port to listen on."; }; plantumlLimitSize = mkOption { type = types.int; default = 4096; description = "Limits image width and height."; }; graphvizPackage = mkPackageOption pkgs "graphviz" { }; plantumlStats = mkOption { type = types.bool; default = false; description = "Set it to on to enable statistics report (https://plantuml.com/statistics-report)."; }; httpAuthorization = mkOption { type = types.nullOr types.str; default = null; description = "When calling the proxy endpoint, the value of HTTP_AUTHORIZATION will be used to set the HTTP Authorization header."; }; }; }; config = mkIf cfg.enable { systemd.services.plantuml-server = { description = "PlantUML server"; wantedBy = [ "multi-user.target" ]; path = [ cfg.home ]; environment = { PLANTUML_LIMIT_SIZE = builtins.toString cfg.plantumlLimitSize; GRAPHVIZ_DOT = "${cfg.graphvizPackage}/bin/dot"; PLANTUML_STATS = if cfg.plantumlStats then "on" else "off"; HTTP_AUTHORIZATION = cfg.httpAuthorization; }; script = '' ${cfg.packages.jdk}/bin/java \ -jar ${cfg.packages.jetty}/start.jar \ --module=deploy,http,jsp \ jetty.home=${cfg.packages.jetty} \ jetty.base=${cfg.package} \ jetty.http.host=${cfg.listenHost} \ jetty.http.port=${builtins.toString cfg.listenPort} ''; serviceConfig = { User = cfg.user; Group = cfg.group; StateDirectory = mkIf (cfg.home == "/var/lib/plantuml") "plantuml"; StateDirectoryMode = mkIf (cfg.home == "/var/lib/plantuml") "0750"; # Hardening AmbientCapabilities = [ "" ]; CapabilityBoundingSet = [ "" ]; DynamicUser = true; LockPersonality = true; NoNewPrivileges = true; PrivateDevices = true; PrivateNetwork = false; PrivateTmp = true; PrivateUsers = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" ]; }; }; }; meta.maintainers = with lib.maintainers; [ truh anthonyroussel ]; }