1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.logstash; 7 pluginPath = lib.concatStringsSep ":" cfg.plugins; 8 havePluginPath = lib.length cfg.plugins > 0; 9 ops = lib.optionalString; 10 verbosityFlag = { 11 debug = "--debug"; 12 info = "--verbose"; 13 warn = ""; # intentionally empty 14 error = "--quiet"; 15 fatal = "--silent"; 16 }."${cfg.logLevel}"; 17 18in 19 20{ 21 ###### interface 22 23 options = { 24 25 services.logstash = { 26 27 enable = mkOption { 28 type = types.bool; 29 default = false; 30 description = "Enable logstash."; 31 }; 32 33 package = mkOption { 34 type = types.package; 35 default = pkgs.logstash; 36 defaultText = "pkgs.logstash"; 37 example = literalExample "pkgs.logstash"; 38 description = "Logstash package to use."; 39 }; 40 41 plugins = mkOption { 42 type = types.listOf types.path; 43 default = [ ]; 44 example = literalExample "[ pkgs.logstash-contrib ]"; 45 description = "The paths to find other logstash plugins in."; 46 }; 47 48 logLevel = mkOption { 49 type = types.enum [ "debug" "info" "warn" "error" "fatal" ]; 50 default = "warn"; 51 description = "Logging verbosity level."; 52 }; 53 54 watchdogTimeout = mkOption { 55 type = types.int; 56 default = 10; 57 description = "Set watchdog timeout value in seconds."; 58 }; 59 60 filterWorkers = mkOption { 61 type = types.int; 62 default = 1; 63 description = "The quantity of filter workers to run."; 64 }; 65 66 enableWeb = mkOption { 67 type = types.bool; 68 default = false; 69 description = "Enable the logstash web interface."; 70 }; 71 72 address = mkOption { 73 type = types.str; 74 default = "0.0.0.0"; 75 description = "Address on which to start webserver."; 76 }; 77 78 port = mkOption { 79 type = types.str; 80 default = "9292"; 81 description = "Port on which to start webserver."; 82 }; 83 84 inputConfig = mkOption { 85 type = types.lines; 86 default = ''stdin { type => "example" }''; 87 description = "Logstash input configuration."; 88 example = literalExample '' 89 # Read from journal 90 pipe { 91 command => "''${pkgs.systemd}/bin/journalctl -f -o json" 92 type => "syslog" codec => json {} 93 } 94 ''; 95 }; 96 97 filterConfig = mkOption { 98 type = types.lines; 99 default = ''noop {}''; 100 description = "logstash filter configuration."; 101 example = literalExample '' 102 if [type] == "syslog" { 103 # Keep only relevant systemd fields 104 # http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html 105 prune { 106 whitelist_names => [ 107 "type", "@timestamp", "@version", 108 "MESSAGE", "PRIORITY", "SYSLOG_FACILITY", 109 ] 110 } 111 } 112 ''; 113 }; 114 115 outputConfig = mkOption { 116 type = types.lines; 117 default = literalExample ''stdout { debug => true debug_format => "json"}''; 118 description = "Logstash output configuration."; 119 example = '' 120 redis { host => "localhost" data_type => "list" key => "logstash" codec => json } 121 elasticsearch { embedded => true } 122 ''; 123 }; 124 125 }; 126 }; 127 128 129 ###### implementation 130 131 config = mkIf cfg.enable { 132 systemd.services.logstash = with pkgs; { 133 description = "Logstash Daemon"; 134 wantedBy = [ "multi-user.target" ]; 135 environment = { JAVA_HOME = jre; }; 136 path = [ pkgs.bash ]; 137 serviceConfig = { 138 ExecStart = 139 "${cfg.package}/bin/logstash agent " + 140 "-w ${toString cfg.filterWorkers} " + 141 ops havePluginPath "--pluginpath ${pluginPath} " + 142 "${verbosityFlag} " + 143 "--watchdog-timeout ${toString cfg.watchdogTimeout} " + 144 "-f ${writeText "logstash.conf" '' 145 input { 146 ${cfg.inputConfig} 147 } 148 149 filter { 150 ${cfg.filterConfig} 151 } 152 153 output { 154 ${cfg.outputConfig} 155 } 156 ''} " + 157 ops cfg.enableWeb "-- web -a ${cfg.address} -p ${cfg.port}"; 158 }; 159 }; 160 }; 161}