Skip to content

Instantly share code, notes, and snippets.

@thomasjsn
Last active August 20, 2025 15:41
Show Gist options
  • Save thomasjsn/bc7d3a3b81d0118f6e89eef7d43f66f3 to your computer and use it in GitHub Desktop.
Save thomasjsn/bc7d3a3b81d0118f6e89eef7d43f66f3 to your computer and use it in GitHub Desktop.
Laravel queue worker using systemd.
# Laravel queue worker using systemd
# ----------------------------------
#
# /lib/systemd/system/queue.service
#
# run this command to enable service:
# systemctl enable queue.service
[Unit]
Description=Laravel queue worker
[Service]
User=www-data
Group=www-data
Restart=on-failure
ExecStart=/usr/bin/php /path/to/laravel/artisan queue:work --daemon --env=production
[Install]
WantedBy=multi-user.target
@bertalanimre
Copy link

Check with this command if the queue worker runs or not: ps aux | grep artisan If there is more than 1 process, then you must kill all of them and start only one process again. If only 1 is present then you are good. If there is none, then the process is not running.

@tentree-development
Copy link

At the top of this post I mentioned the process is there just queue job doesn't get executed (which mens jobs are in the table) unless I manually type command "sudo php artisan queue:work" or "sudo systemctl start laravel_worker" My coworker said just put sudo systemctl start laravel_worker in postdeployment script. Then it seems to work. Is that how I supposed to do? Please advice.

@bertalanimre
Copy link

If the process is there, but no actual job is being done, that looks like privileges issue. Make sure, the process is being run by the same user who is serving the application too. Also, I just noticed, running an artisan worker as root is very much not adviced.

@tentree-development
Copy link

oh I see thank you very much and I appreciate for being patient :)

@glaszig
Copy link

glaszig commented May 18, 2023

the --daemon option is deprecated. programs under control of systemd should not daemonize anyway.

@cAstraea
Copy link

Having a bunch of issues with this ... freaking amazon removed supervisord from amazon linux 2023 and system d is the only way it seems but I'm not experience enough on how to use it. I just wish they would bring back supervisord

@harryqt
Copy link

harryqt commented Apr 19, 2025

Anyone made any working version?

@mohroba
Copy link

mohroba commented Aug 20, 2025

I might be answering late, but I use this script to setup queues, scheduler and reverb on my own project. the content of worker_setup.sh is following, I used AI To Comment it and make it more clear for all :

