[{"data":1,"prerenderedAt":185},["ShallowReactive",2],{"seo-verification":3,"blog-self-host-healthchecks-cron-monitoring-vps-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-self-host-healthchecks-cron-monitoring-vps-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":119,"ctaBody":120,"ctaButton":121,"ctaUrl":122,"relatedPosts":123},504,"self-host-healthchecks-cron-monitoring-vps",{"fr":12,"en":10,"ar":13,"es":14},"self-host-healthchecks-vps","استضافة-healthchecks-على-vps-مراقبة-مهام-cron","autoalojar-healthchecks-monitorizar-cron-vps","Self-Host Healthchecks: Cron Job Monitoring on a VPS","Install Healthchecks on a VPS: every cron job, backup or scheduled task sends a ping, and you are alerted as soon as one is missing, fails or runs too long.",6,0,false,"2026-10-24T00:00:00+00:00","2026-10-24T23:28:56+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},7,"Self-hosting","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fself-host-healthchecks-vps-poster.svg",{"categorySlug":34,"appSlug":35},"monitoring-observability","healthchecks","A cron job that stops running makes no noise. The nightly backup fails, log cleanup stops, a supplier sync breaks — and nothing warns you, because nothing runs. Healthchecks is an open-source (BSD-3 licensed) tool that flips the problem around: each job sends a ping when it finishes, and Healthchecks alerts you when that ping does not arrive. This guide installs it as a single Docker container on a VPS, puts it behind an HTTPS reverse proxy and wires up a first cron job.",[38,42,52,84,87,103,107,110,113,116],{"type":39,"title":40,"body":41},"h2","Why monitor what must run, not just what responds","An uptime monitor checks that a service responds. It cannot see what happens between two requests: the 3 a.m. backup, invoice sending, a certificate renewal, the export to your accountant. These jobs fail silently — a full disk, an expired password, a server rebooted without its timer — and you notice on the day you need them.\n\nCron's `MAILTO` variable barely helps: it only sends a message if the job runs and writes to its output, and says nothing when the job never starts. Healthchecks starts from absence: every job has an expected schedule, and silence beyond the grace time triggers the alert.",{"type":43,"title":44,"items":45},"ul","What Healthchecks brings",[46,47,48,49,50,51],"**Ping-based monitoring** — each job calls a unique URL; a missing ping triggers the alert.","**Cron or period schedules** — a cron expression with time zone, or a simple interval, plus a grace time.","**Run duration** — `\u002Fstart` and `\u002Ffail` pings measure duration and report explicit failures.","**Exit codes and logs** — the exit code and the tail of the command output, viewable in the dashboard.","**More than twenty integrations** — email, webhook, Slack, Discord, Matrix, ntfy, Telegram, Gotify, PagerDuty, Opsgenie…","**Team and API** — separate projects, invited members, status badges and a REST API to create checks from your scripts.",{"type":53,"title":54,"headers":55,"rows":59},"comparison","Healthchecks compared with common approaches",[5,56,57,58],"Healthchecks","Cron MAILTO","Uptime monitor",[60,64,68,71,75,80],[61,62,63,63],"Alert if the job never starts","Yes","No",[65,66,67,63],"Alert if the job fails","Yes, exit code or \u002Ffail","Only if it writes output",[69,70,63,63],"Run duration","Measured",[72,73,62,74],"Machines with no open port","Yes, a simple outbound HTTPS call","No, the target must be reachable",[76,77,78,79],"Alert channels","More than twenty integrations","Local email","Depends on the tool",[81,82,63,83],"Central history","Yes, per check","Yes, for services",{"type":39,"title":85,"body":86},"Prerequisites","An Ubuntu 24.04 VPS with **1 GB of RAM** is enough: Healthchecks runs as a single container and stores its data in an SQLite database. You need Docker with the Compose plugin, and a **domain name** pointing to the VPS, with nginx and an HTTPS certificate: ping URLs and alert links are built on that address, and the application rejects requests sent to another name.\n\nIdeally, install Healthchecks on a machine **separate** from the servers it watches: if it goes down with them, nobody will warn you.",{"type":88,"title":89,"steps":90},"steps","Install Healthchecks with Docker Compose",[91,94,97,100],{"title":92,"body":93},"Prepare the .env file","Create the application directory and a `.env` file holding the secret key and the public address. Replace `hc.example.com` with your domain.\n```bash\nmkdir -p \u002Fopt\u002Fhealthchecks && cd \u002Fopt\u002Fhealthchecks\ncat > .env \u003C\u003CEOF\nSECRET_KEY=$(openssl rand -hex 24)\nSITE_ROOT=https:\u002F\u002Fhc.example.com\nEOF\n```",{"title":95,"body":96},"Create the Compose file","Put this `docker-compose.yml` in the same directory. The port is published on the loopback only, public sign-up is closed and the SQLite database lives in a volume.\n```yaml\nservices:\n  healthchecks:\n    image: healthchecks\u002Fhealthchecks:v5.0.1\n    restart: unless-stopped\n    ports:\n      - \"127.0.0.1:8102:8000\"\n    env_file: .env\n    environment:\n      DEBUG: \"False\"\n      DB_NAME: \u002Fdata\u002Fhc.sqlite\n      REGISTRATION_OPEN: \"False\"\n      GUNICORN_WORKERS: \"2\"\n    volumes:\n      - healthchecks-data:\u002Fdata\nvolumes:\n  healthchecks-data: {}\n```",{"title":98,"body":99},"Start and create the administrator account","On start, the container runs the migrations, then launches the web server and the alert-sending processes. Then create your account: the command asks for an email address and a password.\n```bash\ndocker compose up -d\ndocker compose exec healthchecks .\u002Fmanage.py createsuperuser\n```",{"title":101,"body":102},"Publish over HTTPS behind nginx","Add a `server` block for your domain, with a Let's Encrypt certificate, and forward the origin headers: without `X-Forwarded-Proto`, login fails with a CSRF error.\n```nginx\nlocation \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:8102;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n}\n```",{"type":104,"title":105,"body":106},"tip","Keep sign-up closed","By default, Healthchecks accepts public sign-ups. `REGISTRATION_OPEN: \"False\"` closes them: only the accounts you create or invite into a project can log in. On a server exposed to the Internet, set this from the very first start.",{"type":39,"title":108,"body":109},"Wire up your cron jobs","In the dashboard, create a check, enter the schedule — the job's cron expression and its time zone — then a grace time covering its normal duration. Copy the ping URL and append it to the job.\n```bash\n# crontab: backup at 3 a.m., ping only on success\n0 3 * * * \u002Fusr\u002Flocal\u002Fbin\u002Fbackup.sh && curl -fsS -m 10 --retry 5 -o \u002Fdev\u002Fnull https:\u002F\u002Fhc.example.com\u002Fping\u002F\u003Cuuid>\n\n# variant: signal the start, then send the exit code\nURL=https:\u002F\u002Fhc.example.com\u002Fping\u002F\u003Cuuid>\ncurl -fsS -m 10 --retry 5 -o \u002Fdev\u002Fnull \"$URL\u002Fstart\"\n\u002Fusr\u002Flocal\u002Fbin\u002Fbackup.sh > \u002Ftmp\u002Fbackup.log 2>&1\ncurl -fsS -m 10 --retry 5 -o \u002Fdev\u002Fnull --data-binary @\u002Ftmp\u002Fbackup.log \"$URL\u002F$?\"\n```\n\nThe first form pings only on success: a failure shows up as a missing ping, hence an alert after the grace time. The second is more telling: `\u002Fstart` measures the duration, the exit code sent in place of the ping reports failure immediately, and the output sent in the request body appears in the check's history. The `-m 10 --retry 5` options keep a flaky network from blocking the job or faking an outage.",{"type":39,"title":111,"body":112},"Receive the alerts","Under **Integrations**, add at least one channel you actually read, then attach it to your checks. Webhook, Slack (incoming webhook), Mattermost, ntfy and Gotify work without any server-side configuration. Other integrations need credentials declared in `.env`: a bot token for Telegram, an account and token for Matrix, an OAuth app for Discord.\n\n**Email** alerts go through an SMTP server: add `EMAIL_HOST`, `EMAIL_PORT`, `EMAIL_HOST_USER`, `EMAIL_HOST_PASSWORD` and `DEFAULT_FROM_EMAIL` to `.env`, then restart with `docker compose up -d`. The same settings serve team invitations and periodic reports.",{"type":39,"title":114,"body":115},"Troubleshooting","**The page returns a 400 error.** The request does not arrive with the right host name: check that `SITE_ROOT` exactly matches the domain served by nginx, and that the `location` block forwards the `Host` header.\n\n**Login fails with a CSRF error.** nginx does not forward `X-Forwarded-Proto`: the application thinks it receives HTTP while the browser speaks HTTPS. Add the header and reload nginx.\n\n**A check goes into alert although the job ran.** The ping did not leave: run the `curl` command by hand from the machine concerned, check outbound HTTPS access, and lengthen the grace time if the job lasts longer than expected.\n\n**No email arrives.** Without `EMAIL_HOST`, Healthchecks sends nothing and says so in its logs at start-up: check `docker compose logs healthchecks`.",{"type":39,"title":117,"body":118},"One-click install from the ServOrbit Marketplace","The ServOrbit Marketplace installs Healthchecks on your VPS without a command line: it deploys the container with sign-up closed, creates the administrator account with a generated password, and publishes the application over HTTPS on a subdomain of your domain or on the VPS's free subdomain. The login and password appear in your client area; all that is left is to create your checks.","Your scheduled jobs under watch, on your own VPS","A ServOrbit Ubuntu 24.04 VPS with 1 GB of RAM is enough for Healthchecks. One-click install from the Marketplace, HTTPS on your domain or on the VPS's free subdomain, administrator account created for you.","Install Healthchecks","\u002Fmarketplace\u002Fmonitoring-observability\u002Fhealthchecks",[124,145,168],{"id":125,"slug":126,"slugs":127,"title":131,"excerpt":132,"readTime":133,"views":134,"isPinned":19,"publishedAt":135,"updatedAt":136,"category":137,"categories":142,"featuredImage":30,"bgImage":31,"posterImage":144,"relatedSolution":30},230,"cron-vs-systemd-timers-automate-your-linux-vps",{"fr":128,"en":126,"ar":129,"es":130},"cron-systemd-timers-automatisation-vps","cron-مقابل-systemd-timers-أتمتة-vps-linux","cron-vs-systemd-timers-automatizar-vps-linux","cron vs systemd timers: Automate Your Linux VPS","Practical comparison of cron and systemd timers: syntax, logs, migration and troubleshooting for recurring tasks on a Linux VPS.",12,1,"2026-08-06T00:00:00+00:00","2026-09-20T21:13:53+00:00",{"id":138,"name":139,"slug":140,"color":141,"icon":140},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[143],{"id":138,"name":139,"slug":140,"color":141,"icon":140},"\u002Fblog\u002Fcovers\u002Fcron-systemd-timers-automatisation-vps-poster.svg",{"id":146,"slug":147,"slugs":148,"title":152,"excerpt":153,"readTime":154,"views":138,"isPinned":19,"publishedAt":155,"updatedAt":156,"category":157,"categories":163,"featuredImage":30,"bgImage":31,"posterImage":165,"relatedSolution":166},194,"self-host-ntfy-on-a-vps-push-notifications-for-scripts-and-cicd",{"fr":149,"en":147,"ar":150,"es":151},"self-host-ntfy-vps","استضافة-ntfy-على-vps-إشعارات-فورية-من-سكريبتاتك-وcicd","autoalojar-ntfy-en-un-vps","Self-host ntfy on a VPS: push notifications for scripts and CI\u002FCD","Deploy ntfy on your VPS and send push notifications from any script, cron job or CI\u002FCD pipeline with a plain curl — no SaaS, no API key, no subscription.",11,"2026-07-28T00:00:00+00:00","2026-10-13T14:10:29+00:00",{"id":158,"name":159,"slug":160,"color":161,"icon":162},8,"Security & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[164],{"id":158,"name":159,"slug":160,"color":161,"icon":162},"\u002Fblog\u002Fcovers\u002Fself-host-ntfy-vps-poster.svg",{"categorySlug":34,"appSlug":167},"ntfy",{"id":169,"slug":170,"slugs":171,"title":175,"excerpt":176,"readTime":158,"views":18,"isPinned":19,"publishedAt":177,"updatedAt":178,"category":179,"categories":180,"featuredImage":30,"bgImage":31,"posterImage":182,"relatedSolution":183},105,"monitoring-your-vps-with-uptime-kuma",{"fr":172,"en":170,"ar":173,"es":174},"superviser-vps-uptime-kuma","مراقبة-خادمك-الافتراضي-vps-باستخدام-uptime-kuma","supervisar-vps-con-uptime-kuma","Monitoring your VPS with Uptime Kuma","Deploy Uptime Kuma on your VPS to monitor your sites and services self-hosted, with alerts and a public status page.","2026-03-07T00:00:00+00:00","2026-10-23T23:43:01+00:00",{"id":158,"name":159,"slug":160,"color":161,"icon":162},[181],{"id":158,"name":159,"slug":160,"color":161,"icon":162},"\u002Fblog\u002Fcovers\u002Fsuperviser-vps-uptime-kuma-poster.svg",{"categorySlug":34,"appSlug":184},"uptime-kuma",1792885024775]