Self-hosted service
alseambusher/crontab-ui avatar
alseambusher/crontab-ui

crontab-ui: a web interface for editing crontab without breaking it

Easy and safe way to manage your crontab file

3,287 stars500 forksJavaScriptMIT

At a glance

What is it?
crontab-ui is a Node.js web application that stores cron jobs in its own database and writes them to the crontab file, so a bad edit does not take down every job at once. It is aimed at people running many jobs on one machine who want backups and a UI instead of a text editor.
Who is it for?
crontab-ui fits anyone running a machine with dozens of cron jobs who wants a UI, per-job logs and backups, and who is willing to protect the port with BASIC_AUTH_USER or an nginx proxy. Skip it if you have a single job, or if you cannot accept that the app itself must stay running for the UI to work.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 62 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The failure mode crontab-ui was built around

Editing crontab in a text editor is a single-file operation with no undo. The README states the problem plainly: "A small mistake can easily bring down all the jobs." That is not an exaggeration. The crontab file is parsed as one unit, so a malformed line can invalidate entries you did not touch, and there is no staging step between your edit and the next scheduler reload. The project targets people who manage many jobs on one machine, where the cost of a mistake scales with the number of entries. Its stated features are import from an existing crontab, safe adding, deleting and pausing, backups, export to other machines, error logs, and mailing and hooks. A single job on a laptop does not need any of this. Fifty jobs on a shared box does.

How the job data actually flows

crontab-ui is an Express application (app.js, routes.js, views/ with EJS templates) backed by an embedded database, @seald-io/nedb, rather than by the crontab file directly. Jobs live in that database; the crontab file is written from it. That separation is what makes the safety claim possible: you edit a record, the application renders the file, and a backup is created before an import replaces data. The README notes that a backup is created automatically before importing. Scheduling metadata is handled by cron-parser and cronstrue, which turn expressions into human-readable descriptions in the UI. Mailing uses nodemailer, and the package defines two binaries, crontab-ui and crontab-ui-mailer, so the mailer runs as a separate process. In the Docker image the process model is explicit: supervisord.conf is the CMD, with tini as the entrypoint, which means the container supervises more than one process. The database, backups and logs default to the installation directory, which is why the README recommends overriding CRON_DB_PATH: an npm update can replace the directory the data sits in.

Install crontab-ui and add your first job

The README requires current Node and states the engines field as node >=20.0.0. Install globally from npm and start it, pointing the data directory somewhere outside the package, which is the setting the README recommends overriding.

bash
npm install -g crontab-ui
CRON_DB_PATH=/path/to/folder crontab-ui

The server starts and you open the web interface, where jobs are listed. If you already have entries in the system crontab, the import screen reads them in; the README describes this as importing from the existing crontab automatically. To change the listening address, port or base path, set the environment variables before starting:

bash
HOST=0.0.0.0 PORT=9000 BASE_URL=/alse crontab-ui

If the instance is reachable from anywhere but localhost, add HTTP basic authentication. There is no other login mechanism in the README, and no default password is documented.

bash
BASIC_AUTH_USER=user BASIC_AUTH_PWD=SecretPassword crontab-ui

By default the application keeps its own copy of the jobs and you push changes to the crontab yourself. To write changes through to crontab immediately, start with autosave enabled:

bash
crontab-ui --autosave

The same behaviour is available as the ENABLE_AUTOSAVE environment variable, which is the form you need in a container. The README lists the supported variables as HOST, PORT, BASE_URL, CRON_DB_PATH, CRON_PATH, BASIC_AUTH_USER, BASIC_AUTH_PWD, SSL_CERT, SSL_KEY and ENABLE_AUTOSAVE.

Docker and docker compose, including the host crontab mount

The published image is alseambusher/crontab-ui, and the Dockerfile sets HOST=0.0.0.0, PORT=8000 and CRON_PATH=/etc/crontabs, so the container reads and writes a crontab file inside its own filesystem unless you mount one in. The simplest run is a single published port:

bash
docker run -d -p 8000:8000 alseambusher/crontab-ui

Authentication in Docker goes through the same variables as the npm install:

bash
docker run -e BASIC_AUTH_USER=user -e BASIC_AUTH_PWD=SecretPassword -d -p 8000:8000 alseambusher/crontab-ui

To keep the database and logs across container replacement, mount a directory at /crontab-ui/crontabs. The repository's docker-compose.yml does this with a named volume and a healthcheck against http://localhost:8000/ every 30 seconds:

yaml
services:
  crontab-ui:
    build: .
    image: alseambusher/crontab-ui
    ports:
      - "8000:8000"
    volumes:
      - crontab-data:/crontab-ui/crontabs

