Featured image of post Graylog behind a NGINX Reverse Proxy: API Exposed

Graylog behind a NGINX Reverse Proxy: API Exposed

How I exposed the Graylog behind a NGINX Reverse Proxy

I use Graylog to centrally capture and store many logfiles. The multi-tier solution based on Elasticsearch and MongoDB is awesome!

I also use Nginx a lot. In this case, I use it as reverse proxy to provide a secure access to Graylog. The web-frontend of Graylog works like a charm if you follow the instructions in the Graylog documentation here.

But the native API calls via the

Nginx reverse proxy never really worked with Graylog 4.x, at least not for me. The Developer tools of the browser (Chromium Edge) showed me a lot of 404 and the “real” URL of the backend. In my case that is! The client is then not able to access the API or the API web-frontend (swagger).

I couldn’t find a solution on the Graylog end. So, I came up with this config for my Nginx reverse-proxy:

location / {
   # Only Allow the Cloudflare Servers to use this URL (Not Scope)
   include /etc/nginx/snippets/enatec_CloudFlareAllowlist.conf;

   # Set some Default for Reverse Proxies (Not Scope)
   include /etc/nginx/snippets/enatec_proxydefaults.conf;

   # This is not required
   add_header         Front-End-Https        on;
   add_header         Cache-Control          "public, must-revalidate";

   # Mostly the GrayLog defaults
   proxy_set_header   X-Real-IP              $remote_addr;
   proxy_set_header   X-Forwarded-Proto      $scheme;
   proxy_set_header   Host                   $host:$server_port;
   proxy_set_header   X-Forwarded-Host       $host;
   proxy_set_header   X-Forwarded-Server     $host;
   proxy_set_header   X-Forwarded-For        $proxy_add_x_forwarded_for;
   proxy_set_header   X-Graylog-Server-URL   https://$server_name/;

   # This is not required
   proxy_http_version 1.1;

   # We want do control the returned content/URLs
   proxy_redirect     off;

   # Apply the Filter to every content the Backend returns
   sub_filter_types         *;
   sub_filter_once          off;

   # Modify the Header (not required)
   sub_filter_last_modified  on;

   # This is where we replace with the called hostname
   sub_filter               "http://$proxy_host" "$scheme://$host:$server_port";

   # Remove the Version string (optinal)
   sub_filter               "4.0.5+d95b909" "latest";

   # Fix the Link (optional)
   sub_filter               "" "";

There is also a Gist available.

What this does:

  • Use the Nginx sub_filetr functionality to rewrite the backend URL
  • Remove the fully API version and replace it with the word “latest” (optional)
  • Replace the Swagger Link (optional and nice to have)

In my case (above) I also limit the access to the well-known Cloudflare addresses! That has nothing to do with the functionality and is just an additional security layer for me.

It is not a full Site config! It’s just the location for the published Graylog. In my case it is a single node installation. You can have more than one node in your Graylog cluster (and you should, at least in production), but this makes the config easier to understand!