Cu
Developer Tools Azure

Crontab UI on Ubuntu 24.04 on Azure User Guide

| Product: Crontab UI on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Crontab UI on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Crontab UI is an open source web interface for managing cron jobs. Instead of hand editing crontab text over SSH, you create, edit, pause, resume, run, import, export, back up and restore scheduled jobs from a browser, with a clear view of every job's schedule and command.

The image installs the latest stable Crontab UI release from the npm registry and pins the exact version (recorded in /opt/crontab-ui/VERSION). Crontab UI runs on Node.js 22 LTS under systemd as the dedicated unprivileged crontabui system user and binds to loopback only (127.0.0.1:8000). nginx is the sole network facing surface and terminates TLS on port 443, reverse proxying to Crontab UI. Port 80 redirects to HTTPS.

Secure by default. Crontab UI ships upstream with no authentication at all, which would let anyone who can reach it schedule or run arbitrary commands on your server. This image turns authentication on and generates a unique administrator credential on each virtual machine's first boot, written to a root only file. There are no shared or default credentials, nothing is baked into the image, and the service refuses to start without a credential, so the open no authentication mode can never ship.

Least privilege. Crontab UI manages the crontab of the dedicated crontabui service account rather than root's, so your scheduled jobs run without root privileges. Saving a job in the interface writes it straight to that real crontab (autosave is on).

What is included:

  • The latest stable Crontab UI release, installed from npm on Node.js 22 LTS and run under systemd as the unprivileged crontabui system user

  • Crontab UI bound to loopback only (127.0.0.1:8000); it is never network exposed directly

  • nginx terminating TLS on :443 and reverse proxying to Crontab UI, with HSTS and sensible security headers

  • Port :80 returns a 301 redirect to HTTPS for every path except an unauthenticated /healthz endpoint (HTTP 200) for load balancer probes

  • Authentication on by default with a unique admin credential generated per VM on first boot, written to a root only file

  • The system cron daemon installed and enabled, so scheduled jobs actually run

  • A self signed TLS certificate regenerated per VM on first boot (its Subject Alternative Names include the VM IP, hostname and 127.0.0.1); replace it with your own CA signed certificate for production

  • A built in self test at /usr/local/bin/crontab-ui-selftest that proves the create a job to written to the managed crontab round trip end to end over TLS

  • Ubuntu 24.04 LTS base with the latest security patches applied at build time

  • Azure Linux Agent for seamless cloud integration and SSH key injection

  • 24/7 cloudimg support with a guaranteed 24 hour response SLA

Prerequisites

  • An Azure subscription with permission to deploy virtual machines

  • An SSH key pair for administrative access to the VM as the azureuser account

  • A Network Security Group allowing inbound TCP 443 (HTTPS) and 80 (redirect) from the networks that should reach the service, and 22 (SSH) from your management network only

  • A recommended size of Standard_B2s or larger

Step 1: Deploy from the Azure Portal

  1. Locate the Crontab UI on Ubuntu 24.04 LTS image in the Azure Marketplace and select Create.

  2. Choose your subscription, resource group and region.

  3. Select a VM size (Standard_B2s or larger) and provide your SSH public key for the azureuser account.

  4. On the Networking tab, allow inbound 443 and 80 from your users, and restrict 22 to your management network.

  5. Review and create. When the VM is running, browse to https://<your-public-ip>/.

Step 2: Deploy from the Azure CLI

Deploy the image from the command line, restricting SSH to your management network. Replace the placeholder values with your own before running:

az vm create \
  --resource-group my-resource-group \
  --name crontab-ui \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard

# Allow the web UI from your users and SSH from your management network only
az vm open-port --resource-group my-resource-group --name crontab-ui --port 443 --priority 1001
az network nsg rule create --resource-group my-resource-group --nsg-name crontab-uiNSG \
  --name allow-ssh --priority 1002 --destination-port-ranges 22 \
  --source-address-prefixes <your-mgmt-cidr> --access Allow --protocol Tcp

When the VM is running, browse to https://<public-ip>/.

Step 3: Retrieve your per instance admin credential

Authentication is on by default. Each VM generates its own admin username and password on first boot, written to a root only file. Read it over SSH:

ssh azureuser@<vm-ip> 'sudo cat /root/crontab-ui-credentials.txt'

The file contains the CRONTAB_UI_USER, CRONTAB_UI_PASS and CRONTAB_UI_URL for this specific VM. Keep it secret. The credential lives only in this root only file and in the service environment file, never baked into the image.

Step 4: Sign in to the web interface

Browse to https://<vm-ip>/. Because the certificate is self signed per VM, your browser will show a certificate warning the first time; accept it to proceed (or install the per VM certificate, or place a CA signed certificate in front, as covered in Step 10). Sign in with the username and password from Step 3.

Crontab UI presents the Cronjobs dashboard: a table of every scheduled job with its name, command, schedule and last modified time, plus a toolbar for creating jobs, backing up, importing, exporting, and writing the jobs to the real crontab.

The Crontab UI Cronjobs dashboard after signing in, showing four scheduled jobs (nightly database backup, rotate application logs, site health check and purge old temp files) with their commands and cron schedules, and the toolbar with New, Backup, Import, Export and Save to crontab buttons

Step 5: Create a cron job

Click New to open the job form. Give the job an optional name, enter the command to run, and set the schedule either with a quick preset (Every Minute, Hourly, Daily, Weekly and so on) or by entering the minute, hour, day, month and week of month fields directly. The Job preview at the bottom shows the exact crontab line that will be written.

The Crontab UI new job form with a name of Nightly database backup, a command of /usr/local/bin/pg_backup.sh --all, the schedule fields set to minute 0 hour 2, and quick schedule preset buttons for Every Minute, Hourly, Daily and Weekly

Because autosave is enabled on this image, saving a job writes it straight to the crontabui user's real crontab. You do not need to click Save to crontab manually, though the button is there if you prefer to apply a batch of changes at once.

Step 6: Edit, run, pause and manage jobs

Each row in the dashboard has controls to Edit the job, Run now (run it immediately, on demand), Disable (pause it without deleting it), Duplicate, and delete. Clicking Edit reopens the same form pre filled with the job's current name, command and schedule.

The Crontab UI edit job form pre filled for the Nightly database backup job, showing the command, the schedule fields set to minute 0 hour 2, the resulting 0 2 star star star crontab line in the Job preview, and Enable error logging ticked

With Enable error logging ticked, Crontab UI captures each run's standard output and error to per job log files, viewable from the dashboard, which makes it easy to see why a job failed.

Step 7: Preview what reaches the real crontab

Click Preview crontab at any time to see exactly what Crontab UI will deploy to the system crontab, including the logging wrappers it adds around each command. This is the real crontab content for the crontabui service account.

The Crontab UI Crontab Preview modal showing the rendered crontab lines for the four jobs, each beginning with its schedule such as 0 2 star star star and 30 4 star star 0, with the logging redirection wrappers Crontab UI adds

You can confirm the same content from the shell. On the VM, list the crontabui user's real crontab:

sudo crontab -u crontabui -l 2>/dev/null | head -20 || echo "(no jobs scheduled yet — add one in the web UI)"

Step 8: Verify the deployment

SSH to the VM as azureuser and confirm the services are running and Crontab UI is bound to loopback only:

systemctl is-active crontab-ui nginx cron
sudo ss -tlnp | grep -E ':8000|:443 |:80 ' | sed 's/users:.*//'

All three services report active, and Crontab UI listens on 127.0.0.1:8000 only. nginx is the only component exposed on :80 and :443.

systemctl reports crontab-ui, nginx and cron all active, and ss shows crontab-ui bound to 127.0.0.1:8000 loopback only with nginx listening on 0.0.0.0:80 and 0.0.0.0:443

Run the built in self test. It reads this VM's credential and proves the full round trip over TLS: an unauthenticated request is refused, an authenticated request succeeds, and a cron job is created through the API, written to the crontabui user's real crontab, then removed:

sudo /usr/local/bin/crontab-ui-selftest

The crontab-ui-selftest output reporting OK: unauthenticated request returned 401, authenticated request returned 200, and a job was created, written to crontabui's crontab and removed over TLS

Step 9: TLS and the per instance certificate

