Skip to content

Symfony4 recipe - writable setfacl "Operation not permitted" at second deployment #2932

@romainguerrero

Description

@romainguerrero
  • Deployer version: 6.8.0
  • Deployment OS: Debian GNU/Linux 11 (bullseye)

I have the same problem as reported on closed issues #1976 and #2044 but where the problems seems to not have been understood. Maybe this issue will resolve the problem 🤞

I use the Symfony4 recipe to deploy my application and this recipe indicates that the default shared dirs are 'var/log', 'var/sessions' and the writable dir 'var'.

Here is my very simple deploy.php :

<?php

namespace Deployer;

require 'recipe/symfony4.php';

// Configuration
set('repository', 'git@XXX.git');

add('shared_dirs', ['public/uploads', 'public/media', 'public/pdf']);
add('writable_dirs', ['public/uploads', 'public/media', 'public/pdf']);

// Servers
host('preprod')
    ->hostname('XXX')
    ->user('deploy')
    ->set('branch', 'develop')
    ->set('deploy_path', '/var/www/XXX')
;

If the first deployment was a success, I tried to deploy a new version of my code a few days later and I have now this issue :

  [Deployer\Exception\RuntimeException (1)]                                                                                                  
  The command "cd /var/www/XXX/releases/2 && (setfacl -L -R -m u:"www-data":rwX -m u:`whoami`:rwX var)" failed.  
                                                                                                                                             
  Exit Code: 1 (General error)                                                                                                               
                                                                                                                                             
  Host Name: preprod                                                                                                                         
                                                                                                                                             
  ================                                                                                                                           
  setfacl: var/log/prod-2022-01-28.log: Operation not permitted
  ...

After some investigations, the problem is that the writable code for ACL checks first if the writable folder has ACL configuration for the web server user (here www-data). See recipe/deploy/writable.php#L115 :

// Check if ACL has been set or not
$hasfacl = run("getfacl -p $dir | grep \"^user:$httpUser:.*w\" | wc -l");
// Set ACL for directory if it has not been set before
if (!$hasfacl) {
    run("setfacl -L $recursive $setFaclUsers $dir");
    run("setfacl -dL $recursive $setFaclUsers $dir");
}

Here the global directory 'var' is a fresh one from the git clone, so it hasn't ACL configuration, so the if statement make the code try to set ACL on it, but as the symlinked subfolders log or session contain files created by the webserver, the command fails.
As indicated by this documentation :

Requirement: To issue setfacl, you must be the file owner or have superuser authority
And as the deploy user is neither the owner (here www-data) neither a sudo, the setfacl command fails.

To avoid this issue, the solution is to update the recipe to specify the subfolders (like it was done is Symfony 3 recipe) :

- set('writable_dirs', ['var']);
+ set('writable_dirs', ['var/cache', 'var/log', 'var/sessions']);

With this configuration, at the second deployment, the writable code is now able to check get the information that the 'var/log' and 'var/sessions' folders have already ACL configuration for the web server user, and avoid to call the setfacl function. It will only be called by default on the fresh new empty var/cache folder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions