nix machine / user configurations
at terra 3.6 kB view raw
1{ 2 config, 3 lib, 4 inputs, 5 ... 6}: 7{ 8 services.nginx = { 9 enable = true; 10 recommendedTlsSettings = true; 11 recommendedOptimisation = true; 12 recommendedGzipSettings = true; 13 recommendedProxySettings = true; 14 # /nginx_status 15 statusPage = true; 16 }; 17 18 networking.firewall.allowedTCPPorts = [ 80 443 ]; 19 20 # output json logs so we can consume them more easily 21 services.nginx.appendHttpConfig = '' 22 log_format json_logs escape=json '{' 23 '"_msg":"request completed",' 24 '"time":"$time_local",' 25 '"req.remoteAddr":"$remote_addr",' 26 '"req.method":"$request_method",' 27 '"req.url":"$uri",' 28 '"req.httpVersion":"$server_protocol",' 29 '"res.statusCode":$status,' 30 '"res.bodySize":$body_bytes_sent,' 31 '"req.headers.id":"$request_id",' 32 '"req.headers.referer":"$http_referer",' 33 '"req.headers.user-agent":"$http_user_agent",' 34 '"requestTime":$request_time' 35 '}'; 36 access_log /var/log/nginx/access.log json_logs; 37 ''; 38 39 users.users.nginx.extraGroups = [ "acme" ]; 40 41 age.secrets.bunnyApiKey.file = ../../../secrets/bunnyApiKey.age; 42 security.acme = { 43 acceptTerms = true; 44 defaults = { 45 group = "nginx"; 46 email = (import "${inputs.self}/personal.nix").emails.primary; 47 dnsProvider = "bunny"; 48 credentialFiles = { 49 BUNNY_API_KEY_FILE = config.age.secrets.bunnyApiKey.path; 50 }; 51 }; 52 certs."poor.dog" = { }; 53 certs."ptr.pet" = { }; 54 certs."gaze.systems" = { }; 55 }; 56 services.nginx.virtualHosts."gaze.systems" = { 57 quic = true; 58 kTLS = true; 59 useACMEHost = "gaze.systems"; 60 forceSSL = true; 61 }; 62 services.nginx.virtualHosts."poor.dog" = { 63 quic = true; 64 kTLS = true; 65 useACMEHost = "poor.dog"; 66 forceSSL = true; 67 }; 68 services.nginx.virtualHosts."ptr.pet" = { 69 quic = true; 70 kTLS = true; 71 useACMEHost = "ptr.pet"; 72 forceSSL = true; 73 }; 74 75 services.fluent-bit.settings = { 76 parsers = [ 77 { 78 name = "nginx_json"; 79 format = "json"; 80 time_key = "time"; 81 time_format = "%d/%b/%Y:%H:%M:%S %z"; 82 } 83 ]; 84 pipeline = { 85 inputs = [ 86 { 87 name = "nginx_metrics"; 88 tag = "metrics.nginx"; 89 status_url = "/nginx_status"; 90 nginx_plus = false; 91 } 92 { 93 name = "tail"; 94 tag = "logs.nginx"; 95 path = "/var/log/nginx/*.log"; 96 db = "/var/lib/fluent-bit/nginx-access.db"; 97 "db.locking" = true; 98 buffer_chunk_size = "4m"; 99 buffer_max_size = "32m"; 100 parser = "nginx_json"; 101 } 102 ]; 103 filters = [ 104 { 105 name = "modify"; 106 match = "logs.nginx"; 107 Add = [ "name nginx" ]; 108 } 109 ]; 110 }; 111 }; 112 113 # need so fluent-bit can access nginx 114 systemd.services.fluent-bit.serviceConfig.SupplementaryGroups = lib.mkForce "systemd-journal nginx"; 115 116 services.vmalert.instances."".rules.groups = [ 117 { 118 name = "nginx-logs"; 119 type = "vlogs"; 120 interval = "1m"; 121 rules = [ 122 { 123 record = "nginx_request_count"; 124 expr = "name:nginx | stats (res.statusCode) count() as total_requests"; 125 } 126 { 127 record = "nginx_request_latency"; 128 # filter out subscribeRepos requests because they are long polling http L 129 expr = "name:nginx | filter req.url:!/xrpc/com.atproto.sync.subscribeRepos | stats avg(requestTime) avg, quantile(0.5, requestTime) p50, quantile(0.9, requestTime) p90, quantile(0.99, requestTime) p99"; 130 } 131 ]; 132 } 133 ]; 134}