The part worth reading twice is the host crontab case. The README shows mounting the host's cron directory over the container's CRON_PATH, with the note that on Ubuntu this can look like /etc/cron.d and that /etc/cron.d/root is used:

bash
docker run -d -p 8000:8000 -v /etc/cron.d:/etc/crontabs alseambusher/crontab-ui

That is a real bind mount of a system directory into a web application. If the container is compromised, or if the port is exposed without BASIC_AUTH_USER, the attacker is editing a root-owned cron directory. Treat the mount and the authentication setting as one decision, not two.

Where crontab-ui is the wrong tool

The application is the thing that writes your crontab, so it has to be running when you want to make a change, and the database is the source of truth for jobs you created through it. If the process is down, the UI is unavailable, even though the jobs themselves keep firing because cron reads the file, not the app. The README does not document rollback of an autosaved change beyond the backup feature, and it does not describe what happens if the database and the crontab file diverge, for example after a manual edit on the command line. If you edit crontab by hand while the app is running, you are working outside the model the project is built on. Security is another boundary: the only authentication in the README is HTTP basic auth, and the project also depends on helmet and express-rate-limit, but there is no user model, no roles and no audit trail described. For a fleet of machines, a scheduler that runs jobs on its own workers and keeps state in a real database is a better fit than a per-host file editor. For one or two jobs, cron and an editor are fine.

Alternatives and how they differ in approach

The closest comparison in the search data is Crontab guru, which is a different kind of tool entirely: it parses and explains a cron expression, and it does not touch your machine or your crontab file. Use it to check an expression before you paste it into crontab-ui. Beyond that, the meaningful split is between file-based and daemon-based scheduling. crontab-ui stays on the system cron: it manages the crontab file, and the jobs run under the system scheduler, so behaviour matches whatever cron on that host does. A daemon-based scheduler (systemd timers, or a job runner with its own worker pool) replaces cron rather than editing it, which gives you dependency handling, retries and central state, at the cost of a new runtime to operate and a different mental model for logs. crontab-ui's answer to logs is per-job error logs and the crontab-ui-mailer binary for mailing after execution, which is a thin layer over cron's output rather than a job history with status codes. If you need to know whether a job succeeded, not just what it printed, the file-editing approach is the limiting factor.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-07-31. The most recent release listed is v0.4.2 from 2026-04-20, with v0.4.1 and v0.4.0 a day earlier. The Makefile shows the release process: it rewrites the version in package.json, runs npm publish, then builds and pushes multi-arch images for linux/amd64 and linux/arm64 tagged both latest and the version number. That means an image tag follows the npm version, and latest moves. Pinning a version tag is the only way to make an upgrade deliberate. The upgrade cost is mostly about where your data lives: because the default database, backup and log location is the installation directory, a global npm update can put your jobs somewhere you did not expect. CRON_DB_PATH avoids that, and the README calls overriding it recommended for exactly this reason. The project is MIT licensed, which permits commercial use and modification; the README links to LICENSE.md and the package.json declares "license": "MIT". That is a description of the licence, not legal advice. If you fork it, note that the Makefile's release target publishes to npm and pushes to Docker Hub under the upstream image name.

Editorial conclusion

crontab-ui fits anyone running a machine with dozens of cron jobs who wants a UI, per-job logs and backups, and who is willing to protect the port with BASIC_AUTH_USER or an nginx proxy. Skip it if you have a single job, or if you cannot accept that the app itself must stay running for the UI to work. Before adopting it, verify the CRON_DB_PATH setting, confirm which crontab file CRON_PATH points at on your distribution, and check whether --autosave or ENABLE_AUTOSAVE matches how you want changes written.

Frequently asked questions

Is cron outdated?

The README does not address that question. It treats cron as the scheduler it manages: crontab-ui edits the crontab file and the jobs run under the system cron, so the project assumes cron is still in use rather than replacing it.

What is the purpose of crontab?

The crontab file is the list of scheduled jobs that cron runs. crontab-ui manages that file through a web interface, because the README argues that editing the plain text crontab is error prone for adding, deleting or pausing jobs.

What does * mean in cronjob?

The README does not explain cron expression syntax. crontab-ui depends on cron-parser and cronstrue, which turn expressions into human-readable descriptions in the interface, so the meaning is shown in the UI rather than documented in the README.

How do I run a cron job every 10 minutes?

The README does not give an expression for a ten-minute interval. In crontab-ui you add the job through the web interface and the expression is described back to you by cronstrue, so you can confirm the schedule before saving it.

Official sources

  1. alseambusher/crontab-ui on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alseambusher-crontab-ui.svg)](https://hysenlabs.com/projects/alseambusher-crontab-ui)