Ever since I started this blog I have been using Nginx as a reverse proxy for Ghost.
Ghost is in a kind of weird place between real static and headless CMS like Hugo or Jekyll and fully-fledged CMS like WordPress. Ghost is a Node.js program based on Express that binds to a port and listen to HTTP requests, so it's not deployable like a static website with only static files.
However, the pages are actually static. In development mode, assets will be recompiled upon each request and views will be rerendered. In production mode however, views will be cached. Even with this internal cache, the node.js processes will still have to answer the queries, which doesn't scale well.
Since I was already using Nginx, setting up some proxy cache was really easy and had a huge impact on performance. Since most of my content does not change over time, caching really makes sense.
From my experience, pages cached by Nginx will have a TTFB down to twice as short, and most importantly they'll be able to sustain about 10 times more concurrent requests, at least on my setup, with much less CPU usage. This is useful for high traffic spikes like when I post a link to my blog on Mastodon and hundreds of instances try to fetch the pages in the span of a minute.
My setup has recently changed and I'm using Caddy as a single TLS-terminating reverse proxy, but Ghost still has its own Nginx in its LXC container, which only answers HTTP. The configuration is still easily adaptable.
Here is my configuration, with some comments:
Overall, it's caching everything except admin and preview pages. Also, it bypasses Ghost for static assets (theme's CSS and JS, images) since it has access to the storage. Nginx is very good at serving static files, so it's better to have it handle them than Ghost, since they are not processed (except dynamically resized images).