Describe the bug
I'm using the symfony4 recipe. On second deployment (after using the application), the following error occurs:
The command "cd /opt/myapp/releases/2 && (setfacl -L -R -m u:"www-data":rwX -m u:`whoami`:rwX var)" failed.
Exit Code: 1 (General error)
Host Name: myhost
================
setfacl: var/sessions/prod/sess_pneuui5pv24bk12cig5vsoglm0: Operation not permitted
The reason is that this file was created by the web server user "www-data", so the ACL cannot be changed by the deployment user.
I see that this is exactly what you are trying to prevent already:
https://github.com/deployphp/deployer/blob/5095b5de166498aedb6ef7ffff98d7243fa036ea/recipe/deploy/writable.php#L79
I assume this doesn't work due to the fact that shared dirs are inside the writable directory:
set('shared_dirs', ['var/log', 'var/sessions']);
set('shared_files', ['.env.local.php', '.env.local']);
set('writable_dirs', ['var']);
... but shared directories are processed before writables. This breaks the hasfacl check here:
https://github.com/deployphp/deployer/blob/5095b5de166498aedb6ef7ffff98d7243fa036ea/recipe/deploy/writable.php#L86
My suggestion is to place deploy:writable before deploy:shared in the deployment task of the symfony4 recipe.
Environment
Content of deploy.php
<?php
namespace Deployer;
//require 'recipe/rsync.php';
require 'vendor/deployer/recipes/recipe/rsync.php';
require 'recipe/symfony4.php';
// Project name
set('application', 'myapp');
set('rsync', [
'exclude' => ['.git', 'meta', 'var', 'app/config/parameters.yml'],
'flags' => 'rzcE',
'timeout' => '300',
]);
set('rsync_src', 'src');
// #WORKAROUND --no-dev does't work, because those dependencies are expected on cache:warmup
set('composer_options', '{{composer_action}} --verbose --prefer-dist --no-progress --no-interaction --optimize-autoloader --no-suggest');
add('shared_files', ['app/config/parameters.yml', 'var/.htpasswd']);
add('shared_dirs', ['var/logs', 'var/sessions', 'var/uploads']);
inventory('hosts.yml');
host('myapp');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
//'deploy:update_code',
'rsync',
'deploy:shared',
'deploy:vendors',
'deploy:writable',
'deploy:cache:clear',
'deploy:cache:warmup',
'deploy:symlink',
'deploy:unlock',
'cleanup',
]);
after('deploy:failed', 'deploy:unlock');
But how this is going to help? If you still not have permission. Maybe I don't understand it.
Can you explain it a little bit more? What is your setup? Now is a perfect time to make some changes as new v7 is coming.
There are 2 users, deployer and www-data. This is how it currently works:
var/logs, var/sessions, var/uploads in new release dirdeployervar because it's already theresetfacl -L -R -m u:"www-data":rwX -m u:`whoami`:rwX varwww-datavar/logs, var/sessions, var/uploads in new release dir; notice that it also creates the var directory without FACLdeployervar because it's already theresetfacl -L -R -m u:"www-data":rwX -m u:`whoami`:rwX var and crashes because it is recursive but user deployer cannot change the facls of the files created by www-data above.So, how is my suggestion to move deploy:writable before deploy:shared and deploy:vendors going to help?
First, it's important to notice that deploy:writable uses the -d flag to set the default facl entries for the writable dir. This means that all files created inside will also have the facl entries.
It works, because on second deployment, deploy:writable will create an empty var dir in the new release dir. It's empty, because deploy:shared hasn't been running yet. So it can run the facl command, as there are no files owned by www-data yet. After that, deploy:shared will create the sub-directories (logs, sessions, uploads), but not var itself, so the facl of var is still available and the sub-directories will inherit the facl, due to the -d flag.
In my first comment I wrote that deploy:shared breaks the hasfacl-check, but I was wrong.
BTW you wrote that there will be a new version. Did you also see my comment here? https://github.com/deployphp/deployer/commit/5923e442eea8811762c1e211e55741642b8d303e#r38820081
I don't know if authors are notfied about such code comments.
I get the notification but can not find it there as commit is really big.
I experience exactly the same issue.
The deploying user is myuser
First deployment : succeeds, creates shared dirs and setfacl is OK. (Typically var/log)
Then the app is used and creates var/log/prod.log, owned by www-data (who runs the webserver)
Second deployment : deployer tries to setfacl on var/log, and fails. 馃
Does anyone know of a workaround for this? I've just upgraded a Symfony app from 3.4 to 4.4 and I'm now getting this as well.
@BT643 Use the suggestion in the issue description as workaround: Override the deploy task and put deploy:writable before deploy:shared
I was wondering why I didn't experience this issue. But then remembered I added some stuff to my sudoers file. Consider this a second viable work around if everything is running locally and with use of single deploy user.
I run everything as a deploy user, and added this to /etc/sudoers.d/99-deploy.conf :
`
deploy prod-w2 = (root) NOPASSWD: /bin/chown
deploy prod-w2 = (root) NOPASSWD: /bin/chmod
deploy prod-w2 = (root) NOPASSWD: /bin/chgrp
deploy prod-w2 = (root) NOPASSWD: /bin/setfacl
`
Fixed!
@kjellk doesn't this break your whole security and effectively makes your deploy user as powerful as root?
Btw, deployer v7 can detect sudo and will ASK passwords to you.
Most helpful comment
Fixed!