1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7
8let
9 cfg = config.services.cook-cli;
10 inherit (lib)
11 mkIf
12 mkEnableOption
13 mkPackageOption
14 mkOption
15 getExe
16 types
17 ;
18in
19{
20 options = {
21 services.cook-cli = {
22 enable = lib.mkEnableOption "cook-cli";
23
24 package = lib.mkPackageOption pkgs "cook-cli" { };
25
26 autoStart = lib.mkOption {
27 type = lib.types.bool;
28 default = true;
29 description = ''
30 Whether to start cook-cli server automatically.
31 '';
32 };
33
34 port = lib.mkOption {
35 type = lib.types.port;
36 default = 9080;
37 description = ''
38 Which port cook-cli server will use.
39 '';
40 };
41
42 basePath = lib.mkOption {
43 type = lib.types.str;
44 default = "/var/lib/cook-cli";
45 description = ''
46 Path to the directory cook-cli will look for recipes.
47 '';
48 };
49
50 openFirewall = lib.mkOption {
51 type = lib.types.bool;
52 default = false;
53 description = ''
54 Whether to open the cook-cli server port in the firewall.
55 '';
56 };
57 };
58 };
59
60 config = lib.mkIf cfg.enable {
61 environment.systemPackages = [ cfg.package ];
62
63 systemd.tmpfiles.rules = [
64 "d ${cfg.basePath} 0770 cook-cli users"
65 ];
66
67 users.users.cook-cli = {
68 home = "${cfg.basePath}";
69 group = "cook-cli";
70 isSystemUser = true;
71 };
72 users.groups.cook-cli.members = [
73 "cook-cli"
74 ];
75
76 systemd.services.cook-cli = {
77 description = "cook-cli server";
78 serviceConfig = {
79 ExecStart = "${getExe cfg.package} server --host --port ${toString cfg.port} ${cfg.basePath}";
80 WorkingDirectory = cfg.basePath;
81 User = "cook-cli";
82 Group = "cook-cli";
83 # Hardening options
84 CapabilityBoundingSet = [ "CAP_SYS_NICE" ];
85 AmbientCapabilities = [ "CAP_SYS_NICE" ];
86 LockPersonality = true;
87 NoNewPrivileges = true;
88 PrivateTmp = true;
89 ProtectControlGroups = true;
90 ProtectKernelLogs = true;
91 ProtectKernelModules = true;
92 ProtectKernelTunables = true;
93 ProtectSystem = "strict";
94 ReadWritePaths = cfg.basePath;
95 RestrictNamespaces = true;
96 RestrictSUIDSGID = true;
97 Restart = "on-failure";
98 RestartSec = 5;
99 };
100 wantedBy = mkIf cfg.autoStart [ "multi-user.target" ];
101 wants = [ "network.target" ];
102 };
103
104 networking.firewall = lib.mkIf cfg.openFirewall {
105 allowedTCPPorts = [ cfg.port ];
106 };
107 };
108
109 meta.maintainers = [
110 lib.maintainers.luNeder
111 lib.maintainers.emilioziniades
112 ];
113}