Skip to content

Deploying a Healthchecks App

Introduction

Healthchecks is a powerful, open-source cron job monitoring service that helps you track the reliability and uptime of your scheduled tasks, background jobs, and services. Built with Django and Python, Healthchecks provides a simple yet robust way to ensure your critical processes are running on schedule. When a job fails to check in, Healthchecks sends you instant alerts via email, Slack, webhooks, and dozens of other integrations.

Healthchecks excels at:

  • Cron Job Monitoring: Track scheduled tasks and receive alerts when they fail to execute
  • Uptime Monitoring: Monitor HTTP endpoints and SSL certificate expiration
  • Flexible Alerting: Integrate with 50+ notification channels including Slack, PagerDuty, Discord, and more
  • Grace Periods: Configure how long to wait before considering a check as “down”
  • Self-Hosted Privacy: Keep all your monitoring data under your control
  • Team Collaboration: Manage checks across teams with role-based access
  • API Access: Programmatic access for automation and custom integrations
  • Status Pages: Create public or private status pages for your services

This comprehensive guide walks you through deploying Healthchecks on Klutch.sh using Docker, including detailed installation steps, sample configurations, persistent storage setup, PostgreSQL database integration, and production-ready best practices.

Prerequisites

Before you begin, ensure you have the following:

  • A Klutch.sh account
  • A GitHub account with a repository for your Healthchecks project
  • Docker installed locally for testing (optional but recommended)
  • Basic understanding of Docker, Python, and monitoring concepts
  • A PostgreSQL database (can be deployed separately on Klutch.sh or use a managed service)

Installation and Setup

Step 1: Create Your Project Directory

First, create a new directory for your Healthchecks deployment project:

Terminal window
mkdir healthchecks-klutch
cd healthchecks-klutch
git init

Step 2: Create the Dockerfile

Create a Dockerfile in your project root directory. This will define your Healthchecks container configuration:

FROM python:3.11-slim
# Set environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Clone Healthchecks repository
RUN git clone https://github.com/healthchecks/healthchecks.git /app && \
git checkout v3.3
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir psycopg2-binary gunicorn
# Create directories for static files and media
RUN mkdir -p /app/static /app/hc/media
# Expose the default Healthchecks port
EXPOSE 8000
# Create startup script
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# Run the entrypoint script
ENTRYPOINT ["/docker-entrypoint.sh"]

Step 3: Create the Entrypoint Script

Create a docker-entrypoint.sh file in your project root:

