diff --git a/build/ansible/roles/loki/files/json_log_format.conf b/build/ansible/roles/loki/files/json_log_format.conf new file mode 100644 index 0000000000..b1b5f59f2a --- /dev/null +++ b/build/ansible/roles/loki/files/json_log_format.conf @@ -0,0 +1,12 @@ + 'time="$time_iso8601" ' + 'host=$http_host ' + 'remote_addr=$remote_addr ' + 'request_method=$request_method ' + 'request="$request_uri" ' + 'request_time=$request_time ' + 'body_bytes_sent=$body_bytes_sent ' + 'server_protocol="$server_protocol" ' + 'status=$status ' + 'http_referrer="$http_referer" ' + 'http_x_forwarded_for="$http_x_forwarded_for" ' + 'http_user_agent="$http_user_agent"'; diff --git a/build/ansible/roles/loki/files/loki_location.conf b/build/ansible/roles/loki/files/loki_location.conf new file mode 100644 index 0000000000..a7f858ec1a --- /dev/null +++ b/build/ansible/roles/loki/files/loki_location.conf @@ -0,0 +1,7 @@ + # Loki + location = /loki/api/v1/push { + proxy_pass http://127.0.0.1:3100/$request_uri; + proxy_read_timeout 600; + proxy_set_header Connection ""; + client_body_buffer_size 2m; + } diff --git a/build/ansible/roles/loki/files/nginx.conf b/build/ansible/roles/loki/files/nginx.conf deleted file mode 100644 index a3ef9cc7ab..0000000000 --- a/build/ansible/roles/loki/files/nginx.conf +++ /dev/null @@ -1,62 +0,0 @@ -# user pmm; ## It's ignored when the master process is not run by root. -worker_processes 2; - -daemon off; - -error_log /dev/stderr warn; -pid /run/nginx.pid; - -events { - worker_connections 4096; -} - -http { - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - log_format ext_format - 'time="$time_iso8601" ' - 'host=$http_host ' - 'remote_addr=$remote_addr ' - 'request_method=$request_method ' - 'request="$request_uri" ' - 'request_time=$request_time ' - 'body_bytes_sent=$body_bytes_sent ' - 'server_protocol="$server_protocol" ' - 'status=$status ' - 'http_referrer="$http_referer" ' - 'http_x_forwarded_for="$http_x_forwarded_for" ' - 'http_user_agent="$http_user_agent"'; - - access_log /dev/stdout ext_format; - - sendfile on; - gzip on; - etag on; - - keepalive_timeout 65; - - resolver 8.8.8.8 8.8.4.4 valid=300s; - resolver_timeout 3s; - - ## TODO https://jira.percona.com/browse/PMM-4670 - # CWE-693, CWE-16 - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - # TODO X-XSS-Protection useless for modern browsers which support CSP. We need to implement CSP instead. - add_header X-XSS-Protection "1; mode=block"; - # CWE-524, CWE-525 - add_header Cache-control "no-cache"; - add_header Pragma "no-cache"; - - include /etc/nginx/conf.d/*.conf; -} diff --git a/build/ansible/roles/loki/files/pmm.conf b/build/ansible/roles/loki/files/pmm.conf deleted file mode 100644 index 6c12665d3a..0000000000 --- a/build/ansible/roles/loki/files/pmm.conf +++ /dev/null @@ -1,263 +0,0 @@ - upstream managed-grpc { - server 127.0.0.1:7771; - keepalive 32; - } - upstream managed-json { - server 127.0.0.1:7772; - keepalive 32; - keepalive_requests 100; - keepalive_timeout 75s; - } - - upstream qan-api-grpc { - server 127.0.0.1:9911; - keepalive 32; - } - upstream qan-api-json { - server 127.0.0.1:9922; - keepalive 32; - keepalive_requests 100; - keepalive_timeout 75s; - } - - upstream vmproxy { - server localhost:8430; - keepalive 32; - keepalive_requests 100; - keepalive_timeout 75s; - } - - upstream loki { - server 127.0.0.1:3100; - keepalive 32; - } - - server { - listen 8080; - listen 8443 ssl http2; - server_name _; - server_tokens off; - - # allow huge requests - large_client_header_buffers 128 64k; - - client_max_body_size 10m; - - ssl_certificate /srv/nginx/certificate.crt; - ssl_certificate_key /srv/nginx/certificate.key; - ssl_trusted_certificate /srv/nginx/ca-certs.pem; - ssl_dhparam /srv/nginx/dhparam.pem; - - # this block checks for maintenance.html file and, if it exists, it redirects all requests to the maintenance page - # there are two exceptions for it /v1/updates/Status and /auth_request endpoints - set $maintenance_mode 0; - - if (-f /usr/share/pmm-server/maintenance/maintenance.html) { - set $maintenance_mode 1; - } - - if ($request_uri ~* "^/v1/updates/Status|^/auth_request") { - set $maintenance_mode 0; - } - - if ($maintenance_mode = 1) { - return 503; - } - - error_page 503 @maintenance; - - location @maintenance { - auth_request off; - root /usr/share/pmm-server/maintenance; - rewrite ^(.*)$ /maintenance.html break; - } - - - # Enable passing of the remote user's IP address to all - # proxied services using the X-Forwarded-For header - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # Enable auth_request for all locations, including root - # (but excluding /auth_request). - auth_request /auth_request; - - # Store the value of X-Proxy-Filter header of auth_request subrequest response in the variable. - auth_request_set $auth_request_proxy_filter $upstream_http_x_proxy_filter; - proxy_set_header X-Proxy-Filter $auth_request_proxy_filter; - - # nginx completely ignores auth_request subrequest response body. - # We use that directive to send the same request to the same location as a normal request - # to get a response body or redirect and return it to the client. - # auth_request supports only 401 and 403 statuses; 401 is reserved for this configration, - # and 403 is used for normal pmm-managed API errors. - error_page 401 = /auth_request; - - # Internal location for authentication via pmm-managed/Grafana. - # First, nginx sends request there to authenticate it. If it is not authenticated by pmm-managed/Grafana, - # it is sent to this location for the second time (as a normal request) by error_page directive above. - location /auth_request { - internal; - - auth_request off; - - proxy_pass http://managed-json/auth_request; - - # nginx always strips body from authentication subrequests. - # Overwrite Content-Length to avoid problems on Go side and to keep connection alive. - proxy_pass_request_body off; - proxy_set_header Content-Length 0; - - proxy_http_version 1.1; - proxy_set_header Connection ""; - - # Those headers are set for both subrequest and normal request. - proxy_set_header X-Original-Uri $request_uri; - proxy_set_header X-Original-Method $request_method; - } - - # PMM UI - location /pmm-ui { - # Will redirect on FE to login page if user is not authenticated - auth_request off; - - alias /usr/share/pmm-ui; - try_files $uri /index.html break; - } - - # Grafana - rewrite ^/$ $scheme://$http_host/graph/; - rewrite ^/graph$ /graph/; - location /graph { - proxy_cookie_path / "/;"; - proxy_pass http://127.0.0.1:3000; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $http_host; - proxy_set_header X-Proxy-Filter $auth_request_proxy_filter; - } - - # Prometheus - location /prometheus { - proxy_pass http://127.0.0.1:9090; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - location /prometheus/api/v1 { - proxy_pass http://vmproxy; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - - # VictoriaMetrics - location /victoriametrics/ { - proxy_pass http://127.0.0.1:9090/prometheus/; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection ""; - client_body_buffer_size 10m; - } - - # VMAlert - location /prometheus/rules { - proxy_pass http://127.0.0.1:8880/api/v1/rules; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - location /prometheus/alerts { - proxy_pass http://127.0.0.1:8880/api/v1/alerts; - proxy_read_timeout 600; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - - # Loki - location = /loki/api/v1/push { - proxy_pass http://loki$request_uri; - } - - # Swagger UI - rewrite ^/swagger/swagger.json$ $scheme://$http_host/swagger.json permanent; - rewrite ^(/swagger)/(.*)$ $scheme://$http_host/swagger permanent; - location /swagger { - auth_request off; - root /usr/share/pmm-managed/swagger; - try_files $uri /index.html break; - } - - # pmm-managed gRPC APIs - location /agent. { - grpc_pass grpc://managed-grpc; - # Disable request body size check for gRPC streaming, see https://trac.nginx.org/nginx/ticket/1642. - # pmm-managed uses grpc.MaxRecvMsgSize for that. - client_max_body_size 0; - } - location /inventory. { - grpc_pass grpc://managed-grpc; - } - location /management. { - grpc_pass grpc://managed-grpc; - } - location /server. { - grpc_pass grpc://managed-grpc; - } - - # pmm-managed JSON APIs - location /v1/ { - proxy_pass http://managed-json/v1/; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - - # qan-api gRPC APIs should not be exposed - - # qan-api JSON APIs - location /v1/qan { - proxy_pass http://qan-api-json/v1/qan; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - - # compatibility with PMM 1.x - rewrite ^/ping$ /v1/server/readyz; - # compatibility with PMM 2.x - rewrite ^/v1/readyz$ /v1/server/readyz; - rewrite ^/v1/version$ /v1/server/version; - rewrite ^/logs.zip$ /v1/server/logs.zip; - - # logs.zip in both PMM 1.x and 2.x variants - location /v1/server/logz.zip { - proxy_pass http://managed-json; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } - - # pmm-dump artifacts - location /dump { - alias /srv/dump/; - } - - # This localtion stores static content for general pmm-server purposes. - # Ex.: local-rss.xml - contains Percona's news when no internet connection. - location /pmm-static { - auth_request off; - alias /usr/share/pmm-server/static; - } - - # proxy requests to the Percona's blog feed - # fallback to local rss if pmm-server is isolated from internet. - # https://jira.percona.com/browse/PMM-6153 - location = /percona-blog/feed { - auth_request off; - proxy_ssl_server_name on; - - set $feed https://www.percona.com/blog/feed/; - proxy_pass $feed; - proxy_set_header User-Agent "$http_user_agent pmm-server/3.x"; - error_page 500 502 503 504 /pmm-static/local-rss.xml; - } - } diff --git a/build/ansible/roles/loki/tasks/main.yml b/build/ansible/roles/loki/tasks/main.yml index 94fc4e8530..1f0cef6dce 100644 --- a/build/ansible/roles/loki/tasks/main.yml +++ b/build/ansible/roles/loki/tasks/main.yml @@ -69,16 +69,32 @@ owner: pmm group: pmm -- name: Override pmm.conf file - copy: - src: pmm.conf - dest: /etc/nginx/conf.d/pmm.conf - owner: pmm - group: pmm +- name: Remove the end of log_format line in nginx.conf + command: sed -i 's/^\([[:space:]]*log_format main\).*/\1/' /etc/nginx/nginx.conf -- name: Override nginx.conf file - copy: - src: nginx.conf - dest: /etc/nginx/nginx.conf - owner: pmm - group: pmm +- name: Remove the log_format in nginx.conf + command: sed -i '/log_format/{n;N;d;}' /etc/nginx/nginx.conf + +- name: Replace the original log_format with a json one + blockinfile: + path: /etc/nginx/nginx.conf + marker: "{mark}" + marker_begin: "#LOG_FORMAT_BEGIN" + marker_end: "#LOG_FORMAT_END" + insertafter: "log_format" + block: "{{ lookup('ansible.builtin.file', '/opt/ansible/roles/loki/files/json_log_format.conf') }}" + +- name: Remove ansible markers from nginx.conf + command: sed -i '/^#LOG_FORMAT_.*/d' /etc/nginx/nginx.conf + +- name: Add Loki location to pmm.conf + blockinfile: + path: /etc/nginx/conf.d/pmm.conf + marker: "{mark}" + marker_begin: "#LOKI_LOCATION_BEGIN" + marker_end: "#LOKI_LOCATION_END" + insertbefore: "# Swagger UI" + block: "{{ lookup('ansible.builtin.file', '/opt/ansible/roles/loki/files/loki_location.conf') }}" + +- name: Remove ansible markers from pmm.conf + command: sed -i '/^#LOKI_LOCATION_.*/d'/etc/nginx/conf.d/pmm.conf diff --git a/main.yml b/main.yml new file mode 100644 index 0000000000..6a314753e5 --- /dev/null +++ b/main.yml @@ -0,0 +1,20 @@ +--- +- hosts: all + tasks: + - name: Remove the end of log_format line + command: sed -i -E 's/^\([[:space:]]*log_format main\).*/\1/' nginx.conf + + - name: Remove the log_format itself + command: sed -i -E '/log_format/{n;N;d;}' nginx.conf + + - name: Replace the original log_format with a json one + blockinfile: + path: ./nginx.conf + marker: "{mark}" + marker_begin: "#LOG_FORMAT_BEGIN" + marker_end: "#LOG_FORMAT_END" + insertafter: "log_format" + block: "{{ lookup('ansible.builtin.file', './json_log_format.txt') }}" + + - name: Remove ansible markers + command: sed -i -E '/^#LOG_FORMAT_.*/d' nginx.conf