Using Linux AMI 2 (recommended)
Since the first post the eb roadmap announced that the PHP platform had been updated making things much easier. Below the .ebextensions configuration files and the .platform files that needs to be set up are explained (otherwise nginx will throw 404 errors on all routes)
This image uses Systemd which makes the process much easier since a supervisor is not needed anymore. Unfortunately the services
keyword is not supported yet for the new images so the service has to be started and restarted using the container_commands
keyword.
Setting up the .ebextensions configuration
This file contains all the commands I execute on every production environment, remember to change them to whatever suit your needs:
\.ebextension\01-setup.config
container_commands:
01-no_dev:
command: "composer.phar install --optimize-autoloader --no-dev"
02-config_clear:
command: "php artisan config:clear"
03-view_clear:
command: "php artisan view:clear"
04-route_cache:
command: "php artisan route:cache"
05-view_cache:
command: "php artisan view:cache"
06-migrate:
command: "php artisan migrate --force"
leader_only: true
07-queue_service_restart:
command: "systemctl restart laravel_worker"
files:
/opt/elasticbeanstalk/tasks/taillogs.d/laravel-logs.conf:
content: /var/app/current/storage/logs/laravel.log
group: root
mode: "000755"
owner: root
/etc/systemd/system/laravel_worker.service:
mode: "000755"
owner: root
group: root
content: |
# 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=nginx
Group=nginx
Restart=always
ExecStart=/usr/bin/nohup /usr/bin/php /var/www/html/laravel-project/artisan queue:work --daemon
[Install]
WantedBy=multi-user.target
This second file serves to set up the Laravel scheduler, it is a cron job that runs the php artisan schedule:run
every minute. It must be executed as root, and since the environment variables are not available, we need to get them from /opt/elasticbeanstalk/deployment/env
. Here's a great answer about the topic.
\.ebextension\cron-linux.config
files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root . /opt/elasticbeanstalk/deployment/env && /usr/bin/php /var/app/current/artisan schedule:run 1>> /dev/null 2>&1
commands:
remove_old_cron:
command: "rm -f /etc/cron.d/*.bak"
Setting up the .platform configuration
\.platform\nginx\conf.d\elasticbeanstalk\laravel.conf
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
Using the old Linux AMI (previous image)
The best way is to run supervisor to manage the queues under a service to ensure that it is kept running even after a reboot.
Setting up the .ebextensions configuration
1- Install supervisor with the packages. the python keyword uses pip and easy_install under the hood:
packages:
python:
supervisor: []
2- Create the supervisor configuration file:
files:
/usr/local/etc/supervisord.conf:
mode: "000755"
owner: root
group: root
content: |
[unix_http_server]
file=/tmp/supervisor.sock ; (the path to the socket file)
[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[include]
files = /etc/supervisor/conf.d/*.conf
[inet_http_server]
port = 127.0.0.1:9001
3- Create the supervisor process file, from the configuring supervisor section in the laravel docs:
files:
/etc/supervisor/conf.d/laravel-worker.conf:
content: |
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/app/current/artisan queue:work database --sleep=3 --tries=3
autostart=true
autorestart=true
;user=root
numprocs=1
redirect_stderr=true
;stdout_logfile=/var/app/current/storage/logs/worker.log
stopwaitsecs=3600
4- Create a service that runs supervisor. It is the same as this answer with the chkconfig and processname lines added. These will allow us to run it as a service later.
files:
/etc/init.d/supervisord:
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
#chkconfig: 345 99 76
# processname: supervisord
# Source function library
. /etc/rc.d/init.d/functions
# Source system settings
if [ -f /etc/sysconfig/supervisord ]; then
. /etc/sysconfig/supervisord
fi
# Path to the supervisorctl script, server binary,
# and short-form for messages.
supervisorctl=/usr/local/bin/supervisorctl
supervisord=${SUPERVISORD-/usr/local/bin/supervisord}
prog=supervisord
pidfile=${PIDFILE-/tmp/supervisord.pid}
lockfile=${LOCKFILE-/var/lock/subsys/supervisord}
STOP_TIMEOUT=${STOP_TIMEOUT-60}
OPTIONS="${OPTIONS--c /usr/local/etc/supervisord.conf}"
RETVAL=0
start() {
echo -n $"Starting $prog: "
daemon --pidfile=${pidfile} $supervisord $OPTIONS
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
touch ${lockfile}
$supervisorctl $OPTIONS status
fi
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc -p ${pidfile} -d ${STOP_TIMEOUT} $supervisord
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -rf ${lockfile} ${pidfile}
}
reload() {
echo -n $"Reloading $prog: "
LSB=1 killproc -p $pidfile $supervisord -HUP
RETVAL=$?
echo
if [ $RETVAL -eq 7 ]; then
failure $"$prog reload"
else
$supervisorctl $OPTIONS status
fi
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p ${pidfile} $supervisord
RETVAL=$?
[ $RETVAL -eq 0 ] && $supervisorctl $OPTIONS status
;;
restart)
restart
;;
condrestart|try-restart)
if status -p ${pidfile} $supervisord >&/dev/null; then
stop
start
fi
;;
force-reload|reload)
reload
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload}"
RETVAL=2
esac
exit $RETVAL
5- After all the files are created run the following commands to start the service and to add it so it can be managed:
commands:
command-1:
command: "/etc/init.d/supervisord start"
command-2:
command: "chkconfig --add supervisord"
6- Now the services keyword should work, allowing us to set the enabled and ensurerunning flags to true.
services:
sysvinit:
supervisord:
enabled: "true"
ensureRunning: "true"
files:
- "/usr/local/etc/supervisord.conf"
Place all this in your .config file and deploy to have queues working. If you want to configure the scheduler for the old image, it is also explained in this answer, I won't update it here since I haven't tested it.
Full config file
remember to change the chkconfig number and note that I am running a migrate:fresh command
packages:
python:
supervisor: []
container_commands:
01-migrate:
command: "php artisan migrate:fresh --seed"
cwd: /var/app/ondeck
leader_only: true
files:
/opt/elasticbeanstalk/tasks/taillogs.d/laravel-logs.conf:
content: /var/app/current/storage/logs/laravel.log
group: root
mode: "000755"
owner: root
/etc/supervisor/conf.d/laravel-worker.conf:
content: |
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/app/current/artisan queue:work database --sleep=3 --tries=3
autostart=true
autorestart=true
;user=root
numprocs=1
redirect_stderr=true
;stdout_logfile=/var/app/current/storage/logs/worker.log
stopwaitsecs=3600
/usr/local/etc/supervisord.conf:
mode: "000755"
owner: root
group: root
content: |
[unix_http_server]
file=/tmp/supervisor.sock ; (the path to the socket file)
[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
[include]
files = /etc/supervisor/conf.d/*.conf
[inet_http_server]
port = 127.0.0.1:9001
/etc/init.d/supervisord:
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
#chkconfig: <number>
# processname: supervisord
# Source function library
. /etc/rc.d/init.d/functions
# Source system settings
if [ -f /etc/sysconfig/supervisord ]; then
. /etc/sysconfig/supervisord
fi
# Path to the supervisorctl script, server binary,
# and short-form for messages.
supervisorctl=/usr/local/bin/supervisorctl
supervisord=${SUPERVISORD-/usr/local/bin/supervisord}
prog=supervisord
pidfile=${PIDFILE-/tmp/supervisord.pid}
lockfile=${LOCKFILE-/var/lock/subsys/supervisord}
STOP_TIMEOUT=${STOP_TIMEOUT-60}
OPTIONS="${OPTIONS--c /usr/local/etc/supervisord.conf}"
RETVAL=0
start() {
echo -n $"Starting $prog: "
daemon --pidfile=${pidfile} $supervisord $OPTIONS
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
touch ${lockfile}
$supervisorctl $OPTIONS status
fi
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc -p ${pidfile} -d ${STOP_TIMEOUT} $supervisord
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -rf ${lockfile} ${pidfile}
}
reload() {
echo -n $"Reloading $prog: "
LSB=1 killproc -p $pidfile $supervisord -HUP
RETVAL=$?
echo
if [ $RETVAL -eq 7 ]; then
failure $"$prog reload"
else
$supervisorctl $OPTIONS status
fi
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p ${pidfile} $supervisord
RETVAL=$?
[ $RETVAL -eq 0 ] && $supervisorctl $OPTIONS status
;;
restart)
restart
;;
condrestart|try-restart)
if status -p ${pidfile} $supervisord >&/dev/null; then
stop
start
fi
;;
force-reload|reload)
reload
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload}"
RETVAL=2
esac
exit $RETVAL
commands:
command-1:
command: "/etc/init.d/supervisord start"
command-2:
command: "chkconfig --add supervisord"
services:
sysvinit:
supervisord:
enabled: "true"
ensureRunning: "true"
files:
- "/usr/local/etc/supervisord.conf"