{ config, pkgs, lib, ... }: with builtins // lib; let cfg = config.services.cook-cli; args = escapeShellArgs ([ "--port" (toString cfg.port) ] ++ cfg.extraArgs ++ [ cfg.recipeRoot ]); in { options.services.cook-cli = { enable = mkEnableOption "cook-cli webserver"; package = mkPackageOption pkgs "cook-cli" {}; recipeRoot = mkOption { type = types.path; default = "/var/lib/cookbook"; }; user = mkOption { type = types.str; default = "cook-cli"; }; group = mkOption { type = types.str; default = "cook-cli"; }; port = mkOption { type = types.port; default = 9080; }; extraArgs = mkOption { type = with types; listOf str; default = []; }; nginx = { enable = mkEnableOption "nginx reverse proxy"; virtualHost = mkOption { type = types.str; example = mdDoc '' cook.example.com ''; }; location = mkOption { type = types.str; default = "/"; }; }; }; config = mkIf cfg.enable { users = { users = mkIf (cfg.user == "cook-cli") { ${cfg.user} = { isSystemUser = true; group = cfg.group; }; }; groups = mkIf (cfg.group == "cook-cli") { ${cfg.group} = {}; }; }; systemd.services.cooklang-chef = { description = "A website for serving cooklang cookbooks"; after = [ "network.target" ]; requires = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${getExe cfg.package} server ${args}"; User = cfg.user; Group = cfg.group; IPAddressAllow = "localhost"; IPAddressDeny = "any"; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; PrivateDevices = true; PrivateTmp = true; PrivateUsers = true; ProcSubset = "pid"; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectProc = "invisible"; ProtectSystem = "strict"; ReadWritePaths = cfg.recipeRoot; RemoveIPC = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; UMask = "0027"; WorkingDirectory = cfg.recipeRoot; }; }; services.nginx = mkIf cfg.nginx.enable { enable = mkDefault true; virtualHosts.${cfg.nginx.virtualHost} = { locations.${cfg.nginx.location} = { proxyPass = "http://127.0.0.1:${toString cfg.port}"; }; }; }; }; }