If you have ever managed a home server, self-hosted infrastructure, Docker containers, or small automation workloads, you have probably reached for cron.
Cron is excellent. It is simple, mature, and available almost everywhere. But as soon as scheduled jobs start growing in number, managing them through scattered crontab entries becomes less convenient.
You may want to:
- See all scheduled jobs from one place.
- Enable or disable jobs without editing a crontab.
- Run a job manually.
- Retry failed HTTP requests.
- Inspect the output of previous executions.
- Manage schedules through an API.
- Run everything inside a small Docker container.
- Avoid installing a full application runtime just to execute HTTP requests.
This is the problem Cronix is designed to solve.
Cronix is a lightweight, cron-style scheduler for HTTP jobs that runs inside Docker. Jobs can be managed through a CLI, REST API, or web interface, while their configuration and execution history are persisted as JSON files. The project is written in Go, with a small React/Vite frontend embedded directly into the Go binary. (GitHub)
What Is Cronix?
At its core, Cronix is a scheduler.
You define a job with:
- A name
- A cron schedule
- A
curlcommand - Optional retries
- A retry delay
- An enabled/disabled state
For example:
{
"name": "healthcheck",
"schedule": "*/5 * * * *",
"curl": "curl -s https://example.com/health",
"retries": 2,
"retry_delay": 10,
"enabled": true
}
Cronix evaluates the schedule and executes the configured HTTP request at the appropriate time.
Unlike traditional cron, however, Cronix provides a management layer around those jobs.
You can create and manage jobs using:
- Web UI
- CLI
- REST API
The scheduler itself runs as a Docker container, making it particularly convenient for self-hosted environments. (GitHub)
Why Build Another Cron Scheduler?
Linux already has cron. Docker also has several cron-compatible solutions.
So why build Cronix?
The answer is not that traditional cron is bad.
It is that cron is intentionally minimal.
A traditional crontab might look like:
*/5 * * * * curl -s https://example.com/health
0 2 * * * curl -s https://example.com/backup
30 9 * * 1 curl -s https://example.com/report
This works perfectly.
But managing these jobs becomes less pleasant when you need to:
- Temporarily disable one job.
- Run a job immediately.
- See when a job last succeeded.
- Keep execution history.
- Retry failed requests.
- Expose scheduling through an API.
- Give yourself a small dashboard.
Cronix adds those capabilities while deliberately keeping the execution model small.
The Design Philosophy
One of the most interesting aspects of Cronix is its deliberately constrained execution model.
A Cronix job is fundamentally an HTTP request executed through curl.
The project does not attempt to become a general-purpose shell job runner.
The container contains essentially three important runtime components:
Cronix binary
Static curl binary
CA certificate bundle
The runtime image is built on scratch, keeping the final container extremely small and avoiding unnecessary operating-system packages or runtime dependencies. (GitHub)
This makes Cronix a particularly interesting example of a single-purpose containerized application.
Architecture
At a high level, Cronix looks like this:
┌─────────────────────┐
│ Web Browser │
└──────────┬──────────┘
│
│ HTTP
▼
┌──────────────┐ ┌─────────────────────┐
│ CLI │─────►│ │
└──────────────┘ │ Cronix │
│ │
┌──────────────┐ │ ┌───────────────┐ │
│ REST API │─────►│ │ Scheduler │ │
└──────────────┘ │ └───────┬────────┘ │
│ │ │
│ ▼ │
│ Job Runner │
│ │ │
│ ▼ │
│ curl │
└──────────┬────────────┘
│
▼
External HTTP API
The repository separates the application into several areas.
cmd/
internal/
ui/
Dockerfile
Makefile
go.mod
README.md
The Go entrypoint lives under cmd/cronix, while the application implementation is organized under internal/. The frontend is located in ui/ and is built into the Go application using go:embed. (GitHub)
Two Operating Modes
Cronix essentially has two modes.
Server Mode
Running:
/cronix
starts the main server.
The server:
- Loads persisted jobs.
- Starts the scheduler.
- Starts the HTTP API.
- Serves the web interface.
The API token is required before the server starts. (GitHub)
CLI Mode
Running:
/cronix cli <command>
turns Cronix into an API client.
For Docker deployments, you can execute the CLI from the host using:
docker exec cronix /cronix cli ...
This is an elegant design because the same binary provides both the server and administrative interface.
There is no separate management application that needs to be installed.
Getting Started
The simplest way to run Cronix is with Docker.
First create a data directory:
mkdir -p /tmp/cronix-data
Then start the container:
docker run --rm -d \
--name cronix \
-e CRONIX_API_TOKEN=sekrit \
-e CRONIX_USERNAME=admin \
-e CRONIX_PASSWORD=admin \
-v /tmp/cronix-data:/data \
-p 8080:8080 \
cronix
After starting the container, open:
http://localhost:8080
The web UI can then be used to manage jobs. (GitHub)
For anything beyond a local test environment, change the default credentials and use a strong API token.
Docker Compose
For a real deployment, Docker Compose is generally more convenient.
A simple configuration could look like:
services:
cronix:
image: cronix
container_name: cronix
restart: unless-stopped
ports:
- "8080:8080"
environment:
CRONIX_API_TOKEN: change-this-to-a-long-random-token
CRONIX_USERNAME: admin
CRONIX_PASSWORD: change-this-password
TZ: Asia/Dhaka
volumes:
- ./data:/data
The important part is the /data volume.
Without persistent storage, jobs and run history would disappear when the container is recreated.
How Jobs Are Stored
Cronix intentionally uses JSON rather than a database.
By default:
/data/jobs.json
/data/runs.json
are used for job configuration and execution history respectively.
A job might look like:
{
"id": "3f8a1c2b0d4e",
"name": "ping",
"schedule": "* * * * *",
"curl": "curl -s https://example.com",
"retries": 0,
"retry_delay": 5,
"enabled": true
}
The JSON store has an important reliability characteristic.
Writes are performed using a temporary file followed by a rename.
Conceptually:
jobs.json
│
├── write temporary file
│
└── atomic rename
│
▼
jobs.json
This reduces the risk of leaving a partially written JSON file if the process crashes during a write. (GitHub)
For a lightweight scheduler that does not need thousands of concurrent job updates, this is a very practical trade-off.
Why JSON Instead of PostgreSQL or SQLite?
This is an important architectural decision.
A database would certainly provide more capabilities.
But Cronix is intentionally small.
If the application only needs to store:
jobs
+
run history
a JSON file can be enough.
This means the deployment does not require:
Cronix
PostgreSQL
Database migrations
Database credentials
Database backups
Connection pooling
Instead:
Cronix
│
└── /data
├── jobs.json
└── runs.json
For a small self-hosted scheduler, that simplicity is valuable.
Cron Expressions
Cronix uses standard five-field cron expressions:
minute hour day-of-month month day-of-week
For example:
* * * * *
means every minute.
Other examples:
*/5 * * * *
Every five minutes.
0 9 * * *
Every day at 09:00.
0 0 * * 1-5
Every weekday at midnight.
30 2 1 * *
At 02:30 on the first day of every month.
Cronix supports:
- Ranges
- Lists
- Steps
- Month names
- Weekday names
The scheduler evaluates these schedules using the container's configured timezone. (GitHub)
Timezones Matter
A common problem with containerized schedulers is timezone confusion.
Your host may be in Bangladesh:
Asia/Dhaka
while the container might effectively operate using another timezone.
Cronix provides the TZ environment variable for this purpose.
For example:
environment:
TZ: Asia/Dhaka
This is especially important for jobs such as:
Every day at 02:00
Every Monday at 09:00
Every month on the first day
Without explicitly considering the timezone, a perfectly valid cron expression can execute at an unexpected time.
The Interesting Part: Curl-Only Jobs
Cronix intentionally restricts jobs to commands beginning with:
curl
For example:
curl -s https://example.com
or:
curl -s \
-X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Alice"}' \
https://api.example.com/users
This restriction is deliberate.
Cronix does not provide a general-purpose shell.
There is no:
curl ... && something
There is no:
curl ... | grep ...
There is no:
curl ... > file.txt
There is no:
curl $MY_VARIABLE
The command is tokenized and executed directly rather than being passed through a shell. (GitHub)
Why Avoid a Shell?
This is one of the strongest design choices in the project.
A general shell executor introduces a much larger attack surface.
If arbitrary shell commands were allowed, a job definition could potentially contain:
rm -rf ...
or:
curl ... && malicious-command
or other shell features.
Instead, Cronix effectively follows:
Job definition
│
▼
Validate command starts with curl
│
▼
Parse arguments
│
▼
Execute curl directly
There is no shell expansion.
That means shell constructs such as pipes, redirects, globbing, command substitution, and environment-variable expansion are not available inside job definitions. (GitHub)
For an HTTP scheduler, this is a very sensible boundary.
HTTPS Support
The container includes a CA certificate bundle, and Cronix configures curl to use it.
That means normal HTTPS requests can perform certificate verification without requiring users to manually configure certificates inside the container. (GitHub)
For example:
curl -s https://api.example.com/health
works as expected with TLS certificate validation.
Retries
Network requests fail.
DNS can fail.
A service can temporarily return an error.
A remote server can be restarting.
This is why Cronix supports retries.
Suppose you configure:
{
"retries": 2,
"retry_delay": 10
}
Cronix can make up to:
Attempt 1
│
├── success ──► DONE
│
└── failure
│
▼
wait 10s
│
▼
Attempt 2
│
├── success ──► DONE
│
└── failure
│
▼
wait 10s
│
▼
Attempt 3
│
└── final result
The important detail is that retries represents additional attempts.
So:
retries = 0 → 1 attempt
retries = 1 → 2 attempts
retries = 2 → 3 attempts
The first successful attempt stops the run. (GitHub)
Run History
Cronix does more than execute jobs.
It remembers what happened.
Each execution is recorded in the run history.
A run contains information such as:
{
"job_id": "3f8a1c2b0d4e",
"trigger": "scheduled",
"time": "2026-08-17T12:34:56Z",
"status": "failed",
"exit_code": 6,
"results": [
{
"attempt": 1,
"total": 2,
"exit": 6,
"output": "curl: (6) Could not resolve host"
}
]
}
There are three important states:
ok
failed
error
ok means the command eventually succeeded.
failed means the command executed but returned a non-zero exit code after all attempts.
error means the command could not be started. (GitHub)
Output Is Bounded
Cronix captures combined stdout and stderr from each attempt.
But it does not keep unlimited output.
The stored output is limited to the last 4 KiB.
This is a useful protection against a noisy endpoint filling the run-history file indefinitely. (GitHub)
Run history is also capped at the last 50 runs per job.
That keeps the storage model predictable.
Manual Execution
Scheduled jobs are not always enough.
Sometimes you want to test a job immediately.
Cronix supports:
docker exec cronix \
/cronix cli run \
--token sekrit \
ping1
This is useful when:
- Testing a new API.
- Debugging a failed job.
- Verifying authentication.
- Checking a webhook.
- Confirming that the container can reach an external service.
The result shows the individual attempts and their exit codes. (GitHub)
CLI Management
Cronix provides a straightforward CLI.
List jobs:
docker exec cronix \
/cronix cli list \
--token sekrit
Create a job:
docker exec cronix \
/cronix cli add \
--name healthcheck \
--schedule '*/5 * * * *' \
--curl 'curl -s https://example.com/health' \
--retries 2 \
--retry-delay 10 \
--token sekrit
Get a job:
docker exec cronix \
/cronix cli get \
--token sekrit \
ping1
Disable a job:
docker exec cronix \
/cronix cli disable \
--token sekrit \
ping1
Enable it again:
docker exec cronix \
/cronix cli enable \
--token sekrit \
ping1
Delete it:
docker exec cronix \
/cronix cli delete \
--token sekrit \
ping1
The available commands include:
list
get
add
update
delete
enable
disable
run
help
The CLI also has defined exit codes, making it easier to integrate with scripts and automation. (GitHub)
REST API
One of the biggest advantages over a traditional crontab is the REST API.
All API routes are under:
/api/v1/
and require bearer-token authentication.
The major endpoints include:
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/v1/login |
Login and receive a session token |
| GET | /api/v1/jobs |
List jobs |
| POST | /api/v1/jobs |
Create a job |
| GET | /api/v1/jobs/{id} |
Get a job |
| PUT | /api/v1/jobs/{id} |
Update a job |
| DELETE | /api/v1/jobs/{id} |
Delete a job |
| GET | /api/v1/jobs/{id}/runs |
Get run history |
| POST | /api/v1/jobs/{id}/run |
Run immediately |
(GitHub)
This opens up many possibilities.
For example, another application could automatically create a Cronix job:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "backup",
"schedule": "0 2 * * *",
"curl": "curl -s https://backup.example.com/run"
}' \
http://cronix:8080/api/v1/jobs
Now your application itself can manage scheduled automation.
Web UI
For people who don't want to manage everything from the command line, Cronix includes a small web interface.
The dashboard provides an overview of:
Total jobs
Enabled jobs
Healthy jobs
Failing jobs
You can also:
- Search jobs.
- Create jobs.
- Edit jobs.
- Enable/disable jobs.
- Run jobs immediately.
- Delete jobs.
- View job details.
- Inspect execution history.
The job detail page exposes the schedule, retry configuration, curl command, and historical executions. (GitHub)
The Frontend Is Embedded
Another interesting implementation detail is that the frontend does not require a separate web server.
The UI is built using React and Vite.
The resulting static files are embedded into the Go binary using:
go:embed
So the deployment becomes:
Cronix
│
┌────────┴────────┐
│ │
Backend UI
│ │
└────────┬────────┘
│
Single binary
There is no need to deploy:
Nginx
Node.js
React server
Separate frontend container
The Go application serves the SPA directly. (GitHub)
This is exactly the kind of architecture that makes sense for a small self-hosted tool.
Authentication
Cronix has two authentication concepts.
API Token
The server requires:
CRONIX_API_TOKEN
API requests use:
Authorization: Bearer <token>
Requests without valid credentials receive an authentication error. (GitHub)
Web Login
The web UI uses:
CRONIX_USERNAME
CRONIX_PASSWORD
The defaults are:
admin
admin
These defaults are convenient for testing but should absolutely be changed for a real deployment. (GitHub)
Session Management
After logging in, the web interface receives a session token.
The frontend stores it in:
sessionStorage
rather than persistent local storage.
That means closing the browser tab effectively ends the session.
The configured session lifetime defaults to:
24h
and can be changed using:
CRONIX_SESSION_TTL
(GitHub)
Reverse Proxy Deployment
Cronix does not provide TLS itself.
The project explicitly recommends putting a reverse proxy in front of it when exposing it beyond localhost. (GitHub)
For example:
Internet
│
│ HTTPS
▼
Nginx Proxy Manager
│
│ HTTP
▼
Cronix :8080
This is particularly useful in a self-hosted environment where you already have a reverse proxy.
You could expose:
https://cron.example.com
while Cronix itself continues listening internally on:
http://cronix:8080
The reverse proxy handles:
- TLS certificates
- HTTPS termination
- Domain routing
- External access
while Cronix focuses on scheduling.
Environment Variables
Cronix exposes several environment variables:
| Variable | Default | Purpose |
|---|---|---|
CRONIX_API_TOKEN |
— | Required API bearer token |
CRONIX_USERNAME |
admin |
Web username |
CRONIX_PASSWORD |
admin |
Web password |
CRONIX_SESSION_TTL |
24h |
Web session lifetime |
CRONIX_STORE_PATH |
/data/jobs.json |
Job storage |
CRONIX_RUNS_PATH |
/data/runs.json |
Run history |
CRONIX_HTTP_ADDR |
:8080 |
HTTP listen address |
CURL_PATH |
/usr/local/bin/curl |
Curl executable |
TZ |
Container timezone | Scheduler timezone |
(GitHub)
This makes Cronix easy to configure through Docker Compose or Kubernetes-style environments.
A Practical Example: Monitoring a Home Server
Imagine you have a self-hosted server with several services.
For example:
Jellyfin
Immich
Nginx Proxy Manager
Pi-hole
Expense Tracker
Instead of manually checking each service, you could expose health endpoints.
For example:
https://jellyfin.example.com/health
https://immich.example.com/api/server/ping
https://example.com/api/health
Then create Cronix jobs:
Jellyfin Health
every 5 minutes
Immich Health
every 5 minutes
API Health
every 5 minutes
A job might be:
curl -fsS https://example.com/health
The -f option causes curl to return a failure status for HTTP error responses.
Cronix then interprets the exit code.
That gives you a simple monitoring mechanism:
Cronix
│
├── Healthcheck A ──► 200 OK
│
├── Healthcheck B ──► 200 OK
│
└── Healthcheck C ──► HTTP 500
│
▼
retry
│
▼
retry
│
▼
failed
The failure is then visible in the dashboard and run history.
Webhooks Are Another Natural Use Case
Cronix is especially useful for webhook-based automation.
For example:
curl -X POST \
-H 'Content-Type: application/json' \
-d '{"action":"backup"}' \
https://automation.example.com/webhook
This could trigger:
- Backup processes
- Deployment pipelines
- Notification systems
- Home automation
- Data synchronization
- API maintenance tasks
- Cache invalidation
- Report generation
The scheduler does not need to know what the remote service does.
Its responsibility is simply:
When?
↓
Execute HTTP request
↓
Record result
That keeps the system generic.
Example: Daily Backup Trigger
Suppose you have an external backup service with an API endpoint:
POST https://backup.example.com/run
You could configure:
{
"name": "nightly-backup",
"schedule": "0 2 * * *",
"curl": "curl -fsS -X POST https://backup.example.com/run",
"retries": 3,
"retry_delay": 60,
"enabled": true
}
The behavior becomes:
02:00
│
▼
Start backup request
│
├── success ──► complete
│
└── failure
│
▼
wait 60s
│
▼
retry
This is much easier to manage than scattering shell scripts and crontab entries across multiple servers.
Graceful Shutdown
Cronix also handles container shutdown gracefully.
When receiving:
SIGTERM
SIGINT
the scheduler stops scheduling new jobs and waits up to 10 seconds for in-flight jobs before exiting. (GitHub)
This matters in Docker because:
docker stop cronix
should not abruptly terminate a request that is already running whenever possible.
Container Hardening
The container runs as root by default, but Cronix does not require special privileges for its curl execution.
The documentation therefore suggests that users who want additional hardening can run the container with a non-root user, for example:
docker run \
--user 65534:65534 \
...
(GitHub)
For a production deployment, I would also consider:
Read-only filesystem
Minimal Linux capabilities
Non-root user
Restricted network access
Reverse proxy
Strong credentials
Secret management
depending on the environment.
Cronix vs Traditional Cron
It is useful to understand where Cronix fits.
| Feature | Traditional Cron | Cronix |
|---|---|---|
| Cron schedules | ✅ | ✅ |
| Docker-native | ❌ | ✅ |
| Web UI | ❌ | ✅ |
| REST API | ❌ | ✅ |
| Job enable/disable | Manual | ✅ |
| Manual execution | Manual | ✅ |
| Run history | Usually external | ✅ |
| HTTP jobs | Via shell | Native focus |
| Retry support | Manual | ✅ |
| Database required | ❌ | ❌ |
| Large runtime | ❌ | ❌ |
| Arbitrary shell commands | ✅ | ❌ |
Cron is still better when you need arbitrary local commands:
backup.sh
find ...
rsync ...
tar ...
Cronix is better when the workload is primarily HTTP-oriented:
GET
POST
PUT
DELETE
Webhooks
Health checks
API triggers
Remote automation
Cronix vs Heavy Schedulers
There are also much larger scheduling systems.
For example, systems such as Airflow, Kubernetes-based schedulers, or distributed task schedulers can provide:
- DAGs
- Distributed workers
- Queues
- Persistent databases
- Complex workflows
- Dependencies
- Advanced retry strategies
- Observability
But those systems solve a much larger problem.
Cronix takes the opposite approach.
Its philosophy is closer to:
I have some HTTP requests.
I want them to run on a schedule.
I want a UI.
I want retries.
I want history.
I don't want a huge platform.
That is a very useful niche.
What Cronix Does Not Try to Do
Understanding the limitations is just as important as understanding the features.
Cronix is not intended to replace:
- Bash
- System cron
- Airflow
- Kubernetes Jobs
- Celery
- Full workflow engines
- General-purpose task queues
A job cannot simply be:
rsync ...
because Cronix expects the command to start with curl.
Likewise, this is intentionally unsupported:
curl ... | jq ...
because there is no shell pipeline.
That limitation is part of the design rather than an accidental missing feature. (GitHub)
Migration From Older Cronix Versions
An interesting change in the project is the move away from environment-variable-defined jobs.
Older Cronix versions used variables such as:
CRON_SCHEDULE_<i>
CRON_CURL_<i>
Jobs are now first-class objects stored in the JSON job store.
This is a significant improvement in manageability.
Instead of:
Environment
│
├── CRON_SCHEDULE_1
├── CRON_CURL_1
├── CRON_SCHEDULE_2
└── CRON_CURL_2
the architecture is now:
Cronix
│
└── Job Store
│
├── Job A
├── Job B
└── Job C
Jobs can then be managed consistently through the UI, CLI, or API. (GitHub)
Project Structure
The repository itself is relatively easy to understand:
cronix/
├── cmd/
│ └── cronix/
│ └── ...
│
├── internal/
│ ├── api/
│ ├── auth/
│ ├── controller/
│ ├── runner/
│ ├── store/
│ ├── spa/
│ └── ...
│
├── ui/
│ └── React + Vite application
│
├── Dockerfile
├── Makefile
├── go.mod
├── go.sum
└── README.md
The separation between the frontend, command entrypoint, and internal application packages keeps the project relatively clean.
The UI build is ultimately embedded into the Go executable, allowing the final application to remain a single deployable unit. (GitHub)
A Minimal Production Setup
For a small self-hosted server, I would structure the deployment like this:
Internet
│
▼
Reverse Proxy
HTTPS / TLS
│
▼
┌────────────┐
│ Cronix │
│ :8080 │
└─────┬──────┘
│
┌──────┴──────┐
│ │
jobs.json runs.json
│ │
└──────┬──────┘
│
/data
Docker Compose:
services:
cronix:
image: cronix
container_name: cronix
restart: unless-stopped
environment:
CRONIX_API_TOKEN: ${CRONIX_API_TOKEN}
CRONIX_USERNAME: ${CRONIX_USERNAME}
CRONIX_PASSWORD: ${CRONIX_PASSWORD}
TZ: Asia/Dhaka
volumes:
- ./data:/data
expose:
- "8080"
Then let your reverse proxy expose the service.
This keeps Cronix isolated from the public network while still allowing HTTPS access through the proxy.
Things I Would Improve Further
Cronix is intentionally small, but there are several directions where it could evolve.
Notifications
A natural next feature would be notifications:
Job fails
│
├── Email
├── Discord
├── Telegram
├── Slack
└── Webhook
The current architecture already records failures, so notification support could build on that.
Better Scheduling Controls
Future scheduling features could include:
- Timezone per job
- Start/end dates
- Misfire policies
- Concurrency limits
- Maximum execution duration
More Execution Targets
The curl-only model is a strong security boundary, but some users may eventually want:
HTTP
Shell
Container
SSH
Webhook
That would need to be designed carefully so the simplicity and security of the current model are not lost.
Metrics
Prometheus metrics would also be useful:
cronix_jobs_total
cronix_job_runs_total
cronix_job_failures_total
cronix_job_duration_seconds
That would make Cronix easier to integrate into existing monitoring stacks.
Why Cronix Is Interesting
The most interesting thing about Cronix is not that it implements cron scheduling.
That part is relatively straightforward.
The interesting part is how aggressively it keeps the problem small.
The architecture is essentially:
Cron expression
│
▼
Scheduler
│
▼
curl
│
▼
HTTP endpoint
│
▼
Result + history
Around that core, Cronix provides:
┌─────────────┐
│ Web UI │
└──────┬──────┘
│
┌─────────┐ ┌─────▼─────┐ ┌─────────┐
│ CLI │───►│ REST API │◄───│ Browser │
└─────────┘ └─────┬─────┘ └─────────┘
│
▼
Job Store
│
▼
Scheduler
│
▼
curl
There is no unnecessary database.
There is no message queue.
There is no worker cluster.
There is no Node.js runtime in production.
There is no shell execution.
There is no separate frontend server.
That simplicity is the feature.
Final Thoughts
Cronix sits in an interesting space between a traditional crontab and a full-blown workflow platform.
If all you need is:
Run this HTTP request
at this time
with these retries
and let me see what happened
then a heavyweight scheduler can feel excessive.
Traditional cron can also feel too primitive once you want a UI, API, history, and manual execution.
Cronix fills that middle ground.
It combines:
- Standard cron expressions
- Docker-native deployment
- A small Go backend
- A React web UI
- REST API
- CLI management
- JSON persistence
- Retry support
- Run history
- Manual execution
- Restricted curl-based execution
- Minimal container runtime
The result is a small, self-contained scheduler that is particularly well suited to self-hosted infrastructure, webhooks, health checks, API automation, and Docker-based homelabs.
For someone running a home server with several services, Cronix can be a nice addition to the toolbox: instead of maintaining another collection of scattered cron entries and scripts, you get one place to define, execute, inspect, and manage HTTP-based automation.
Repository: github.com/iashraful/cronix
Top comments (0)