Skip to content

Ghost Monitoring and Logging — Track Site Health, Errors and Alerts

DodaTech Updated 2026-06-28 11 min read

In this tutorial, you'll learn how to monitor Ghost CMS — reading and interpreting Ghost logs, setting up uptime monitoring with external services, configuring error alerts via email or Slack, tracking performance metrics over time, and debugging common issues using log analysis.

What You'll Learn

  • Ghost log structure and location
  • Reading and filtering Ghost logs
  • Setting up uptime monitoring (Pingdom, UptimeRobot)
  • Error alerting via email, Slack, and webhooks
  • Performance metrics monitoring (response time, memory usage)
  • Database query monitoring
  • Ghost Health API endpoint
  • Using PM2 for process monitoring
  • Setting up log rotation
  • Debugging common errors using logs
  • Creating a monitoring dashboard

Why It Matters

You cannot fix what you cannot see. Without monitoring, your site could be down for hours before you notice. Ghost logs contain the first clues when something goes wrong — a database connection failure, a memory limit exceeded, a theme error. A proper monitoring setup notifies you within minutes of an issue and provides the log data needed to diagnose and fix it quickly.

Real-World Use

A Ghost site starts returning 502 Bad Gateway errors at 3 AM. The admin receives an email alert from UptimeRobot within 2 minutes. They check the Ghost logs and find: "Error: connect ECONNREFUSED 127.0.0.1:3306." The MySQL service stopped due to an out-of-memory condition. The admin restarts MySQL, the site comes back up, and they add MySQL to the monitoring system so it auto-restarts next time.

Learning Path