#!/bin/bash
set -e
# Wait for database to be ready with timeout
echo "Waiting for database..."
MAX_RETRIES=60
RETRY_COUNT=0
while ! python manage.py dbshell < /dev/null 2>&1; do
RETRY_COUNT=$((RETRY_COUNT+1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "Error: Database connection timeout after ${MAX_RETRIES} attempts"
exit 1
fi
echo "Attempt ${RETRY_COUNT}/${MAX_RETRIES}..."
sleep 1
done
echo "Database is ready!"
# Run database migrations
echo "Running database migrations..."
python manage.py migrate --noinput
# Collect static files
echo "Collecting static files..."
python manage.py collectstatic --noinput --clear
# Compress static files
echo "Compressing static files..."
python manage.py compress
# Create superuser if SUPERUSER_EMAIL is set
if [ -n "$SUPERUSER_EMAIL" ] && [ -n "$SUPERUSER_PASSWORD" ]; then
echo "Creating superuser..."
python manage.py shell << END
from django.contrib.auth import get_user_model
User = get_user_model()
if not User.objects.filter(email='$SUPERUSER_EMAIL').exists():
User.objects.create_superuser(email='$SUPERUSER_EMAIL', password='$SUPERUSER_PASSWORD')
print('Superuser created successfully')
else:
print('Superuser already exists')
END
fi
# Start Gunicorn
echo "Starting Gunicorn..."
exec gunicorn hc.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 4 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
--log-level info

Step 4: Create Local Settings Configuration

Create a local_settings.py file for custom Django settings:

local_settings.py
import os
# Security settings
SECRET_KEY = os.environ.get('SECRET_KEY', 'change-this-to-a-random-secret-key')
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',')
# Database configuration
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'healthchecks'),
'USER': os.environ.get('DB_USER', 'healthchecks'),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# Site configuration
SITE_ROOT = os.environ.get('SITE_ROOT', 'https://example-app.klutch.sh')
SITE_NAME = os.environ.get('SITE_NAME', 'Healthchecks')
# Email configuration
EMAIL_HOST = os.environ.get('EMAIL_HOST', '')
try:
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', '587'))
except (ValueError, TypeError):
EMAIL_PORT = 587
EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'True') == 'True'
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '')
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'healthchecks@example.com')
# Registration
REGISTRATION_OPEN = os.environ.get('REGISTRATION_OPEN', 'True') == 'True'
# Integrations
SLACK_CLIENT_ID = os.environ.get('SLACK_CLIENT_ID', '')
SLACK_CLIENT_SECRET = os.environ.get('SLACK_CLIENT_SECRET', '')
DISCORD_CLIENT_ID = os.environ.get('DISCORD_CLIENT_ID', '')
DISCORD_CLIENT_SECRET = os.environ.get('DISCORD_CLIENT_SECRET', '')
PUSHOVER_API_TOKEN = os.environ.get('PUSHOVER_API_TOKEN', '')
PUSHOVER_SUBSCRIPTION_URL = os.environ.get('PUSHOVER_SUBSCRIPTION_URL', '')
try:
PUSHOVER_EMERGENCY_RETRY_DELAY = int(os.environ.get('PUSHOVER_EMERGENCY_RETRY_DELAY', '300'))
except (ValueError, TypeError):
PUSHOVER_EMERGENCY_RETRY_DELAY = 300
try:
PUSHOVER_EMERGENCY_EXPIRATION = int(os.environ.get('PUSHOVER_EMERGENCY_EXPIRATION', '86400'))
except (ValueError, TypeError):
PUSHOVER_EMERGENCY_EXPIRATION = 86400
TELEGRAM_BOT_NAME = os.environ.get('TELEGRAM_BOT_NAME', '')
TELEGRAM_TOKEN = os.environ.get('TELEGRAM_TOKEN', '')
# Twilio
TWILIO_ACCOUNT = os.environ.get('TWILIO_ACCOUNT', '')
TWILIO_AUTH = os.environ.get('TWILIO_AUTH', '')
TWILIO_FROM = os.environ.get('TWILIO_FROM', '')

Step 5: Update the Dockerfile to Include Local Settings

Modify your Dockerfile to copy the local settings file:

FROM python:3.11-slim
# Set environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Clone Healthchecks repository
RUN git clone https://github.com/healthchecks/healthchecks.git /app && \
git checkout v3.3
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir psycopg2-binary gunicorn
# Copy local settings
COPY local_settings.py /app/hc/local_settings.py
# Create directories for static files and media
RUN mkdir -p /app/static /app/hc/media
# Expose the default Healthchecks port
EXPOSE 8000
# Copy and set up entrypoint
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# Run the entrypoint script
ENTRYPOINT ["/docker-entrypoint.sh"]

Step 6: Create Environment Configuration

Create a .env.example file to document the required environment variables:

Terminal window
# Database Configuration
DB_NAME=healthchecks
DB_USER=healthchecks
DB_PASSWORD=your-secure-database-password
DB_HOST=postgres-app.klutch.sh
DB_PORT=8000
# Django Settings
SECRET_KEY=your-very-long-random-secret-key-here
DEBUG=False
ALLOWED_HOSTS=example-app.klutch.sh,*.klutch.sh
# Site Configuration
SITE_ROOT=https://example-app.klutch.sh
SITE_NAME=My Healthchecks
# Email Configuration (SMTP)
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=healthchecks@example.com
EMAIL_HOST_PASSWORD=your-email-password
DEFAULT_FROM_EMAIL=healthchecks@example.com
# User Registration
REGISTRATION_OPEN=True
# Superuser (Optional - for initial setup)
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_PASSWORD=your-admin-password
# Integrations (Optional)
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
PUSHOVER_API_TOKEN=
TELEGRAM_BOT_NAME=
TELEGRAM_TOKEN=
TWILIO_ACCOUNT=
TWILIO_AUTH=
TWILIO_FROM=