nginx terminates TLS on port 443 and redirects plain HTTP on port 80 to HTTPS. Confirm the redirect, that an unauthenticated request is refused, and that a request carrying this VM's credential succeeds:

curl -s -o /dev/null -w 'port 80 -> HTTP %{http_code}\n' http://127.0.0.1/
curl -sk -o /dev/null -w 'unauthenticated -> HTTP %{http_code}\n' https://127.0.0.1/
U=$(sudo grep '^CRONTAB_UI_USER=' /root/crontab-ui-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^CRONTAB_UI_PASS=' /root/crontab-ui-credentials.txt | cut -d= -f2-)
curl -sk -o /dev/null -w 'authenticated -> HTTP %{http_code}\n' -u "$U:$P" https://127.0.0.1/

Port 80 returns 301, an unauthenticated request returns 401, and a request with this VM's credential returns 200. The self signed certificate is regenerated per VM on first boot, with the VM IP and hostname in its Subject Alternative Names:

curl shows port 80 returning a 301 redirect, an unauthenticated request returning 401 and an authenticated request returning 200, and openssl printing the per VM self signed certificate subject and Subject Alternative Names

Step 10: Version and the credential note

The baked version and this VM's credential summary are recorded on the VM. The password line is redacted below; read the full value from the root only file in Step 3:

cat /opt/crontab-ui/VERSION
sudo sed 's/^CRONTAB_UI_PASS=.*/CRONTAB_UI_PASS=<redacted per-VM secret>/' /root/crontab-ui-credentials.txt | grep -E '^CRONTAB_UI_'

The /opt/crontab-ui/VERSION file showing the baked Crontab UI and Node.js versions, and the per VM crontab-ui-credentials.txt showing the admin username and URL with the password redacted

Step 11: Replace the certificate for production

The per VM certificate is self signed, so browsers warn on first use. For a public deployment, put a real certificate in front. The simplest path is to point a DNS name at the VM and obtain a free certificate with Certbot:

# Point https://<your-domain> at this VM first, then:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>

Alternatively, terminate TLS at an Azure Application Gateway or a load balancer in front of the VM and forward to port 443.

Step 12: Back up, restore and change the managed user

  • Back up and restore. Use the Backup button in the toolbar to snapshot your jobs, and the Backups menu to restore a previous snapshot, so a mistaken edit is never final. Export downloads the job database and Import uploads it, which is handy for moving jobs between servers.

  • Import an existing crontab. If you already have jobs in the crontabui user's crontab, Get from crontab imports them into the interface.

  • Change the managed crontab. By default Crontab UI manages the crontab of the unprivileged crontabui service account. This is the least privilege default. The service definition is at /etc/systemd/system/crontab-ui.service and its environment (bind address, autosave, database path and the per VM credential) is in /etc/crontab-ui/crontab-ui.env.

  • Rotate the credential by editing BASIC_AUTH_USER and BASIC_AUTH_PWD in /etc/crontab-ui/crontab-ui.env and restarting the service, or by placing your own identity aware proxy in front.

Security notes

  • No default login. Authentication is on by default and a unique admin credential is generated on each VM's first boot into a root only file and the service environment file. The service refuses to start without one.

  • Loopback only application. Crontab UI binds to 127.0.0.1:8000 and is only reachable through the nginx TLS reverse proxy on :443. Keep it that way and let nginx (or a load balancer) be the sole network facing surface.

  • Least privilege scheduling. Jobs are managed in the crontab of the unprivileged crontabui account, not root's. A cron management tool grants command execution to anyone who signs in, so treat the credential as highly sensitive and restrict who can reach the service.

  • Restrict access. Allow 443 only from the networks that need it, keep 22 restricted to your management network, and replace the self signed certificate with a CA signed one for production.

  • HTTPS is load bearing. A cron management interface over plaintext HTTP would expose the login credentials and let anyone schedule commands. Always reach it over TLS.

Support

This image is backed by 24/7 cloudimg support with a guaranteed 24 hour response SLA. Contact support@cloudimg.co.uk for assistance. Crontab UI is open source software distributed under the MIT License and is free; the cloudimg charge covers packaging, hardening, security patching, image maintenance and support.