Supervisor / "Pseudo Cron Jobs" in ddev

Recently, I was looking for an easy solution to run "cron jobs" like TYPO3's scheduler or workers like Symfony's messenger consumer via ddev without adding additional dependencies. I came up with a solution based on the existing supervisord. Here's how to do that.

What's ddev?
ddev is an open source tool providing simple, cross-platform, docker based local development setups for web / PHP projects. !!! Find out more at


Supervisor is basically a process control system that is able to "watch" processes and restart them on failures, making sure they "just keep on running". See for more information.

Ddev is already using supervisor in the web image, which you can verify by running service supervisor status in the ddev container.

How to set up supervisor on ddev

To make sure we do not break the web image, we need to first copy the existing ddev supervisord config in a directory on our local system, in my case I did:

    ddev ssh
    mkdir supervisor_temp
    cp /etc/supervisor/conf.d/* /var/www/html/supervisor_temp/

Then we create a folder below the .ddev folder for the configs and move the files from supervisor_temp to that new folder on the host:

    mkdir .ddev/supervisor
    mv supervisor_temp/* .ddev/supervisor/
    rm -Rf supervisor_temp

Next, we need to mount that folder as new supervisor conf folder, by creating a .ddev/docker-compose.supervisor.yml which adds a volume definition:

version: "3.6"

      - ./supervisor:/etc/supervisor/conf.d

Now we can restart ddev and already have supervisor use a folder which we can populate from the host with our own additional configs.

Example: Symfony messenger:consume worker in ddev

The following example shows how to get the worker for the symfony messenger component configured as a service on supervisor but it can be used for any other worker-like process as well.

With supervisor up and running and having control over the config folder, we only need to create a .conf file in the .ddev/supervisor folder to make our service known.

Create a file called symfony-messenger-consume.conf with the following content:

command=/usr/bin/php /var/www/html/bin/console messenger:consume default

This will start the consumer on startup automatically as well as restart the consumer if it fails for whatever reason - including up to 10 retries.

Restart ddev after creating the config file and check whether the consumer is running:

    ddev ssh
    ps x | grep consume

Example: "pseudo" cron job for TYPO3 scheduler in ddev

The requirements for running the TYPO3 scheduler are slightly different. Instead of a long-running process we have a process required to run at certain intervals instead. However, we can fake it as long-running process, too, by creating a bash script with an interval in an endless loop.

Caveat: In comparison to a real crontab, this only gives us an easy way to run scripts at a certain interval. Cron itself is a lot more powerful - but in case of the TYPO3 scheduler, all of that power is not necessary.

Create a file called in .ddev/supervisor with the following content (make sure to make it executable with chmod +x):

#!/usr/bin/env bash

while true
  sleep 60
  /var/www/html/vendor/bin/typo3 scheduler:run

Then add a supervisor conf file in addition .ddev/supervisor/typo3-scheduler.conf:


... and restart ddev. The script itself will just keep on running - and because of the sleep-loop it will start the TYPO3 scheduler every minute.

The idea here is taken from the original "Cron Job in ddev" snippet - see for that (the main difference is that no additional packages are required with supervisor)