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
@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