1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.graylog;
7
8 confFile = pkgs.writeText "graylog.conf" ''
9 is_master = ${boolToString cfg.isMaster}
10 node_id_file = ${cfg.nodeIdFile}
11 password_secret = ${cfg.passwordSecret}
12 root_username = ${cfg.rootUsername}
13 root_password_sha2 = ${cfg.rootPasswordSha2}
14 elasticsearch_hosts = ${concatStringsSep "," cfg.elasticsearchHosts}
15 message_journal_dir = ${cfg.messageJournalDir}
16 mongodb_uri = ${cfg.mongodbUri}
17 plugin_dir = /var/lib/graylog/plugins
18
19 ${cfg.extraConfig}
20 '';
21
22 glPlugins = pkgs.buildEnv {
23 name = "graylog-plugins";
24 paths = cfg.plugins;
25 };
26
27in
28
29{
30 ###### interface
31
32 options = {
33
34 services.graylog = {
35
36 enable = mkEnableOption (lib.mdDoc "Graylog");
37
38 package = mkOption {
39 type = types.package;
40 default = if versionOlder config.system.stateVersion "23.05" then pkgs.graylog-3_3 else pkgs.graylog-5_0;
41 defaultText = literalExpression (if versionOlder config.system.stateVersion "23.05" then "pkgs.graylog-3_3" else "pkgs.graylog-5_0");
42 description = lib.mdDoc "Graylog package to use.";
43 };
44
45 user = mkOption {
46 type = types.str;
47 default = "graylog";
48 description = lib.mdDoc "User account under which graylog runs";
49 };
50
51 isMaster = mkOption {
52 type = types.bool;
53 default = true;
54 description = lib.mdDoc "Whether this is the master instance of your Graylog cluster";
55 };
56
57 nodeIdFile = mkOption {
58 type = types.str;
59 default = "/var/lib/graylog/server/node-id";
60 description = lib.mdDoc "Path of the file containing the graylog node-id";
61 };
62
63 passwordSecret = mkOption {
64 type = types.str;
65 description = lib.mdDoc ''
66 You MUST set a secret to secure/pepper the stored user passwords here. Use at least 64 characters.
67 Generate one by using for example: pwgen -N 1 -s 96
68 '';
69 };
70
71 rootUsername = mkOption {
72 type = types.str;
73 default = "admin";
74 description = lib.mdDoc "Name of the default administrator user";
75 };
76
77 rootPasswordSha2 = mkOption {
78 type = types.str;
79 example = "e3c652f0ba0b4801205814f8b6bc49672c4c74e25b497770bb89b22cdeb4e952";
80 description = lib.mdDoc ''
81 You MUST specify a hash password for the root user (which you only need to initially set up the
82 system and in case you lose connectivity to your authentication backend)
83 This password cannot be changed using the API or via the web interface. If you need to change it,
84 modify it here.
85 Create one by using for example: echo -n yourpassword | shasum -a 256
86 and use the resulting hash value as string for the option
87 '';
88 };
89
90 elasticsearchHosts = mkOption {
91 type = types.listOf types.str;
92 example = literalExpression ''[ "http://node1:9200" "http://user:password@node2:19200" ]'';
93 description = lib.mdDoc "List of valid URIs of the http ports of your elastic nodes. If one or more of your elasticsearch hosts require authentication, include the credentials in each node URI that requires authentication";
94 };
95
96 messageJournalDir = mkOption {
97 type = types.str;
98 default = "/var/lib/graylog/data/journal";
99 description = lib.mdDoc "The directory which will be used to store the message journal. The directory must be exclusively used by Graylog and must not contain any other files than the ones created by Graylog itself";
100 };
101
102 mongodbUri = mkOption {
103 type = types.str;
104 default = "mongodb://localhost/graylog";
105 description = lib.mdDoc "MongoDB connection string. See http://docs.mongodb.org/manual/reference/connection-string/ for details";
106 };
107
108 extraConfig = mkOption {
109 type = types.lines;
110 default = "";
111 description = lib.mdDoc "Any other configuration options you might want to add";
112 };
113
114 plugins = mkOption {
115 description = lib.mdDoc "Extra graylog plugins";
116 default = [ ];
117 type = types.listOf types.package;
118 };
119
120 };
121 };
122
123
124 ###### implementation
125
126 config = mkIf cfg.enable {
127
128 users.users = mkIf (cfg.user == "graylog") {
129 graylog = {
130 isSystemUser = true;
131 group = "graylog";
132 description = "Graylog server daemon user";
133 };
134 };
135 users.groups = mkIf (cfg.user == "graylog") { graylog = {}; };
136
137 systemd.tmpfiles.rules = [
138 "d '${cfg.messageJournalDir}' - ${cfg.user} - - -"
139 ];
140
141 systemd.services.graylog = {
142 description = "Graylog Server";
143 wantedBy = [ "multi-user.target" ];
144 environment = {
145 GRAYLOG_CONF = "${confFile}";
146 };
147 path = [ pkgs.which pkgs.procps ];
148 preStart = ''
149 rm -rf /var/lib/graylog/plugins || true
150 mkdir -p /var/lib/graylog/plugins -m 755
151
152 mkdir -p "$(dirname ${cfg.nodeIdFile})"
153 chown -R ${cfg.user} "$(dirname ${cfg.nodeIdFile})"
154
155 for declarativeplugin in `ls ${glPlugins}/bin/`; do
156 ln -sf ${glPlugins}/bin/$declarativeplugin /var/lib/graylog/plugins/$declarativeplugin
157 done
158 for includedplugin in `ls ${cfg.package}/plugin/`; do
159 ln -s ${cfg.package}/plugin/$includedplugin /var/lib/graylog/plugins/$includedplugin || true
160 done
161 '';
162 serviceConfig = {
163 User="${cfg.user}";
164 StateDirectory = "graylog";
165 ExecStart = "${cfg.package}/bin/graylogctl run";
166 };
167 };
168 };
169}