1{
2 config,
3 lib,
4 options,
5 pkgs,
6 ...
7}:
8
9with lib;
10
11let
12
13 cfg = config.services.ntopng;
14 opt = options.services.ntopng;
15
16 createRedis = cfg.redis.createInstance != null;
17 redisService =
18 if cfg.redis.createInstance == "" then
19 "redis.service"
20 else
21 "redis-${cfg.redis.createInstance}.service";
22
23 configFile =
24 if cfg.configText != "" then
25 pkgs.writeText "ntopng.conf" ''
26 ${cfg.configText}
27 ''
28 else
29 pkgs.writeText "ntopng.conf" ''
30 ${concatStringsSep "\n" (map (e: "--interface=${e}") cfg.interfaces)}
31 --http-port=${toString cfg.httpPort}
32 --redis=${cfg.redis.address}
33 --data-dir=/var/lib/ntopng
34 --user=ntopng
35 ${cfg.extraConfig}
36 '';
37
38in
39
40{
41
42 imports = [
43 (mkRenamedOptionModule [ "services" "ntopng" "http-port" ] [ "services" "ntopng" "httpPort" ])
44 ];
45
46 options = {
47
48 services.ntopng = {
49
50 enable = mkOption {
51 default = false;
52 type = types.bool;
53 description = ''
54 Enable ntopng, a high-speed web-based traffic analysis and flow
55 collection tool.
56
57 With the default configuration, ntopng monitors all network
58 interfaces and displays its findings at http://localhost:''${toString
59 config.${opt.http-port}}. Default username and password is admin/admin.
60
61 See the {manpage}`ntopng(8)` manual page and http://www.ntop.org/products/ntop/
62 for more info.
63
64 Note that enabling ntopng will also enable redis (key-value
65 database server) for persistent data storage.
66 '';
67 };
68
69 interfaces = mkOption {
70 default = [ "any" ];
71 example = [
72 "eth0"
73 "wlan0"
74 ];
75 type = types.listOf types.str;
76 description = ''
77 List of interfaces to monitor. Use "any" to monitor all interfaces.
78 '';
79 };
80
81 httpPort = mkOption {
82 default = 3000;
83 type = types.int;
84 description = ''
85 Sets the HTTP port of the embedded web server.
86 '';
87 };
88
89 redis.address = mkOption {
90 type = types.str;
91 example = literalExpression "config.services.redis.ntopng.unixSocket";
92 description = ''
93 Redis address - may be a Unix socket or a network host and port.
94 '';
95 };
96
97 redis.createInstance = mkOption {
98 type = types.nullOr types.str;
99 default = optionalString (versionAtLeast config.system.stateVersion "22.05") "ntopng";
100 description = ''
101 Local Redis instance name. Set to `null` to disable
102 local Redis instance. Defaults to `""` for
103 `system.stateVersion` older than 22.05.
104 '';
105 };
106
107 configText = mkOption {
108 default = "";
109 example = ''
110 --interface=any
111 --http-port=3000
112 --disable-login
113 '';
114 type = types.lines;
115 description = ''
116 Overridable configuration file contents to use for ntopng. By
117 default, use the contents automatically generated by NixOS.
118 '';
119 };
120
121 extraConfig = mkOption {
122 default = "";
123 type = types.lines;
124 description = ''
125 Configuration lines that will be appended to the generated ntopng
126 configuration file. Note that this mechanism does not work when the
127 manual {option}`configText` option is used.
128 '';
129 };
130
131 };
132
133 };
134
135 config = mkIf cfg.enable {
136
137 # ntopng uses redis for data storage
138 services.ntopng.redis.address =
139 mkIf createRedis
140 config.services.redis.servers.${cfg.redis.createInstance}.unixSocket;
141
142 services.redis.servers = mkIf createRedis {
143 ${cfg.redis.createInstance} = {
144 enable = true;
145 user = mkIf (cfg.redis.createInstance == "ntopng") "ntopng";
146 };
147 };
148
149 # nice to have manual page and ntopng command in PATH
150 environment.systemPackages = [ pkgs.ntopng ];
151
152 systemd.tmpfiles.rules = [ "d /var/lib/ntopng 0700 ntopng ntopng -" ];
153
154 systemd.services.ntopng = {
155 description = "Ntopng Network Monitor";
156 requires = optional createRedis redisService;
157 after = [ "network.target" ] ++ optional createRedis redisService;
158 wantedBy = [ "multi-user.target" ];
159 serviceConfig.ExecStart = "${pkgs.ntopng}/bin/ntopng ${configFile}";
160 unitConfig.Documentation = "man:ntopng(8)";
161 };
162
163 users.extraUsers.ntopng = {
164 group = "ntopng";
165 isSystemUser = true;
166 };
167
168 users.extraGroups.ntopng = { };
169 };
170
171}