Migration guide
Move EasyCron, cron-job.org, and GitHub Actions timers onto a scheduler you host
Most hosted cron is a crontab string and an HTTP ping. You can run that next to the app it calls, on a machine you already pay for.

EasyCron, cron-job.org, and GitHub Actions scheduled workflows all sit outside the box that actually does the work. That path holds URLs, bearer tokens, and run history. When the bill is monthly, you are renting a timer. NexusCron is the same architecture on your host: schedule, HTTP fire, retry, SQLite logs.
Target architecture
01
Host
Docker on a VPS or home server. Same network as the job target when you can.
02
Store
SQLite volume for jobs and run history. Back it up with the rest of the disk.
03
Fire
Cron expression plus HTTP GET/POST. Timeouts and retries in config, not a plan tier.
04
Observe
Status codes, bodies, and retry counts on disk. Replay from the UI or API.
Hosted cron vs NexusCron
| Concern | Cloud cron SaaS | NexusCron |
|---|---|---|
| Where the timer runs | Vendor account (EasyCron, cron-job.org, GitHub Actions cron) | Container on a VPS or home box you already keep up |
| Job store | Vendor dashboard, export if they still offer it | SQLite on disk you back up with the rest of the host |
| HTTP pings | Their egress to your URL, timeouts and concurrency by plan | Local HTTP from the same network as the app it wakes |
| Secrets in headers | Stored in the hosted job definition | Env file next to Compose. Never leaves the host |
| Logs | Last N runs in a vendor UI, then gone | Run history in SQLite you can query and retain |
| Limits | Job caps, request caps, minute granularity by tier | Your CPU, disk, and network |
| Cost after year one | Still monthly, often $20–$50 for a real job list | Zero. License is one payment |
Docker Compose
Put the data volume on the same disk you already back up. Secrets stay in cron.env, not in the image.
services:
nexuscron:
image: nexuscron:latest
restart: unless-stopped
ports:
- "127.0.0.1:8787:8787"
environment:
TZ: Europe/Madrid
NEXUSCRON_DATA: /data
NEXUS_TELEMETRY: "off"
CRON_ADMIN_TOKEN: \${CRON_ADMIN_TOKEN}
volumes:
- ./data:/data
- ./jobs.json:/app/jobs.json:ro
- ./cron.env:/run/secrets/env:roProduction environment
Set TZ to the zone your cron expressions assume. Rotate CRON_ADMIN_TOKEN like any other admin secret.
# cron.env (chmod 600) CRON_ADMIN_TOKEN=replace-me TZ=Europe/Madrid # Optional: HMAC on inbound health pings CRON_PING_SECRET=replace-me # Optional: default timeout for HTTP jobs CRON_HTTP_TIMEOUT_MS=15000
jobs.json
One object per hosted timer. Keep the same cron string and URL so cutover is a pause on the vendor side, not an app change.
{
"jobs": [
{
"id": "billing-reconcile",
"cron": "15 3 * * *",
"timezone": "Europe/Madrid",
"http": {
"url": "http://billing.internal/jobs/reconcile",
"method": "POST",
"headers": { "Authorization": "Bearer ${BILLING_TOKEN}" }
},
"retry": { "max": 3, "backoff_ms": 2000 }
},
{
"id": "uptime-ping",
"cron": "*/5 * * * *",
"http": {
"url": "https://app.yourdomain.com/internal/health",
"method": "GET"
}
}
]
}Cutover without missed pings
- Export every hosted job (expression, URL, headers).
- Bring NexusCron up. Confirm /health.
- Load jobs.json. Run one job immediately.
- Dual-run for one interval if the endpoint is idempotent.
- Pause EasyCron / cron-job.org. Keep the CSV until you trust SQLite.
# 1. Health
curl -sS -o /dev/null -w "%{http_code}\\n" http://127.0.0.1:8787/health
# 2. Load jobs and fire one now
curl -sS -X POST http://127.0.0.1:8787/api/jobs/uptime-ping/run \\
-H "Authorization: Bearer $CRON_ADMIN_TOKEN"
# 3. After a clean day, pause EasyCron / cron-job.org entries
# Keep their export CSV next to jobs.json until you trust the tableRelated setup page: Self-hosted cron alternative.
NexusCron
Own the scheduler
$94.99one-time
- Source license for NexusCron
- Docker Compose and jobs.json examples
- HTTP jobs, retries, SQLite history
- No monthly job or request caps
Checkout stays on Whop. You get the source after payment.
Questions people ask before they switch
Do I still need crontab on the box?
No. NexusCron is the scheduler. Keep systemd or Compose restarting the container. crontab is optional for a single ping; this is for a dashboard, logs, and HTTP jobs you can edit without SSH.
Can I dual-run EasyCron during cutover?
Yes. Recreate jobs in NexusCron pointing at the same URLs. Let both fire for one interval if the endpoint is idempotent, then pause the cloud jobs.
What about GitHub Actions scheduled workflows?
If the workflow is only an HTTP ping or a script you already run on a VPS, move it here. Keep Actions for CI that needs GitHub’s runners.
Where do failed runs go?
The run table on disk. Open the job, read the status code and body, then retry from the UI or POST /api/jobs/{id}/run.
Keep reading
Guide
Self-hosted cron alternative
Stop paying a monthly bill to fire HTTP on a timer. NexusCron is a self-hosted cron alternative you deploy with Docker on machines you already own.
Guide
EasyCron and cron-job.org alternative
Compare EasyCron, cron-job.org, and other hosted cron products with NexusCron. Same job, no subscription, logs and secrets stay on your disk.
Guide
Migrate off EasyCron to a self-hosted runner
Step-by-step migration from EasyCron to a self-hosted cron runner. Export jobs, map cron expressions, Docker Compose, HTTP pings, and cutover without downtime.
Guide
Migrate cron jobs off cloud providers to self-hosted
Technical guide for migrating cron jobs off cloud providers to self-hosted NexusCron. Architecture, Docker Compose, job mapping, and cutover without missed pings.
Guide
Migrate EasyCron jobs to self-hosted NexusCron
Architecture, Docker Compose, and cost math for replacing $20–$50/month hosted cron with NexusCron on a VPS you already run. One lifetime payment.
Guide
Self-hosted webhook router
A self-hosted webhook router that receives, transforms, and forwards events on your infrastructure. One payment. No Zapier tax for simple routing.
Guide
Replace cloud webhook services with self-hosted Webhook Router
Architecture, Docker Compose, and config mapping to replace Hookdeck, Svix, Zapier, and Make with NexusCore Webhook Router on your VPS. One lifetime payment.
Guide
Replace cloud webhook queues with local SQLite routing
Technical architecture for replacing cloud webhook queues with local SQLite routing. Production Docker Compose, under 50MB RAM, WAL mode, retries, and dead-letter replay.
Guide
Self-hosted pipeline setup
NexusPipeline is a FastAPI Docker execution engine. Clone it, compose up, and keep job state on disk you control. One payment. No worker SaaS.
Guide
Self-hosted admin dashboard setup
NexusAdmin is the self-hosted dashboard that sits next to NexusPipeline. One payment, Docker Compose, no SaaS admin tenant.
Guide
Self-hosted log stream setup
LogStream is a single-binary Node.js collector. HTTP and UDP ingest, SQLite, live dashboard, webhook alerts. One payment. No observability SaaS.
Guide
Self-hosted env sync setup
EnvSync Agent syncs .env values across VPS hosts, laptops, and microservices. Encrypted key-value store. One payment. No secrets tenant.
Guide
Self-hosted API proxy setup
API Proxy Service sits between your code and upstream APIs. Retries, rate limits, fallbacks, circuit breakers. One payment. No gateway SaaS.