I was deploying a site today with Laravel Envoy and noticed that Composer was complaining about using a build older than 30 days old. Logging in manually and running the self-update is totally doable, but why not use Envoy to make the update? I added the following to my deployment script:
@task('deploy', ['on' => 'web']) composer self-update git reset --hard git checkout master git pull origin master composer install --no-dev @endtask
However, I quickly found that the web user didn’t have the appropriate permissions to update Composer when installed globally to /usr/local/bin/composer.
[firstname.lastname@example.org]: [Composer\Downloader\FilesystemException] Filesystem exception: Composer update failed: the "/usr/local/bin/composer" file could not be written
The user does have sudo ability, though, so I tried prefixing the command with sudo. Unfortunately the command then prompted for a password which Envoy can’t handle. To get around this issue I dug in deeper and modified the sudoers file:
$ sudo visudo [sudo] password for <user>:
Inside the file I added a line which allows any user in the ‘sudo’ group to run composer as root without it requesting a password. That line looks something like this:
# Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL %sudo ALL=(ALL) NOPASSWD: /usr/local/bin/composer
This new line is pretty cryptic, so let’s break it down.
|%sudo||Group name, must be prefixed with % to signify this rule is for a group. Without the % it will be considered a user name.|
|ALL=||Host list. This gives access to all hosts and can be restricted down to only certain specified IPs or hosts.|
|(ALL)||Operator list. This is a list of users the sudoer must be running the command as.|
|NOPASSWD:||Tag list. In this case, we specify to not request a password on execution.|
|/usr/local/bin/composer||Command list. The command(s) that are available to be executed with root privileges.
This can be set to “ALL” to allow access to all commands (dangerous!)
Set to “/usr/local/bin/composer self-update” to only allow the user to run the self-update command.
You can set the parameter to “/usr/local/bin/composer self-update,/usr/local/bin/composer install” to allow the user to self-update or install with root privileges.
Lastly, “/usr/local/bin/composer s*” would allow the user to run search, self-update, show, and status with root privileges. Pretty cool!
I saved the file and then re-ran my Envoy script…voila!
$ envoy run deploy [email@example.com]: Updating to version 0c85ca426d6e8235366340f29ad0e6aab1747b83. Downloading: 100% Use composer self-update --rollback to return to version 1efa02a7ab43b7fc555dccb7d31294acbc62bbeb ...