flowchart LR
  A["Security"] --> B["Monitoring & Logging
You are here"]:::current B --> C["Production Deployment"] C --> D["Course Complete"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

Ghost Log Structure

Log Locations

Log Path Purpose
Ghost application log content/logs/<filename>.log Ghost process logs
Nginx access log /var/log/nginx/access.log HTTP request log
Nginx error log /var/log/nginx/error.log Nginx-level errors
MySQL log /var/log/mysql/error.log Database errors
System log /var/log/syslog System-level events

Log Format

Ghost logs follow this format:

[YYYY-MM-DD HH:MM:SS] LEVEL: Message
[2026-06-28 14:30:15] INFO: Ghost is running in production mode
[2026-06-28 14:30:16] INFO: Ghost is using MySQL database
[2026-06-28 14:30:18] INFO: Ghost server started on http://127.0.0.1:2368

Log Levels

Level Meaning Example
INFO Normal operation Server started, migration complete
WARN Potential issue Slow query, deprecated API call
ERROR Operation failed Database connection failed
FATAL Process stopping Out of memory, critical config error

Reading and Filtering Logs

Basic Log Reading

# View last 50 lines
ghost log --tail 50

# View logs in real time
ghost log --tail

# View errors only
ghost log errors --tail 20

# View specific date range
ghost log --since "2026-06-27" --until "2026-06-28"

Advanced Filtering with grep

# Find all database errors
grep "database" content/logs/*.log

# Find all 5xx errors
grep "ERROR" content/logs/*.log

# Find memory-related issues
grep -i "memory|heap|allocation" content/logs/*.log

# Count error types
grep -c "ERROR" content/logs/*.log
grep -c "WARN" content/logs/*.log

Log Analysis Script

#!/bin/bash
# analyze-ghost-logs.sh

LOG_DIR="/var/www/ghost/content/logs"
echo "=== Ghost Log Analysis ==="
echo "Date: $(date)"
echo ""

# Count log entries by level
echo "Log entries by level:"
grep -c "\[INFO\]" $LOG_DIR/*.log 2>/dev/null || echo "  No INFO entries"
grep -c "\[WARN\]" $LOG_DIR/*.log 2>/dev/null || echo "  No WARN entries"
grep -c "\[ERROR\]" $LOG_DIR/*.log 2>/dev/null || echo "  No ERROR entries"
grep -c "\[FATAL\]" $LOG_DIR/*.log 2>/dev/null || echo "  No FATAL entries"

# Find recent errors
echo ""
echo "Recent errors (last 24h):"
grep "ERROR" $LOG_DIR/*.log 2>/dev/null | tail -10

# Check for specific issues
echo ""
echo "Database issues:"
grep -i "database\|mysql\|sqlite\|connection" $LOG_DIR/*.log 2>/dev/null | tail -5

Uptime Monitoring

Using UptimeRobot

  1. Create a free UptimeRobot account
  2. Add a new monitor:
    • Monitor Type: HTTP(S)
    • URL: https://yoursite.com
    • Interval: 5 minutes
    • Alert Contacts: Email, Slack, or SMS

Using Pingdom

  1. Create a Pingdom account
  2. Add a new check:
    • URL: https://yoursite.com
    • Check frequency: 1 minute
    • Alert when down for: 1 minute
    • Integrations: Email, Slack, PagerDuty

Self-Hosted Monitoring with Upptime

Upptime is an open-source uptime monitor that runs on GitHub Actions:

# .upptimerc.yml
sites:
  - name: Ghost Production
    url: https://yoursite.com
  - name: Ghost Admin
    url: https://yoursite.com/ghost/

status-website:
  baseUrl: /status
  logoUrl: https://yoursite.com/favicon.png
  name: Ghost Site Status

Error Alerting

Email Alerts via Ghost Health Endpoint

Ghost provides a health check endpoint:

# Simple health check script
#!/bin/bash
URL="https://yoursite.com"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" $URL)

if [ "$STATUS" != "200" ]; then
  echo "Site is down! Status: $STATUS" | \
    mail -s "ALERT: Ghost Site Down" admin@yoursite.com
fi

Slack Alerts

#!/bin/bash
# slack-alert.sh

SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
URL="https://yoursite.com"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" $URL)

if [ "$STATUS" != "200" ]; then
  curl -X POST -H "Content-type: application/json" \
    --data "{\"text\":\"ALERT: Ghost site ($URL) returned status $STATUS\"}" \
    $SLACK_WEBHOOK
fi

Schedule with cron:

*/5 * * * * /home/ghost/scripts/slack-alert.sh

Webhook-Based Alerts

Use Ghost's own webhooks to trigger alerts on specific events:

  1. Go to Settings → Integrations → Add Custom Integration
  2. Create webhooks for:
    • post.added — notify when new content is published
    • member.added — track member growth
    • subscription.created — monitor revenue events

Performance Metrics Monitoring

Response Time Monitoring

#!/bin/bash
# monitor-response-time.sh

URL="https://yoursite.com"
LOG_FILE="/var/log/ghost/response-times.log"

TIME=$(curl -s -o /dev/null -w "%{time_total}" $URL)
echo "$(date +%Y-%m-%dT%H:%M:%S) $TIME" >> $LOG_FILE

# Alert if response time exceeds 2 seconds
if (( $(echo "$TIME > 2.0" | bc -l) )); then
  echo "ALERT: Response time $TIME seconds exceeds threshold of 2s" | \
    mail -s "Ghost Performance Alert" admin@yoursite.com
fi

Monitoring Memory and CPU

#!/bin/bash
# monitor-system.sh

LOG_FILE="/var/log/ghost/system-stats.log"
THRESHOLD_MEM=80  # Alert at 80% memory usage
THRESHOLD_CPU=90  # Alert at 90% CPU usage

MEM_USAGE=$(free | grep Mem | awk '{print int($3/$2 * 100)}')
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print int($2)}')
DISK_USAGE=$(df -h / | tail -1 | awk '{print int($5)}')

echo "$(date +%Y-%m-%dT%H:%M:%S) MEM:$MEM_USAGE% CPU:$CPU_USAGE% DISK:$DISK_USAGE%" \
  >> $LOG_FILE

