Trigger Symfony Console commands from signed HTTP URLs, with an execution strategy that adapts to the hosting's capabilities.
Designed for shared hostings (Infomaniak, OVH mutualisé, …) that only offer web-based scheduled tasks and no real cron.
The hosting's scheduler hits a signed URL on your Thelia site. The module authenticates the request (HMAC-SHA256 signature with a short time window), picks the best available execution strategy and runs the configured command.
Three strategies are available. The auto strategy (default) picks the best
one supported by the hosting — detected and cached at runtime.
| Strategy | Requires | Behaviour |
|---|---|---|
cli_fork |
proc_open + a PHP CLI binary |
Spawns nohup php Thelia <cmd> & detached from the HTTP worker. HTTP responds in milliseconds. Best choice for long-running syncs. |
fastcgi_finish |
fastcgi_finish_request |
Responds to the client, flushes the PHP-FPM buffer, then runs the command in-process (via an external process if proc_open is allowed, in-process Thelia Application otherwise). |
sync |
none | Runs the command in the HTTP request and returns the output. Limited by PHP's max_execution_time. Last-resort fallback. |
- Static HMAC-signed trigger URLs — paste once in your hosting's cron panel, never rotate it
- Per-task opaque slug and secret (secret revealed once at creation); rotating the secret invalidates the URL
- Per-task IP allowlist (CIDR), minimum interval rate limit, maximum runtime
- Concurrency lock (
symfony/lock, file-based) — overlapping calls are skipped - Execution history with status, exit code, strategy used and command output
- Back-office diagnostic panel — shows which capabilities the hosting provides and which strategies are supported
- Back-office CRUD for tasks, manual "trigger now" button, secret regeneration
- Any Symfony Console command registered in Thelia is schedulable (no need to write module-side glue)
composer require thelia/web-scheduler-moduleActivate the module in the back-office → Modules.
- Back-office → Tools → Web Scheduler
- Create a task — pick a command (auto-completed from your registered
Symfony commands), set optional arguments, choose
autostrategy. - On save, the secret is revealed once — store it if you ever need to sign URLs outside the module.
- Copy the Trigger URL from the task list (or from the task edit page).
- Paste that URL into your hosting's scheduled-tasks panel.
On Infomaniak's "Planifier une tâche" panel:
- URL: paste the full trigger URL (including
?ts=...&sig=...) - Password: leave unchecked — the HMAC signature replaces URL basic-auth
Paste the URL once and let Infomaniak call it on its schedule. The URL is stable — there is no timestamp or expiry. If the URL ever leaks and you want to invalidate it, hit Regenerate secret in the task form: the slug stays the same, the signature changes, every previously-copied URL stops working.
- Each task has a unique 32-hex opaque slug embedded in the URL path.
- The URL is signed:
sig = HMAC-SHA256(slug, secret). The signature is static (no timestamp), so the URL is stable for web-cron usage. - Signature comparison is timing-safe (
hash_equals). - Command arguments are frozen per task — nothing from the query string influences the executed command. No RCE surface.
- Optional per-task IP allowlist (CIDR, one entry per line) — the strongest defence-in-depth layer if the URL leaks.
- Optional per-task rate limit (
min_interval_seconds). - Rejected requests always respond
202 Acceptedwith a neutral body, to avoid leaking task existence. - To invalidate a leaked URL: Regenerate secret in the task form.
- Namespace:
WebScheduler\*(PSR-4) - Requires PHP 8.3+, Thelia 2.6+, Symfony 6.4 or 7.x
- Strategies are services tagged
webscheduler.execution_strategy, loaded intoStrategyResolvervia#[AutowireIterator] - Lock store:
FlockStorerooted atTHELIA_CACHE_DIR/webscheduler_locks - Command capture: output is truncated to 64 KiB per execution
LGPL-3.0-or-later