Discourse-health-check: one-shot CLI overview of your Discourse server

A small bash script I created for my own forum that gives a one-shot health overview of Discourse server. Sharing for anyone who finds this type of quick overview useful.

Checks system resources: Docker, Discourse services (Postgres, Redis, Nginx, Unicorn, Sidekiq), backup freshness, TLS, and security basics. Ends with a pass / warning / critical summary and an exit code suitable for cron.

Install

curl -O https://raw.githubusercontent.com/haydenjames/discourse-health-check/main/discourse-health-check.sh
chmod +x discourse-health-check.sh
sudo ./discourse-health-check.sh

Source, options, and a cron example in the README:


New version v1.0.4:

Two fixes:

  1. Discourse replaced Unicorn with Pitchfork (default in 2026.2, Unicorn removed entirely
    in 2026.4), so the web server check now detects both. Thanks @RGJ for flagging this
    back in June.

  2. The service probes were matching their own command line. pgrep -f <name> so pgrep matched itself and the check passed whether or not the service was actually up. Sidekiq had been reporting “running” unconditionally since 1.0.0. It could have been dead and you’d still get a green check and exit code 0 from cron. Same root cause as the Puma false positive in 1.0.1, which turned out to have been renamed rather than fixed.

9 likes

Discourse doesn’t run Puma.

3 likes

Unicorn. Fixed thank you.

1 like

Pitchfork nowadays!!

2 likes

Nice offering, thanks!

For backups, I’d suggest checking the latest backup to see if it has been read since it was written. That’s a proxy, for checking if it has been copied offsite. (Or, if not checking the latest, perhaps check all.)

If no backup has been copied offsite for a week, that’s worth warning about.

(I think you can subtract stat -c %Y from stat -c %X or perhaps just compare them. They will be different if the backup file has been read since it was written.)

5 likes

@Ed_S Great suggestion. Added in v1.0.2. Compares atime vs mtime on the latest backup and warns if it hasn’t been read since being written, with a noatime check to skip cleanly where atime is unreliable. Credited you, thanks!

4 likes