Security Note: Never commit actual passwords or sensitive data to your repository. Use environment variables in Klutch.sh dashboard.

Step 7: Create a README

Create a README.md file with deployment instructions:

# Healthchecks Deployment on Klutch.sh
This repository contains the configuration for deploying Healthchecks on Klutch.sh.
## Prerequisites
- PostgreSQL database (deployed separately or managed service)
- SMTP server for email notifications (optional but recommended)
## Quick Start
1. Deploy a PostgreSQL database on Klutch.sh or use a managed service
2. Push this repository to GitHub
3. Create a new app on Klutch.sh and connect this repository
4. Configure environment variables (see .env.example)
5. Deploy!
## Environment Variables
See `.env.example` for all required and optional environment variables.
## Post-Deployment
After deployment, access your Healthchecks instance at your app URL and:
1. Log in with your superuser credentials (if configured)
2. Configure notification channels
3. Create your first check
4. Add the check URL to your cron jobs or services
## Documentation
- <a href="https://healthchecks.io/docs/" target="_blank" rel="noopener noreferrer">Healthchecks Documentation</a>
- <a href="https://docs.klutch.sh?utm_source=docs" target="_blank">Klutch.sh Documentation</a>

Step 8: Test Locally (Optional)

Before deploying to Klutch.sh, you can test your Healthchecks setup locally using Docker Compose for development:

# docker-compose.yml (for local testing only)
version: '3.8'
services:
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: healthchecks
POSTGRES_USER: healthchecks
POSTGRES_PASSWORD: localpassword
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthchecks:
build: .
ports:
- "8000:8000"
environment:
DB_NAME: healthchecks
DB_USER: healthchecks
DB_PASSWORD: localpassword
DB_HOST: postgres
DB_PORT: 5432
SECRET_KEY: local-development-secret-key
DEBUG: "True"
SITE_ROOT: http://localhost:8000
SITE_NAME: Local Healthchecks
REGISTRATION_OPEN: "True"
SUPERUSER_EMAIL: admin@localhost
SUPERUSER_PASSWORD: admin
depends_on:
- postgres
volumes:
postgres_data:

Note: This Docker Compose file is for local development only. Klutch.sh does not support Docker Compose for deployments.

To test locally:

Terminal window
# Build and start services
docker-compose up -d
# View logs
docker-compose logs -f healthchecks
# Access Healthchecks at http://localhost:8000
# Stop services when done
docker-compose down

Step 9: Push to GitHub

Commit your files to your GitHub repository:

Terminal window
git add Dockerfile docker-entrypoint.sh local_settings.py .env.example README.md
git commit -m "Add Healthchecks Dockerfile and configuration"
git remote add origin https://github.com/yourusername/healthchecks-klutch.git
git push -u origin main

Deploying to Klutch.sh

Now that your Healthchecks project is ready and pushed to GitHub, follow these steps to deploy it on Klutch.sh with persistent storage and a PostgreSQL database.

