Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Supervisord Laravel Package

francodacosta/supervisord

PHP client for Supervisord's XML-RPC API that lets you start, stop, restart and inspect supervisor programs and processes, read logs, and check status from Laravel or any plain PHP application.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, framework-agnostic PHP library whose only job is to render supervisord .ini configuration files. It ships no service provider, no facade, and no Laravel integration — you composer require francodacosta/supervisord and call it directly, typically from an Artisan command or deploy script.

Because the package is thin (3 stars, no dependents) and largely undocumented, the first thing to do is read vendor/francodacosta/supervisord/src — it is a handful of classes modelling the supervisord sections (Supervisord / Program / ProgramGroup). Names in the snippets below follow that structure; confirm them for the pinned version.

The most useful first use case is turning a hand-maintained /etc/supervisor/conf.d/laravel.conf into generated output:

use Francodacosta\Supervisord\Supervisord;
use Francodacosta\Supervisord\Program;

$config = new Supervisord();

$worker = new Program();
$worker->setName('laravel-queue-default');
$worker->setCommand('/usr/bin/php /var/www/app/artisan queue:work --queue=default --sleep=1 --tries=3');
$worker->setNumprocs(4);
$worker->setProcessName('%(program_name)s_%(process_num)02d');
$worker->setUser('www-data');
$worker->setAutostart(true);
$worker->setAutorestart(true);

$config->addProgram($worker);

file_put_contents('/etc/supervisor/conf.d/laravel.conf', $config->getConfig());

Then supervisorctl reread && supervisorctl update applies it.

Implementation Patterns

Config-driven generation. Keep a config/supervisor.php that describes programs declaratively, and let one Artisan command render everything. This is where the package earns its keep — it saves you from string-concatenating INI.

// config/supervisor.php
return [
    'programs' => [
        'laravel-queue-default' => [
            'command'   => 'php artisan queue:work --queue=default --tries=3 --sleep=1',
            'numprocs'  => (int) env('QUEUE_PROCS', 4),
            'user'      => 'www-data',
        ],
        'laravel-scheduler' => [
            'command'  => 'php artisan schedule:work',
            'numprocs' => 1,
            'user'     => 'www-data',
        ],
    ],
];
class GenerateSupervisorConfig extends Command
{
    protected $signature = 'supervisor:generate {--dry-run} {--path=/etc/supervisor/conf.d/laravel.conf}';

    public function handle(): int
    {
        $config = new Supervisord();

        foreach (config('supervisor.programs') as $name => $opts) {
            $program = new Program();
            $program->setName($name);
            $program->setCommand(
                str_replace('php artisan', PHP_BINARY.' '.base_path('artisan'), $opts['command'])
            );
            $program->setDirectory(base_path());
            $program->setNumprocs($opts['numprocs']);
            $program->setProcessName('%(program_name)s_%(process_num)02d');
            $program->setUser($opts['user'] ?? 'www-data');
            $program->setAutostart(true);
            $program->setAutorestart(true);
            $program->setStopwaitsecs(30);
            $config->addProgram($program);
        }

        $ini = $config->getConfig();

        if ($this->option('dry-run')) {
            $this->line($ini);
            return self::SUCCESS;
        }

        file_put_contents($this->option('path'), $ini);
        $this->call('shell', ['cmd' => 'supervisorctl reread && supervisorctl update']);
        return self::SUCCESS;
    }
}

Deploy hook. Run php artisan supervisor:generate in your deploy pipeline after the new release directory exists and before the queue restart. Diff the generated file against the deployed one and only reread/update when it changed — unnecessary reloads bounce healthy workers.

Program groups. Use one group per app ([group:laravel]) so operators can supervisorctl restart laravel:* without touching other tenants on a shared box. This is the main reason to model sections instead of writing a heredoc.

Docker entrypoints. Generate at container boot from env vars (queue names, proc counts), then exec supervisord -n. This keeps images identical across environments.

Golden-file tests. Snapshot $config->getConfig() into a fixture and assert against it in CI. It catches accidental numprocs or command changes far earlier than a production queue that silently stops draining.

Coexistence with Horizon. Don't duplicate Horizon's own supervisor setup. Use this package only for non-Horizon daemons: schedule:work, queue:work --queue=low, or bespoke long-running workers (websocket consumers, feed pollers).

Thin wrapper. Wrap the library in your own SupervisorConfigBuilder so swapping to a Blade/heredoc template later is a one-file change — the package is small enough that this costs almost nothing and protects you from abandonment.

Gotchas and Tips

  • Percent signs are supervisord directives. %(program_name)s, %(process_num)02d, and %(ENV_X)s are interpreted by supervisord. Any literal % in a command (URL-encoded args, date +%s) must be escaped as %%. Verify the library escapes for you or do it yourself.
  • Booleans must be lowercase true/false in the INI; PHP setAutostart(true) is fine, but passing 'True' or 1 produces config supervisord rejects.
  • numprocs > 1 requires process_name, otherwise every child gets the same name and supervisorctl cannot address them individually.
  • Absolute paths only. Supervisord does not inherit your shell's PATH or cwd. Use PHP_BINARY/base_path('artisan') and set directory= explicitly — a relative php artisan will fail with can't find command.
  • Supervisord does not load .env from your project root for its own process, and child env comes from the config environment= line or the supervisor daemon's environment. If your workers depend on exported vars, set them explicitly.
  • File permissions matter. Supervisord ignores conf files that are world-writable. Write as 0644, owned by root, into a directory matched by an include in the main supervisord.conf. Missing include glob is the #1 "my generated file does nothing" cause.
  • reread ≠ update. reread reloads file contents; update actually adds/removes/restarts programs. Changing a command requires both, and even then existing processes restart only with update.
  • Log destination. Set stdout_logfile/stderr_logfile (or /dev/stdout under Docker) and plan rotation — stdout_logfile_maxbytes. Unrotated queue worker logs fill disks quietly.
  • Shutdown behaviour. For queue workers set stopsignal=TERM and a sane stopwaitsecs (e.g. 30) so in-flight jobs finish; killasgroup=true prevents orphaned child processes when using --tries wrappers.
  • Debugging: validate a candidate file with supervisord -n -c /path/to/supervisord.conf in the foreground, then supervisorctl status, supervisorctl tail -f <name> stderr.
  • No supervisorctl API here. The package only renders text. Anything live (status, restart, tail) is your own Process/shell_exec call — wrap and escape carefully, since program names go straight into a shell command.
  • Treat the dependency as at-risk. Zero dependents and low activity means no security patches coming. Pin the version in composer.json, and because the blast radius is "renders a text file," the wrapper approach above lets you drop it in an afternoon if needed.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package