diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 14951d8ec4c2..1851eaf0e8cf 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -222,6 +222,8 @@ - [GoDNS](https://github.com/TimothyYe/godns), a dynamic DNS client written in Go, which supports multiple DNS providers. Available as [services.godns](option.html#opt-services.godns.enable). +- [CookCLI](https://cooklang.org/cli/) Server, a web UI for cooklang recipes. + ## Backward Incompatibilities {#sec-release-25.05-incompatibilities} diff --git a/nixos/modules/services/web-apps/cook-cli.nix b/nixos/modules/services/web-apps/cook-cli.nix new file mode 100644 index 000000000000..e1addb21318e --- /dev/null +++ b/nixos/modules/services/web-apps/cook-cli.nix @@ -0,0 +1,113 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + cfg = config.services.cook-cli; + inherit (lib) + mkIf + mkEnableOption + mkPackageOption + mkOption + getExe + types + ; +in +{ + options = { + services.cook-cli = { + enable = lib.mkEnableOption "cook-cli"; + + package = lib.mkPackageOption pkgs "cook-cli" { }; + + autoStart = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to start cook-cli server automatically. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 9080; + description = '' + Which port cook-cli server will use. + ''; + }; + + basePath = lib.mkOption { + type = lib.types.str; + default = "/var/lib/cook-cli"; + description = '' + Path to the directory cook-cli will look for recipes. + ''; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to open the cook-cli server port in the firewall. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + systemd.tmpfiles.rules = [ + "d ${cfg.basePath} 0770 cook-cli users" + ]; + + users.users.cook-cli = { + home = "${cfg.basePath}"; + group = "cook-cli"; + isSystemUser = true; + }; + users.groups.cook-cli.members = [ + "cook-cli" + ]; + + systemd.services.cook-cli = { + description = "cook-cli server"; + serviceConfig = { + ExecStart = "${getExe cfg.package} server --host --port ${toString cfg.port} ${cfg.basePath}"; + WorkingDirectory = cfg.basePath; + User = "cook-cli"; + Group = "cook-cli"; + # Hardening options + CapabilityBoundingSet = [ "CAP_SYS_NICE" ]; + AmbientCapabilities = [ "CAP_SYS_NICE" ]; + LockPersonality = true; + NoNewPrivileges = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + ReadWritePaths = cfg.basePath; + RestrictNamespaces = true; + RestrictSUIDSGID = true; + Restart = "on-failure"; + RestartSec = 5; + }; + wantedBy = mkIf cfg.autoStart [ "multi-user.target" ]; + wants = [ "network.target" ]; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + }; + + meta.maintainers = [ + lib.maintainers.luNeder + lib.maintainers.emilioziniades + ]; +}