Deployment Steps

    1. Deploy PostgreSQL Database

      Before deploying Healthchecks, you need a PostgreSQL database. You have two options:

      Make note of your database connection details (host, port, username, password, database name).

    2. Log in to Klutch.sh

      Navigate to klutch.sh/app and sign in to your account.

    3. Create a New Project

      Go to Create Project and give your project a meaningful name (e.g., “Healthchecks Monitoring”).

    4. Create a New App

      Navigate to Create App and configure the following settings:

    5. Select Your Repository

      • Choose GitHub as your Git source
      • Select the repository containing your Healthchecks Dockerfile
      • Choose the branch you want to deploy (usually main or master)
    6. Configure Traffic Type

      • Traffic Type: Select HTTP (Healthchecks serves a web interface via HTTP)
      • Internal Port: Set to 8000 (the default port that Healthchecks listens on)
    7. Set Environment Variables

      Add the following environment variables for your Healthchecks configuration. These are critical for proper operation:

      Database Configuration (Required):

      • DB_NAME: Your PostgreSQL database name (e.g., healthchecks)
      • DB_USER: Your PostgreSQL username (e.g., healthchecks)
      • DB_PASSWORD: Your PostgreSQL password (use a strong, secure password)
      • DB_HOST: Your PostgreSQL host (e.g., postgres-app.klutch.sh for Klutch.sh deployed databases, or your managed database host)
      • DB_PORT: PostgreSQL port (use 8000 if connecting to a Klutch.sh deployed database with TCP traffic, or 5432 for managed services)

      Django Settings (Required):

      • SECRET_KEY: A long, random string for Django security (generate using a password generator, at least 50 characters)
      • DEBUG: Set to False for production
      • ALLOWED_HOSTS: Your app domain (e.g., example-app.klutch.sh,*.klutch.sh)

      Site Configuration (Required):

      • SITE_ROOT: Your full app URL (e.g., https://example-app.klutch.sh)
      • SITE_NAME: A friendly name for your instance (e.g., My Healthchecks)

      Email Configuration (Recommended for notifications):

      • EMAIL_HOST: Your SMTP server (e.g., smtp.gmail.com, smtp.sendgrid.net)
      • EMAIL_PORT: SMTP port (typically 587 for TLS or 465 for SSL)
      • EMAIL_USE_TLS: Set to True for TLS (most common)
      • EMAIL_HOST_USER: Your SMTP username
      • EMAIL_HOST_PASSWORD: Your SMTP password
      • DEFAULT_FROM_EMAIL: The “from” email address (e.g., healthchecks@yourdomain.com)

      Optional Settings:

      • REGISTRATION_OPEN: Set to True to allow new user registrations, or False to restrict access
      • SUPERUSER_EMAIL: Admin email for initial superuser creation
      • SUPERUSER_PASSWORD: Admin password for initial superuser

      Security Note: Always use strong, unique passwords for production deployments. Use the “secret” toggle in Klutch.sh to hide sensitive values.

    8. Attach a Persistent Volume

      Healthchecks needs persistent storage for media files, uploaded assets, and SQLite-based features:

      • In the Volumes section, click “Add Volume”
      • Mount Path: Enter /app/hc/media (where Healthchecks stores uploaded files)
      • Size: Choose an appropriate size (1GB is typically sufficient for most use cases, scale up as needed)

      Note: While the main data is stored in PostgreSQL, the media volume ensures any uploaded files or generated assets persist across deployments.

    9. Configure Additional Settings

      • Region: Select the region closest to your users for optimal latency
      • Compute Resources: Choose CPU and memory based on your usage (minimum 512MB RAM recommended, 1GB+ for production)
      • Instances: Start with 1 instance (you can scale horizontally later as usage grows)
    10. Deploy Your Application

      Click “Create” to start the deployment. Klutch.sh will:

      • Automatically detect your Dockerfile in the repository root
      • Build the Docker image with all dependencies
      • Run database migrations automatically
      • Create the superuser if configured
      • Attach the persistent volume
      • Start your Healthchecks container
      • Assign a URL for external access (e.g., https://example-app.klutch.sh)

      The initial deployment may take 3-5 minutes as it clones the Healthchecks repository, installs dependencies, and runs migrations.

    11. Verify Deployment

      Once deployment is complete, you’ll receive a URL like example-app.klutch.sh. Navigate to this URL in your browser to access your Healthchecks instance:

      https://example-app.klutch.sh

      You should see the Healthchecks login page. If you configured SUPERUSER_EMAIL and SUPERUSER_PASSWORD, log in with those credentials. Otherwise, you can create an account if REGISTRATION_OPEN is set to True.


Getting Started with Healthchecks

After your Healthchecks instance is deployed, follow these steps to start monitoring your services and cron jobs.

Creating Your First Check

  1. Log in to Healthchecks

    Navigate to your Healthchecks instance (e.g., https://example-app.klutch.sh) and log in.

  2. Create a New Check

    • Click the “Add Check” button on the dashboard
    • Give your check a meaningful name (e.g., “Database Backup Job”)
    • Set the Period (how often the job should check in, e.g., “1 day” for daily backups)
    • Set the Grace Time (how long to wait before alerting, e.g., “1 hour”)
    • Optionally add tags to organize your checks
    • Click “Save”
  3. Get Your Check URL

    After creating the check, you’ll receive a unique check URL like:

    https://example-app.klutch.sh/ping/abc123def-4567-890a-bcde-f0123456789

Adding Checks to Your Cron Jobs

To monitor a cron job, add a curl request at the end of your cron script:

Simple ping:

Terminal window
# Your cron job
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123def > /dev/null

Report success or failure:

#!/bin/bash
# Your backup script
# Run backup
/usr/local/bin/backup.sh
# Ping Healthchecks with exit status
if [ $? -eq 0 ]; then
curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123def
else
curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123def/fail
fi

Send job output:

#!/bin/bash
# Run backup and capture output
OUTPUT=$(/usr/local/bin/backup.sh 2>&1)
# Send output to Healthchecks
curl -fsS -m 10 --retry 5 --data-raw "$OUTPUT" https://example-app.klutch.sh/ping/abc123def

Monitoring HTTP Endpoints

Healthchecks can also monitor HTTP/HTTPS endpoints:

  1. Create a new check and select “HTTP” as the check type
  2. Enter the URL you want to monitor (e.g., https://myapi.com/health)
  3. Set how often to check (e.g., every 5 minutes)
  4. Configure expected HTTP status code (default: 200)
  5. Optionally set keyword matching or response time thresholds

Setting Up Notifications

Configure notification channels to receive alerts when checks fail:

  1. Go to SettingsIntegrations

  2. Choose from 50+ notification channels:

    • Email: Default, configured via environment variables
    • Slack: Add a webhook URL or OAuth integration
    • Discord: Add a webhook URL
    • PagerDuty: Integrate for on-call alerting
    • Telegram: Connect your Telegram bot
    • Webhook: Send custom HTTP requests
    • Many more: MS Teams, Opsgenie, VictorOps, Pushover, etc.
  3. Assign notification channels to specific checks or use them globally


Environment Variables Reference

Complete list of Healthchecks environment variables you can configure in Klutch.sh:

Required Variables

VariableDescriptionExample
DB_NAMEPostgreSQL database namehealthchecks
DB_USERPostgreSQL usernamehealthchecks
DB_PASSWORDPostgreSQL passwordsecure-password-here
DB_HOSTPostgreSQL hostpostgres-app.klutch.sh
DB_PORTPostgreSQL port8000 (for Klutch.sh TCP) or 5432
SECRET_KEYDjango secret key (50+ random characters)abc123...xyz789
ALLOWED_HOSTSAllowed hostnames (comma-separated)example-app.klutch.sh,*.klutch.sh
SITE_ROOTFull URL to your instancehttps://example-app.klutch.sh
SITE_NAMEFriendly name for your instanceMy Healthchecks
VariableDescriptionExample
EMAIL_HOSTSMTP server hostnamesmtp.gmail.com
EMAIL_PORTSMTP server port587
EMAIL_USE_TLSUse TLS for SMTPTrue
EMAIL_HOST_USERSMTP usernamehealthchecks@example.com
EMAIL_HOST_PASSWORDSMTP passwordyour-smtp-password
DEFAULT_FROM_EMAILFrom email addresshealthchecks@example.com

Optional Settings

VariableDescriptionDefault
DEBUGEnable debug mode (never use in production)False
REGISTRATION_OPENAllow new user registrationsTrue
SUPERUSER_EMAILInitial admin emailNone
SUPERUSER_PASSWORDInitial admin passwordNone

Integration Variables (Optional)

VariableDescription
SLACK_CLIENT_IDSlack OAuth client ID
SLACK_CLIENT_SECRETSlack OAuth client secret
DISCORD_CLIENT_IDDiscord OAuth client ID
DISCORD_CLIENT_SECRETDiscord OAuth client secret
PUSHOVER_API_TOKENPushover API token
TELEGRAM_BOT_NAMETelegram bot name
TELEGRAM_TOKENTelegram bot token
TWILIO_ACCOUNTTwilio account SID
TWILIO_AUTHTwilio auth token
TWILIO_FROMTwilio phone number

Production Best Practices

Security Recommendations

  • Strong Passwords: Use a password manager to generate strong, random passwords for all credentials
  • Secret Management: Store all sensitive credentials as environment variables in Klutch.sh, never in your Dockerfile or repository
  • HTTPS Only: Klutch.sh provides HTTPS by default; ensure you only access Healthchecks via HTTPS
  • Database Security: Use a dedicated PostgreSQL user with minimal required permissions
  • Regular Backups: Implement a backup strategy for your PostgreSQL database
  • Update Regularly: Keep Healthchecks updated to the latest version for security patches
  • Restrict Registration: Set REGISTRATION_OPEN=False in production and create users manually
  • Rate Limiting: Configure rate limiting for check pings to prevent abuse
  • Audit Logs: Regularly review user activity and check configurations

Performance Optimization

  • Database Connection Pooling: Gunicorn with multiple workers automatically manages database connections
  • Static File Serving: Static files are collected and compressed during deployment
  • Caching: Enable Django caching for frequently accessed data
  • Worker Count: Adjust Gunicorn workers based on CPU cores (formula: 2 × CPU cores + 1)
  • Resource Allocation: Monitor your application and increase compute resources if response times degrade
  • Database Indexing: PostgreSQL automatically maintains indexes for optimal query performance
  • Check Frequency: Be mindful of check frequency to balance monitoring granularity with server load

Monitoring and Maintenance

Monitor your Healthchecks deployment for:

  • Response Times: Ensure the web interface loads quickly
  • Database Performance: Watch for slow queries or connection issues
  • Check Processing: Monitor the time it takes to process incoming check pings
  • Storage Usage: Track PostgreSQL database size and media volume usage
  • Memory Usage: Healthchecks should use consistent memory; watch for leaks
  • Email Delivery: Ensure notification emails are being sent successfully
  • Uptime: Use an external monitoring service to alert you if Healthchecks goes down

Database Maintenance

  • Regular Backups: Use PostgreSQL’s pg_dump or managed backup solutions
  • Vacuum Operations: PostgreSQL automatically maintains the database, but manual vacuuming may be beneficial for large installations
  • Data Retention: Configure check history retention to manage database growth
  • Connection Limits: Monitor and adjust PostgreSQL connection limits based on usage
  • Replication: Consider setting up PostgreSQL replication for high-availability production deployments

Backup Strategy

Database Backups:

Terminal window
# Backup PostgreSQL database
pg_dump -h postgres-app.klutch.sh -p 8000 -U healthchecks healthchecks > backup-$(date +%Y%m%d).sql
# Restore from backup
psql -h postgres-app.klutch.sh -p 8000 -U healthchecks healthchecks < backup-20240315.sql

Media Files Backup: Since media files are stored in a persistent volume, consider periodic snapshots or exports of the /app/hc/media directory.


Using the Healthchecks API

Healthchecks provides a comprehensive API for programmatic access to checks, integrations, and more.

Authentication

The API uses API keys for authentication. Get your API key from your Healthchecks account settings:

  1. Log in to Healthchecks
  2. Go to SettingsAPI Access
  3. Copy your API key (or create a new read-only key)

Common API Operations

List all checks:

Terminal window
curl https://example-app.klutch.sh/api/v1/checks/ \
-H "X-Api-Key: your-api-key-here"

Create a check:

Terminal window
curl -X POST https://example-app.klutch.sh/api/v1/checks/ \
-H "X-Api-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"name": "Database Backup",
"tags": "backup database",
"timeout": 86400,
"grace": 3600
}'

Get check details:

Terminal window
curl https://example-app.klutch.sh/api/v1/checks/<check-uuid> \
-H "X-Api-Key: your-api-key-here"

Update a check:

Terminal window
curl -X POST https://example-app.klutch.sh/api/v1/checks/<check-uuid> \
-H "X-Api-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Check Name",
"timeout": 43200
}'

Pause/Unpause a check:

Terminal window
# Pause
curl -X POST https://example-app.klutch.sh/api/v1/checks/<check-uuid>/pause \
-H "X-Api-Key: your-api-key-here"
# Unpause
curl -X POST https://example-app.klutch.sh/api/v1/checks/<check-uuid>/pause \
-H "X-Api-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{"paused": false}'

Delete a check:

Terminal window
curl -X DELETE https://example-app.klutch.sh/api/v1/checks/<check-uuid> \
-H "X-Api-Key: your-api-key-here"

Python API Client Example

import requests
import json
API_URL = "https://example-app.klutch.sh/api/v1"
API_KEY = "your-api-key-here"
headers = {
"X-Api-Key": API_KEY,
"Content-Type": "application/json"
}
# List all checks
response = requests.get(f"{API_URL}/checks/", headers=headers)
checks = response.json()
print(f"Total checks: {len(checks['checks'])}")
# Create a new check
new_check = {
"name": "API Test Check",
"tags": "test api",
"timeout": 3600,
"grace": 300
}
response = requests.post(f"{API_URL}/checks/", headers=headers, json=new_check)
check = response.json()
print(f"Created check: {check['ping_url']}")

Advanced Configurations

Custom Domain Setup

To use a custom domain with your Healthchecks instance:

  1. Add your custom domain in the Klutch.sh dashboard (e.g., healthchecks.yourdomain.com)
  2. Update your DNS records to point to Klutch.sh (follow instructions in the dashboard)
  3. Update environment variables:
    Terminal window
    SITE_ROOT=https://healthchecks.yourdomain.com
    ALLOWED_HOSTS=healthchecks.yourdomain.com,example-app.klutch.sh
  4. Redeploy your application

Scaling Horizontally

For high-traffic deployments, you can scale Healthchecks horizontally:

  1. Increase the number of instances in Klutch.sh dashboard
  2. Ensure all instances share the same PostgreSQL database
  3. Use a load balancer (Klutch.sh provides this automatically)
  4. Ensure session storage is database-backed (Django default)

Customizing Branding

To customize the appearance of your Healthchecks instance:

  1. Create a custom logo and save it as logo.png
  2. Update your Dockerfile to copy custom assets:
    COPY logo.png /app/static/img/logo.png
  3. Add custom CSS by creating a custom.css file and mounting it
  4. Rebuild and redeploy

Webhook Integration

Create a webhook integration to receive real-time notifications:

  1. Set up an endpoint to receive POST requests
  2. In Healthchecks, go to SettingsIntegrations
  3. Add a Webhook integration
  4. Enter your endpoint URL
  5. Choose when to send notifications (check goes down, up, or both)

Example webhook payload:

{
"check_id": "abc123def-4567-890a-bcde-f0123456789",
"check_name": "Database Backup",
"tags": "backup database",
"status": "down",
"ping_count": 42,
"last_ping": "2024-03-15T10:30:00Z"
}

Troubleshooting

Cannot Access Healthchecks Dashboard

  • Verify your app is running in the Klutch.sh dashboard
  • Check that the internal port is set to 8000
  • Ensure HTTP traffic type is selected
  • Review application logs for startup errors
  • Verify the Dockerfile and entrypoint script are correct

Database Connection Errors

  • Verify PostgreSQL is running and accessible
  • Check database credentials in environment variables
  • Ensure the DB_HOST and DB_PORT are correct
  • For Klutch.sh deployed databases using TCP, use port 8000
  • Test database connectivity using psql or a database client
  • Review database logs for connection issues

Migrations Not Running

  • Check the entrypoint script is executable
  • Review application logs for migration errors
  • Ensure the database user has CREATE permissions
  • Try manually running migrations in a debug container

Static Files Not Loading

  • Verify collectstatic ran successfully during deployment
  • Check the /app/static directory exists and contains files
  • Ensure Gunicorn is serving static files correctly
  • Review the Django static files configuration

Email Notifications Not Sending

  • Verify SMTP credentials are correct
  • Test SMTP connectivity using telnet or openssl s_client
  • Check email provider’s security settings (app passwords, less secure apps)
  • Review application logs for SMTP errors
  • Consider using a dedicated transactional email service like SendGrid or Mailgun

Check Pings Not Registering

  • Verify the check URL is correct and accessible
  • Check for network issues or firewalls blocking requests
  • Ensure the cron job or script is running successfully
  • Review Healthchecks logs for incoming ping requests
  • Test the ping URL manually using curl

High Memory Usage

  • Monitor the number of Gunicorn workers
  • Check for database query inefficiencies
  • Review check frequency and volume
  • Consider increasing compute resources
  • Look for memory leaks in custom integrations

Performance Issues

  • Monitor PostgreSQL query performance
  • Check Gunicorn worker count and adjust if needed
  • Review Django debug toolbar output (only in development)
  • Ensure database indexes are optimal
  • Consider caching frequently accessed data
  • Scale horizontally by adding more instances

Upgrading Healthchecks

To upgrade Healthchecks to a new version:

  1. Update the Dockerfile:

    # Change the git checkout line to the new version
    RUN git clone https://github.com/healthchecks/healthchecks.git /app && \
    git checkout v3.4
  2. Test Locally (recommended):

    Terminal window
    docker build -t healthchecks-test .
    docker run -it healthchecks-test /bin/bash
    # Verify the new version installed correctly
  3. Commit and Push:

    Terminal window
    git add Dockerfile
    git commit -m "Upgrade Healthchecks to version 3.4"
    git push
  4. Deploy on Klutch.sh: Klutch.sh will automatically rebuild and redeploy your application. The entrypoint script will run database migrations automatically.

  5. Verify the Upgrade:

    • Check that the app starts successfully
    • Review logs for any migration errors
    • Test core functionality (creating checks, sending pings)
    • Verify all integrations still work
  6. Rollback if Needed: If issues occur, revert the Dockerfile changes and redeploy:

    Terminal window
    git revert HEAD
    git push

Use Cases and Examples

Monitoring Cron Jobs

Daily Database Backups:

/usr/local/bin/backup-database.sh
#!/bin/bash
# Start signal
curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123/start
# Run backup
pg_dump -h db.example.com -U postgres mydb > /backups/mydb-$(date +%Y%m%d).sql
# Signal completion
if [ $? -eq 0 ]; then
curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123
else
curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123/fail
fi

Scheduled Data Processing:

scheduled_job.py
import requests
import sys
CHECK_URL = "https://example-app.klutch.sh/ping/def456"
def process_data():
try:
# Start signal
requests.get(f"{CHECK_URL}/start")
# Your data processing logic
result = perform_complex_calculation()
# Success signal
requests.get(CHECK_URL)
return True
except Exception as e:
# Failure signal with error message
requests.post(f"{CHECK_URL}/fail", data=str(e))
return False
if __name__ == "__main__":
success = process_data()
sys.exit(0 if success else 1)

Monitoring System Services

Monitor Docker Container Health:

/usr/local/bin/check-docker-health.sh
#!/bin/bash
CONTAINER_NAME="my-app"
CHECK_URL="https://example-app.klutch.sh/ping/ghi789"
if docker inspect -f '{{.State.Health.Status}}' $CONTAINER_NAME | grep -q "healthy"; then
curl -fsS -m 10 --retry 5 $CHECK_URL
else
curl -fsS -m 10 --retry 5 $CHECK_URL/fail
fi

Monitoring Web Services

Use Healthchecks’ HTTP monitoring to check your web services:

  1. Create a check with type “HTTP”
  2. Enter your service URL: https://api.example.com/health
  3. Set check interval: Every 5 minutes
  4. Configure expected status code: 200
  5. Optionally add keyword matching for response body

Additional Resources


Conclusion

Deploying Healthchecks on Klutch.sh with Docker provides a powerful, self-hosted monitoring solution with full control over your data. By following this comprehensive guide, you’ve set up a production-ready Healthchecks instance with PostgreSQL database storage, persistent media volumes, email notifications, and scalable infrastructure. Your monitoring platform is now ready to track cron jobs, background tasks, and web services, ensuring you’re immediately notified when critical processes fail. With Healthchecks running on Klutch.sh, you have a reliable, privacy-focused monitoring solution that scales with your needs.