`
#!/bin/bash

Enhanced Script to set up Laravel queue workers (multiple instances per queue),

Reverb, and Scheduler as systemd services,

with folder ownership & permission fixes so www-data can write logs.

Function to prompt for input with a default value

prompt_default() {
local PROMPT_TEXT=$1
local DEFAULT_VALUE=$2
read -r -p "$PROMPT_TEXT [$DEFAULT_VALUE]: " INPUT_VALUE
echo "${INPUT_VALUE:-$DEFAULT_VALUE}"
}

echo "=== Laravel Services Setup Script ==="

Prompt for the Laravel project path

PROJECT_PATH=$(prompt_default "Enter the path to your Laravel project" "/var/www/program")

Prompt for the user and group to run the services as

SERVICE_USER=$(prompt_default "Enter the user to run the services as" "www-data")
SERVICE_GROUP=$(prompt_default "Enter the group to run the services as" "$SERVICE_USER")

Configure worker timeout (via environment variable or default)

WORKER_TIMEOUT=${WORKER_TIMEOUT:-180}
echo "Using queue worker timeout of ${WORKER_TIMEOUT}s"

Prompt for queues to create workers for (comma-separated)

read -r -p "Enter the queue names to create workers for (comma-separated) (include default): " QUEUES
IFS=',' read -ra QUEUE_ARRAY <<< "$QUEUES"

Prompt for number of workers per queue

declare -A WORKER_COUNTS
for QUEUE in "${QUEUE_ARRAY[@]}"; do
QUEUE_NAME=$(echo "$QUEUE" | xargs)
COUNT=$(prompt_default "How many workers for queue '$QUEUE_NAME'?" "1")
WORKER_COUNTS[$QUEUE_NAME]=$COUNT
done

Ensure Laravel storage & cache dirs exist and are writable

echo "Ensuring Laravel storage & cache dirs exist and are writable by $SERVICE_USER:$SERVICE_GROUP..."
sudo mkdir -p "$PROJECT_PATH/storage/logs" "$PROJECT_PATH/bootstrap/cache"
sudo chown -R "$SERVICE_USER":"$SERVICE_GROUP" "$PROJECT_PATH/storage" "$PROJECT_PATH/bootstrap/cache"
sudo chmod -R ug+rwx "$PROJECT_PATH/storage" "$PROJECT_PATH/bootstrap/cache"

--- Queue Workers Setup ---

Disable & remove any existing laravel-worker services

echo "Stopping & disabling any existing laravel-worker services..."
sudo systemctl disable --now laravel-worker-* 2>/dev/null || true
sudo rm -f /etc/systemd/system/laravel-worker-*.service

Create one service file per worker instance

for QUEUE in "${!WORKER_COUNTS[@]}"; do
COUNT=${WORKER_COUNTS[$QUEUE]}
for (( i=1; i<=COUNT; i++ )); do
SERVICE_NAME="laravel-worker-${QUEUE}-${i}"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"

echo "Creating & enabling service $SERVICE_NAME (queue='$QUEUE', instance #$i)..."
sudo tee "$SERVICE_FILE" > /dev/null <<EOL

[Unit]
Description=Laravel Queue Worker for '${QUEUE}' (instance ${i})
After=network.target

[Service]
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
Environment="PATH=/usr/bin:/bin:/usr/sbin:/sbin"
ExecStart=/bin/bash -lc '/usr/bin/php ${PROJECT_PATH}/artisan queue:work --verbose --queue=${QUEUE} --sleep=3 --tries=5 --timeout=${WORKER_TIMEOUT}
| tee -a ${PROJECT_PATH}/storage/logs/queue-worker-${QUEUE}-${i}.log
| logger -t laravel-worker-${QUEUE}-${i}'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOL

sudo systemctl daemon-reload
sudo systemctl start  "$SERVICE_NAME"
sudo systemctl enable "$SERVICE_NAME"

done
done

--- Reverb WebSocket Server Setup ---

echo "Stopping & disabling existing Reverb service..."
sudo systemctl disable --now reverb 2>/dev/null || true
sudo rm -f /etc/systemd/system/reverb.service

echo "Creating Reverb service file..."
sudo tee /etc/systemd/system/reverb.service > /dev/null <<EOL
[Unit]
Description=Reverb WebSocket Server
After=network.target

[Service]
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
Environment="PATH=/usr/bin:/bin:/usr/sbin:/sbin"
ExecStart=/bin/bash -lc '/usr/bin/php ${PROJECT_PATH}/artisan reverb:start --host=127.0.0.1 --port=6001
| tee -a ${PROJECT_PATH}/storage/logs/reverb.log
| logger -t reverb'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOL

sudo systemctl daemon-reload
sudo systemctl start reverb
sudo systemctl enable reverb

--- Scheduler Setup ---

echo "Stopping & disabling existing Scheduler service..."
sudo systemctl disable --now laravel-scheduler 2>/dev/null || true
sudo rm -f /etc/systemd/system/laravel-scheduler.service

echo "Creating Scheduler service file..."
sudo tee /etc/systemd/system/laravel-scheduler.service > /dev/null <<EOL
[Unit]
Description=Laravel Scheduler Service
After=network.target

[Service]
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
Environment="PATH=/usr/bin:/bin:/usr/sbin:/sbin"
ExecStart=/bin/bash -lc '/usr/bin/php ${PROJECT_PATH}/artisan schedule:work
| tee -a ${PROJECT_PATH}/storage/logs/scheduler.log
| logger -t laravel-scheduler'
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
EOL

sudo systemctl daemon-reload
sudo systemctl start laravel-scheduler
sudo systemctl enable laravel-scheduler

echo "Setup complete! Logs are in $PROJECT_PATH/storage/logs/*.log"
echo "You can also inspect via journalctl, e.g.:"
echo " journalctl -t laravel-worker--"
echo " journalctl -t reverb"
echo " journalctl -t laravel-scheduler"
`

@glaszig
Copy link

glaszig commented Aug 20, 2025

@mohroba please use proper markdown code fencing. this is unusable as it is.

@mohroba
Copy link

mohroba commented Aug 20, 2025

@glaszig @thomasjsn Sorry About the mess.
I created a simple repo for my script, I hope it helps others:
Laravel Services Setup (Queue Workers, Reverb, Scheduler)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment