-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule.nix
More file actions
130 lines (109 loc) · 3.31 KB
/
module.nix
File metadata and controls
130 lines (109 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{ config, lib, pkgs, ... }:
let
cfg = config.services.blaze;
# Import the package from the flake
blazePackage = cfg.package;
in
{
options.services.blaze = {
enable = lib.mkEnableOption "Blaze task board service";
package = lib.mkOption {
type = lib.types.package;
description = "The blaze package to use.";
};
port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = "Port to listen on.";
};
host = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "Host/IP to bind to. Use 0.0.0.0 for all interfaces.";
};
dataDir = lib.mkOption {
type = lib.types.path;
default = "/var/lib/blaze";
description = "Directory for persistent data.";
};
passwordFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to a file containing the API token/password.
If null, a random token is generated on first start and stored in dataDir.
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open the firewall port.";
};
user = lib.mkOption {
type = lib.types.str;
default = "blaze";
description = "User account under which blaze runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "blaze";
description = "Group under which blaze runs.";
};
};
config = lib.mkIf cfg.enable {
# Create user and group
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
home = cfg.dataDir;
description = "Blaze task board service user";
};
users.groups.${cfg.group} = { };
# Systemd service
systemd.services.blaze = {
description = "Blaze Service";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = {
BLAZE_DATA_DIR = cfg.dataDir;
} // lib.optionalAttrs (cfg.passwordFile != null) {
BLAZE_TOKEN_FILE = cfg.passwordFile;
};
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = cfg.dataDir;
ExecStart = ''
${blazePackage}/bin/blaze-server \
--host ${cfg.host} \
--port ${toString cfg.port}
'';
Restart = "on-failure";
RestartSec = "5s";
# Create state directory with correct permissions
StateDirectory = "blaze";
StateDirectoryMode = "0750";
# Hardening
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
# Allow binding to ports
AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
};
};
# Firewall
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
};
}