# Alert checks
if [ $MEM_USAGE -gt $THRESHOLD_MEM ]; then
  echo "ALERT: Memory usage at $MEM_USAGE% exceeds threshold" | \
    mail -s "Ghost Memory Alert" admin@yoursite.com
fi

if [ $DISK_USAGE -gt 90 ]; then
  echo "ALERT: Disk usage at $DISK_USAGE% — action required!" | \
    mail -s "Ghost Disk Alert" admin@yoursite.com
fi

PM2 Monitoring

If you run Ghost with PM2, use PM2's built-in monitoring:

# Monitor Ghost process
pm2 monit

# List all processes with resource usage
pm2 list

# Show detailed process info
pm2 show ghost

# Set up PM2 auto-restart on crash
pm2 start index.js --name ghost --max-memory-restart 512M

Ghost Health API

Ghost exposes a health-check endpoint:

curl https://yoursite.com/ghost/api/admin/site/

Response:

{
  "site": {
    "version": "5.80.0",
    "status": "healthy"
  }
}

You can also check the database status:

curl https://yoursite.com/ghost/api/admin/db/

Log Rotation

Without log rotation, log files grow indefinitely and fill the disk.

Configuring logrotate

Create /etc/logrotate.d/ghost:

/var/www/ghost/content/logs/*.log {
    weekly
    rotate 4
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

For Nginx logs:

/var/log/nginx/*.log {
    weekly
    rotate 12
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

Test logrotate configuration:

sudo logrotate -d /etc/logrotate.d/ghost

Creating a Monitoring Dashboard

Using Netdata

Netdata provides real-time monitoring with a web dashboard:

# Install Netdata
bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# Access dashboard
# http://yoursite.com:19999/

Using Grafana + Prometheus

For advanced monitoring, set up Prometheus to collect metrics and Grafana for visualization:

  1. Install Prometheus Node Exporter on the server
  2. Configure Prometheus to scrape Ghost metrics
  3. Set up Grafana with a Ghost monitoring dashboard
  4. Configure alert rules in Grafana

Debugging Common Errors

Ghost Won't Start

Check logs:

ghost log errors --tail 20

Common causes:

Error Likely Cause Fix
EADDRINUSE Port 2368 already in use Kill the process: sudo kill $(sudo lsof -t -i:2368)
ECONNREFUSED MySQL not running Start MySQL: sudo systemctl start mysql
ENOENT Missing config file Check config.production.json exists
Module not found Broken npm packages Reinstall: npm install --production

Site Loading Slowly

# Check Ghost process resource usage
ps aux | grep ghost

# Check MySQL process list
mysql -e "SHOW FULL PROCESSLIST;"

# Check Nginx error log
tail -50 /var/log/nginx/error.log

# Check available memory
free -h

502 Bad Gateway

This means Nginx cannot reach the Ghost process:

# Check if Ghost is running
ghost status

# Check if Ghost is listening on correct port
ss -tlnp | grep 2368

# Check Nginx error log
tail -20 /var/log/nginx/error.log

Common Mistakes

  1. Not monitoring at all: Many Ghost sites have no monitoring setup. The first sign of trouble is a user email or a tweet. Set up at least basic uptime monitoring with email alerts before going live.

  2. Ignoring warning-level logs: WARN entries are often the first indicator of a developing problem. A slow query warning today becomes a timeout error next week. Investigate warnings before they become errors.

  3. Not setting up log rotation: Ghost logs can grow to gigabytes over time. Without log rotation, logs fill the disk, which causes Ghost to crash because it cannot write new log entries.

  4. Checking logs only during incidents: Logs are most useful when you know what normal looks like. Review logs regularly (weekly automation) so you recognize anomalies quickly when they appear.

  5. Using only one monitoring tool: Uptime monitoring tells you the site is down, but not why. Combine uptime monitoring (is the site accessible?) with log monitoring (what errors are occurring?) and system monitoring (CPU, memory, disk).

  6. Alert fatigue from poorly tuned thresholds: Setting alert thresholds too low generates false alarms. Setting them too high misses real issues. Tune thresholds based on baseline data collected during the first month of operation.

Practice Questions

  1. Where does Ghost store its log files and what formats do they use? Answer: Ghost stores logs in content/logs/ with filenames like <timestamp>.log. The format is: [YYYY-MM-DD HH:MM:SS] LEVEL: Message. Levels include INFO (normal), WARN (potential issue), ERROR (operation failed), and FATAL (process stopping).

  2. How do you set up automated uptime monitoring for a Ghost site? Answer: Use an external monitoring service like UptimeRobot or Pingdom to check the site URL at regular intervals (e.g., every 5 minutes). Configure alerts via email, Slack, or SMS when the site returns a non-200 status code. Optionally add multi-location checks to verify global availability.

  3. What is log rotation and why is it necessary for Ghost? Answer: Log rotation automatically archives and compresses old log files to prevent them from consuming unlimited disk space. Without it, Ghost logs can grow to gigabytes, fill the server disk, and cause Ghost to crash. Tools like logrotate handle this with weekly/daily rotation and retention policies.

  4. Challenge: Build a complete Ghost monitoring system. Set up: uptime monitoring with UptimeRobot or similar, Slack/email alerts for downtime, a system resource monitor that checks CPU, memory, and disk usage every 5 minutes, logwatch-style daily log summary emailed to the admin, and a Grafana dashboard showing response time trends.

FAQ

Does Ghost have built-in monitoring?

Ghost has a health API endpoint (/ghost/api/admin/site/) that returns the version and status, and logs at content/logs/. There is no built-in uptime monitoring, alerting, or dashboard. All monitoring features must be added externally.

How do I check if Ghost is running without logging into the server?

Use a monitoring tool to check the HTTP status of your site URL (expect 200). You can also set up a cron job that runs curl and sends an alert if the status is not 200. The Ghost health API also works remotely.

What should I monitor first on a new Ghost site?

Start with these three: uptime (is the site accessible?), disk space (will it run out of room for images and logs?), and SSL certificate expiry (will the certificate expire?). Add response time and error rate monitoring after the first month.

How can I monitor Ghost member activity?

Ghost does not expose member activity metrics in logs by default. Use Google Analytics or Plausible for traffic analytics, and export member data from Ghost admin for subscription analytics. Integration with Stripe provides payment monitoring.

Can I send Ghost logs to a centralized logging service?

Yes. Use Filebeat or Logstash to forward Ghost logs from content/logs/ to services like Elasticsearch, Logz.io, or Datadog. Configure them as systemd services that monitor the log directory and ship new entries in real time.

How do I monitor Ghost database query performance?

Enable MySQL's slow query log: SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2;. Queries taking longer than 2 seconds are logged. Use mysqldumpslow to analyze the slow query log and identify problematic queries.

Mini Project

Your task: Implement a complete monitoring and logging system for a Ghost production site.

  1. Set up uptime monitoring with email and Slack alerts using a free service (UptimeRobot or similar).
  2. Create a system resource monitor script that checks CPU, memory, and disk usage every 5 minutes.
  3. Configure logrotate for both Ghost logs and Nginx logs.
  4. Create a daily log summary script that emails key statistics (error count, unique errors, warnings).
  5. Set up a health check endpoint monitoring script.
  6. Create a simple monitoring dashboard with response time trends.
  7. Write a troubleshooting guide based on common error patterns in Ghost logs.
  8. Document the alert thresholds and escalation procedures.

This exercise gives you a production-grade monitoring and alerting system.

What's Next

Now that monitoring is in place, learn about production deployment:

Continue to Lesson 40: Production Deployment — Deploy Ghost for scale and reliability.

Related lessons:

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro