at master 4.6 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 utils, 6 ... 7}: 8let 9 inherit (lib) 10 escapeShellArgs 11 getBin 12 hasPrefix 13 literalExpression 14 mkBefore 15 mkEnableOption 16 mkIf 17 mkOption 18 mkPackageOption 19 optionalString 20 types 21 ; 22 cfg = config.services.victorialogs; 23 startCLIList = [ 24 "${cfg.package}/bin/victoria-logs" 25 "-storageDataPath=/var/lib/${cfg.stateDir}" 26 "-httpListenAddr=${cfg.listenAddress}" 27 ] 28 ++ lib.optionals (cfg.basicAuthUsername != null) [ 29 "-httpAuth.username=${cfg.basicAuthUsername}" 30 ] 31 ++ lib.optionals (cfg.basicAuthPasswordFile != null) [ 32 "-httpAuth.password=file://%d/basic_auth_password" 33 ]; 34in 35{ 36 options.services.victorialogs = { 37 enable = mkEnableOption "VictoriaLogs is an open source user-friendly database for logs from VictoriaMetrics"; 38 package = mkPackageOption pkgs "victorialogs" { }; 39 listenAddress = mkOption { 40 default = ":9428"; 41 type = types.str; 42 description = '' 43 TCP address to listen for incoming http requests. 44 ''; 45 }; 46 stateDir = mkOption { 47 type = types.str; 48 default = "victorialogs"; 49 description = '' 50 Directory below `/var/lib` to store VictoriaLogs data. 51 This directory will be created automatically using systemd's StateDirectory mechanism. 52 ''; 53 }; 54 basicAuthUsername = lib.mkOption { 55 default = null; 56 type = lib.types.nullOr lib.types.str; 57 description = '' 58 Basic Auth username used to protect VictoriaLogs instance by authorization 59 ''; 60 }; 61 62 basicAuthPasswordFile = lib.mkOption { 63 default = null; 64 type = lib.types.nullOr lib.types.str; 65 description = '' 66 File that contains the Basic Auth password used to protect VictoriaLogs instance by authorization 67 ''; 68 }; 69 extraOptions = mkOption { 70 type = types.listOf types.str; 71 default = [ ]; 72 example = literalExpression '' 73 [ 74 "-loggerLevel=WARN" 75 ] 76 ''; 77 description = '' 78 Extra options to pass to VictoriaLogs. See {command}`victoria-logs -help` for 79 possible options. 80 ''; 81 }; 82 }; 83 config = mkIf cfg.enable { 84 85 assertions = [ 86 { 87 assertion = 88 (cfg.basicAuthUsername == null && cfg.basicAuthPasswordFile == null) 89 || (cfg.basicAuthUsername != null && cfg.basicAuthPasswordFile != null); 90 message = "Both basicAuthUsername and basicAuthPasswordFile must be set together to enable basicAuth functionality, or neither should be set."; 91 } 92 ]; 93 94 systemd.services.victorialogs = { 95 description = "VictoriaLogs logs database"; 96 wantedBy = [ "multi-user.target" ]; 97 after = [ "network.target" ]; 98 startLimitBurst = 5; 99 100 serviceConfig = { 101 ExecStart = lib.concatStringsSep " " [ 102 (escapeShellArgs startCLIList) 103 (utils.escapeSystemdExecArgs cfg.extraOptions) 104 ]; 105 DynamicUser = true; 106 LoadCredential = lib.optional ( 107 cfg.basicAuthPasswordFile != null 108 ) "basic_auth_password:${cfg.basicAuthPasswordFile}"; 109 RestartSec = 1; 110 Restart = "on-failure"; 111 RuntimeDirectory = "victorialogs"; 112 RuntimeDirectoryMode = "0700"; 113 StateDirectory = cfg.stateDir; 114 StateDirectoryMode = "0700"; 115 116 # Hardening 117 DeviceAllow = [ "/dev/null rw" ]; 118 DevicePolicy = "strict"; 119 LockPersonality = true; 120 MemoryDenyWriteExecute = true; 121 NoNewPrivileges = true; 122 PrivateDevices = true; 123 PrivateTmp = true; 124 PrivateUsers = true; 125 ProtectClock = true; 126 ProtectControlGroups = true; 127 ProtectHome = true; 128 ProtectHostname = true; 129 ProtectKernelLogs = true; 130 ProtectKernelModules = true; 131 ProtectKernelTunables = true; 132 ProtectProc = "invisible"; 133 ProtectSystem = "full"; 134 RemoveIPC = true; 135 RestrictAddressFamilies = [ 136 "AF_INET" 137 "AF_INET6" 138 "AF_UNIX" 139 ]; 140 RestrictNamespaces = true; 141 RestrictRealtime = true; 142 RestrictSUIDSGID = true; 143 SystemCallArchitectures = "native"; 144 SystemCallFilter = [ 145 "@system-service" 146 "~@privileged" 147 ]; 148 }; 149 150 postStart = 151 let 152 bindAddr = (optionalString (hasPrefix ":" cfg.listenAddress) "127.0.0.1") + cfg.listenAddress; 153 in 154 mkBefore '' 155 until ${getBin pkgs.curl}/bin/curl -s -o /dev/null http://${bindAddr}/ping; do 156 sleep 1; 157 done 158 ''; 159 }; 160 }; 161}