no newsletter · no popup
Blog
Engineering notes, release announcements, and the occasional design rationale.
- posts
- 20
- latest
- 2026-11-05
- feed
- rss.xml →
-
#020 latest
Scheduling restic or borg backups with alerts when they fail: systemd timer, cron or borgmatic
Four ways to run restic or borg on a schedule and hear about it when a backup fails or never runs: a systemd timer with OnFailure=, cron with a Healthchecks ping, resticprofile and borgmatic. Tested with restic 0.18 and 0.19, including exit 3, stale locks and catch-up after downtime.
-
#019
Django periodic tasks without Celery or Redis: 5 Docker Compose setups
You need clearsessions every night and a report every 15 minutes, and every tutorial adds Celery, beat and Redis. Five setups without them, each with a Compose file: a management command plus supercronic, APScheduler (and why it runs 3 times under gunicorn), Huey on SQLite, django-q2 on your database, and RunWisp.
-
#018
Laravel scheduler in Docker: schedule:run with cron, schedule:work or Supervisor?
Four ways to run Laravel's scheduler in a container, tested on Laravel 12 and 13: which see your env vars, where the output goes, what docker stop does to a running task, and why schedule:run exits 0 when a task fails.
-
#017
Nitro scheduled tasks not running in production (Nuxt): 8 things to check
Your Nuxt scheduledTasks work in nuxi dev and do nothing in production. The experimental.tasks flag, serverless presets that drop tasks without a warning, hosts that stop the process, NODE_ENV=test, node-cluster running each task once per worker, and how to keep a record of runs.
-
#016
Bun.cron logs and Bun.cron not running: where the output goes and 8 things to check
Bun.cron has two forms that behave differently. The OS-level one writes to your crontab, runs from your home directory without your .env, and its output goes to cron's mail. Where the logs are on Linux and macOS, why a job didn't run, timezones, removal, and Bun.cron vs node-cron.
-
#015
node-cron runs multiple times in PM2 cluster mode (and @nestjs/schedule too): 7 fixes
Under pm2 -i 4, every node-cron or @nestjs/schedule job runs four times. Why, and seven ways to make it run once: the NODE_APP_INSTANCE guard, node-cron's distributed option, a fork-mode scheduler, Redis locks, BullMQ and more.
-
#014
Vercel Cron jobs not running on self-hosted Next.js (Docker, Coolify, VPS): 4 fixes
The crons in vercel.json do nothing outside Vercel, and nothing warns you. Four ways to run them on a self-hosted Next.js app, with the CRON_SECRET header, the instrumentation.ts double-run trap and Docker's HOSTNAME gotcha.
-
#013
Ubuntu 26.04 Rust coreutils (uutils) vs GNU: what changes for cron and shell scripts
Which uutils commands behave differently from GNU coreutils on Ubuntu 26.04 and 26.10, tested on 567 commands: mkdir locks, mv and mtime, timeout, date and DST, df, chown. How to check which you have and how to use GNU instead.
-
#012
Debian cron vs cronie vs BusyBox crond: CRON_TZ, /etc/cron.d, env vars and syntax compared
How cron differs on Ubuntu, Debian, Fedora, RHEL, Arch and Alpine: which crons support CRON_TZ, read /etc/cron.d, pass Docker env vars, handle a bad crontab line, and accept seconds, L, W and #. Tested on six distros.
-
#011
When does cron's @reboot run? Not when your container restarts
@reboot runs the first time cron starts after /run was emptied. On a server that's once per boot. In Docker it's once per container, so a restart, or a host reboot with a restart policy, skips it. We tested six crons.
-
#010
How to add a cron job from a script, without crontab -e
The usual one-liner adds the job twice when it runs twice, and a pipe that fails replaces your whole crontab with nothing. We tested it on four distros, plus the /etc/cron.d mistakes cron skips without telling you.
-
#009
Where are cron logs? And why your job's output isn't in them
Cron logs to the journal, /var/log/syslog, /var/log/cron or /var/log/messages, depending on the distro. We ran the same failing job on six of them. None logged its exit code, and two threw its output away.
-
#008
How to put a timeout on a cron job, and what it leaves running
timeout 20m in front of the command is the standard answer. We timed out the same five jobs with GNU, uutils and busybox timeout, systemd and RunWisp. Six of the seven setups left at least one process running.
-
#007
We counted 20,254 cron schedules. 63% start at :00.
Nearly two in three public cron schedules fire at minute zero, and one in five of those set to an hour ask for midnight UTC. What that costs, why sleep $RANDOM doesn't fix it, and what does.
-
#006
Cron job not running? Check these 11 things, in order
The script works when you run it by hand and does nothing from crontab. A checklist that starts with the one question that halves the search: did cron even try?
-
#005
How to stop a cron job from running twice at the same time
Cron starts the next run whether or not the last one finished. flock fixes that in one word, with three gotchas: the exit code, the lock file location, and child processes that keep the lock.
-
#004
How to get alerted when a cron job fails (and when it never runs)
MAILTO, a curl on failure, a heartbeat service, or a scheduler that alerts on its own. What each one catches, what it misses, and the two-layer setup that covers both.
-
#003
Your 02:30 cron job might run twice on October 25
Or not at all next March. We mapped every clock change in 418 time zones and tested six schedulers: which cron lines break, where, and a 30-second check for your own box.
-
#002
Docker Compose cron jobs with a web UI: 4 approaches
Four ways to schedule jobs in a docker-compose stack, why three of them fail silently, and how to get a dashboard that shows every run's exit code and output.
-
#001
Why one binary
RunWisp embeds SQLite, a web dashboard, and a TUI into a single static Go binary. Here's why, and what it costs.
Start in 30 seconds. Ship on your terms.
A single Go binary. If it doesn't earn the disk space, rm it. No account, no signup, no catch.
curl -fsSL https://get.runwisp.com | sh