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:
mkdir healthchecks-klutchcd healthchecks-klutchgit initStep 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 variablesENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1
# Install system dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ libpq-dev \ git \ curl \ && rm -rf /var/lib/apt/lists/*
# Set working directoryWORKDIR /app
# Clone Healthchecks repositoryRUN git clone https://github.com/healthchecks/healthchecks.git /app && \ git checkout v3.3
# Install Python dependenciesRUN pip install --no-cache-dir -r requirements.txt && \ pip install --no-cache-dir psycopg2-binary gunicorn
# Create directories for static files and mediaRUN mkdir -p /app/static /app/hc/media
# Expose the default Healthchecks portEXPOSE 8000
# Create startup scriptCOPY docker-entrypoint.sh /docker-entrypoint.shRUN chmod +x /docker-entrypoint.sh
# Run the entrypoint scriptENTRYPOINT ["/docker-entrypoint.sh"]Step 3: Create the Entrypoint Script
Create a docker-entrypoint.sh file in your project root:
#!/bin/bashset -e
# Wait for database to be ready with timeoutecho "Waiting for database..."MAX_RETRIES=60RETRY_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 1done
echo "Database is ready!"
# Run database migrationsecho "Running database migrations..."python manage.py migrate --noinput
# Collect static filesecho "Collecting static files..."python manage.py collectstatic --noinput --clear
# Compress static filesecho "Compressing static files..."python manage.py compress
# Create superuser if SUPERUSER_EMAIL is setif [ -n "$SUPERUSER_EMAIL" ] && [ -n "$SUPERUSER_PASSWORD" ]; then echo "Creating superuser..." python manage.py shell << ENDfrom django.contrib.auth import get_user_modelUser = 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')ENDfi
# Start Gunicornecho "Starting Gunicorn..."exec gunicorn hc.wsgi:application \ --bind 0.0.0.0:8000 \ --workers 4 \ --timeout 120 \ --access-logfile - \ --error-logfile - \ --log-level infoStep 4: Create Local Settings Configuration
Create a local_settings.py file for custom Django settings:
import os
# Security settingsSECRET_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 configurationDATABASES = { '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 configurationSITE_ROOT = os.environ.get('SITE_ROOT', 'https://example-app.klutch.sh')SITE_NAME = os.environ.get('SITE_NAME', 'Healthchecks')
# Email configurationEMAIL_HOST = os.environ.get('EMAIL_HOST', '')try: EMAIL_PORT = int(os.environ.get('EMAIL_PORT', '587'))except (ValueError, TypeError): EMAIL_PORT = 587EMAIL_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')
# RegistrationREGISTRATION_OPEN = os.environ.get('REGISTRATION_OPEN', 'True') == 'True'
# IntegrationsSLACK_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 = 300try: 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', '')
# TwilioTWILIO_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 variablesENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1
# Install system dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ libpq-dev \ git \ curl \ && rm -rf /var/lib/apt/lists/*
# Set working directoryWORKDIR /app
# Clone Healthchecks repositoryRUN git clone https://github.com/healthchecks/healthchecks.git /app && \ git checkout v3.3
# Install Python dependenciesRUN pip install --no-cache-dir -r requirements.txt && \ pip install --no-cache-dir psycopg2-binary gunicorn
# Copy local settingsCOPY local_settings.py /app/hc/local_settings.py
# Create directories for static files and mediaRUN mkdir -p /app/static /app/hc/media
# Expose the default Healthchecks portEXPOSE 8000
# Copy and set up entrypointCOPY docker-entrypoint.sh /docker-entrypoint.shRUN chmod +x /docker-entrypoint.sh
# Run the entrypoint scriptENTRYPOINT ["/docker-entrypoint.sh"]Step 6: Create Environment Configuration
Create a .env.example file to document the required environment variables:
# Database ConfigurationDB_NAME=healthchecksDB_USER=healthchecksDB_PASSWORD=your-secure-database-passwordDB_HOST=postgres-app.klutch.shDB_PORT=8000
# Django SettingsSECRET_KEY=your-very-long-random-secret-key-hereDEBUG=FalseALLOWED_HOSTS=example-app.klutch.sh,*.klutch.sh
# Site ConfigurationSITE_ROOT=https://example-app.klutch.shSITE_NAME=My Healthchecks
# Email Configuration (SMTP)EMAIL_HOST=smtp.example.comEMAIL_PORT=587EMAIL_USE_TLS=TrueEMAIL_HOST_USER=healthchecks@example.comEMAIL_HOST_PASSWORD=your-email-passwordDEFAULT_FROM_EMAIL=healthchecks@example.com
# User RegistrationREGISTRATION_OPEN=True
# Superuser (Optional - for initial setup)SUPERUSER_EMAIL=admin@example.comSUPERUSER_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 service2. Push this repository to GitHub3. Create a new app on Klutch.sh and connect this repository4. 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 channels3. Create your first check4. 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:
# Build and start servicesdocker-compose up -d
# View logsdocker-compose logs -f healthchecks
# Access Healthchecks at http://localhost:8000
# Stop services when donedocker-compose downStep 9: Push to GitHub
Commit your files to your GitHub repository:
git add Dockerfile docker-entrypoint.sh local_settings.py .env.example README.mdgit commit -m "Add Healthchecks Dockerfile and configuration"git remote add origin https://github.com/yourusername/healthchecks-klutch.gitgit push -u origin mainDeploying 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
-
Deploy PostgreSQL Database
Before deploying Healthchecks, you need a PostgreSQL database. You have two options:
- Option A: Deploy PostgreSQL on Klutch.sh by following the PostgreSQL deployment guide
- Option B: Use a managed PostgreSQL service like ElephantSQL or DigitalOcean Managed Databases
Make note of your database connection details (host, port, username, password, database name).
-
Log in to Klutch.sh
Navigate to klutch.sh/app and sign in to your account.
-
Create a New Project
Go to Create Project and give your project a meaningful name (e.g., “Healthchecks Monitoring”).
-
Create a New App
Navigate to Create App and configure the following settings:
-
Select Your Repository
- Choose GitHub as your Git source
- Select the repository containing your Healthchecks Dockerfile
- Choose the branch you want to deploy (usually
mainormaster)
-
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)
-
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.shfor Klutch.sh deployed databases, or your managed database host)DB_PORT: PostgreSQL port (use8000if connecting to a Klutch.sh deployed database with TCP traffic, or5432for 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 toFalsefor productionALLOWED_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 (typically587for TLS or465for SSL)EMAIL_USE_TLS: Set toTruefor TLS (most common)EMAIL_HOST_USER: Your SMTP usernameEMAIL_HOST_PASSWORD: Your SMTP passwordDEFAULT_FROM_EMAIL: The “from” email address (e.g.,healthchecks@yourdomain.com)
Optional Settings:
REGISTRATION_OPEN: Set toTrueto allow new user registrations, orFalseto restrict accessSUPERUSER_EMAIL: Admin email for initial superuser creationSUPERUSER_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.
-
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.
-
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)
-
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.
-
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.shYou should see the Healthchecks login page. If you configured
SUPERUSER_EMAILandSUPERUSER_PASSWORD, log in with those credentials. Otherwise, you can create an account ifREGISTRATION_OPENis set toTrue.
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
-
Log in to Healthchecks
Navigate to your Healthchecks instance (e.g.,
https://example-app.klutch.sh) and log in. -
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”
-
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:
# Your cron job0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123def > /dev/nullReport success or failure:
#!/bin/bash# Your backup script
# Run backup/usr/local/bin/backup.sh
# Ping Healthchecks with exit statusif [ $? -eq 0 ]; then curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123defelse curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123def/failfiSend job output:
#!/bin/bash# Run backup and capture outputOUTPUT=$(/usr/local/bin/backup.sh 2>&1)
# Send output to Healthcheckscurl -fsS -m 10 --retry 5 --data-raw "$OUTPUT" https://example-app.klutch.sh/ping/abc123defMonitoring HTTP Endpoints
Healthchecks can also monitor HTTP/HTTPS endpoints:
- Create a new check and select “HTTP” as the check type
- Enter the URL you want to monitor (e.g.,
https://myapi.com/health) - Set how often to check (e.g., every 5 minutes)
- Configure expected HTTP status code (default: 200)
- Optionally set keyword matching or response time thresholds
Setting Up Notifications
Configure notification channels to receive alerts when checks fail:
-
Go to Settings → Integrations
-
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.
-
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
| Variable | Description | Example |
|---|---|---|
DB_NAME | PostgreSQL database name | healthchecks |
DB_USER | PostgreSQL username | healthchecks |
DB_PASSWORD | PostgreSQL password | secure-password-here |
DB_HOST | PostgreSQL host | postgres-app.klutch.sh |
DB_PORT | PostgreSQL port | 8000 (for Klutch.sh TCP) or 5432 |
SECRET_KEY | Django secret key (50+ random characters) | abc123...xyz789 |
ALLOWED_HOSTS | Allowed hostnames (comma-separated) | example-app.klutch.sh,*.klutch.sh |
SITE_ROOT | Full URL to your instance | https://example-app.klutch.sh |
SITE_NAME | Friendly name for your instance | My Healthchecks |
Email Configuration (Recommended)
| Variable | Description | Example |
|---|---|---|
EMAIL_HOST | SMTP server hostname | smtp.gmail.com |
EMAIL_PORT | SMTP server port | 587 |
EMAIL_USE_TLS | Use TLS for SMTP | True |
EMAIL_HOST_USER | SMTP username | healthchecks@example.com |
EMAIL_HOST_PASSWORD | SMTP password | your-smtp-password |
DEFAULT_FROM_EMAIL | From email address | healthchecks@example.com |
Optional Settings
| Variable | Description | Default |
|---|---|---|
DEBUG | Enable debug mode (never use in production) | False |
REGISTRATION_OPEN | Allow new user registrations | True |
SUPERUSER_EMAIL | Initial admin email | None |
SUPERUSER_PASSWORD | Initial admin password | None |
Integration Variables (Optional)
| Variable | Description |
|---|---|
SLACK_CLIENT_ID | Slack OAuth client ID |
SLACK_CLIENT_SECRET | Slack OAuth client secret |
DISCORD_CLIENT_ID | Discord OAuth client ID |
DISCORD_CLIENT_SECRET | Discord OAuth client secret |
PUSHOVER_API_TOKEN | Pushover API token |
TELEGRAM_BOT_NAME | Telegram bot name |
TELEGRAM_TOKEN | Telegram bot token |
TWILIO_ACCOUNT | Twilio account SID |
TWILIO_AUTH | Twilio auth token |
TWILIO_FROM | Twilio 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=Falsein 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_dumpor 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:
# Backup PostgreSQL databasepg_dump -h postgres-app.klutch.sh -p 8000 -U healthchecks healthchecks > backup-$(date +%Y%m%d).sql
# Restore from backuppsql -h postgres-app.klutch.sh -p 8000 -U healthchecks healthchecks < backup-20240315.sqlMedia 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:
- Log in to Healthchecks
- Go to Settings → API Access
- Copy your API key (or create a new read-only key)
Common API Operations
List all checks:
curl https://example-app.klutch.sh/api/v1/checks/ \ -H "X-Api-Key: your-api-key-here"Create a check:
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:
curl https://example-app.klutch.sh/api/v1/checks/<check-uuid> \ -H "X-Api-Key: your-api-key-here"Update a check:
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:
# Pausecurl -X POST https://example-app.klutch.sh/api/v1/checks/<check-uuid>/pause \ -H "X-Api-Key: your-api-key-here"
# Unpausecurl -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:
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 requestsimport 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 checksresponse = requests.get(f"{API_URL}/checks/", headers=headers)checks = response.json()print(f"Total checks: {len(checks['checks'])}")
# Create a new checknew_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:
- Add your custom domain in the Klutch.sh dashboard (e.g.,
healthchecks.yourdomain.com) - Update your DNS records to point to Klutch.sh (follow instructions in the dashboard)
- Update environment variables:
Terminal window SITE_ROOT=https://healthchecks.yourdomain.comALLOWED_HOSTS=healthchecks.yourdomain.com,example-app.klutch.sh - Redeploy your application
Scaling Horizontally
For high-traffic deployments, you can scale Healthchecks horizontally:
- Increase the number of instances in Klutch.sh dashboard
- Ensure all instances share the same PostgreSQL database
- Use a load balancer (Klutch.sh provides this automatically)
- Ensure session storage is database-backed (Django default)
Customizing Branding
To customize the appearance of your Healthchecks instance:
- Create a custom logo and save it as
logo.png - Update your Dockerfile to copy custom assets:
COPY logo.png /app/static/img/logo.png
- Add custom CSS by creating a
custom.cssfile and mounting it - Rebuild and redeploy
Webhook Integration
Create a webhook integration to receive real-time notifications:
- Set up an endpoint to receive POST requests
- In Healthchecks, go to Settings → Integrations
- Add a Webhook integration
- Enter your endpoint URL
- 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_HOSTandDB_PORTare correct - For Klutch.sh deployed databases using TCP, use port 8000
- Test database connectivity using
psqlor 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
collectstaticran successfully during deployment - Check the
/app/staticdirectory 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
telnetoropenssl 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:
-
Update the Dockerfile:
# Change the git checkout line to the new versionRUN git clone https://github.com/healthchecks/healthchecks.git /app && \git checkout v3.4 -
Test Locally (recommended):
Terminal window docker build -t healthchecks-test .docker run -it healthchecks-test /bin/bash# Verify the new version installed correctly -
Commit and Push:
Terminal window git add Dockerfilegit commit -m "Upgrade Healthchecks to version 3.4"git push -
Deploy on Klutch.sh: Klutch.sh will automatically rebuild and redeploy your application. The entrypoint script will run database migrations automatically.
-
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
-
Rollback if Needed: If issues occur, revert the Dockerfile changes and redeploy:
Terminal window git revert HEADgit push
Use Cases and Examples
Monitoring Cron Jobs
Daily Database Backups:
#!/bin/bash# Start signalcurl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123/start
# Run backuppg_dump -h db.example.com -U postgres mydb > /backups/mydb-$(date +%Y%m%d).sql
# Signal completionif [ $? -eq 0 ]; then curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123else curl -fsS -m 10 --retry 5 https://example-app.klutch.sh/ping/abc123/failfiScheduled Data Processing:
import requestsimport 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:
#!/bin/bashCONTAINER_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_URLelse curl -fsS -m 10 --retry 5 $CHECK_URL/failfiMonitoring Web Services
Use Healthchecks’ HTTP monitoring to check your web services:
- Create a check with type “HTTP”
- Enter your service URL:
https://api.example.com/health - Set check interval: Every 5 minutes
- Configure expected status code: 200
- Optionally add keyword matching for response body
Additional Resources
- Klutch.sh Documentation
- Official Healthchecks Documentation
- Healthchecks GitHub Repository
- Klutch.sh Volumes Guide
- PostgreSQL Deployment on Klutch.sh
- Klutch.sh Networking Guide
- PostgreSQL Documentation
- Gunicorn Documentation
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.